dingusppc/zdocs/openfirmware.md

12 KiB

Open Firmware in Power Macintosh

compiled from various sources by Max Poliakovski.

Open Firmware is a platform-independent boot firmware architecture covered by an IEEE standard.

All Power Macintosh computers run Open Firmware except the very first generation that uses Nubus instead of PCI.

Open Firmware is used to perform hardware identification and initialization during the booting process after power-on. It also provides a platform-independent description of the attached devices available for operating systems. In this respect, Open Firmware can be compared with BIOS, widely used in the PC world.

Being based upon the Forth programming language, Open Firmware offers an operating system, an interactive environment as well as a programming language in one package. Its shell can be used as well by users for controlling the boot enviroment as by developers for developing and debugging device drivers.

This document focuses on various aspects of Apple's Open Firmware implementation as found in various Power Macintosh models.

Open Firmware Versions

Old World Macs

ROM dump/Machine BootROM codename OF version OF image offset
Power Macintosh 7300/7600/8600/9600 TNT 1.0.5 0x330000
Bandai Pippin Pip 1.0.5 0x330000
Power Macintosh,Performa 6400 Alchemy 2.0 0x330000
Power Macintosh G3 desktop Gossamer 2.0f1 0x320000
PowerBook G3 Wallstreet v2 GRX 2.0.1 0x330000
Power Macintosh 4400/7220 Zanzibar 2.0.2 0x330000
Power Macintosh 6500 Gazelle 2.0.3 0x330000
Power Macintosh G3 v3 Gossamer 2.4 0x320000

NewWorld Macs

TBD

Open Firmware image

Old World Macs

Open Firmware in OldWorld Macs is stored in the monolithic 4MB ROM. Its hibernated image is located at offset 0x320000 or 0x330000 from beginning of the ROM. That corresponds to the physical address 0xFFF20000 or 0xFFF30000, respectively.

The size of the Open Firmware image varies from 98KB (v1.0.5) to 172KB (v2.4).

Apple's Open Firmware image has the following structure:

Section type Architecture Relative Size (v1.0.5) Relative Size (v2.4)
OF kernel PowerPC 26% 18%
OF main code FCode 62% 51%
OF device packages FCode 12% 31%

OF image is wrapped in the COFF container. At the start of the image, a COFF file header and a section header are located. The following example parses the COFF headers of the OF image from the Gossamer ROM v3:

org 0xFFF20000

; OF COFF file header
dc.w     0x1DF      ; COFF magic
dc.w         1      ; number of sections
dc.l    'Gary'      ; Gary Davidian's signature replaces time and date
dc.l         0      ; ptr to the symbol table
dc.l         0      ; number of entries in the symbol table
dc.w         0      ; size of the optional header
dc.w         0      ; flags

; OF COFF section header
dc.b    '.text', 0, 0, 0    ; section name
dc.l         0      ; physical address
dc.l         0      ; virtual address
dc.l   0x2ADB0      ; section size in bytes (= 171KB)
dc.l      0x3C      ; file offset to section data
dc.l         0      ; file offset to section relocations
dc.l         0      ; file offset to line number entries
dc.w         0      ; number of relocation entries
dc.w         0      ; number of line number entries
dc.l      0x20      ; section flags (this section contains executable code)

Right after the COFF section header, a vital OF kernel data structure called StartVec is located. It contains among others several important offsets into the OF image for finding all required OF parts. That's also the location HWInit passes control to when invoking OF:

org 0xFFF2003C

; OF execution starts here
mflr    r11             ; save return address to HWInit in R11
bl      OF_kernel_start ; pass control to OF kernel
                        ; LR will contain physical address of StartVec

; Begin of StartVec structure
; All offsets are from the beginning of the .text section (0xFFF2003C)
FFF20044  dc.l   0x7918 ; offset to the FCode stream of the OF main package
...
FFF2007C  dc.l  0x28C48 ; offset to the last driver in the device packages
...
FFF20084  dc.l   0x7720 ; offset to the last Forth word descriptor of the kernel

This StartVec structure in ROM is not to be confused with the @startvec structure in RAM. Open Firmware 2.4 lists the fields of @startvec:

0x488 0000 FF808000 >of.next              00001000
0x489 0004 FF808004 >of.dev-ven           00000000
0x48A 0008 FF808008 >of.class             00000000
0x48B 000C FF80800C >of.offset            00000000
0x48C 0010 FF808010 >of.fcode             00000000
0x48D 0008 FF808008 >imagesize            00000000
0x48E 000C FF80800C >'cold2               00000000
0x48F 0010 FF808010 >'map-page            00000000
0x490 0014 FF808014 >'map-io              00000000
0x491 0018 FF808018 >endiango             FF808940
0x492 001C FF80801C >little?              00000000
0x493 0020 FF808020 >swizzle?             00000000
0x494 0024 FF808024 >real?                00000000
0x495 0028 FF808028 >rom-base             FFF2003C
0x496 002C FF80802C >real_base            00400000
0x497 0030 FF808030 >virt_base            FF800000
0x498 0034 FF808034 >real-vt-hd           004DFC00
0x499 0038 FF808038 >restart              FFF201DC
0x49A 003C FF80803C >fcimage              FFF27954
0x49B 0040 FF808040 >fcfiles              FFF48C84
0x49C 0044 FF808044 >lasttoken            00000EB5
0x49D 0048 FF808048 >word-list            FF85D4E8
0x49E 004C FF80804C >'ferror              FF80D0B0 ferror
0x49F 0050 FF808050 >'(poplocals)         FF80A350 (poplocals)
0x4A0 0054 FF808054 >'cold-load           FF80F738 cold-load
0x4A1 0058 FF808058 >'cold-init           FF818350 _cold-init
0x4A2 005C FF80805C >'quit                FF8179A8 quit
0x4A3 0060 FF808060 >'abort               FF811FA0 abort
0x4A4 0064 FF808064 >'syscatch            FF819638 _syscatch
0x4A5 0068 FF808068 >'excp                FF819338 _exception
0x4A6 006C FF80806C >'bp-done             00000000
0x4A7 0070 FF808070 >'step-done           00000000
0x4A8 0074 FF808074 >'mini-nub            00000000
0x4A9 0078 FF808078 >hwinitlr             FFF04D50
0x4AA 007C FF80807C >hwinitiv             00000000
0x4AB 0080 FF808080 >hwinit3              00009000
0x4AC 0084 FF808084 >hwinit4              00009120
0x4AD 0088 FF808088 >hwinit8              FFF03058
0x4AE 008C FF80808C >hwinit9              F3060000
0x4AF 0090 FF808090 >sccac                F3013020
0x4B0 0094 FF808094 >sccad                F3013030
0x4B1 0098 FF808098 >ramsize              30000000
0x4B2 009C FF80809C >cpuclock             0DF092B0
0x4B3 00A0 FF8080A0 >busclock             03FB97A0
0x4B4 00A4 FF8080A4 >tbclock              00FEE5E8
0x4B5 00A8 FF8080A8 >here                 FF85D524
0x4B6 00AC FF8080AC >free-top             FF8E0000
0x4B7 00B0 FF8080B0 >free-bot             FF8D0000
0x4B8 00B4 FF8080B4 >#dsi-ints            00000000
0x4B9 00B8 FF8080B8 >#isi-ints            00000000
0x4BA 00BC FF8080BC >dl-buf               FF8F0800
0x4BB 00C0 FF8080C0 >ttp800               FF8D6000
0x4BC 00C4 FF8080C4 >'cientry             FF809E18 cientry
0x4BD 00C8 FF8080C8 >'cicall              FF829498 cicall
0x4BE 00CC FF8080CC >'my-self             FF80D8D0
0x4BF 00D0 FF8080D0 >'<sc-int>            00409D10
0x4C0 00D4 FF8080D4 >ofregsv              FF8DFA00 ^-720600
0x4C1 00D8 FF8080D8 >ciregsv              FF8DF800
0x4C2 00DC FF8080DC >ofregsr              004DFA00
0x4C3 00E0 FF8080E0 >ciregsr              004DF800
0x4C4 00E4 FF8080E4 >intvectv             FF8DF600
0x4C5 00E8 FF8080E8 >intvectr             004DF600
0x4C6 00EC FF8080EC >regsvalid?           FF808000
0x4C7 00F0 FF8080F0 >ciwords              FF82A3D0
0x4C8 00F4 FF8080F4 >htab                 004E0000
0x4C9 00F8 FF8080F8 >keepbat2?            00000000
0x4CA 00FC FF8080FC >keepbat3?            00000000
0x4CB 0100 FF808100 >rp                   FF800800
0x4CC 0104 FF808104 >dp                   FF800400
0x4CD 0108 FF808108 >fp                   FF801000
0x4CE 010C FF80810C >lp                   FF800C00
0x4CF 0110 FF808110 >ep                   FF801800
0x4D0 0114 FF808114 >ttp                  FF804000
0x4D1 0118 FF808118 >tib                  FF801C00
0x4D2 011C FF80811C >noname               FF802000
0x4D3 0120 FF808120 >dec-ints             00000000
0x4D4 0124 FF808124 >dec-msec             00004141
0x4D5 0128 FF808128 >r13-31               FFF03078

The above is produced by this:

: dump_fields { addr fcodestart fcodeend ; token }
    cr fcodeend 1+ fcodestart do
        i ." 0x" 3 u.r space
        i get-token drop -> token
        0 token execute 4 u.r space
        addr token execute dup 8 u.r space
        token name.
        #out @ d# 42 < if d# 42 #out @ - spaces then
        @ dup 8 u.r space
        \ check if the field might point to a xt token and if so, output its name
        dup @startvec u> if
            dup dup xt>hdr 4+ dup c@ + 8 + -8 and = if name. else drop then
        else drop then
        cr
    loop
;

: dumpstartvec
    @startvec 488 4d5 dump_fields ;

dumpstartvec

Open Firmware internals

Apple's Open Firmware contains a small kernel implemented in the native PowerPC code. This kernel performs the following actions:

  • set up memory translation for OF execution
  • relocate itself from ROM to RAM
  • initialize Forth runtime environment
  • recompile OF main image from FCode to native PPC code
  • pass control to recompiled OF that starts building the device tree
  • process low-level exceptions

Open Firmware and the Macintosh boot process

Old World Macs

  1. In response to power coming on, HWInit code in the Power Macintosh ROM performs initialization of the memory controller and the basic I/O facilities as well as some self-testing. After that, the startup chime is played.
  2. HWInit passes control to Open Firmware kernel that prepares OF execution from RAM. OF builds the device tree - a platform-independent description of the attached HW.
  3. OF returns control to HWInit that initializes several low-level data structures required by the Nanokernel.
  4. HWInit passes control to the Nanokernel that initializes the native execution enviroment and the 68k emulator.
  5. 68k emulator executes the start-up code in the Macintosh ROM that initializes various managers.
  6. The device tree generated by the Open Firmware in step 2 is imported by the Expansion Bus Manager initialization code and stored in the NameRegistry.
  7. An operating system is located and loaded.

New World Macs

TBD

Open Firmware bugs

Apple OF is known to contain numerous bugs. The following table lists some recently discrovered bugs, not mentioned elsewhere.

OF version affected Bug description
2.0f1, 2.4 A numerical overflow in um/mod used by get-usecs-60x causes the OF console to become unresponsive after approx. 71 minutes. You have to restart your computer once the bug is triggered.
1.0.5 /chaos/control fill-rectangle is ( ? color y x w h -- ) instead of ( color x y w h -- )
2.4 string literal buffers " on the command line are 256 bytes but will overflow if you enter more than 256 bytes.

get-inherited-property notes.txt discusses known bugs regarding get-inherited-property and map-in in Open Firmware 1.0.5.