Do you have any additional info on extracting these FCode images from a Mac's BootROM? I'd like to extract the FCode ROMs for some onboard video cards of some machines, as well as see if it's possible to modify the necessary (SPD?) data in, say, an iMac G3 slot-loading BootROM, to get it to detect larger L2 cache chips being installed. This is normally done by way of modifying a small I2C EEPROM on machines with removable CPU cards, but in the iMac G3 slot-loader, the CPU/L2 cache chips are on the main board, and the L2 cache ratio and capacity data is hard-coded in the BootROM.
Is your iMac G3 slot-loader rom listed in the "List of Open Firmware versions" spoiler of
#1 ? If not, then I wouldn't mind getting a dump to look at.
Is the L2 cache ratio and capacity data in the Open Firmware part of the rom or in the HWInit part (which happens before Open Firmware)? I see there's a
l2-cache-props
word that sets up some properties depending on the CPU and whatever is in the L2CR register. This is used by
make-cpu-properties
.
For Old World ROMs, the fcode images are not compressed and exist in ROM where
byte_load_file
can load them. My detok command handles all the fcode images in that case.
I've posted my commands at
https://www.dropbox.com/s/t1zkywm7cc1dc45/JoesOpenBIOSStuff.zip?dl=0
detok is used by DumpPCIRom.sh which can dump an individual fcode image or a PCI rom that includes an fcode image. It is also used by DumpMacRom.sh which works with the Open Firmware part of a Mac ROM and dumps assembly part of Open Firmware and the fcode images (the result of detok is converted to Forth using a perl script).
For New World ROMs, you have to get the ROM, extract the fcode images individually, decompress them, then concatenate the parts together for my DumpMacRom.sh command to disassemble, detokenize, and convert to Forth. Instructions for getting the New World ROM are in the first post in the "nvramrc Patches for PowerPC Macs to support GPUs up to 512MB" spoiler which directs you to
#137
I've posted the New World ROMs at
https://www.dropbox.com/s/8v2nhupgcx7t4uw/NewWorldROMs.zip?dl=0
In my detok command, the decode.cpp source file contains functions decode_rom_token2, decode_rom_token203, and decode_rom_token3 which detect the start of a new fcode image in an Old World ROM or a decompressed and concatenated New World ROM. These functions mostly ignore the structures that
byte_load_file
uses because
byte_load_file
looks at fcode images starting from the last image, while detok looks at fcode images in order). The functions just look for bytes that may indicate the start of another fcode image or they skip bytes that are probably not the start of another fcode image.
I've posted Open Firmware dumps at
https://www.dropbox.com/s/ya5gfv67eqvrwil/ROMDumps.zip?dl=0
A dump consists of Part1.txt which is the compiled part of Open Firmware, and Part2.of which is the fcode images of Open Firmware converted to Forth. Each fcode image starts with
\ detokenizing start at offset ........
and ends with
\ detokenizing finished after ...... of ...... bytes.
. These comments exist in both Part1.txt and Part2.of. You can see the bytes that precede each fcode image in Part1.txt. Part1.txt does't include the fcode and Part2.of doesn't include the bytes that surround the fcode.
Thinking about this a bit more, it seems to me you could look at how
byte_load_file
works. For Old World Macs, check the dump for "ROM PM G3". This contains Open Firmware 2.4 which is useful because it includes all the names for the words. For New World Macs, "ROM Quad G5" is the latest (that I have) and also has all the names. The
byte_load_file
code starts with the last fcode image in the rom (pointed to by the
>fcfiles
field of the
@startvec
structure). It compares the vendor/product ID (
>of.dev-ven
) and/or class code/fcode image# (
>of.class
) of an fcode image structure. if it matches, then it executes the fcode image, otherwise it goes to the next fcode image (
>of.offset
is a negative offset). You can create a word to list these images by looping through them like
byte_load_file
does. You can dump the bytes of the fcode images so that you can detokenize / convert to Forth using my DumpPCIRom.sh script. To determine the length of an fcode image, you could use the address of the fcode structure of the following fcode image (by address) as the end address, or you can parse the length from the start of the fcode image (but only if the start has
fcode-version2
or similar).
The
>fcfiles
chain does not include the main fcode image. It exists separately before the first fcode-image by address of the
>fcfiles
chain (or last fcode-image by link) and after the assembly part of Open Firmware (after
cold-load
in Part1.txt). The main fcode image is pointed to by the
>fcimage
field of the
@startvec
structure. The attached file "OF 2.4 list of fcode images.txt" is the end of Part1.txt showing the parsed values for the fcode-image chain. The dumps of the main fcode image and the fcode images of the chain are in Part2.of.
Open Firmware startup:
cold-load
is executed, which loads the main fcode image pointed to by
>fcimage
, which builds the device tree (including cpus) and compiles all the words. Then
cold-load
calls
cold-init
which does the nvramrc and probe-all then one of reset-nvram, diagnostic-boot, target-mode, Open Firmware UI, multi-boot, boot-command, or boot.
Some versions of Open Firmware have
.time-stamps
and
.time-stamps\
words that will output a log of what happened during Open Firmware startup. I've never tried them before. Some versions of Open Firmware have the time-stamps info but don't have the words to dump the info. I suppose you could copy those words from another version of Open Firmware.
To find the fcode image for built-in GPU:
You would perform the same analysis for the ROM you are working with as I did in "OF 2.4 list of fcode images.txt". Find at the end of Part1.txt an fcode image structure that matches the graphics controller. ATI GPUs have a vendor of 1002 and maybe a class code of 03:00:00 like in this example:
Code:
0269CC: FFFF D8C0 ; >of.next
0269D0: 4750 1002 ; >of.dev-ven 00:12.0 VGA compatible controller [0300]: Advanced Micro Devices, Inc. [AMD/ATI] 3D Rage Pro PCI [1002:4750] (rev 5c) (prog-if 00 [VGA controller])
0269D4: 0003 0000 ; >of.class VGA compatible controller : VGA controller
0000 0010 ; >of.offset
; >of.fcode
0269DC: \ detokenizing start at offset 0269DC
028C84: \ detokenizing finished after 8872 of 8872 bytes.
Included in the Open Firmware dumps is a BBEdit worksheet which contains the commands for creating the Open Firmware dumps. In "ROM iMac.worksheet", you start with the "Divide the ROM" section.
First it divides the entire New World ROM into 5 parts: the start part, two copies of nvram, a rom image part, and a recovery part which is mostly a copy of the rom image part.
@FFF00000 len-4000 Start.rom
@FFF04000 len-2000 Nvram1.rom
@FFF06000 len-2000 Nvram2.rom
@FFF08000 len-78000 Recovery.rom
@FFF80000 len-80000 Rom Image.rom
Next it decompresses the Recovery and Rom Image parts. The
decompressrom
function gets the start and length of each part from offset 0x20 and 0x24. It uses lzss to decompress the parts.
https://www.dropbox.com/s/v93d0o3k9wc5b32/joevt-lzss.zip?dl=0
The only reason to do both the Recovery and Rom Image parts is to compare them to see if any interesting differences exist.
The iMac only has one decompression step. Things get more complicated with later Open Firmware versions such as for the G4 FW 800. it has multiple compressed parts (one per fcode image). In this case, they are concatenated together so my detok can parse them like older Open Firmware versions. Even later Open Firmware versions such as for the G5 or iBook G4 give each compressed part a name. What I haven't done is compare my concatenated New World ROMs with what
byte_load_file
sees but at least my detok can parse the concatenated New World ROMs.
Back to the "ROM iMac.worksheet", once the ROM parts are decompressed and concatenated together (if there's more than one part), you can go up to the "Dump ROM" section to use the DumpMacRom.sh script to disassemble, detokenize, and convert to Forth the created decompressed rom. All the files are generated in the Dump directory. The two important files are Part1.txt and Part2.of. The other files are logs and statistics, not really errors.