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;.