Section 4.11. Alternate Booting Scenarios


4.11. Alternate Booting Scenarios

In this section, we look at the following examples of booting in alternate ways: booting a user-specified kernel, booting from a software RAID device, and booting over the network.

4.11.1. Booting an Alternate Kernel

A kernel other than the default can be booted by appropriately setting Open Firmware's boot-file variable, which is empty on a typical Mac OS X installation. BootX explicitly looks for the kernel by its default name (mach_kernel) in the root directory of the boot device. Setting boot-file overrides this behavior.

Suppose the alternate kernel you wish to boot also resides in the root directory of the file system containing the default kernel. Let the alternate kernel's name be mach_kernel.debug. First, we determine the BSD name of the disk device containing these kernels.

$ mount /dev/disk0s3 on / (local, journaled) ...


We see that the root file system is on the third partition of disk 0. Although we can use the complete Open Firmware pathname of the disk while setting boot-file, in this case it is simpler to use the hd alias, which expands to the complete pathname of the primary disk. Figure 418 shows an example of retrieving an Open Firmware path for a given BSD device node.[23]

[23] There may be multiple Open Firmware pathnames for a given device.

Figure 418. Retrieving a BSD device node's Open Firmware path

// getfwpath.c #include <stdio.h> #include <fcntl.h> #include <stdlib.h> #include <unistd.h> #include <sys/disk.h> #define PROGNAME "getfwpath" int main(int argc, char **argv) {     int fd;     dk_firmware_path_t path = { { 0 } };     if (argc != 2) {         fprintf(stderr, "usage: %s <path>\n", PROGNAME);         exit(1);     }     if ((fd = open(argv[1], O_RDONLY)) < 0) {         perror("open");         exit(1);     }     if (ioctl(fd, DKIOCGETFIRMWAREPATH, &path) < 0) {         perror("ioctl");         close(fd);         exit(1);     }     printf("%s\n", path.path);     close(fd);     exit(0); } $ gcc -Wall -o getfwpath getfwpath.c $ machine # PowerPC-based Macintosh ppc970 $ sudo ./getfwpath /dev/rdisk0 first-boot/@0:0 $ sudo ./getfwpath /dev/rdisk0s3 first-boot/@0:3 $ sudo ./getfwpath /dev/rdisk1 sata/k2-sata@1/@:0 $ machine # x86-based Macintosh i486 $ sudo ./getfwpath /dev/rdisk0 /PCI0@0/SATA@1F,2/@0:0

In the context of the current example, the following setting for boot-file will result in /mach_kernel.debug being booted instead of /mach_kernel.

$ sudo nvram boot-file boot-file $ sudo nvram boot-file="hd:3,mach_kernel.debug"


If booting the alternate kernel fails, or if you otherwise wish to revert to the previous kernel, you can edit the value of boot-file appropriately. In particular, if boot-file previously had a custom value, you can restore it to its original value. Alternatively, you can reset all Open Firmware variables, which will result in /mach_kernel being used by default. The following sequence of Open Firmware commands will achieve this:

0 > set-defaults 0 > sync-nvram 0 > reset-nvram 0 > mac-boot


set-defaults resets most configuration variables to their default values. However, it does not alter any user-created configuration variables. It also does not affect security-related variables.

4.11.1.1. NVRAM Caveats

There are certain noteworthy caveats regarding the manipulation of NVRAM variables from Mac OS X. Most importantly, it must be realized that making any changes to the NVRAM variables does not result in the NVRAM controller committing those changes to flash memory immediately. The changes are only stored in the I/O Kit, which maintains them under the options node. When the system goes through a proper shutdownsay, due to a halt or a rebootthe Platform Expert makes a call to the NVRAM controller, which commits the in-memory NVRAM image to nonvolatile storage. Therefore, if you change the value of an NVRAM variable using the nvram command-line program and simply power off the system without a proper shutdown, the change will be lost.

When a kernel panic occurs, a panic log may be saved to NVRAM under certain circumstances. In particular, it is not saved if panic debugging is enabled. When the log is present, it is contained in NVRAM as the value of a firmware variable called aapl,panic-info. The kernel attempts to compress the log before saving it to NVRAM. If the panic log is too large,[24] it is truncated before it is saved.

[24] The kernel uses a hardcoded value of 2040 bytes as the upper limit on the size of the panic logcompressed or otherwisethat can be saved to NVRAM.

Moreover, it is possible for certain NVRAM variables to be altered or reset as a side effect of using a system application. For example, the boot-args variable is reset, and the boot-device variable is modified, as side effects of choosing a different system to boot in the Startup Disk preference pane. Specifically, the Startup Disk bundle (StartupDisk.prefPane) resets boot-args to prevent potential interference by arguments that might be inappropriate in the new boot scenario.

4.11.2. Booting from a Software RAID Device

Newer versions of BootX support booting from a RAID device configured using Apple's software RAID implementation (AppleRAID). AppleRAID may be visualized as a type of partitioning schemeone that spans multiple disks but presents a single virtual disk. Let us consider a specific example of an AppleRAID configuration and see how a Mac OS X installation is booted. Figure 419 shows a RAID 0 configuration with two disks.

Figure 419. An AppleRAID software RAID configuration


Each disk in Figure 419 has a small auxiliary partition of type Apple_Boot, which is conventionally named eXternal booter. This partition contains an HFS Plus file system, which in turn contains BootX, a boot property list (plist) file (com.apple.Boot.plist), and a few other files. The plist file lists the RAID set's members.

$ cat com.apple.Boot.plist ... <plist version="1.0"> <array>         <dict>                 <key>IOBootDevicePath</key>                 <string>IODeviceTree:sata/k2-sata@1/@0:4</string>                 <key>IOBootDeviceSize</key>                 <integer>159898714112</integer>         </dict>         <dict>                 <key>IOBootDevicePath</key>                 <string>IODeviceTree:first-boot/@0:4</string>                 <key>IOBootDeviceSize</key>                 <integer>159898714112</integer>         </dict> </array> </plist>


The boot-device NVRAM variable in this setup refers to one of the Apple_Boot partitions.

$ nvram boot-device boot-device     sata/k2-sata@1/@0:3,\\:tbxi $ sudo ./getfwpath /dev/rdisk0s3 sata/k2-sata@1/@0:3


When a RAID-capable BootX looks for boot paths, it checks for the existence of a boot plist file on the boot device. If one is found, its contents are parsed and entered into a dictionary. It then iterates over the list of potential RAID set members, examining the RAID header of each. An Apple RAID header[25] resides on an Apple_RAID partition at an offset that is a function of the partition's size:

[25] This example uses version 2 of the AppleRAID header.

enum {     kAppleRAIDHeaderSize       = 0x1000,     kAppleRAIDDefaultChunkSize = 0x8000 }; #define ARHEADER_OFFSET(s) ((UInt64) \     (s) / kAppleRAIDHeaderSize * kAppleRAIDHeaderSize - kAppleRAIDHeaderSize) ... struct AppleRAIDHeaderV2 {     char        raidSignature[16];     char        raidUUID[64];     char        memberUUID[64];     UInt64      size;     char        plist[]; };


The RAID headers on disk0s4 and disk1s4 in our example contain sufficient information to allow BootX to identify them as members of a RAID set.

/* disk0s4 RAID header */ ... <key>AppleRAID-MemberUUID</key> <string >4C7D4187-5A3A-4711-A283-844730B5041B</string> ... <key>AppleRAID-SetUUID</key> <string >2D10F9DB-1E42-497A-920C-F318AD446518</string> ... <key>AppleRAID-Members</key> <array >     <string >77360F81-72F4-4FB5-B9DD-BE134556A253</string>     <string IDREF="3"/> </array> ... /* disk1s4 RAID header */ ... <key>AppleRAID-MemberUUID</key> <string >77360F81-72F4-4FB5-B9DD-BE134556A253</string> ... <key>AppleRAID-SetUUID</key> <string >2D10F9DB-1E42-497A-920C-F318AD446518</string> ... <key>AppleRAID-Members</key> <array >     <string IDREF="3"/>     <string >4C7D4187-5A3A-4711-A283-844730B5041B</string> </array> ...


If BootX determines that all members of a RAID set that are required to make the set complete have been found, it proceeds with booting. BootX itself implements a library for performing I/O on RAID devices. The library provides open, close, read, write,[26] and seek functions for RAID device I/O.

[26] Writing to a RAID device is not supported by BootX. This function simply returns an error.

4.11.3. Booting over a Network

We saw earlier how to "boot" Forth programs by downloading them using TFTP from a remote computer. Mac OS X itself can be both booted and "rooted" over the network. The easiest way to configure and manage network booting for one or more Mac OS X computers is through the NetBoot service in Mac OS X Server. Such managed network booting offers several benefits.

  • Several client systems can boot from a single server-based disk image. Consequently, the administrator has to manage only one image.

  • Groups of client systems can boot from images customized for the respective groups.

  • Large clusters of computers, whether they are computational clusters or computers within a data center, can be identically configured, booted, and managed.

  • Computers can be booted in "diskless" mode for simplified administration in controlled computing environments such as kiosks and quality assurance (QA) installations. Another use of diskless booting is for diagnosing and fixing problems on a client computer, especially if a problem involves the client's local disks. Disk images for such booting can be served over NFS or HTTP.

Mac OS X can automatically discover a network boot image on the server using a BOOTP/DHCP extension: the Boot Server Discovery Protocol (BSDP).


If you have at least two machines, network booting can be quite useful while debugging a kernel or a kernel extension. One machine hosts the kernel, and the other is the test machine that runs the kernel. It is especially convenient if the host machine is also the build machine.

Although Apple's NetBoot service makes it easier to configure network booting, it is not required to boot Mac OS X over the network. Let us look at an example of network booting a client "manually." We will assume a simple setup suitable for the aforementioned kernel-debugging scenario: The test machinethe booting clientwill use the root file system on its local disk.

Let us call the booting system CLIENT. The other machinecall it SERVERcan be any system capable of running the TFTP service. However, we will assume that both CLIENT and SERVER are running Mac OS X. We will explicitly assign an IP address to CLIENT for network booting. If it must get an IP address dynamically, a DHCP server would also be required.

CLIENT would need to download three items from SERVER: BootX, the kernel, and an mkext cache.

First we must ensure that the TFTP service is enabled on SERVER. Recall from our earlier examples that we can use the service command to enable or disable services.

$ sudo service tftp start


Next, we copy BootX and the kernel to the TFTP directory. If SERVER is also the build machine, a symbolic link pointing to the kernel's build location could be created in the TFTP directory.

$ sudo cp /usr/standalone/ppc/bootx.xcoff /private/tftpboot/bootx.xcoff $ sudo cp /path/to/kernel /private/tftpboot/mach_kernel.debug $ sudo chmod 0644 /private/tftpboot/bootx.xcoff /private/tftpboot/mach_kernel.debug


The mkext cache must be created on CLIENT. Doing so avoids problems that may arise from CLIENT and SERVER having different kernel extension requirements.

$ kextcache -l -n -a ppc -m /tmp/mach_kernel.debug.mkext /System/Library/Extensions


The -l option in the kextcache command line instructs kextcache to include the extensions required for local disk boot, and the -n option specifies extensions for network boot. The resultant mkext file is transferred to SERVER and copied to the TFTP directory. Note that the name of the mkext file is not arbitraryfor a kernel file named foo, BootX will look for an mkext file called foo.mkext.

Next, we need to set the values of three Open Firmware variables on CLIENT: boot-device, boot-file, and boot-args. Let us assume that the IP addresses of SERVER and CLIENT are 10.0.0.1 and 10.0.0.2, respectively. We set the values of boot-device and boot-file using the network booting syntax we came across in previous examples.

0 > setenv boot-device enet:10.0.0.1,bootx.xcoff,10.0.0.2;255.255.255.0,;10.0.0.1 0 > setenv boot-file enet:10.0.0.1,mach_kernel.debug,10.0.0.2;255.255.255.0,;10.0.0.1


We noted that the names of the kernel and the mkext cache must be related. However, there is a caveat due to the way certain versions of BootX parse the boot-file variable. For computing the mkext file's name, BootX assumes the kernel's name to be the string after the last comma in the contents of boot-file. In our current example, the kernel's name, as computed by BootX, would be ;10.0.0.1. In a typical network booting configuration, where we do not need to specify CLIENT's IP address, this issue will not arise because boot-file is of the form enet:<TFTP server's IP address>,<kernel filename>. If the BootX implementation you are using exhibits this behavior, you can get around the issue by creating a symbolic link named ;10.0.0.1.mkext to mach_kernel. debug.mkext in SERVER's TFTP directory.


The remaining configuration step is to set the value of boot-args:

0 > setenv boot-args -s -v rd=*<root device specification>


The -s and -v arguments specify single-user and verbose boot modes, respectively. The rd argument specifies C's root device prefixed with an asterisk character, which forces the root file system to be local. Here is a specific example:

0 > setenv boot-args -s -v rd=*/pci@f4000000/ata-6@d/disk@0:3


Finally, we can flush the NVRAM and reboot.

0 > sync-nvram ... 0 > mac-boot


If everything is set up correctly, the network boot process will start. You might see a flashing globe briefly, followed by the Apple logo with a spinning globe below it. CLIENT should boot into a single user shell.




Mac OS X Internals. A Systems Approach
Mac OS X Internals: A Systems Approach
ISBN: 0321278542
EAN: 2147483647
Year: 2006
Pages: 161
Authors: Amit Singh

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net