GitHub - gm-stack/classic-mac-rom-ghidra-tools: Disassembling and annotating the Q800 ROM (and others) in Ghidra (Quadra/Centris 610,650,800 checksum F1ACDA13)
Disassembling and annotating the Q800 ROM (and others) in Ghidra (Quadra/Centris 610,650,800 checksum F1ACDA13) - gm-stack/classic-mac-rom-ghidra-tools
github.com
I've posted some scripts to load into Ghidra to play with ROM images.
There's full info in the README.md in the Git repository, but in short:
AnnotateRomTables.py:
Initially based on rb6502's unirom, this one creates a bunch of structs to let you browse the Universal machine support tables in the ROM, and when disassembling the code, allows the decompiler view to show actual struct names and decode bitfields for some of this data (more to come).
So far only tested on the Quadra 800 ROM (F1ACDA13) - but might be made to work on others.
FixupBSR6.py:
A lot of the subroutines in the early boot use a calling convention where the subroutine is JMP'd to, with a return address in A6. Ghidra does not understand this, and especially does not understand that the JMP (A6) in the end of the subroutine is not an entire-address-space sized jump table. This finds JMP instructions that follow a LEA into A6 with a relative offset to PC and applies a flow override to tag them as a CALL. JMP(A6) instructions are then tagged as RETURN, and the decompiler is now a lot happier.
FindRomWrites.py:
I've got a copy of the ROM mapped as an "overlay" in Ghidra's address space to 0x00000000 as that's where it is at very early boot before the overlay is switched off. This reassociates all cross-references to memory read/write in this area with the bank of RAM defined there, though some of them are genuine and will need to be fixed up.
After it jumps to the "main" copy of the ROM at base address 0x40800000, all the ROM accesses are up there, so no problems.
ImportLomemGlobals.py
Imports a (modified) copy of the Low Memory Globals list from the Mac Almanac, so all those memory accesses to short immediate have the correct names.
ImportSymbolsShifted.py
Modified copy of the one that comes with Ghidra, that allows specifying a base address, and memory segment. Used with https://github.com/cy384/68k-mac-rom-maps to import them offset to the base address of the ROM.
RemoveUndefinedTypes.py
Removes any data blocks with undefined1 / undefined2 / undefined4 type but no actual reference to anywhere else, as these stop decompilation when hit.
... and the Ghidra project?
It's a pretty big mess at the moment, but when I have a cleaner version I'll post it. A few screenshots attached showing the decompiler almost giving a decent result. (though to be fair GetHardwareInfo is a massive mess that jumps all around the ROM with pretty crazy program flow)
(one final note re the decompiler - no, there's no chance you'll ever be able to actually compile that C code and get a working ROM. It's basically C syntax pseudocode for what the assembly is doing - much easier to read!)