How OPENSTEP 4.2 boots in m68k hardware.
A NEXTSTEP/OPENSTEP CD cannot be made to boot in both sparc and m68k hardware. With NEXTSTEP 3.3, there was one installation CD for m68k/i386 and another installation CD for sparc/hppa. For sparc, the hardware expects the bootloader to start at offset 0x00000200 (512) of the CD. For m68k, the hardware expects a disklabel at the very start of the CD, and the disklabel contains a pointer to the bootloader somewhere else in the CD. A disklabel is 7240 bytes in size and cannot fit into the available first 512 bytes of a sparc-bootable CD.
With OPENSTEP 4.2, there was a single "User" installation CD for m68k/i386/sparc (I think they dropped support for the hppa platform at that time). Given those three platforms, NeXT probably opted to make the CD bootable on sparc hardware. The sparc magic number 01 03 01 07 is present at offset 0x00000200 of the CD. Note that to boot from a CD, sparc workstations need SCSI CDROM drives that provide 512-byte sectors, instead of the more common 2048-byte sectors. Older drives from Plextor, Yamaha, and Pioneer typically have a jumper that sets the sector size. Trying to boot the CD from m68k hardware gives the following error:
Bad version 0x80000000 Bad cksum Bad version 0x0 Bad cksum Bad label
An m68k/i386 installation diskette and an i386 driver diskette were provided in 3.5" 1.44MB format. The installation diskette is used to bootstrap the installation into m68k hardware. I could not find an m68k bootloader anywhere in the installation diskette, which leads me to think that the boot process probably traps into the m68k ROM, which then loads a copy of the disklabel from either offset 0x00002000 or offset 0x00003C00 of the CD. From the disklabel, the m68k bootloader can be located in the CD and the boot process continues, loading the m68k kernel "sdmach".
How OPENSTEP 4.2 boots in i386 hardware.
An i386 ROM loads the i386 initial "B1" bootloader from the first 512 bytes of the diskette. The initial bootloader loads the standard i386 bootloader from offset 0x00008000 of the diskette. In the boot process, the i386 kernel "mach_kernel" is loaded, "sarld" is loaded, the user is prompted to insert the driver diskette, drivers are loaded (the driver for the IDE or SCSI CD drive needs to be loaded so the CD can be read), and installation copies files from the CD into the hard disk.
Creating an m68k-bootable "User" OPENSTEP CD.
Since m68k hardware looks for a disklabel at the start of the CD, we need only to copy the duplicate disklabel located at offset 0x00002000 or offset 0x00003C00 of the CD. From a raw "ISO" image of the OPENSTEP 4.2 CD, the disklabel can be extracted with:
dd bs=1 count=7680 if=OPENSTEP42CD.iso of=OPENSTEP42CD.lbl skip=8192
Overlay the extracted disklabel into the first part of the CD image:
dd bs=1 count=7680 if=OPENSTEP42CD.lbl of=OPENSTEP42CD.iso
Several bytes in the disklabel need to be changed. The structure of the disklabel is available at bootblock.h. The first set that needs to be changed is the block number in the disklabel. If the disklabel originally came from offset 0x00002000, then its block number is 4 (where a block is 2048 bytes). The new disklabel at the start of the disk should be at block number 0.
The second set of bytes that need to be changed is the pointer to the boot blocks (bootloader). There are two pointers in the disklabel. The first points to an hppa bootloader (block 0x10), and the second points to an m68k bootloader (block 0x30). The hppa bootloader surprised me because I thought hppa platform support has been dropped in OPENSTEP. Also note that the sparc bootloader that started at offset 0x00000200 has been partially overlaid by the new disklabel, so the new CD image will not be sparc-bootable. We change the boot block pointers in the disklabel to point only to the m68k boot blocks — first pointer is set to 0x30, second pointer is set to 0xFFFFFFFF.
The third set of bytes that need to be changed is the default kernel loaded by the bootloader. From the original disklabel, the kernel name is "mach_kernel". Although "mach_kernel" is present on the CD, it is a tri-fat binary. The m68k bootloader cannot load the tri-fat binary, and instead needs to load the Mach-O binary "sdmach". Although you can manually specify the kernel name on the ROM boot prompt, the disklabel is altered to use "sdmach" instead of "mach_kernel" as the default.
The last set of bytes that need to be changed is a checksum on the disklabel. NS_CKSUM.C is a very short program that illustrates the checksum calculation. It reads the bytes in the disklabel preceding the checksum itself, and outputs a 16-bit hexadecimal value to use as the new checksum. With the updated OPENSTEP 4.2 CD disklabel, the checksum calculated is 0xCE22.
Creating an i386-bootable "User" OPENSTEP CD.
The i386 bootloader is located on the install diskette boot blocks. This is a copy of the /usr/standalone/i386/boot binary located on the CD. Additionally, the first 512 bytes of the diskette contains a copy of the /usr/standalone/i386/boot1f binary. Unlike m68k hardware, i386 hardware does not bootstrap from the first few blocks of the CD. Instead, i386 hardware makes use of the El Torito specification for bootstrapping from a CD. The El Torito specification was developed by Phoenix and IBM. With an El Torito CD, a bootstrap image is loaded by the BIOS. The bootstrap image can be treated as a diskette in drive "A:".
One limitation in El Torito is that you can only bootstrap a single image. Although it allows you to select from multiple bootstrap images on the CD, you only bootstrap one of the images ("B:" cannot be mapped to another image in the CD). You also cannot "swap" images during the El Torito boot process, as required by the OPENSTEP i386 installation process where it asks that you eject the install diskette and insert the driver diskette.
With "mach_kernel" and "sarld", no additional drivers can fit in a 1.44MB install diskette. The good thing in El Torito is that the bootstrap image can be the image of a 2.88MB diskette. If we can combine the OPENSTEP install diskette and driver diskette into a single 2.88MB diskette, it can be used to boot from the CD.
There are several ways to create the 2.88MB diskette. One way is to use an actual 2.88MB SCSI diskette drive and initialize a 2.88MB diskette appropriately, then copy the contents of both OPENSTEP diskettes into the new diskette. Since I was currently working on a Windows box, I opted to use a virtual machine running OPENSTEP to set up the diskette image.
First, create a 2.88MB file (2,949,120 bytes). You can use any available utility to create a file of that exact size. The contents do not matter, since it will be re-initialized from within OPENSTEP. I tried to mount the 2.88MB file as a virtual floppy drive in VirtualBox. However, when treated as a floppy drive, the OPENSTEP i386 floppy driver refuses to initialize it as 2.88MB, citing that 1.44MB is the limit. VirtualBox does not provide a BIOS configuration screen where you can change "A:" into a 2.88MB drive. Virtual PC 2007 has the BIOS configuration screen, but as reported by others, OPENSTEP installation causes a processor exception in Virtual PC 2007.
The 2.88MB file is mounted as a virtual IDE disk in VirtualBox. The VMware-format F288.vmdk file is used to describe the virtual disk F288.img as having 160 cylinders, 2 heads, and 18 sectors/track. IDE sectors are 512 bytes in length, giving a total of 160*2*18*512 = 2.88MB.
Once assigned in VirtualBox running OPENSTEP, the 2.88MB disk is initialized as:
/usr/etc/disk -i -b -B1 /usr/standalone/i386/boot1f /dev/rhd1a
The new disk is mounted:
mkdir /F288 mount /dev/hd1a /F288
And files copied from the install diskette and driver diskettes:
cp -r /4.2mach_Install/* /F288 cp -r /4.2mach_Drivers/* /F288
Not all the drivers will fit, so some of them should not be copied. I opted to not copy most of the SCSI drivers, since I will be installing from an IDE/ATAPI CD drive. The /F288/private/Drivers/i386/System.config/Instance0.table is edited so "Prompt For Driver Disk" is "No". We now have a 2.88MB "F288.img" file that can be used as the El Torito bootstrap image.
How do we combine the OPENSTEP 4.2 CD, and the 2.88MB bootstrap image into a single El Torito ISO9660 CD? The OPENSTEP 4.2 CD is not in ISO9660 format. It is in a variant of the 4.3BSD UFS format. What’s great in this format is that the UFS filesystem is in a "relative" location in the CD. In bootblock.h, the disklabel specifies the size (in blocks) of the "front porch" that precedes the actual UFS filesystem. The "front porch" contains disk housekeeping information and precedes the UFS filesystem. The raw UFS filesystem can be extracted from the CD image with:
dd bs=2048 if=OPENSTEP42CD.iso of=OPENSTEP42CD.ufs skip=80
Having "F288.img" and "OPENSTEP42CD.ufs", we fire up our disk-burning application to create an El Toriro CD image. The ISO9660 filesystem contains only the single OPENSTEP42CD.ufs file. With the CD image created, we can find that the UFS filesystem got stored starting at offset 0x00360000.
We need to put the same block 0 disklabel into the CD image, but several bytes need to be changed. The first set of bytes that need to be changed is the size of the "front porch". Since the UFS filesystem has been moved to offset 0x00360000, the "front porch" value should be 0x06C0 (1728 blocks). The other set of bytes that need to be changed is the checksum on the disklabel. With this updated disklabel, the checksum calculated is 0xD492.
The disklabel is again overlayed into the start of the CD image:
dd bs=1 count=7680 if=OPENSTEP42CD.Block00.ElTorito.lbl of=Disc.iso
Creating an m68k-bootable and i386-bootable OPENSTEP CD.
Extending the concepts further, we can create a CD that is bootable in both m68k and i386 hardware. The ISO9660 volume descriptors start at offset 0x00008000 (block 16). 32KB is not enough to fit a disk label and an m68k bootloader. The /usr/standalone/boot.cdrom file is 49812 bytes in size.
For this El Torito CD image, the ISO9660 file system contains the two files boot.cdrom and OPENSTEP42CD.ufs, along with the 2.88MB bootstrap image. A few changes are in order for the disklabel. The UFS file system now starts at offset 0x0036C800 of the CD, so the "front porch" value should be 0x06D9 (1753 blocks). The boot.cdrom image starts at offset 0x0036C000 of the CD. The first boot block pointer should be 0x06C0, and the second boot block pointer is left as 0xFFFFFFFF. The new checksum of the disklabel is 0xDB3B.
The disklabel is again overlayed into the start of the CD image:
dd bs=1 count=7680 if=OPENSTEP42CD.Block00.ElTorito.m68k.lbl of=Disc.iso
With those changes to Disc.iso, the image can be burned to a CD which is bootable in both m68k platforms (as long as you have the latest ROM that allows booting from the CD) and i386 platforms.