Articles from The Mac Elite, CubeOwner & more

Wednesday, April 2, 2008

Exchange HD and CD in Open Firmware

Open Firmware uses a table of device aliases to abstract from the machine-specific and long nomenclature derived from the device tree. screen for example is defined as the first display of the first graphics card found and is used for any output from the boot ROM (as the Open Firmware console or the gray Apple logo shown when booting Mac OS X). The device aliases can be seen using devalias at the Open Firmware command prompt or ioreg -bp IODeviceTree -n aliases in the Terminal.

In a Cube hd and cd are predefined as the master respectively slave ATA drive and are used by most components accessing those drives, including FireWire Target Disk Mode and booting or ejecting a CD. There is no automatism to adapt these aliases when master and slave are exchanged, but devalias can be used to update them.

At the Open Firmware command prompt two commands like devalias hd /pci@…/disk@1 and devalias cd /pci@…/disk@0 (using the complete path as determined above) can be used to temporarily correct the situation; nvalias … instead of devalias … would add the new values to the nvramrc making them a part of every system start.

I've wrapped a portable variant of the required statements in a script called Exchange HD and CD in OF (available for download as target-mode.zip) that can be launched from the Finder. Before extending the nvramrc it verifies that

  1. Mac OS X has been booted from a slave drive,
  2. hard disk and optical drive are on the same ATA bus and
  3. devalias hd still names a master drive

to protect the innocent (but don't run it twice in a row):

#! /bin/bash -

[[ `ioreg -p IODeviceTree -n chosen -w0 | fgrep bootpath` = *@1:* ]] || exit

while IFS=\" read -ra devalias; do
    [ "${devalias[1]}" = hd ] && hd="${devalias[3]}"
    [ "${devalias[1]}" = cd ] && cd="${devalias[3]}"
done << aliases
`ioreg -p IODeviceTree -n aliases -w0`
aliases

[ "${hd%@*}" = "${cd%@*}" -a "${hd##*@}" = 0 ] || exit

echo '
This script tells Open Firmware that your optical drive is configured
as master and your hard disk drive as slave instead. This information
is needed by the FireWire Target Disk Mode as well as the keys for
booting or ejecting a CD.'

read -rd $'\0' nvram nvramrc << nvramrc
`nvram nvramrc 2>&-`
nvramrc

sudo nvram 'use-nvramrc?=true' nvramrc='dev /aliases
" hd" active-package get-package-property 0= if
" cd" active-package get-package-property 0= if
" hd" property " cd" property then then device-end'" $nvramrc" &&
echo 'Target Disk Mode & friends can be used again.'
sudo -k

I've thrown in a second script Set HD to start volume in OF as a free bonus that redefines devalias hd to the device Mac OS X has been started from if both differ, but performs no further checking. It is intended for PowerMacs other than a Cube (because the definition of cd remains unchanged); my Sawtooth happens to boot from the second hard disk. Judging from a glance at the code I expect the Target Disk Mode to be able to work with any drive that could also be booted from, like SCSI or SATA drives connected to a PCI card:

#! /bin/bash -

IFS=\": bootpath=(`ioreg -p IODeviceTree -n chosen  -w0 | fgrep bootpath`)
IFS=\"       hd=(`ioreg -p IODeviceTree -n aliases -w0 | fgrep \"hd\"  `)
unset IFS

[ "${bootpath[3]}" != "${hd[3]}" ] || exit

echo '
This script tells Open Firmware to access your boot disk drive through
FireWire Target Disk Mode (instead of the ATA master).'

read -rd $'\0' nvram nvramrc << nvramrc
`nvram nvramrc 2>&-`
nvramrc

sudo nvram 'use-nvramrc?=true' nvramrc="devalias hd ${bootpath[3]}
$nvramrc" &&
echo 'Target Disk Mode can be now used to access the boot disk drive.'
sudo -k