24.3 The FreeBSD Boot Loader The FreeBSD boot loader is the environment provided prior to loading and starting the FreeBSD kernel. Rather than a simple program that simply loads in a hard-coded filename, the boot loader provides the user with the option to choose which kernel to boot. It also allows the user to pass options to the kernel that is being loaded. For example, the user can request that the system be booted into single user mode. Additionally, the boot loader allows the user to load kernel modules to supplement the functionality of the base system. FreeBSD can be booted from a number of devices, including floppy disks, hard disks, CD-ROM's, and network adapters. Each of these boot paths will be covered in turn in the following sections. Each of these boot paths depends on a machine dependent miniature operating system that controls and abstracts access to the hardware. 24.3.1 The i386 Bootstrap This section assumes you are familiar with the i386 architecture, including protected, real, and virtual 86 modes, as well as the memory organization used in each mode, specifically segments and selectors. It also assumes that you are familiar with the method used to handle external interrupts. 24.3.1.1 The i386 BIOS Bootstrap All i386 machine BIOS's use the same bootstrap algorithm. They attempt to boot from a set of devices one at a time until one signals success by never returning. For older PC's, this set was fixed, with the first device being the first floppy drive and the second device being the first hard disk drive. Newer BIOS's add support for booting from other devices, such as CD-ROM's and network adapters, as well as from other hard disk drives or floppy drives in the system. Note that the i386 bootstrap process is performed in real mode. 24.3.1.1.1 Booting from a Disk Device All disk devices, whether they are floppy disks, hard disks, or large removable disks are treated exactly the same. The first sector of data is read from the disk and stored at location 0x7c0. The BIOS then jumps to the address 0x0000:0x007c to execute the sector of data it just read from the disk. This one sector must then load up any more data it needs from the boot disk via the BIOS. Note that hard disks usually store a table known as the Master Boot Record, or MBR, in their first sector. This table lists up to four main slices of the hard drive. Each slice is tagged with an identifier identifying its file system type. Also, at most one slice is marked active. The default MBR boot code boots the operating system found in the active slice similar to the way that the BIOS boots the system from a disk. 24.3.1.1.2 Booting from a CD-ROM Presently, the only way to boot from a CD-ROM is to use a CD-ROM that conforms with the El Torito bootable CD format. This format allows for several different methods of booting. The first method, which is currently used on FreeBSD CD's, uses a file on the CD to emulate a floppy disk. The system is then booted from the emulated floppy disk as outlined above. A second method simply loads in an entire file off of the CD into memory at a specified address. By default, this address is 0x7c0. This second method also provides direct access to the data on the CD through the BIOS. Note that this requires a BIOS that supports booting from El Torito CD-ROM's. Also, some BIOS's only support the first method but not the second method. Even worse, some BIOS's only support part of the first method. For example, nearly every BIOS that supports El Torito CD booting supports emulating a 1.44 MB floppy disk. However, some of these BIOS's cannot handle emulating a 2.88 MB floppy disk. Since FreeBSD currently uses a 2.88 MB image file for its boot file, this means that some BIOS's that claim to support El Torito CD booting won't boot off of the FreeBSD CD's. 24.3.1.1.3 Booting from a Network Adapter Currently, the only network adapters FreeBSD supports as boot devices are PXE-enabled network adapters. The PXE BIOS uses DHCP to negotiate an IP address for the card. It then uses TFTP to transfer a boot program over the network. This boot program is stored at 0x7c0 and then executed. This program can use the PXE BIOS to perform any other network operations necessary. 24.3.1.2 The i386 Boot Extender (BTX) BTX is a simple virtual 86 mode monitor. It provides a single task environment, two system calls, interrupt handling, simple fault handling, and a virtual 86 interface that client programs can use to simulate calling the BIOS in real mode. 24.3.1.2.1 BTX Memory Layout The BTX uses the following memory layout: Physical Offset Length Description -------- ------ --------------------------------------------- 0x1000 0x0800 Privilege Level 0 Supervisor Stack 0x1800 0x0600 Scratch Buffer 0x1e00 0x0198 Privilege Level 1 Link Stack 0x1f98 0x2068 Task State Segment Used to Manage Client 0x2000 0x2000 I/O Permission Bitmap Within the TSS 0x4000 0x1000 Page Directory (*) 0x5000 0x4000 Page Tables (*) 0x9000 0x1000 BTX Code and Data 0xa000 Client Memory * Note: Only used if BTX is compiled with paging support. By default paging support is disabled since paging limits memory accesses to the first 16 megabytes of the addressable memory space. The client memory extends from its start address of 0xa000 up to the end of free base memory. Usually free base memory ends at 0xa0000, the start of video memory. However, some BIOS extensions, such as PXE, may use some base memory, decreasing the amount of memory available to the client. BTX uses the following selectors: Selector Description -------- ---------------------------------------------------------- 0x0000 Null Selector 0x0008 BTX Code Segment, Privilege Level 0, Execute/Read, 32-bit 0x0010 BTX Data Segment, Privilege Level 0, Read/Write 0x0018 Real Mode Code Segment, Privilege Level 0, Execute/Read, 16-bit 0x0020 Real Mode Data Segment, Privilege Level 0, Read/Write 0x0028 Client Code Segment, Privilege Level 3, Execute/Read, 32-bit 0x0030 Client Data Segment, Privilege Level 3, Read/Write 0x0038 TSS Used by BTX to Manage Client 24.3.1.2.2 BTX Services BTX provides several services to client applications. These can be split into two groups. The first group of services are provided transparently to the client. The second group of services are explicitly called by the client. The transparent services include emulating several instructions, such as pushf, popf, cli, sti, iret, and hlt. Another transparent service traps and emulates the BIOS call used to copy extended memory from one place to another. Finally, all hardware interrupts are trapped and routed through virtual 86 mode to the default BIOS handlers. The explicitly called services consist of two system calls and the virtual 86 interface. The first system call, exit, terminates BTX and reboots the system. The second system call, exec, jumps to a passed in address in supervisor mode. This way, the called application is free to leave protected mode, to replace the descriptor tables, and to replace or setup the page tables. Finally, the virtual 86 interface instructs the BTX to either invoke an interrupt or call a routine in virtual 86 mode. 24.3.1.2.3 Fault Handling BTX does not ignore faults. Instead, it prints out a rather cryptic register dump, followed by a stack dump and a code dump. While this information may not seem very understandable, it is very helpful to the people who work on BTX. If you get a fault, please include the full fault in your bug report. Example BTX Fault int=0000000d err=00000000 efl=00010207 eip=00004316 eax=00000008 ebx=00000001 ecx=fffffff7 edx=00001000 esi=0000000a edi=0003f7c4 ebp=000845d8 esp=0008459c cs=002b ds=0033 es=0033 fs=0033 gs=0033 ss=0033 cs:eip=fb b3 68 31 68 af 30 79-fa 32 68 00 00 00 8b 55 ss:esp=c4 f7 03 00 01 00 00 00-c4 f7 03 00 00 10 00 00 24.3.1.3 The i386 Bootstrap Programs Several different programs are used in the i386 bootstrap. Several of these programs are BTX clients. All of these programs are used to either load a kernel directly or to load up the boot loader. 24.3.1.3.1 Boot0 and MBR Boot0 and mbr are not technically part of the FreeBSD bootstrap. Rather, they are two different boot codes used with a hard disk's MBR. The mbr code simply performs the default action of booting the active slice. Boot0, on the other hand, presents the user with a simple menu of choices based on the contents of the slice table stored in the MBR. The user can then choose which slice they wish to boot. Note that the fdisk command uses the mbr boot code by default when it creates an MBR on a hard disk. Therefore, if you want a boot menu on your hard disk, you must either tell fdisk to use boot0 as the MBR boot code, or use the boot0cfg utility to install boot0 after running fdisk. 24.3.1.3.2 Boot1 and Boot2 Boot1 and Boot2 are used to boot off of floppy disks and hard disk slices. Boot1 is simply one sector long. When it is loaded, it locates the boot2 binary located behind it on the disk. Boot1 then loads boot2 into memory. Since boot2 is a BTX client, the binary comes bundled with the BTX environment. Boot1 relocates the BTX code to 0x9000 and relocates the boot2 client code to 0xa000. It then starts up BTX. After BTX finishes initialization, it starts up the boot2 client. At this point, the user is allowed to either boot a kernel or the boot loader. More information on the syntax and usage of boot2 can be found in &man.boot.8;. 24.3.1.3.3 CD Loader The new CD loader program, cdldr, uses the second method of booting from El Torito CD-ROM's mentioned above. By itself, cdldr is not very useful. However, cdldr and the boot loader can be concatenated together to form the cdboot binary. When the CD boots, it loads all of the cdboot binary into memory. The cdldr program then locates the loader binary located behind it in memory. It then parses the loader binary and relocates the relevant sections to the loader's entry point. Once that is done it copies the BTX out of the loader's binary. It then sets up a small part of itself as a BTX client. Finally, cdldr starts up BTX, which starts up the small BTX client contained in cdldr. This small client simply passes along the required boot parameters to the loader and then starts the loader via an exec system call. 24.3.1.3.4 PXE Loader The new PXE loader program, pxeldr, is almost identical to the cdldr program. It is also joined with the loader binary to form the pxeboot binary. This binary is then transferred over the network and booted. The PXE loader differs from the CD loader because it sends different startup parameters to the loader binary when starting it. 24.3.1.3.5 Btxldr Btxldr is not really a separate bootstrap program. Instead, btxldr is strapped onto the very front of the loader's code segment. In order to support old bootstraps, btxldr accepts the same boot arguments as a kernel. Btxldr then shuts down BTX and copies the loader down into lower memory. Once that is safely down, btxldr restarts BTX. BTX now has the loader as its client, and when it finishes its initialization, it starts up the loader. 24.3.2 Alpha Booting with SRM 24.3.3 The Boot Loader Program The boot loader program provides the machine independent interface used to boot FreeBSD. Here, the user can load and unload modules, kernels, and configuration files. The user can also set variables to configure the kernel. Also, the boot loader includes the FICL programming language, which is a subset of Forth. This allows for the creation of complex scripts. For example, the user can create customized boot menus for different kernels and configurations. For more information on the boot loader program, see &man.loader.8; and &man.loader.conf.5;.