Declaration ROM hacks


Declaration ROMs are the "firmware" on Nubus and some PDS cards for 68k and some PPC macs. These ROMs describe the card and can, among other things, provide a driver that is automatically loaded. I've hacked up a set of small programs to generate valid Declaration ROMs here These are small POSIXy tools which should work on most modern unix like systems, but I've been using them under Linux.

Using the tools, I have created a valid Declaration ROM I've burned to a 27C256 EPROM and used that to replace the stock EPROM on an Asante ethernet card. The system recognized my DeclROM, and loaded my test driver:

The driver I loaded was the ROMDisk driver mentioned here.

Driver Loading:
Drivers loaded from the DeclROM are loaded after the system boots but before INITs are loaded from the Extensions folder. This means just providing the driver in the DeclROM doesn't make the card bootable. In order to make the card bootable, you need to provide an sRsrcBootRec record in the DeclROM, which contains code that gets executed by the Macintosh ROM early in the startup process.
The only "gotcha" I encountered in this experiment was in driver matching. In a given sResource within the DeclROM can be an sRsrcDrvrDir, which contains a directory of drivers with one entry per CPU type. Designing Cards and Drivers for the Macintosh Family says the CPU types are downward compatible, so a 68030 CPU can use a 68020 or 68000 driver. Unfortunately in my IIx, it would only load a 68020 driver. Drivers marked as 68030 and 68000 would not get loaded by the IIx, but change that CPU type to 68020 and it worked fine.

DeclROM Interchangeability:
You can't necessarily swap declaration roms between different types of cards and have it work. Nubus and PDS has the concept of "Byte Lanes", meaning a card can use only a given set of bytes within the 32 bit wide data path. The last byte of the DeclROM defines what byte lanes the card (or at least the DeclROM) uses. DeclROMs are frequently stored in EPROMs that only have a 1 byte data path, but which byte in the 4 byte lanes on the 32bit bus, can be different between card designs. It really doesn't matter which byte lane is used, but the DeclROM needs to match what the card uses. Just updating the last byte to match the card isn't sufficient, since the DeclROM checksum includes the bytelane byte.
So, providing my DeclROM won't necessarily work, depending on the type of card you try to put it on.

Booting:
The sRsrcBootRec record in the DeclROM is an sExecBlock (aka code) that gets executed once or twice during the boot process. IFF the PRAM says to boot from your slot, and your slot has the matching sResource ID, and a valid sRsrcBootRec, the boot ROM will run your sRsrcBootRec code prior to booting. If not (even if no other bootable devices are found, the ROM will not attempt to boot from your DeclROM), the system will boot normally, and prior to INITs loading, your sRsrcBootRec will get invoked.
If your DeclROM has an sRsrcBootRec, it is responsible for loading your driver and opening it. The system will not load your driver for you in this case.

I've managed to get a custom DeclROM booting! Make sure when loading your driver from the sRsrcBootRec code, to use the extended Device Control Entry structure. The initial Device Control Entry as documented in Inside Macintosh Volume II was extended after the Slot Manager was introduced to include slot information. WHen loading your device driver, be sure the slot information fields of the extended structure are populated. The Startup Device control panel will look at these entries and populate PRAM with them, which is what causes your sRsrcBootRec to be executed at boot time. Alternatively, if you don't want to use the Startup control panel, a custom app using SetDefaultStartup() works as well.

System ROM:
The system ROM, starting with the Mac II, has a DeclROM at the end of it. Unfortunately, the II, IIx, and SE/30 ROMS (at least, possibly IIfx) is not terribly useful. At least with the IIsi, and probably the IIci, can load drivers and be used almost the same way a peripheral DeclROM is used. Unfortunately, due to the way booting is handled, you can't actually boot from a driver located in the system DeclROM. When booting from a DeclROM, the Slot you want to boot from (and resource, and hwid, etc.) are stored in PRAM. Unfortunately, a 0 in the slot field appears special, and won't be booted from.

Video Parameters:
Video DeclROMs have some extra information. First, in their board resource, they've got a directory of mode names. The entries in the directory are the IDs of the resources the mode name corresponds to, and the offset in the directory is the offset to an sBlock containing the name string.
Then each reasource starting at 128 can contain video modes and parameters for those modes. Here's the example output of catdecl tool in the declrom tools below:

Resource 218
        sRsrcType: 3 1 1 1005
        sRsrcName: Radius PrecisionColor 24Xk
        RsrcDrvrDir:
                id: 2, len: 14390
        sRsrcFlags: 0x6
        sRsrcHWDevId: 1
        MinorBaseOS: 0x0
        MinorLength: 0x3fd800
        Video Mode 128:
                Mode Name: Other / Multi-Frequency
                Dev Type: 0
                Page Count: 1
                Video Parameters:
                        vpBaseOffset: 0
                        vpRowBytes: 104
                        vpVersion: 0
                        vpHRes: 0x480000
                        vpVRes: 0x480000
                        vpPixelType: 0
                        vpPixelSize: 1
                        vpCmpCount: 1
                        vpCmpSize: 1
                        vpPlaneBytes: 0
        Video Mode 129:
                Mode Name: Other / Multi-Frequency
                Dev Type: 0
                Page Count: 1
                Video Parameters:
                        vpBaseOffset: 0
                        vpRowBytes: 416
                        vpVersion: 0
                        vpHRes: 0x480000
                        vpVRes: 0x480000
                        vpPixelType: 0
                        vpPixelSize: 4
                        vpCmpCount: 1
                        vpCmpSize: 4
                        vpPlaneBytes: 0
        Video Mode 130:
                Mode Name: Other / Multi-Frequency
                Dev Type: 0
                Page Count: 1
                Video Parameters:
                        vpBaseOffset: 0
                        vpRowBytes: 832
                        vpVersion: 0
                        vpHRes: 0x480000
                        vpVRes: 0x480000
                        vpPixelType: 0
                        vpPixelSize: 8
                        vpCmpCount: 1
                        vpCmpSize: 8
                        vpPlaneBytes: 0
        Video Mode 131:
                Mode Name: Other / Multi-Frequency
                Dev Type: 2
                Page Count: 1
                Video Parameters:
                        vpBaseOffset: 0
                        vpRowBytes: 1664
                        vpVersion: 0
                        vpHRes: 0x480000
                        vpVRes: 0x480000
                        vpPixelType: 16
                        vpPixelSize: 16
                        vpCmpCount: 3
                        vpCmpSize: 5
                        vpPlaneBytes: 0
        Video Mode 132:
                Mode Name: Other / Multi-Frequency
                Dev Type: 2
                Page Count: 1
                Video Parameters:
                        vpBaseOffset: 0
                        vpRowBytes: 3328
                        vpVersion: 0
                        vpHRes: 0x480000
                        vpVRes: 0x480000
                        vpPixelType: 16
                        vpPixelSize: 32
                        vpCmpCount: 3
                        vpCmpSize: 8
                        vpPlaneBytes: 0

Other information:
I've started posting some information on the mac68k forums. Specifically, there's some interesting posts in this thread.

Software:
I've written some software to help create and debug DeclROMs, and here it is:
More DeclROM Tools!: This includes a "libdecl", a library for manipulating DeclROMs. I've used this for adding drivers to existing DeclROMs, and completely writing my own from scratch fairly easily.
DeclROM Tools: Tools to create DeclROMs on Linux. Check out the README.
dumpdrvr: Lists loaded drivers and their slot number in the UnitTable.
myslottest: Uses the Slot Manager APIs to list all DeclROMs, their resources, and any drivers they might have.
sRsrcBootRec: A pretty generic DeclROM sRsrcBootRec function useful for loading and opening device drivers, ei ther at boot or INIT 31 time.
ROMDisk Driver: This is the actual binary driver I used for the ROMDisk driver. It expects the ROMDisk to exist 512KB into the System ROM, and expects it to be 512KB long. This binary is suitable input to drvrrsrc from the DeclROM Tools above.
Boot code: This is the boot code I used. It should be pretty generic, but only tested with the above DeclROM. This is suitable input to execblock from the DeclROM Tools above.
TestROM: This is the actual DeclROM I used above. Keep in mind the interchangeability issues I noted above, it might not work in all (or even most?) Nubus cards.

Updated October 21 2012