The translation is temporarily closed for contributions due to maintenance, please come back later.

Source string Read only

(itstool) path: sect1/para
Context English State
The <acronym>BIOS</acronym> (Basic Input Output System) is a chip on the motherboard that has a relatively small amount of read-only memory (<acronym>ROM</acronym>). This memory contains various low-level routines that are specific to the hardware supplied with the motherboard. The processor will first jump to the address 0xfffffff0, which really resides in the <acronym>BIOS</acronym>'s memory. Usually this address contains a jump instruction to the <acronym>BIOS</acronym>'s POST routines.
The <acronym>POST</acronym> (Power On Self Test) is a set of routines including the memory check, system bus check, and other low-level initialization so the <acronym>CPU</acronym> can set up the computer properly. The important step of this stage is determining the boot device. Modern <acronym>BIOS</acronym> implementations permit the selection of a boot device, allowing booting from a floppy, <acronym>CD-ROM</acronym>, hard disk, or other devices.
The very last thing in the <acronym>POST</acronym> is the <literal>INT 0x19</literal> instruction. The <literal>INT 0x19</literal> handler reads 512 bytes from the first sector of boot device into the memory at address <literal>0x7c00</literal>. The term <emphasis>first sector</emphasis> originates from hard drive architecture, where the magnetic plate is divided into a number of cylindrical tracks. Tracks are numbered, and every track is divided into a number (usually 64) of sectors. Track numbers start at 0, but sector numbers start from 1. Track 0 is the outermost on the magnetic plate, and sector 1, the first sector, has a special purpose. It is also called the <acronym>MBR</acronym>, or Master Boot Record. The remaining sectors on the first track are never used.
This sector is our boot-sequence starting point. As we will see, this sector contains a copy of our <filename>boot0</filename> program. A jump is made by the <acronym>BIOS</acronym> to address <literal>0x7c00</literal> so it starts executing.
The Master Boot Record (<literal>boot0</literal>)
<primary>MBR</primary>
After control is received from the <acronym>BIOS</acronym> at memory address <literal>0x7c00</literal>, <filename>boot0</filename> starts executing. It is the first piece of code under FreeBSD control. The task of <filename>boot0</filename> is quite simple: scan the partition table and let the user choose which partition to boot from. The Partition Table is a special, standard data structure embedded in the <acronym>MBR</acronym> (hence embedded in <filename>boot0</filename>) describing the four standard PC <quote>partitions</quote> <_:footnote-1/>. <filename>boot0</filename> resides in the filesystem as <filename>/boot/boot0</filename>. It is a small 512-byte file, and it is exactly what FreeBSD's installation procedure wrote to the hard disk's <acronym>MBR</acronym> if you chose the <quote>bootmanager</quote> option at installation time. Indeed, <filename>boot0</filename> <emphasis>is</emphasis> the <acronym>MBR</acronym>.
As mentioned previously, the <literal>INT 0x19</literal> instruction causes the <literal>INT 0x19</literal> handler to load an <acronym>MBR</acronym> (<filename>boot0</filename>) into memory at address <literal>0x7c00</literal>. The source file for <filename>boot0</filename> can be found in <filename>sys/boot/i386/boot0/boot0.S</filename> - which is an awesome piece of code written by Robert Nordier.
A special structure starting from offset <literal>0x1be</literal> in the <acronym>MBR</acronym> is called the <emphasis>partition table</emphasis>. It has four records of 16 bytes each, called <emphasis>partition records</emphasis>, which represent how the hard disk is partitioned, or, in FreeBSD's terminology, sliced. One byte of those 16 says whether a partition (slice) is bootable or not. Exactly one record must have that flag set, otherwise <filename>boot0</filename>'s code will refuse to proceed.
A partition record has the following fields:
the 1-byte filesystem type
the 1-byte bootable flag
the 6 byte descriptor in CHS format
the 8 byte descriptor in LBA format
A partition record descriptor contains information about where exactly the partition resides on the drive. Both descriptors, <acronym>LBA</acronym> and <acronym>CHS</acronym>, describe the same information, but in different ways: <acronym>LBA</acronym> (Logical Block Addressing) has the starting sector for the partition and the partition's length, while <acronym>CHS</acronym> (Cylinder Head Sector) has coordinates for the first and last sectors of the partition. The partition table ends with the special signature <literal>0xaa55</literal>.
The <acronym>MBR</acronym> must fit into 512 bytes, a single disk sector. This program uses low-level <quote>tricks</quote> like taking advantage of the side effects of certain instructions and reusing register values from previous operations to make the most out of the fewest possible instructions. Care must also be taken when handling the partition table, which is embedded in the <acronym>MBR</acronym> itself. For these reasons, be very careful when modifying <filename>boot0.S</filename>.
Note that the <filename>boot0.S</filename> source file is assembled <quote>as is</quote>: instructions are translated one by one to binary, with no additional information (no <acronym>ELF</acronym> file format, for example). This kind of low-level control is achieved at link time through special control flags passed to the linker. For example, the text section of the program is set to be located at address <literal>0x600</literal>. In practice this means that <filename>boot0</filename> must be loaded to memory address <literal>0x600</literal> in order to function properly.
It is worth looking at the <filename>Makefile</filename> for <filename>boot0</filename> (<filename>sys/boot/i386/boot0/Makefile</filename>), as it defines some of the run-time behavior of <filename>boot0</filename>. For instance, if a terminal connected to the serial port (COM1) is used for I/O, the macro <literal>SIO</literal> must be defined (<literal>-DSIO</literal>). <literal>-DPXE</literal> enables boot through <acronym>PXE</acronym> by pressing <keycap>F6</keycap>. Additionally, the program defines a set of <emphasis>flags</emphasis> that allow further modification of its behavior. All of this is illustrated in the <filename>Makefile</filename>. For example, look at the linker directives which command the linker to start the text section at address <literal>0x600</literal>, and to build the output file <quote>as is</quote> (strip out any file formatting):
<filename>sys/boot/i386/boot0/Makefile</filename>
BOOT_BOOT0_ORG?=0x600
LDFLAGS=-e start -Ttext ${BOOT_BOOT0_ORG} \
-Wl,-N,-S,--oformat,binary
Let us now start our study of the <acronym>MBR</acronym>, or <filename>boot0</filename>, starting where execution begins.
Some modifications have been made to some instructions in favor of better exposition. For example, some macros are expanded, and some macro tests are omitted when the result of the test is known. This applies to all of the code examples shown.
<filename>sys/boot/i386/boot0/boot0.S</filename>
start:
cld # String ops inc
xorw %ax,%ax # Zero
movw %ax,%es # Address
movw %ax,%ds # data
movw %ax,%ss # Set up
movw 0x7c00,%sp # stack
When in doubt, we refer the reader to the official Intel manuals, which describe the exact semantics for each instruction: <link xlink:href="http://www.intel.com/content/www/us/en/processors/architectures-software-developer-manuals.html"/>.
This first block of code is the entry point of the program. It is where the <acronym>BIOS</acronym> transfers control. First, it makes sure that the string operations autoincrement its pointer operands (the <literal>cld</literal> instruction) <_:footnote-1/>. Then, as it makes no assumption about the state of the segment registers, it initializes them. Finally, it sets the stack pointer register (<literal>%sp</literal>) to address <literal>0x7c00</literal>, so we have a working stack.
The next block is responsible for the relocation and subsequent jump to the relocated code.
movw $0x7c00,%si # Source
movw $0x600,%di # Destination
movw $512,%cx # Word count
rep # Relocate
movsb # code
movw %di,%bp # Address variables
movb $16,%cl # Words to clear
rep # Zero
stosb # them
incb -0xe(%di) # Set the S field to 1
jmp main-0x7c00+0x600 # Jump to relocated code
As <filename>boot0</filename> is loaded by the <acronym>BIOS</acronym> to address <literal>0x7C00</literal>, it copies itself to address <literal>0x600</literal> and then transfers control there (recall that it was linked to execute at address <literal>0x600</literal>). The source address, <literal>0x7c00</literal>, is copied to register <literal>%si</literal>. The destination address, <literal>0x600</literal>, to register <literal>%di</literal>. The number of bytes to copy, <literal>512</literal> (the program's size), is copied to register <literal>%cx</literal>. Next, the <literal>rep</literal> instruction repeats the instruction that follows, that is, <literal>movsb</literal>, the number of times dictated by the <literal>%cx</literal> register. The <literal>movsb</literal> instruction copies the byte pointed to by <literal>%si</literal> to the address pointed to by <literal>%di</literal>. This is repeated another 511 times. On each repetition, both the source and destination registers, <literal>%si</literal> and <literal>%di</literal>, are incremented by one. Thus, upon completion of the 512-byte copy, <literal>%di</literal> has the value <literal>0x600</literal>+<literal>512</literal>= <literal>0x800</literal>, and <literal>%si</literal> has the value <literal>0x7c00</literal>+<literal>512</literal>= <literal>0x7e00</literal>; we have thus completed the code <emphasis>relocation</emphasis>.
Next, the destination register <literal>%di</literal> is copied to <literal>%bp</literal>. <literal>%bp</literal> gets the value <literal>0x800</literal>. The value <literal>16</literal> is copied to <literal>%cl</literal> in preparation for a new string operation (like our previous <literal>movsb</literal>). Now, <literal>stosb</literal> is executed 16 times. This instruction copies a <literal>0</literal> value to the address pointed to by the destination register (<literal>%di</literal>, which is <literal>0x800</literal>), and increments it. This is repeated another 15 times, so <literal>%di</literal> ends up with value <literal>0x810</literal>. Effectively, this clears the address range <literal>0x800</literal>-<literal>0x80f</literal>. This range is used as a (fake) partition table for writing the <acronym>MBR</acronym> back to disk. Finally, the sector field for the <acronym>CHS</acronym> addressing of this fake partition is given the value 1 and a jump is made to the main function from the relocated code. Note that until this jump to the relocated code, any reference to an absolute address was avoided.
The following code block tests whether the drive number provided by the <acronym>BIOS</acronym> should be used, or the one stored in <filename>boot0</filename>.

Loading…

No matching activity found.

Browse all component changes

Source information

Source string comment
(itstool) path: sect1/para
Flags
read-only
Source string location
book.translate.xml:547
String age
a year ago
Source string age
a year ago
Translation file
books/arch-handbook.pot, string 64