I have a PowerMac G3 Blue and White, which I acquired because the previous owner didn't want it and I knew I could run OpenBSD on it. It runs quite nicely, if somewhat noisily, warmly and slowly. However, the BIOS battery is depleted, and so it loses its firmware settings and the clock resets every time it loses mains power. The clock settings can be fixed with NTP, but the loss of boot settings is inconvenient, as this requires having a keyboard (and preferably also a monitor) connected to it every time it (re)boots to manually enter boot instructions. I don't have room to have (another) standalone monitor on my desk for this machine (nor a keyboard), so I needed a workaround.
The PowerMac (as well as other "New World" PowerPC Apple machines) use Open Firmware, a standardised firmware interface which most hardware vendors who aren't Intel or ARM have used at one point or another. In my experience, Open Firmware is actually pretty nice to work with. It's quite similar to the U-Boot bootloader (which though technically a bootloader is commonly used as a firmware ROM image on single-board devices) in that you get a reasonably featureful command-line interface to configure the boot settings, and both have some scripting capability. They do have their differences, as U-Boot usually loads an operating system to execute directly, and so needs a fair amount of intelligence and configurability to support the broad range of devices and configurations it runs on (as there isn't much of a standard for this in the SBC world). Open Firmware, on the other hand, only needs to load a second-stage bootstrap program to load the operating system, and thus (typically) doesn't need to be quite as smart (or at least not as cunning). Open Firmware is also standardised which means that the interface and command semantics are consistent across implementations, which rather conveniently means that the firmware interface on the PowerMac is the same as the UltraSPARC system I have on a shelf somewhere.
It's also worth noting that Open Firmware came into being in the mid nineties, predating (U)EFI (or at least the widespread use thereof) by a few years. If it weren't for the fact that all the architectures using Open Firmware died and/or lost their markets (and maybe Intel's monopoly of consumer silicon), the already-unified and extensible Open Firmware might have remained a common firmware interface [citation needed]. While an interesting historical and philosophical point, this doesn't help me get the PowerMac to boot reliably.
The PowerMac's firmware's default settings are as follows:
Scan for hard disks, and if one is found, attempt to load MacOS from it.
If that fails, check if there is a CD in the optical disk drive. If there is a CD present, attempt to boot from that.
If that fails, initialise the ethernet card and start sending DHCP/BOOTP requests.
The hard disk I have in the PowerMac has OpenBSD installed on it (and therefore no partitions with an HFS filesystem), so the first step fails, however in order to get OpenBSD onto the machine in the first place I used a bootable CD. The firmware will boot from this CD automatically if left unattended. This CD contains a second-stage bootloader, which in turn loads a ramdisk kernel containing the installation environment from the CD. So in order to investigate my options I loaded the installation disk I had used and got to a boot(8)
prompt. boot(8)
has a couple of knobs that can be turned, such as passing arguments to the kernel so it boots in single user mode, and variables which directly influence the behaviour of boot(8)
itself, one of which is the path of the root disk.
Open Firmware (from which the bootloader gets hardware information) represents attached devices as a filesystem-like tree (which can be viewed by issuing dev /
and then ls
at the Open Firmware prompt), however the device paths can be quite long, so devices such as storage media are usually referred to via a shorthand alias for brevity's sake -- the primary IDE hard disk on this machine is aliased to hd
and the CD drive is aliased to cd
. The complete list can be viewed using the devalias
command.
Thus, I found that the path to the primary IDE hard disk is /pci/@d/pci-ata@1/ata-4@0/disk@0
, and if I issued set device /pci/@d/pci-ata@1/ata-4@0/disk@0
at the boot(8)
prompt then the CD bootloader would load the kernel from the hard disk. boot(8)
will attempt to read configuration from the /etc/boot.conf
file before prompting, so I thought I could put the appropriate root disk configuration into a boot.conf(8)
file which would be loaded automatically. However as the CD bootloader is loaded from the CD, it won't search the hard disk for a boot.conf(8)
file there. So my next idea was to remaster the boot CD ISO image to include a suitable configuration file.
I downloaded a copy of the OpenBSD 6.3 macppc boot-only CD to use as a starting point. Mounting ISO images is pretty easy, however creating them is a little more involved, especially if they're intended to be bootable, so I went and looked up how OpenBSD builds bootable ISO images for macppc, and eventually found this Makefile. The appropriate incantation for creating the ISO image are these lines here:
mkhybrid -v -v -r -part -hfs \
-hfs-bless ${.OBJDIR}/cd-dir/${OSREV}/macppc \
-map ${.CURDIR}/../../../gnu/usr.sbin/mkhybrid/src/more.mapping \
-A "OpenBSD ${OSREV} macppc bootonly CD" \
-P "Copyright (c) `date +%Y` Theo de Raadt, The OpenBSD project" \
-p "Theo de Raadt <deraadt@openbsd.org>" \
-V "OpenBSD/macppc ${OSREV} boot-only CD" \
-o ${.OBJDIR}/cd${OSrev}.iso ${.OBJDIR}/cd-dir
There is a lot of byzantine magic in that command; while mkhybrid(8)
has a manual page, I'll provide a brief walkthrough of the options:
-v
turns on verbose ouput.
-r
turns on creation of Rock Ridge extended attributes, additionally setting fields such as user ID and file permissions to sensible defaults.
-hfs
turns on creation of a hybrid ISO 9660/HFS filesystem.
-part
creates an HFS partition partition table in the generated ISO image.
-hfs-bless
sprinkles some magic in the HFS volume metadata as part of making the generated filesystem image bootable (explained in more detail later on).
-map
is a file with mappings from file extensions to HFS file types, to be stored in the HFS metadata.
-A
, -V
, -P
and -p
set the Application ID, Volume ID, Publisher and Preparer fields in the filesystem metadata.
-o
sets the name of the output ISO image file, and the last parameter is the filesystem tree which should be placed into the ISO image.
So, I copied the contents of the boot CD to a directory, created a suitable boot.conf
file and then created my test ISO image using a command similar to the one in the Makefile above. After locating some blank CD's to use, I burned the ISO and then attempted to boot the PowerMac from my magic CD.
It booted into the ramdisk kernel on the CD instead of the kernel image on the hard disk, i.e. it didn't work.
Given that the CD bootloader was booting the kernel image on the CD, my next idea was to replace the kernel image on the ISO file. So I repeated my previous steps, except I copied the kernel image from /bsd
over the image at /6.3/macppc/bsd.rd
in the CD's filesystem. This ISO image worked (and there was much rejoicing), however this had the major disadvantage that upgrading the kernel required a new CD to be burnt. As it turned out I had exhausted my stock of recordable CD's (I only had two to begin with), so I settled with this (decidedly suboptimal) solution for the time being.
I came back the next day, and lacking any other blank CD's to test with, I did some finer investigation of the PowerMac's boot process. I found a few interesting bits of information:
The default boot command executed on the PowerMac is boot hd:,\\:tbxi
.
The OpenBSD boot-only CD contains a file /6.3/macppc/bsd.tbxi
, also found at /usr/mdec/bsd.tbxi
on an OpenBSD/macppc installation and in OpenBSD's CVS tree here. This appears to be some sort of XML file, but contains the string boot cd:,ofwboot /6.3/macppc/bsd.rd
inside a BOOT-SCRIPT
tag.
The HFS file type mapping file (given as the argument to the mkhybrid(8)
-map
option above) has an entry for "tbxi", with the application description being "bootable description file".
Some googling for "open firmware tbxi" yielded this page on booting Linux on PowerPC Apple devices, which rather explicitly wraps this all up: it explains that a boot target of e.g. cd:,\\:tbxi
instructs the firmware to boot from the file on the CD with HFS file type "tbxi" in the magic blessed directory.
From this, I guessed that the boot target the PowerMac's firmware tried after failing to boot from the hard disk (as there's no HFS partition there) must be cd:,\\:tbxi
-- the OpenBSD boot CD is loaded automatically, and it contains a blessed magic HFS directory with a "tbxi" file, and this file loads the second-stage bootloader and kernel from the CD. So at this point it looked like what I needed to do to make the PowerMac automatically boot from disk was to create an image with a modified bsd.tbxi
file with an appropriate boot script.
Firstly, I acquired more writable CD's.
I have only OpenBSD installed on this PowerMac's hard disk (i.e. there is no MacOS dual-booting), so the installer created a small MSDOS partition with a FAT filesystem for storing the second-stage OpenBSD bootloader. Open Firmware understands FAT and can load images from such a filesystem, so I made a copy of the default bsd.tbxi
file and changed the boot script to boot hd:,ofwboot
. This is the command I had to enter manually when booting the PowerMac beforehand, and it instructs the firmware to load the second-stage bootloader ofwboot
from (the first partition of) the primary hard disk. I created an ISO image containing this ISO file with the appropriate partitioning, mapping and blessing, something like this (on a system with CVS checked out):
$ cd /tmp; mkdir -p root/boot
$ cp /usr/mdec/bsd.tbxi root/boot
$ sed -i 's|cd:,ofwboot /6.3/macppc/bsd.rd|hd:,ofwboot|' root/boot/bsd.tbxi
$ cp /bsd root/ # The ISO image needs to be at least 800K in size for mkhybrid to like it
$ mkhybrid -v -v -r -part -hfs -hfs-bless /tmp/root/boot \
-map /usr/src/gnu/usr.sbin/mkhybrid/src/more.mapping \
-A "OpenBSD macppc magic boot CD" -V "OpenBSD magic boot disk" \
-P $(whoami) -p $(whoami) -o image.iso /tmp/root
I then burnt this image and tried it out. This worked (more rejoicing), and will not be affected by kernel upgrades.
This certainly a much better solution than sourcing a replacement 3.6V half-AA motherboard battery.