x86 BootstrapThis note describes how the new x86 bootstrap code works. The x86 bootstrap has been rewritten several times, and the code is difficult to read because portions of it are in 16-bit assembler. I am writing this note both as a reminder to myself and as a possible source of information for other x86 OS authors. 1. Sequence of OperationHere is a summary discussion of the sequence of events in booting an x86 machine. 1.1 Load Master Boot RecordThe BIOS first loads sector zero of the disk at (linear) 0x7c00, and branches to it by jumping to the segmented 16-bit address 0:0x7c00. On entry to the MBR, the following values are in registers:
No assumptions should be made about other registers. In particular, I am not aware of any safe assumptions concerning other segment registers. If this is a floppy boot, then this is not an MBR, and execution proceeds as described under boot record, below. If this is in fact an MBR sector, the code embedded in the MBR record moves itself out of the way (where to is not documented, and no safe assumptions can be made) and then searches the partition table for the ``active'' partition. If an active partition is found, the MBR loads sector zero of that partition at linear address 0x7c00 and branches to it. If no partition is active, processing halts at this point. 1.2 Load Partition Boot RecordThe partition (or floppy) boot record is entered with the following register environment:
1.3 Load Extended BootstrapFrom this point on, what happens is entirely the business of the operating system-specific boot code. The initial boot sector has 512 bytes less some tables in which to load a more general bootstrap. A complication in reading the EROS bootstrap code is that it is written using a 32-bit assembler. Some operations can be coded directly, but don't mean what they say they mean (e.g. `` Suffice it to say that this is entirely unmaintainable, and an utter pain in the ass to read. Bryan Ford did us all a great service by introducing the For this reason, the EROS bootstrap logic loads the rest of the primary bootstrap as fast as possible, gets into 32-bit code, and then does it's best to stay there. Some OS bootstraps load the secondary bootstrap cleverly, making use of the information in the partition table. The EROS bootstrap instead follows the *BSD convention: the sectors to be loaded are precomputed by a bootstrap installer utility. The EROS bootstrap code simply reads and applies this precomputed table. The table originally compiled in to the raw bootstrap binary is suitable for use in a 1.44M floppy. The extended bootstrap is loaded to a precompiled linear address (presently 0x80000, controlled in I'ld love to claim some grand rationale for this, but the harsh truth is that I was unable to squeeze the partition-sensitive arithmetic into the available space given the constraints of the 32-bit assembler. The necessary code is a little tricky, because it amounts to mixed-base arithmetic. At some point I will bite the bullet and bytecode the whole damn thing, at which point I shall have the space to do it better. 2. EROS Extended BootstrapThe goal of the extended bootstrap is to enter the operating system. It proceeds in three steps:
2.1 Entering 32-bit Protected ModeOn entry into the extended bootstrap code, the first thing done is to enter 32-bit protected mode. This allows us to use the assembler straightforwardly, and more importantly to use the C compiler to write much of the remaining bootstrap. For the most part, the only tricky aspect to entering protected mode is the number of constraints on the problem. The global descriptor table must contain the following:
The last is required because we will need to switch back into 16-bit mode in order to call the BIOS to load further disk sectors. For a similar reason, the stack of the secondary bootstrap must fall within the low 1Mbyte of real memory (this is why we did not load the extended bootstrap above the 1Mbyte boundary. Finally, the extended bootstrap places its heap at 1Mbyte (growing upward). This allows the decompression library to run, but means that malloc'd memory cannot be passed as a buffer to the BIOS, because the BIOS cannot address such memory. 2.2 Balance of Extended BootstrapThe balance of the extended bootstrap is written in a mix of C/C++. Experience suggests that the bootstrap code changes, and that the C code serves as it's own best documentation. In fact, all of this code should be written in C. The only reason that C++ was used was for compatibility with some structure declarations used by the kernel proper. Note, in particular, that the program is linked without the standard runtime environment, and that global constructors are not executed. This isn't a problem, because there are no globals requiring construction in the current bootstrap. 3 Compressed and Ramdisk VolumesIf the volume is marked as a ramdisk, it is loaded by the extended bootstrap into the highest available physical memory. This area is then reported to the kernel as unavailable. A ramdisk image can be optionally compressed. EROS volumes compress favorably, because most of their space is initially occupied by ``zero pages.'' The compression mechanism uses the publicly available ZLIB library (as of this writing, version 1.4), minimally modified to add one Because EROS is persistent, a compressed volume must also be a ramdisk volume. The compression mechanism is not intended to support a compressed low-level disk volume, and we have no plans to add such support. If the disk image is compressed, this is indicated in a flags word embodied in sector zero (the original primary bootstrap). The structure of the compressed disk volume is shown below. The bootstrap also encodes the size of the bootstrap area and the size of the decompressed disk image (needed to allocate memory for the ramdisk image.
+-----------------+----------------------------+
| bootstrap area | ZLIB-compressed disk image |
+-----------------+----------------------------+
Copyright 1998 by Jonathan Shapiro. All rights reserved. For terms of redistribution, see the GNU General Public License |