-
Notifications
You must be signed in to change notification settings - Fork 295
ROM Analysis in Basilisk II Emulation
- Table of Contents
- Assumptions
- Disassemble original 68k Mac ROM
- Mac ROM in real Macintosh hardware
- Mac ROM in Basilisk II emulation
- Bibliography
The analysis below is based on the study of the Performa old world 32bit clean ROM (with MD5 hash af343f3f1362bf29cefd630687efaa25
). I found that this Performa 630 ROM works great for System 7 and Mac OS 8.1.
Assuming you get a Mac ROM binary file for BII from somewhere, the next step is to poke around it. A ROM file is a collection of data and M68K machine code which performs hardware test at boot time, provides low level common routines such A-Trap and etc.
For emulation purposes, BII patches the original ROM so that it can handle hardware interrupts, A-Trap and etc with emulated devices. I will demonstrate disassembling this Mac ROM with cxmon and radare2.
$ cd macemu/cxmon
$ ./bootstrap
$ ./configure
$ make
$ sudo make install
The command below disassemble ROM file and dump the text into an external file.
cxmon -m ‘[ 0 “PERFORMA.ROM”’ ‘d68 0 fffff’ > PERFORMA.ROM.DISAM
You can also run cxmon in standalone interactive mode or even enable --with-mon
option in BII build to debug at runtime. Please refer to cxmon help
NOTE:
After reading the disassemble code, cxmon didn't disassemble correctly in some cases. This is due to the fact that ROM mixed with data and code. For example, read ROM starting from 0x2a offset. The machine code 0x46fc2700 should be at address $0000008c. The correct assembly should be move #?2700, sr
, instead of ori.b #$fc,d0
and move.l d0,-(a3)
.
11 000000000000002a: 4efa 0060 jmp ($0000008c,pc)
...
37 000000000000008a: 0000 46fc ori.b #$fc,d0
38 000000000000008e: 2700 move.l d0,-(a3)
39 0000000000000090: 4dfa 000a lea ($0000009c,pc),a6
Build radare2 from git repo. You also need to build acr.
The documentation of radare2 is long. TLDR; Here is an example of using it:
[Ricky@xps ROM.Disas]$ radare2 PERFORMA.ROM
-- Switch between print modes using the 'p' and 'P' keys in visual mode
[0x00000000]> e asm.arch=m68k
[0x00000000]> pd 10 arch=m68k
0x00000000 066842140000 addi.w 0x4214, 0x0(a0)
0x00000006 002a067c4efa ori.b 0x7c, 0x4efa(a2)
| 0x0000000c 00804efa007c ori.l 0x4efa007c, d0
| 0x00000012 32f10100 move.w (a1, d0.w), (a1)+
| 0x00000016 00000044 ori.b 0x44, d0
| 0x0000001a 0007ec10 ori.b 0x10, d7
| 0x0000001e 4efa1220 jmp 0x1220(pc)
| 0x00000022 000d2da0 invalid
| 0x00000026 4efa22e8 jmp 0x22e8(pc)
| 0x0000002a 4efa0060 jmp 0x60(pc)
NOTE: radare2 has the same issue as cxmon. This is the dead end.
In Apple Mac IIci and Mac Quadra 900 Developer Note, it specified ROM in a fixed address space. In fact, ROM machine code is written as position independent code. In reality, its location in memory is relocatable. That’s why BII can load ROM to whatever memory address in guest OS without breaking its logic.
So far I haven’t found an automatic way to disassemble Performa ROM without human tagging code segment. I can’t easily get a full picture of what Performa ROM contains. But reading BII ROM patches, Macintosh ToolBox trap and Macintosh OS trap, I think I need to have basic understanding of using illegal instruction exception technique to extend Macintosh OS.
M68k CPU suspend execution instruction flow if it encounter an illegal instruction. An illegal instruction is an instruction that contains any bit pattern in its first word that does
not correspond to the bit pattern of the first word of a valid M68k instruction or is a
MOVEC
instruction with an undefined register specification field in the first extension word.
When illegal instruction exception happens, there are four steps in processing exception [1]:
- The processor makes an internal copy of the status register. Then the processor sets the S bit, changing to the supervisor privilege level. Next, the processor inhibits tracing of the exception handler by clearing the T1 and T0 bits.
- The processor determines the vector number of the exception. In this case, it is
4
. - The processor save the current processor context and creates an exception stack frame on the active supervisor stack and fills it with context information appropriate for the type of exception.
- The processor multiple the vector number of the exception by 4 to get the offset of vector table. Add the offset with Vector Base Register
VBR
to get the address of exception handler routine. Then, load Program CounterPC
with the look-up address and resume execution.
Macintosh OS reserves the first word 1010
(0xA) unimplemented instruction to implement so called A-Trap to provide ToolBox and OS API.
Basilisk II also uses illegal instruction exception MOVEC
to patch Mac ROM and implement its emulated drivers. We will discuss this in next section.
TODO add more
After BII loads the ROM from file into memory, it patches the ROM in PatchRom()
function from the file src/rom_patches.cpp
.
TODO add more
Emulation starts at relative address 0x2a
i.e (MacROMBaseMac + 0x2a) in the patched ROM. TODO add more