1== Why BootX? == 2 3BootX, the Mac OS X Secondary Loader, exists to bootstrap execution of 4the Mac OS X kernel, xnu (named /mach_kernel in the filesystem). It serves 5a few purposes. 6 7* Filesystem abstraction. Mac OS X supports many filesystems, and 8 can root off a handful of them. However, OpenFirmware mainly only 9 supports HFS and/or HFS+, ISO9660, tftp. In order to root off 10 non-native (to OF) filesystems, BootX must be placed somewhere that 11 is accessible, and then BootX's filesystem code can be used to access 12 the root filesystem. This is used for UFS booting, for example, which 13 is not directly supported by OpenFirmware. Since BootX lives on-disk, 14 it can also be updated to support new filesystems trivially, while 15 it is harder to update OpenFirmware (although BootROM upgrades do 16 exist) 17* I/O abstraction. Even if OF could load xnu directly (in the case of 18 an HFS+ root partition), the kernel would need to have device drivers 19 to access the the drive containing kernel extensions. Since even 20 device drivers are loadable kernel models, this is clearly a paradox. 21 BootX runs in the OpenFirmware execution environment, and can use 22 generic ATA, SCSI, ethernet drivers to load multiple files needed 23 by the kernel 24* File-format abstraction. The xnu kernel is in the Mach-O file format, 25 which was not and is not considered "native" to OpenFirmware. 26 Different versions of OpenFirmware support different file formats, 27 including XCOFF, ELF, and bootinfo. 28* Security measures. BootX for Mac OS X 10.2 implements restrictions 29 on the owner and mode of files that it loads. For example, if 30 mach_kernel was world writable, it's possible that someone 31 may have modified it during the last boot, and executing it could 32 compromise the system and data on the machine. If OF directly 33 executed xnu, and had not been updated to honor these restrictions, 34 there would be no way to stop a boot once it started. 35 36Two questions follow from this summary. How does OpenFirmware find 37BootX, and how does BootX find the root filesystem to start booting 38Mac OS X. 39 40The process of finding BootX is a function of the model of the computer 41(Old World vs. New World) and the root filesystem that will be booted. 42 43== New World booting from HFS+ == 44New World machines (with OF 3.0+) support HFS+, ISO9660, and FAT. When 45Mac OS X is installed on an HFS+ volume, BootX is typically placed 46in the /System/Library/CoreServices directory, and given the HFS+ 47type attribute of 'tbxi'. Furthermore, the CoreServices folder is 48"blessed", which means that it's directory ID (analogous to an inum 49in FFS terminology) is recorded, in the HFS+ volume header. 50 51When Open Firmware begins searching for an operating system, it starts 52by building up a device tree based on all buses and peripherals it knows 53about. It then consults the boot-device open firmware variable 54(use "nvram boot-device") to see what this is set to. A typical 55boot-device is "mac-io/ata-4@1f000/@0:8,\\:tbxi", which can be 56logically tokenized into "mac-io/ata-4@1f000/@0", 8, "\\", "tbxi". 57 58First, OF uses the device path ("mac-io...") to find the hard drive or 59CD-ROM or DVD-ROM containing the operating system. Once it has 60determined this, some OF code responsible for parsing Apple Partition 61Maps analyzes the beginning of the disk and determines the location of 62the 8th partition (partitions are 1-indexed, with the first partition 63being the partition map partition). The next two components of 64boot-device are used to located the BootX secondary loader. The first 65("\\") is a special syntax denoting the blessed system folder 66mentioned above. The HFS+ volume format allows a directory ID to 67quickly map to the directory entry and its contents. Because a 68directory (and not a file) was specified, ":tbxi" is used to filter 69entries that have the HFS+ type of 'tbxi'. If multiple files in the 70directory have the same HFS+ type, the first one (in directory order) 71is used, which is somewhat non-deterministic from the operating system 72point of view, and is not necessarily the alphabetically first entry. 73 74Above, we used "\\" to denote the blessed system folder. However, 75this could have been made explicit by using 76"\System\Library\CoreServices\". Directory paths should always end in 77a trailing "\", while files should not. A '\' is used instead of the 78typical Unix path delimiter '/' because '/' is a valid filename 79character on HFS+, and '\' somewhat disambiguates this. Also, we could 80have avoided the filter mechanism and specified the path to BootX 81directly. The following forms are all equivalent, and would occur 82after the last comma in boot-device variable (assuming the path itself 83doesn't have commas itself): 84 85\\:tbxi 86\\BootX 87\System\Library\CoreServices\:tbxi 88\System\Library\CoreServices\BootX 89 90In the new world situation, BootX is in the bootinfo format, which is 91to say that it is an XCOFF with XML headers which specify additional 92Forth commands. 93 94You can create a new bootingo-format BootX in the CoreServices folder 95by running: 96bless -folder /Volumes/test/System/Library/CoreServices -bootinfo \ 97 /usr/standalone/ppc/bootx.bootinfo 98To set the OF boot-device variable to point at a volume, use 99bless -mount /Volumes/test -setOF 100or 101bless -device /dev/disk0s13 -setOF 102To simultaneously bless and set OF, use: 103bless -folder /Volumes/test/System/Library/CoreServices -bootinfo \ 104 /usr/standalone/ppc/bootx.bootinfo -setOF 105 106 107== Old World booting from HFS+ == 108Old World machines (OF < 3.0) mainly support HFS only (not HFS+). This 109is quite a predicament if your operating system is on an HFS+ 110volume. Additionally, Old World machines will automatically begin 111executing the Mac OS ROM (for traditional Mac OS) on boot, which it 112should not do if it will be booting Mac OS X. The solution to this is 113multi-pronged 114 115* Store the BootX in some special location 116* Store a pointer to the BootX location somewhere known 117* Patch open firmware to not execute the Mac OS ROM, and instead load 118 BootX from the special location 119* Include a stub HFS filesystem in front of the HFS+ filesystem with 120 code to repatch OF if the patches are erased (e.g. if PRAM is zapped) 121 122Under Mac OS X, the XCOFF version of BootX (slightly modified) is 123stored in part of the extents overflow file. On an HFS+ volume, the 124B-Tree Catalog directly stores up to 8 extents (contiguous on-disk 125blocks representing part of the file) per file. Further extents are 126stored in the extents file. Files typically do not get fragmented 127badly enough to overflow, and certainly not frequently such that the 128extents file would be filled up. In the event that this unlikely event 129does occur, the extents file (like all HFS+ special files) can be 130grown. Because of this, Storing the BootX in part of the space 131originally allocated for the extents overflow file is safe, and 132prevents direct modification in the filesystem by the user (which 133might cause the file to get split or moved without updating the 134pointer mentioned above). Since the HFS+ volume header subtracts space 135from the extents file allocated extent, the space is marked as 136belonging to the HFS+ Startup File (just so all allocation blocks in 137the volume are marked as used, and so BootX doesn't get overwritten by 138the runtime HFS+ allocator). It is important to note that because 139BootX is listed as belonging to the Startup File extents, nothing 140actually semantically interprets this as having boot code. It's just 141for bookkeeping purposes, and is, at a cosmic level, appropriate 142because that area is being used to boot an OS. 143 144The OpenFirmware patch used on Old World machines for booting OS X 145is derived from similar patches used to boot A/UX. OpenFirmware 146completely ignores the boot-device variable (which was used for New 147World booting), and instead looks at the drive partition map. It looks 148for map entries set like so: 149 pmLgBootStart 0x00003840 (14400) 150 pmBootSize 0x000C1000 (790528) 151 pmBootAddr 0x01C00000 (29360128) 152 pmBootAddr2 0x00000000 (0) 153 pmBootEntry 0x01C00CB0 (29363376) 154 pmBootEntry2 0x00000000 (0) 155 pmBootCksum 0x00000000 (0) 156 pmProcessor powerpc 157 158The first such map entry is used to find BootX. pmLgBootStart is 159the sector location of the start of BootX (same as the Startup File 160extent start), and is pmBootSize bytes (usually less than the total 161amount of space reserved for the Startup File). Once the code is 162loaded into memory, Open Firmware begins executing at the speicifed 163entry point. 164 165Since Old World OF does not use boot-device to find BootX, it is 166important that there only be one partition with this information set, 167and that it is compatible with the OS being booted. 168 169As you can see, none of this process actually tries to interpret the 170volume as HFS or HFS+. But how then does Open Firmware get patched 171initially? The answer is that most HFS+ volumes are actually wrapped 172HFS+ volumes. Graphically, the volume looks approximately like: 173 174volume 175start 2 3 n n+2 n+3 176+-------+-----+------------+--------------------------- 177| | | +=====+====+============ 178| BB | MDB | HFS data | | VH | HFS+ data ... 179| | | +=====+====+============ 180+-------+-----+------------+--------------------------- 181 182To an older HFS client (like Old World OF), the volume looks like a 183pure HFS volume with a bunch of used space taking up most of the 184volume. The used space corresponds exactly to a pure HFS+ volume 185(except it's a few MB smaller than the size of the partition would 186otherwise hold because of the wrapper goo. 187 188When OF is unpatched, the Mac OS ROM looks for HFS volumes with valid boot 189blocks in the first 2 sectors. If a volume has this, it looks for a 190System file contain the Mac OS. At this point, one of two System files 191can be used. One system file actually has code to patch OF and trigger 192a reboot. The default wrapper installed by newfs_hfs has just enough 193code to delve into the HFS+ embedded volume to find a System file in 194the embedded blessed volume, which has a full HFS+ read/write stack in 195one of its resources. Once the wrapper system file has loaded the 196code, it searches the embedded for the System file again. Once it 197finds it, at this point, OF is patched and the machine is 198rebooted. The version to repatch OF in the wrapper is typically used 199on CDs, and the version to repatched OF in the embedded volume is 200typically used on hard drives. 201 202To set up the fake system file that will repatch OF: 203bless -folder /Volumes/test/System/Library/CoreServices \ 204 -folder9 /Volumes/test/System/Library/CoreServices \ 205 -bootinfo /usr/standalone/ppc/bootx.bootinfo \ 206 -bootBlockFile /usr/share/misc/bootblockdata \ 207 -systemfile /usr/share/misc/hdbootdata 208Then, to set up the XCOFF, unmount the partition, and run: 209bless -device /dev/disk3s9 -xcoff /usr/standalone/ppc/bootx.xcoff 210 211== New World booting from UFS (and other foreign file systems) == 212Since even New World OF (currently) does not support UFS and other 213filesystems which the Mac OS X kernel might root off of (or which a 214third-party might add support for), some alternate mechanism is 215needed. The Old World solution of patching OF is not applicable, since 216arbitrary filesystems won't support HFS/HFS+ wrappers. The alternative 217is adding an auxiliary partition with an HFS+ filesystem. 218 219Under Mac OS X, this is referred to as a booter partition, and has 220partition type Apple_Boot. The partition has a regular, blessed HFS+ 221filesystem, complete with BootX. If the UFS (or other) partition is 222partition n, the Apple_Boot should be either n-2 or n-1 (see below). 223 224== Old World booting from UFS == 225For old world booting, something auxiliary is also needed. The 226traditional solution has been to create a small partition of type 227Apple_Loader. This has no filesystem, but rather has the BootX XCOFF 228written into it. The partition map entry has the A/UX boot settings, 229with the start address being just 0 (i.e. load the XCOFF from the 230beginning of the partition). 231 232In order to make a UFS volume bootable for both Old World and New 233World, the partition layout might look like: 234 235## Type_________________ Name____________ Start___ Size____ End_____ 236... 237 8 Apple_Boot MOSX_OF3_Booter 1544 16384 17927 238 9 Apple_Loader SecondaryLoader 17928 1024 18951 23910 Apple_UFS Mac_OS_X 18952 5102592 5121543 240 241On a New World machine, BootX will look for the root filesystem two 242partitions up from boot-device is pointing to. On an Old World 243machine, BootX will look for the root filesystem one partition up. 244 245A new scheme is being developer post-10.2 which uses a single 246partition for both Old and New World. It will have a type Apple_Boot, 247and have a wrapper HFS+ filesystem, which a blessed BootX for New 248World, and the XCOFF as the Startup File (with corresponding partition 249additions) for Old World. In this case, New World will only look to 250the next partition for the root filesystem. 251 252To create a combined booter partition, either use SPI in MediaKit, or 253create an 8.5MB (17408 512-byte sectors) partition of type Apple_Boot 254and partition name "eXternal booter". Then: 255bless -device /dev/disk1s10 -format -label "Boot OSX" -fsargs \ 256 "-c e=1024" -xcoff /usr/standalone/ppc/bootx.xcoff 257mkdir -p /mnt 258mount -t hfs /dev/disk1s10 /mnt 259bless -folder /mnt -folder9 /mnt -bootinfo \ 260 /usr/standalone/ppc/bootx.bootinfo -systemfile \ 261 /usr/share/misc/hdbootdata -bootBlockFile \ 262 /usr/share/misc/bootblockdata 263umount /mnt 264New World machines will immediately load the bootinfo BootX. Old World 265machines will get repatched if necessary, and otherwise load the XCOFF 266 267== What version of Open Firmware do I have == 268Run "ioreg -p IODeviceTree -n openprom" and look for the "model" key. 269Versions 1 and 2 are Old World. Version 3 is New World. Not that this 270discussion is limited to PCI bus Macintoshes. A more useful programmatic 271method is to use "sysctl hw.epoch", which can be implemented programmatically 272with sysctl(3). 0 is Old World, and 1 is New World. 273 274A list of Hardware to OF versions can be found at 275http://www.netbsd.org/Ports/macppc/models.html 276 277== References == http://louis.gerbarg.org/papers/BootX.pdf 278 279"TN1061: Fundamentals of Open Firmware, Part I: The User Interface" - http://developer.apple.com/technotes/tn/tn1061.html 280 281"TN1062: Fundamentals of Open Firmware, Part II: The Device Tree" - http://developer.apple.com/technotes/tn/tn1062.html 282 283"TN1044: Fundamentals of Open Firmware, Part III: Understanding PCI Expansion ROM Choices for Mac OS 8" - http://developer.apple.com/technotes/tn/tn1044.html 284 285"TN1167: The Mac ROM Enters a New World" - http://developer.apple.com/technotes/tn/tn1167.html 286 287http://bananajr6000.apple.com/ 288 289http://www.netbsd.org/Ports/macppc/faq.html#ofw 290 291Darwin CVS project bless 292 293Darwin CVS project boot 294 295Darwin CVS project xnu 296 297Darwin CVS project diskdev_cmds - newfs_hfs, pdisk 298 299Darwin CVS project system_cmds - nvram 300 301http://www.netbsd.org/Ports/macppc/models.html 302 303