From owner-freebsd-doc@FreeBSD.ORG Tue Jan 14 15:19:50 2014 Return-Path: Delivered-To: freebsd-doc@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:1900:2254:206a::19:1]) (using TLSv1 with cipher ADH-AES256-SHA (256/256 bits)) (No client certificate requested) by hub.freebsd.org (Postfix) with ESMTPS id CC3E8168; Tue, 14 Jan 2014 15:19:50 +0000 (UTC) Received: from wonkity.com (wonkity.com [67.158.26.137]) (using TLSv1 with cipher DHE-RSA-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.freebsd.org (Postfix) with ESMTPS id 799161FC3; Tue, 14 Jan 2014 15:19:50 +0000 (UTC) Received: from wonkity.com (localhost [127.0.0.1]) by wonkity.com (8.14.7/8.14.7) with ESMTP id s0EFJmUF097230; Tue, 14 Jan 2014 08:19:48 -0700 (MST) (envelope-from wblock@wonkity.com) Received: from localhost (wblock@localhost) by wonkity.com (8.14.7/8.14.7/Submit) with ESMTP id s0EFJmqE097227; Tue, 14 Jan 2014 08:19:48 -0700 (MST) (envelope-from wblock@wonkity.com) Date: Tue, 14 Jan 2014 08:19:48 -0700 (MST) From: Warren Block To: =?ISO-8859-15?Q?Sergio_Andr=E9s_G=F3mez_del_Real?= Subject: Re: Proposed change to Bootstrapping and Kernel Initialization in FreeBSD Architecture Handbook In-Reply-To: Message-ID: References: User-Agent: Alpine 2.00 (BSF 1167 2008-08-23) MIME-Version: 1.0 Content-ID: X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.4.3 (wonkity.com [127.0.0.1]); Tue, 14 Jan 2014 08:19:49 -0700 (MST) Content-Type: TEXT/PLAIN; CHARSET=ISO-8859-15; format=flowed Content-Transfer-Encoding: 8BIT X-Content-Filtered-By: Mailman/MimeDel 2.1.17 Cc: freebsd-hackers@freebsd.org, freebsd-doc@freebsd.org X-BeenThere: freebsd-doc@freebsd.org X-Mailman-Version: 2.1.17 Precedence: list List-Id: Documentation project List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Tue, 14 Jan 2014 15:19:50 -0000 On Tue, 14 Jan 2014, Sergio Andrés Gómez del Real wrote: > I started studying the FreeBSD boot system and found that the documentation > is limited and, in some cases, not true; for example it doesn't address > appropriately the boot1 stage, stating erroneously that it is limited for > booting with a floppy. > Anyway, I've been working on an up-to-date version, and would like to hear > some feedback. > > I attach the diff file for > doc/en_US.ISO8859-1/books/arch-handbook/boot/chapter.xml. Thank you for working on this. From a doc perspective, it appears that whitespace and content changes have been mixed, which makes the work of translators more difficult. The new XML source is largely unformatted, and should be wrapped at 70 columns. Please see http://www.freebsd.org/doc/en_US.ISO8859-1/books/fdp-primer/book.html#writing-style-tag-style Rather than "FreeBSD", use the &os; entity. I did not look at the content much, but am willing if the first two problems can be fixed. Thanks! From owner-freebsd-doc@FreeBSD.ORG Tue Jan 14 20:50:00 2014 Return-Path: Delivered-To: freebsd-doc@smarthost.ysv.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [8.8.178.115]) (using TLSv1 with cipher ADH-AES256-SHA (256/256 bits)) (No client certificate requested) by hub.freebsd.org (Postfix) with ESMTPS id DF77A8C9 for ; Tue, 14 Jan 2014 20:50:00 +0000 (UTC) Received: from freefall.freebsd.org (freefall.freebsd.org [IPv6:2001:1900:2254:206c::16:87]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mx1.freebsd.org (Postfix) with ESMTPS id B816317A7 for ; Tue, 14 Jan 2014 20:50:00 +0000 (UTC) Received: from freefall.freebsd.org (localhost [127.0.0.1]) by freefall.freebsd.org (8.14.7/8.14.7) with ESMTP id s0EKo07r091114 for ; Tue, 14 Jan 2014 20:50:00 GMT (envelope-from gnats@freefall.freebsd.org) Received: (from gnats@localhost) by freefall.freebsd.org (8.14.7/8.14.7/Submit) id s0EKo0K6091100; Tue, 14 Jan 2014 20:50:00 GMT (envelope-from gnats) Resent-Date: Tue, 14 Jan 2014 20:50:00 GMT Resent-Message-Id: <201401142050.s0EKo0K6091100@freefall.freebsd.org> Resent-From: FreeBSD-gnats-submit@FreeBSD.org (GNATS Filer) Resent-To: freebsd-doc@FreeBSD.org Resent-Reply-To: FreeBSD-gnats-submit@FreeBSD.org, Sergio Andrés Gómez del Real Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:1900:2254:206a::19:1]) (using TLSv1 with cipher ADH-AES256-SHA (256/256 bits)) (No client certificate requested) by hub.freebsd.org (Postfix) with ESMTPS id B3B878C3 for ; Tue, 14 Jan 2014 20:49:47 +0000 (UTC) Received: from oldred.freebsd.org (oldred.freebsd.org [IPv6:2001:1900:2254:206a::50:4]) (using TLSv1 with cipher DHE-RSA-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.freebsd.org (Postfix) with ESMTPS id 9DE0B179F for ; Tue, 14 Jan 2014 20:49:47 +0000 (UTC) Received: from oldred.freebsd.org ([127.0.1.6]) by oldred.freebsd.org (8.14.5/8.14.7) with ESMTP id s0EKnlWc047553 for ; Tue, 14 Jan 2014 20:49:47 GMT (envelope-from nobody@oldred.freebsd.org) Received: (from nobody@localhost) by oldred.freebsd.org (8.14.5/8.14.5/Submit) id s0EKnlra047547; Tue, 14 Jan 2014 20:49:47 GMT (envelope-from nobody) Message-Id: <201401142049.s0EKnlra047547@oldred.freebsd.org> Date: Tue, 14 Jan 2014 20:49:47 GMT From: Sergio Andrés Gómez del Real To: freebsd-gnats-submit@FreeBSD.org X-Send-Pr-Version: www-3.1 Subject: docs/185780: Rewrite of Bootstrapping in FreeBSD Architecture Handbook X-BeenThere: freebsd-doc@freebsd.org X-Mailman-Version: 2.1.17 Precedence: list List-Id: Documentation project List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Tue, 14 Jan 2014 20:50:00 -0000 >Number: 185780 >Category: docs >Synopsis: Rewrite of Bootstrapping in FreeBSD Architecture Handbook >Confidential: no >Severity: non-critical >Priority: low >Responsible: freebsd-doc >State: open >Quarter: >Keywords: >Date-Required: >Class: change-request >Submitter-Id: current-users >Arrival-Date: Tue Jan 14 20:50:00 UTC 2014 >Closed-Date: >Last-Modified: >Originator: Sergio Andrés Gómez del Real >Release: 10.0-RC5 >Organization: >Environment: FreeBSD UIX 10.0-RC5 FreeBSD 10.0-RC5 #0 r260430: Wed Jan 8 05:10:04 UTC 2014 root@snap.freebsd.org:/usr/obj/usr/src/sys/GENERIC amd64 >Description: Documentation of the boot process in the FreeBSD Architecture Handbook is currently both outdated and wrong. I've been working on a more precise and detailed version; it is not yet complete, but here is something to start. >How-To-Repeat: >Fix: Apply patch. Patch attached with submission follows: Index: boot/chapter.xml =================================================================== --- boot/chapter.xml (revision 43469) +++ boot/chapter.xml (working copy) @@ -3,89 +3,123 @@ The FreeBSD Documentation Project Copyright (c) 2002 Sergey Lyubka +Copyright (c) 2014 Sergio Andrés Gómez del Real All rights reserved $FreeBSD$ --> - - Bootstrapping and Kernel Initialization + + + Bootstrapping and Kernel Initialization + - SergeyLyubkaContributed by + SergeyLyubkaContributed by - - + + Sergio AndrésGómez del Real + + + Synopsis - - Synopsis + BIOS + firmware + POST + IA-32 + booting + system initialization - BIOS - firmware - POST - IA-32 - booting - system initialization - This chapter is an overview of the boot and system - initialization process, starting from the BIOS (firmware) POST, - to the first user process creation. Since the initial steps of - system startup are very architecture dependent, the IA-32 - architecture is used as an example. - + The &os;Boot System is not a trivial + software. As soon as we get execution + control from the BIOS, we must handle + a considerable amount of low-level + configuration before the kernel can be loaded + and executed. We must, moreover, do this in + a simple and flexible manner, as to allow the + user a great deal of customization possibilities. + This chapter is an overview of the boot and system + initialization process, starting from the + BIOS (firmware) POST, to the first user process + creation. Since the initial steps of system + startup are very architecture dependent, the + IA-32 architecture is used as an example. + - - Overview + + Overview - A computer running FreeBSD can boot by several methods, - although the most common method, booting from a harddisk where - the OS is installed, will be discussed here. The boot process - is divided into several steps: + The Boot Process is an extremely + machine-dependent activity; not only code + must be written for every computer architecture + case, but there may also be different forms to + boot under the same architecture. For example, + taking a look at the + /usr/sys/src/boot + directory will reveal a great amount of + architecture-dependent code; there is a + directory for each of the various supported + architectures. For instance, we find the + directories + arm, i386, ia64, powerpc, + etc. Moreover, if we enter the directory + specific to the x86 architecture + (that is, i386), we + can see directories belonging to different + boot standards. For example, + mbr, which stands + for Master Boot Record, + gpt, which stands + for GUID Partition Table, or + efi, which stands + for Extensible Firmware Interface. Each + boot standard has got its own conventions + and data structures that conform to that standard. + Here we study in detail the boot process + for the x86 architecture using the MBR boot standard. + The key to understand this process is that + it is divided into a sequence of + stages, each one more + complex than the preceding one. These stages + are named boot1, boot2 + and loader in + &man.boot.8; for the first, second and third + stage respectively. The Boot System executes + each stage in sequence, and the third and + last stage, loader, + is responsible for loading the &os; kernel. + We will look at each stage in the following + sections. Additionally, prior to the first + stage (boot1), an + additional step is necessary in the process. + This step is the Master Boot Record, conveniently + called boot0. + Here is an example of the output + generated by the different boot stages. + Please note that the actual data may + differ from machine to machine: + + + + + Output (may vary) + BIOS (firmware) messages + - - BIOS POST - boot0 stage - boot2 stage - loader stage - kernel initialization - - - BIOS POST - boot0 - boot2 - loader - The boot0 and boot2 - stages are also referred to as bootstrap stages 1 and - 2 in &man.boot.8; as the first steps in FreeBSD's - 3-stage bootstrapping procedure. Various information is printed - on the screen at each stage, so you may visually recognize them - using the table that follows. Please note that the actual data - may differ from machine to machine: - - - - - - Output (may vary) - BIOS (firmware) messages - - - - F1 FreeBSD + + F1 FreeBSD F2 BSD F5 Disk 2 - boot0 - + boot0 + - - >>FreeBSD/i386 BOOT + + >>FreeBSD/i386 BOOT Default: 1:ad(1,a)/boot/loader boot: - boot2This - prompt will appear if the user presses a key just - after selecting an OS to boot at the - boot0 - stage. - + boot2This prompt will appear if the user presses a key just after selecting an OS to boot at the boot0stage. - - BTX loader 1.0 BTX version is 1.01 + + BTX loader 1.0 BTX version is 1.01 BIOS drive A: is disk0 BIOS drive C: is disk1 BIOS 639kB/64512kB available memory @@ -95,41 +129,66 @@ /kernel text=0x1234 data=0x2345 syms=[0x4+0x3456] Hit [Enter] to boot immediately, or any other key for command prompt Booting [kernel] in 9 seconds..._ - loader - + loader + - - Copyright (c) 1992-2002 The FreeBSD Project. + + Copyright (c) 1992-2002 The FreeBSD Project. Copyright (c) 1979, 1980, 1983, 1986, 1988, 1989, 1991, 1992, 1993, 1994 The Regents of the University of California. All rights reserved. FreeBSD 4.6-RC #0: Sat May 4 22:49:02 GMT 2002 devnull@kukas:/usr/obj/usr/src/sys/DEVNULL Timecounter "i8254" frequency 1193182 Hz - kernel - - - - + kernel + + + + + + The rest of this chapter comprises the following sections: + + The BIOS + The Master Boot Record + boot1 stage + The BTX Server + boot2 stage + loader stage + Kernel Initialization + + + BIOS POST + MBR and boot0 + boot1 + The BTX Server + BTX client: boot2 + BTX client: loader + - BIOS POST + The BIOS + When the PC powers on, the processor's registers are set to some predefined values. One of the registers is the instruction pointer register, and its value after a power on is well defined: it is a 32-bit value of - 0xfffffff0. The instruction pointer register points to code to - be executed by the processor. One of the registers is the + 0xfffffff0. The instruction pointer register (also known as the Program Counter) points to code to + be executed by the processor. Another important register is the cr0 32-bit control register, and its value - just after the reboot is 0. One of the cr0's bits, the bit PE + just after the reboot is 0. One of the cr0's bits, the bit PE (Protection Enabled) indicates whether the processor is running - in protected or real mode. Since at boot time this bit is - cleared, the processor boots in real mode. Real mode means, + in 32-bit protected or 16-bit real mode. + Since at boot time this bit is cleared, the processor + boots in 16-bit real mode. Real mode means, among other things, that linear and physical addresses are - identical. + identical. The reason for the processor not to start + immediately in 32-bit protected mode is + backwards compatibility. In particular, the boot process + relies on the services provided by the BIOS, and the + BIOS itself work in legacy, 16-bit code. - The value of 0xfffffff0 is slightly less then 4Gb, so unless + The value of 0xfffffff0 is slightly less then 4Gb, so unless the machine has 4Gb physical memory, it cannot point to a valid memory address. The computer's hardware translates this address so that it points to a BIOS memory block. @@ -139,7 +198,7 @@ has a relatively small amount of read-only memory (ROM). This memory contains various low-level routines that are specific to the hardware supplied with the motherboard. So, the processor - will first jump to the address 0xfffffff0, which really resides + will first jump to the address 0xfffffff0, which really resides in the BIOS's memory. Usually this address contains a jump instruction to the BIOS's POST routines. @@ -154,7 +213,7 @@ The very last thing in the POST is the INT 0x19 instruction. That instruction reads 512 bytes from the first sector of boot device into the memory at address - 0x7c00. The term first sector originates + 0x7c00. The term first sector originates from harddrive architecture, where the magnetic plate is divided to a number of cylindrical tracks. Tracks are numbered, and every track is divided by a number (usually 64) sectors. Track @@ -166,145 +225,997 @@ utilities such as &man.disklabel.8; may store the information in this area, mostly in the second sector.. + This sector is our boot-sequence starting + point; as we will see, this sector is in fact + our boot0 program. A + jump is made by the BIOS to address + 0x7c00 so it starts executing. - <literal>boot0</literal> Stage + The Master Boot Record MBR - Take a look at the file /boot/boot0. - This is a small 512-byte file, and it is exactly what FreeBSD's - installation procedure wrote to your harddisk's MBR if you chose - the bootmanager option at installation - time. +After control is received from the BIOS at memory + address 0x7c00, boot0 + starts executing; it is the first piece of code under our + control. In essence, the task of boot0 + 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 + MBR (hence embedded in boot0) describing + the 4 standard PC partitions + + en.wikipedia.org/wiki/Master_boot_record. + boot0 resides in the filesystem at + location /boot/boot0. + It is a small 512-byte file, and it is exactly what + &os;'s installation procedure wrote to your + harddisk's MBR if you chose the bootmanager + option at installation time; indeed, + boot0 is the MBR. - As mentioned previously, the INT 0x19 - instruction loads an MBR, i.e., the boot0 - content, into the memory at address 0x7c00. Taking a look at - the file sys/boot/i386/boot0/boot0.S can - give a guess at what is happening there - this is the boot - manager, which is an awesome piece of code written by Robert - Nordier. +As mentioned previously, the INT 0x19 + instruction loads an MBR, i.e., the boot0 + content, into the memory at address 0x7c00. + The source file for boot0 can be found + in sys/boot/i386/boot0/boot0.S - which + is an awesome piece of code written by Robert Nordier. - The MBR, or, boot0, has a special - structure starting from offset 0x1be, called the - partition table. It has 4 records of 16 - bytes each, called partition records, which - represent how the harddisk(s) are 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 boot0's code - will refuse to proceed. - A partition record has the following fields: +As pointed out earlier, the MBR, or + boot0, has a special + structure starting from offset 0x1be, + called the partition table. + It has 4 records of 16 bytes each, called + partition records, which + represent how the harddisk(s) are partitioned, or, in &os;'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 boot0's code + will refuse to proceed. - - - the 1-byte filesystem type - +A partition record has the following fields: + + + the 1-byte filesystem type + - - the 1-byte bootable flag - + + the 1-byte bootable flag + - - the 6 byte descriptor in CHS format - + + the 6 byte descriptor in CHS format + - - the 8 byte descriptor in LBA format - - + + the 8 byte descriptor in LBA format + + - A partition record descriptor has the information about - where exactly the partition resides on the drive. Both - descriptors, LBA and CHS, describe the same information, but in - different ways: LBA (Logical Block Addressing) has the starting - sector for the partition and the partition's length, while CHS - (Cylinder Head Sector) has coordinates for the first and last - sectors of the partition. +A partition record descriptor has the information about + where exactly the partition resides on the drive. Both + descriptors, LBA and CHS, describe the same information, but in + different ways: LBA (Logical Block Addressing) has the starting + sector for the partition and the partition's length, while CHS + (Cylinder Head Sector) has coordinates for the first and last + sectors of the partition. The partition table ends with the special signature 0xaa55. - The boot manager scans the partition table and prints the - menu on the screen so the user can select what disk and what - slice to boot. By pressing an appropriate key, - boot0 performs the following - actions: +It is important to note that, because of + the size contraint of the MBR (it must fit + in 512 bytes, that is, in 1 disk sector), + and because care must be taken when handling + the Partition Table (which is embedded in + the MBR itself), this program make use + of little low-level 'tricks', like + ...using side effects + of certain instructions, reusing register + values from previous operations, etc., + so as to make the most out of the least + possible instructions. For this reason, + extreme care must be taken when modifying + boot0.S. +Also, note that the boot0.S source + file is assembled "as is"; instructions are translated one + by one to binary, with no additional information + (no ELF 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 + 0x600. In practice this means that + boot0 must be loaded to memory address + 0x600 in order to function properly. +It is also worth looking at the Makefile for + boot0 + (sys/boot/i386/boot0/Makefile), + as it defines some of its behaviour. For instance, + if a terminal connected to the serial port (COM 1) + is used for I/O, the macro SIO + must be defined (-DSIO). + Other options include enabling boot through + PXE pressing F6 (-DPXE). + Additionally, the program defines a set of + flags that allow to further + modify its behavior. All this is illustrated in + the Makefile. Let us, for + example, look at the linker directives which + command the linker to start the text section + at address 0x600, and to + build the output file "as is" + (strip out any file formatting): + +sys/boot/i386/boot0/Makefile: + BOOT_BOOT0_ORG?=0x600 + LDFLAGS=-e start -Ttext ${BOOT_BOOT0_ORG} \ + -Wl,-N,-S,--oformat,binary + + +Let us now start our study of the MBR, or + boot0, program, starting where + execution begins: + + Please note that subtle modifications were + made to some instructions + in favor of better exposition. This applies to + all our code examples.: +sys/boot/i386/boot0/boot0.S: +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 + +This first block of code is the entry point of + the program; it is where the BIOS transfers control. + First, it makes sure that the string operations + autoincrement its pointer operands + (the cld instruction) + + When in doubt, we remit the reader + to the official Intel Manuals, which describe + the exact semantics for each + instruction: + http://www.intel.com/content/www/us/en/processors/architectures-software-developer-manuals.html.. + Then, it makes no assumption about the state of the + segment registers, so it initializes them. Finally, + it sets the stack pointer register (%sp) + to address 0x7c00, so we have a + working stack. + +The next block is responsible for the relocation + and subsequent jump to the relocated code: +sys/boot/i386/boot0/boot0.S: + 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-LOAD+ORIGIN # Jump to relocated code + +Because boot0 is loaded by + the BIOS to address 0x7C00, it copies + itself to address 0x600 and then + transfers control there (recall that it was linked to + execute at address 0x600). The source address, + 0x7c00, is copied to register %si; + the destination address, 0x600, to + register %di. The number of bytes to copy, + 512 (the program's size), is copied to + register %cx. Next, the rep instruction repeats the + instruction that follows, that is, movsb, the number of + times dictaded by the %cx register. The movsb instruction + copies the byte pointed to by %si to the address pointed + to by %di. This is repeated another 511 times; on each + repetition, both the source and destination registers, + %si and %di, are incremented by one. Thus, upon + completion of the 512-byte copy, %di has the value + 0x600+512= + 0x800, and %si has the value + 0x7c00+512= + 0x7e00; we have thus completed the + code relocation. Next, the + destination register %di is now copied to %bp; %bp + gets the value 0x800. The value + 16 is now copied to %cl in + preparation for a new string operation + (like our previous movsb). Now, stosb is executed 16 + times. This instruction copies a 0 + value to the address pointed to by the destination + register (%di, which is 0x800), + and increments it. This is repeated another 15 times, + so %di ends up with value + 0x810. Effectively, this clears + the address range + 0x800-0x80f; + this range is used as a (fake) partition table for + writing back the MBR to disk. Finally, the sector + field for the CHS addressing of this fake partition + is set, 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 simply tests if the drive + number provided by the BIOS should be used, or else + the one saved by boot0: +sys/boot/i386/boot0/boot0.S: +main: + testb $SETDRV,-69(%bp) # Set drive number? + jnz disable_update # Yes + testb %dl,%dl # Drive number valid? + js save_curdrive # Possibly (0x80 set) + +This code tests the SETDRV bit in the + flags variable. Recall that register + %bp points to address location 0x800, + so the test is done to the flags + variable at address 0x800- + 69=0x7bb. + This is an example of the type of modifications that + can be done to boot0. The SETDRV + flag is not set by default, but it + can be set in the Makefile; when set, + the drive number stored in the MBR + is used instead of the one provided by the BIOS. We assume + the defaults, and that the BIOS provided a valid drive + number, so we jump to save_curdrive. + +The next block saves the + drive number provided by the BIOS, + and calls putn to print a new line + on the screen: +sys/boot/i386/boot0/boot0.S: +save_curdrive: movb %dl, (%bp) # Save drive number + pushw %dx # Also in the stack +#ifdef TEST /* test code, print internal bios drive */ + rolb $1, %dl + movw $drive, %si + call putkey +#endif +callw putn # Print a newline + +Note that we assume TEST is not defined, so the + conditional code in it is not assembled and won't + appear in our executable boot0. +Our next block implements the actual scanning of + the partition table. It prints to the screen the + partition type for each of the 4 entries in the partition + table; it compares each type with a list of well-known + operating system file systems. Examples of recognized + partition types are NTFS (Windows; ID 0x7), ext2fs + (Linux; ID 0x83) and, of course, ffs/ufs2 + (&os;; ID 0xa5). The implementation is fairly simple: + + + movw $(partbl+0x4),%bx # Partition table (+4) + xorw %dx,%dx # Item number + +read_entry: movb %ch,-0x4(%bx) # Zero active flag (ch == 0) + btw %dx,_FLAGS(%bp) # Entry enabled? + jnc next_entry # No + movb (%bx),%al # Load type + test %al, %al # skip empty partition + jz next_entry + movw $bootable_ids,%di # Lookup tables + movb $(TLEN+1),%cl # Number of entries + repne # Locate + scasb # type + addw $(TLEN-1), %di # Adjust + movb (%di),%cl # Partition + addw %cx,%di # description + callw putx # Display it + +next_entry: incw %dx # Next item + addb $0x10,%bl # Next entry + jnc read_entry # Till done + +It is important to note that the active flag for + each entry is cleared, so after the scanning, + no partition entry is active + in our memory copy of boot0. + Later, the active flag will be set for the selected + partition. This ensures that only 1 active partition + exists if the user chooses to write-back the changes to disk. + Our next block tests for other drives present. + At startup, the BIOS writes the number of drives present + in the computer to address 0x475. + If there is any other drive present, + boot0 prints the current drive to + screen; the user may command boot0 + to scan partitions on another drive later: + + popw %ax # Drive number + subb $0x80-0x1,%al # Does next + cmpb NHRDRV,%al # drive exist? (from BIOS?) + jb print_drive # Yes + decw %ax # Already drive 0? + jz print_prompt # Yes + +We make the assumption that a single drive is + present, so the jump to print_drive + is not performed. We also assume nothing strange + happened, so we jump to print_prompt. +This next block just prints out a prompt followed + by the default option: + +print_prompt: movw $prompt,%si # Display + callw putstr # prompt + movb _OPT(%bp),%dl # Display + decw %si # default + callw putkey # key + jmp start_input # Skip beep + +Finally, a jump is perfored to + start_input, where the BIOS services are + used to start a timer and for reading user input from + the keyboard; if the timer expires, the default option + will be selected: + +start_input: + xorb %ah,%ah # BIOS: Get + int $0x1a # system time + movw %dx,%di # Ticks when + addw _TICKS(%bp),%di # timeout +read_key: + movb $0x1,%ah # BIOS: Check + int $0x16 # for keypress + jnz got_key # Have input + xorb %ah,%ah # BIOS: int 0x1a, 00 + int $0x1a # get system time + cmpw %di,%dx # Timeout? + jb read_key # No + +Note that an interrupt is requested with number + 0x1a, and argument 0 + in register %ah. The BIOS has a predefined + list of interrupt services, requested through the + int instruction and receiving arguments + in registers (in this case, %ah). + Here, particularly, we are requesting the number of clock + 'ticks' since last midnight; this value is computed by + the BIOS through the Real Time Clock. + This clock can be programmed to work at frequencies + ranging from 2hz to + 8192hz; the BIOS sets it to + 18.2hz at startup. The 32-bit result is + returned by the BIOS in registers %cx + and %dx (lower bytes in + %dx). This result (the + %dx part) is copied to register + %di, and the value of the TICKS + variable is added to + %di. This variable is placed + in boot0 + at offset _TICKS (a negative value) + from register %bp (which, recall, points + to 0x800). The default value of this variable is + 0xb6 (182 in decimal). The idea is that + boot0 constantly requests the time to + the BIOS, and when the value returned in register + %dx is greater than the value stored + in %di, the time is up and the + default selection would be made. Since the Real Time Clock + ticks 18.2 times per second, this + condition will be met after 10 seconds (this default + behaviour can be changed in the + Makefile. While this time has not + passed, boot0 continually asks the + BIOS for any user input; this is done through + int 0x16, argument 1 + in %ah. Whether a key was pressed, or + the time expired, subsequent code validates the selection, + the register %si is set to point to + the appropiate partition entry in the partition table, + according to the selection, and that selection overrides + the previous default one; indeed, it becomes the + new default. Finally, the ACTIVE + flag of the selected partition is set. If enabled at + compile time, boot0 with these + modified values, are written back to the MBR + on disk. We leave the details of this implementation + to the reader. +We now end our study with the last code + block from the boot0 program: + + movw $0x7c00,%bx # Address for read + movb $0x2,%ah # Read sector + callw intx13 # from disk + jc beep # If error + cmpw $0xaa55,0x1fe(%bx) # Bootable? + jne beep # No + pushw %si # Save ptr to selected part. + callw putn # Leave some space + popw %si # Restore, next stage uses it + jmp *%bx # Invoke bootstrap + +Recall that %si points to the + appropiate partition entry. This entry tells us where + the partition begins on disk; we assume, of course, + that the partition selected is a &os; partition. + The transfer buffer is set to 0x7c00 + (register %bx), and a read for + the first sector of the &os; partition is requested + by calling intx13. We assume that + everything went OK, so a jump to + beep is not + performed. In particular, the new sector read must end + with the magic sequence + 0xaa55. Finally, the value at + %si + (the pointer to the selected partition table) is + preserved for use by the next stage, and a jump is + performed to address 0x7c00, where + execution of our next stage (the just-read block) is started. + + + <literal>boot1</literal> Stage + + So far we have gone through the following sequence: - modifies the bootable flag for the selected partition to - make it bootable, and clears the previous + The BIOS did some early hardware initialization, including the POST. The MBR (boot0) was loaded from absolute disk sector 1 to address 0x7c00. Execution control was passed to that location. - saves itself to disk to remember what partition (slice) - has been selected so to use it as the default on the next - boot + boot0 relocated itself to the location it was linked to execute (0x600), followed by a jump to continue execution at the appropiate place. Finally, boot0 loaded the first disk sector from the &os; partition (slice) to address 0x7c00. Execution control was passed to that location. - - - loads the first sector of the selected partition (slice) - into memory and jumps there - - What kind of data should reside on the very first sector of - a bootable partition (slice), in our case, a FreeBSD slice? As - you may have already guessed, it is - boot2. - + boot1 is the next step in our + boot-loading sequence; it is the first of three boot + stages. It is important to note that we have been + dealing exclusively with disk + sectors. Indeed, the BIOS loads the absolute first sector, + while boot0 loads the first sector + of the &os; slice; both loads are to address + 0x7c00. We can conceptually think of + these disk sectors as files containing + boot0 and boot1, + respectively, but in reality this is not entirely true + for boot1. Strictly speaking, there + is no file boot1 + + There is a file /boot/boot1, + but it is not the file read at boot time; it is + concatanated with boot2 to + form boot.; + instead, a single, full-blown file, boot, + is what you will find in the file system + (boot/boot). This file is a + composition of boot1, + boot2 and the + Boot Extender (or BTX). + This big file is greater in size than a single + sector (greater than 512 bytes). Fortunately, + boot1 occupies + exactly the first 512 bytes of this + single file, so, indeed, when boot0 + loads the first sector of the &os; slice (512 bytes), + it is actually loading boot1 and + transferring control to it. + The main task of boot1 is + to load the next boot stage. This next stage is + somewhat more complex; it is composed of + the server, called the + Boot Extender, or + BTX, and a client, + called boot2. We say + a client because, as we will see, + the last boot stage is loader, which + is also a client of the BTX server. - - <literal>boot2</literal> Stage + Let us now look in detail what exactly is done + by boot1, starting like we did + for boot0, at its entry point: + sys/boot/i386/boot2/boot1.S: +start: + jmp main - You might wonder, why boot2 comes after - boot0, and not boot1. Actually, there is a - 512-byte file called boot1 in the directory - /boot as well. It is used for booting from - a floppy. When booting from a floppy, - boot1 plays the same role as - boot0 for a harddisk: it locates - boot2 and runs it. +The entry point at start simply jumps + past a special data area to the label + main, which in turn looks like this: +sys/boot/i386/boot2/boot1.S: +main: cld # String ops inc + xor %cx,%cx # Zero + mov %cx,%es # Address + mov %cx,%ds # data + mov %cx,%ss # Set up + mov $start,%sp # stack + mov %sp,%si # Source + mov $0x700,%di # Destination + incb %ch # Word count + rep # Copy + movsw # code - You may have realized that a file - /boot/mbr exists as well. It is a - simplified version of boot0. The code in - mbr does not provide a menu for the user, - it just blindly boots the partition marked active. +Note that, just like boot0, the + above code relocates + boot1, this time to memory address + 0x700. However, unlike + boot0, it does not jump over + there. In fact, boot1 is linked to execute + at address 0x7c00, effectively where + it was loaded in the first place. The reason for this + relocation will be discussed shortly. - The code implementing boot2 resides in - sys/boot/i386/boot2/, and the executable - itself is in /boot. The files - boot0 and boot2 that - are in /boot are not used by the bootstrap, - but by utilities such as boot0cfg. - The actual position for boot0 is in the - MBR. For boot2 it is the beginning of a - bootable FreeBSD slice. These locations are not under the - filesystem's control, so they are invisible to commands like - ls. +Next comes a loop that looks for the &os; partition. + Note that, although boot0 in fact + loaded boot1 from the &os; partition, + no information was passed to it about this partition + + Actually we did pass a pointer to the partition + entry in register %si. However, boot1 + does not assume that it was loaded + by boot0 (perhaps other MBR loaded + it that did not pass this information), so it assumes + nothing.; + boot1 effectively needs to rescan the + partition table to find where the &os; partition starts. + Therefore, it rereads the MBR: +sys/boot/i386/boot2/boot1.S: + mov $part4,%si # Partition + cmpb $0x80,%dl # Hard drive? + jb main.4 # No + movb $0x1,%dh # Block count + callw nread # Read MBR - The main task for boot2 is to load the - file /boot/loader, which is the third stage - in the bootstrapping procedure. The code in - boot2 cannot use any services like - open() and read(), - since the kernel is not yet loaded. It must scan the harddisk, - knowing about the filesystem structure, find the file - /boot/loader, read it into memory using a - BIOS service, and then pass the execution to the loader's entry - point. +Note that in the code above, register + %dl maintains information about the + boot device; this is passed on by the BIOS and preserved + by the MBR. Numbers 0x80 and greater + tells us that we are dealing with a hard drive, so a call + is made to nread, where the MBR is + read. Arguments to nread are passed through + %si and %dh. + The memory address at label part4 is + copied to %si. This memory address + holds a 'fake partition', to be used by + nread. The following is the data found + in this fake partition: - Besides that, boot2 prompts for user - input so the loader can be booted from different disk, unit, - slice and partition. +sys/boot/i386/boot2/boot1.S: +part4: .byte 0x80, 0x00, 0x01, 0x00 + .byte 0xa5, 0xfe, 0xff, 0xff + .byte 0x00, 0x00, 0x00, 0x00 + .byte 0x50, 0xc3, 0x00, 0x00 - The boot2 binary is created in special - way: +In particular, the LBA for this fake partition is + hardcoded to 0; this effectively is used as an argument + to the BIOS for reading absolute sector 1 from the hard + drive. Let us now proceed to take a look at + nread: +sys/boot/i386/boot2/boot1.S: +nread: mov $0x8c00,%bx # Transfer buffer + mov 0x8(%si),%ax # Get + mov 0xa(%si),%cx # LBA + push %cs # Read from + callw xread.1 # disk + jnc return # If success, return - sys/boot/i386/boot2/Makefile: +Recall that %si points to the fake + partition. The word + + In the context of 16-bit real mode, a word is 2 + bytes. + at offset 0x8 is copied to register + %ax and word at offset + 0xa to %cx; they + are interpreted by the BIOS as a the lower 4-byte value + denoting the LBA to be read (the upper 4 bytes are assumed 0). + Register %bx holds the memory address + where the MBR will be loaded. The instruction pushing + %cs onto the stack is very + interesting. In this context, it accomplishes + nothing, but, as we will + see shortly, xread.1 makes no assumption + about the context in which it is + invoked. Particularly, boot2 'traps' there; + xread.1 then executes in VM86 + (Virtual Real Mode). But, because boot2 + executes in 32-bit protected mode, a long return is executed + when xread.1 finishes execution. + This instruction pops out from the stack the code + segment (register %cs) to + return. This mechanism will become more clear + later. Now, the code at xread.1 further calls + the read function, which actually calls + the BIOS asking for the disk sector: +sys/boot/i386/boot2/boot1.S: +xread.1: # Starting + pushl $0x0 # absolute + push %cx # block + push %ax # number + push %es # Address of + push %bx # transfer buffer + xor %ax,%ax # Number of + movb %dh,%al # blocks to + push %ax # transfer + push $0x10 # Size of packet + mov %sp,%bp # Packet pointer + callw read # Read from disk + lea 0x10(%bp),%sp # Clear stack + lret # To far caller + +Note the long return instruction + at the end of this block. This instruction pops out the + %cs register pushed by + nread, and returns. Finally, + nread also + returns. Now, with the MBR loaded to memory, the actual loop for + searching the &os; partition begins. The implementation + is as follows: +sys/boot/i386/boot2/boot1.S: + mov $0x1,%cx # Two passes +main.1: mov $MEM_BUF+PRT_OFF,%si # Partition table + movb $0x1,%dh # Partition +main.2: cmpb $PRT_BSD,0x4(%si) # Our partition type? + jne main.3 # No + jcxz main.5 # If second pass + testb $0x80,(%si) # Active? + jnz main.5 # Yes +main.3: add $0x10,%si # Next entry + incb %dh # Partition + cmpb $0x1+PRT_NUM,%dh # In table? + jb main.2 # Yes + dec %cx # Do two + jcxz main.1 # passes + +This code, which follows the call to + nread, implements the scan in the + partition table looking for the &os; + partition. If a &os; partition is successfully identified, + execution continues at main.5; + we assume this behaviour, so we continue execution + there: +sys/boot/i386/boot2/boot1.S: +main.5: mov %dx,MEM_ARG # Save args + movb $0x10,%dh # Sector count + callw nread # Read disk + mov $MEM_BTX,%bx # BTX + mov 0xa(%bx),%si # Get BTX length and set + add %bx,%si # %si to start of boot2.bin + mov $MEM_USR+SIZ_PAG*2,%di # Client page 2 + mov $MEM_BTX+(NSECT-1)*SIZ_SEC,%cx # Byte + sub %si,%cx # count + rep # Relocate + movsb # client + +Recall that at this point, register + %si points to the &os; partition entry + in the MBR partition table, so a call to + nread will effectively read sectors at + the beginning of this partition. The argument passed on + register %dh tells nread + to read 16 disk sectors. Recall that the first 512 bytes, + (the first sector of the &os; partition), coincides with + the boot1 program. Also recall that the + file written to the beginning of the &os; partition is + not /boot/boot1, but + /boot/boot. Let's take a look at the + size of these files in the filesystem: +sys/boot/i386/boot2/boot1.S: +-r--r--r-- 1 root wheel 512B Jan 8 00:15 /boot/boot0 +-r--r--r-- 1 root wheel 512B Jan 8 00:15 /boot/boot1 +-r--r--r-- 1 root wheel 7.5K Jan 8 00:15 /boot/boot2 +-r--r--r-- 1 root wheel 8.0K Jan 8 00:15 /boot/boot + +As you can see from this output, both + boot0 and boot1 are + 512 bytes each, so they fit exactly + in 1 disk sector. Note that boot2 is + much bigger; boot2 holds the BTX program + and the boot2 client. Finally, a file + called simply boot is 512 bytes larger + than boot2; it is a concatenation + of boot1 and + boot2. As already noted, + boot0 is the file + written to the absolute first disk sector (the MBR), and + boot is the file written to the first + sector of the &os; partition; boot1 + and boot2 are not + written to disk. Following is the command used to + concatenate boot1 and + boot2 into a single file + boot: +sys/boot/i386/boot2/boot1.S: +cat boot1 boot2 > boot + +So, effectively, boot1 + occupies exactly the first 512 of + the boot file and, because + boot is written to the first sector + of the &os; partition, boot1 + fits exactly in this first + sector. Now, returning to our execution, because + nread reads the first 16 sectors of + the &os; partition, it effectively is reading the + entire boot file. + + 512*16=8192 bytes, exactly the size of + boot + We will see more details about how boot + is formed from boot1 and + boot2 in the next section. + +Recall that nread uses memory address + 0x8c00 as the transfer buffer to hold + the sectors read. This address is conveniently + chosen. Indeed, because boot1 belongs to the + first 512 bytes, it is stored at address range + 0x8c00- + 0x8dff. The 512 bytes that + follows (range 0x8e00 + -0x8fff) is used to store the + disklabel + + If you ever wondered where &os; stored this + information, it is in this region. + Starting at address 0x9000 is the beginning + of the BTX server, and immediately + following the BTX is the + boot2 client. As we will see, + the BTX server acts as a kernel, and + executes in protected mode in the most privileged + level. In contrast, the BTX clients (boot2, + for example), execute in user mode; we will see how this + is accomplished in the next section. The code after the + call to nread locates the beginning of + boot2 in the memory buffer, and copies + it to memory address 0xc000. This is + because the BTX arranges boot2 to execute + in a segment starting at + 0xa000. We explore this in detail + in the following section. + +The last code block of boot1 enables + access to memory above 1MB + + This is necessary for legacy reasons; the interested + reader is remitted to + http://en.wikipedia.org/wiki/A20_line. + and concludes with a jump to the starting point of the + BTX server: +sys/boot/i386/boot2/boot1.S: +seta20: cli # Disable interrupts +seta20.1: dec %cx # Timeout? + jz seta20.3 # Yes + inb $0x64,%al # Get status + testb $0x2,%al # Busy? + jnz seta20.1 # Yes + movb $0xd1,%al # Command: Write + outb %al,$0x64 # output port +seta20.2: inb $0x64,%al # Get status + testb $0x2,%al # Busy? + jnz seta20.2 # Yes + movb $0xdf,%al # Enable + outb %al,$0x60 # A20 +seta20.3: sti # Enable interrupts + + jmp start+MEM_JMP-MEM_ORG# Start BTX + +Note that right before the jump, interrupts are enabled. + + + The BTX Server + Next in our boot sequence is the + BTX Server. Let's quickly remember how we got here: + + + BIOS loads the absolute sector 1 (the MBR, or boot0), to address 0x7c00 and jumps over there. + + + + boot0 relocates to 0x600, the address it was linked to execute, and jumps over there. It then reads the first sector of the &os; partition (which consists of boot1) into address 0x7c00 and jumps over there. + + + + boot1 loads the first 16 + sectors of the &os; partition into address + 0x8c00. This 16 sectors, or + 8192 bytes, consists + exactly of the + boot file. The + boot file consists of a + concatenation of boot1 and + boot2 and, + boot2, in turn, contains the + BTX server and the + boot2 client. Finally, a jump is + made to address 0x9010, the entry + point of the BTX server. + + + Let us further review how the single, all-in-one + boot file is + created. The commands stated in the + Makefile + are quite long, so let's go step by step. The + way boot is built is defined in + its Makefile + (/usr/src/sys/boot/i386/boot2/Makefile). Let's look at the rule that creates the + boot file: + sys/boot/i386/boot2/Makefile: +boot: boot1 boot2 + cat boot1 boot2 > boot + +This tells us that boot1 and + boot2 are needed, and the rule + simply concatenates them to produce a single file + called boot. The rules for + creating boot1 are also quite + simple: +sys/boot/i386/boot2/Makefile: +boot1: boot1.out + objcopy -S -O binary boot1.out ${.TARGET} + +boot1.out: boot1.o + ld -e start -Ttext 0x7c00 -o boot1.out boot1.o + +In order to apply the rule for creating + boot1, boot1.out + must be resolved. This, in turn, depends on the existence + of boot1.o. This last file is simply + the result of assembling our familiar + boot1.S, without linking. Now, the rule + for creating boot1.out is applied. + This tells us that boot1.o should be + linked with start as its entry point, + and starting at address 0x7c00. + Finally, boot1 is created from + boot1.out applying the appropiate rule. + This rule is the objcopy command applied + to boot1.out. Note the flags passed + to objcopy: -S tells it to strip all + relocation and symbolic information; -O binary indicates the + output format, that is, a simple, unformatted binary file. + We now have boot1. Let's take a look + at how boot2 is constructed: +sys/boot/i386/boot2/Makefile: +boot2: boot2.ld + @set -- `ls -l boot2.ld`; x=$$((7680-$$5)); \ + echo "$$x bytes available"; test $$x -ge 0 + dd if=boot2.ld of=${.TARGET} obs=7680 conv=osync + boot2.ld: boot2.ldr boot2.bin ${BTXKERN} btxld -v -E ${ORG2} -f bin -b ${BTXKERN} -l boot2.ldr \ + -o ${.TARGET} -P 1 boot2.bin + +boot2.ldr: + dd if=/dev/zero of=${.TARGET} bs=512 count=1 + +boot2.bin: boot2.out + objcopy -S -O binary boot2.out ${.TARGET} + +boot2.out: ${BTXDIR}/lib/crt0.o boot2.o sio.o + ld -Ttext 0x2000 -o boot2.out + +boot2.o: boot2.s + ${CC} ${ACFLAGS} -c boot2.s + +SRCS= boot2.c boot2.h + +boot2.s: boot2.c boot2.h ${.CURDIR}/../../common/ufsread.c + ${CC} ${CFLAGS} -S -o boot2.s.tmp ${.CURDIR}/boot2.c + sed -e '/align/d' -e '/nop/d' "MISSING" boot2.s.tmp > boot2.s + rm -f boot2.s.tmp + +boot2.h: boot1.out + ${NM} -t d ${.ALLSRC} | awk '/([0-9])+ T xread/ \ + { x = $$1 - ORG1; \ + printf("#define XREADORG %#x\n", REL1 + x) }' \ + ORG1=`printf "%d" ${ORG1}` \ + REL1=`printf "%d" ${REL1}` > ${.TARGET} + +The mechanism for building boot2 is + far more elaborated. Let's point out the most relevant facts. + The dependency list is as follows: +sys/boot/i386/boot2/Makefile: +boot2: boot2.ld +boot2.ld: boot2.ldr boot2.bin ${BTXDIR}/btx/btx +boot2.bin: boot2.out +boot2.out: ${BTXDIR}/lib/crt0.o boot2.o sio.o +boot2.o: boot2.s +boot2.s: boot2.c boot2.h ${.CURDIR}/../../common/ufsread.c +boot2.h: boot1.out + +Note that initially there is no header + boot2.h file; its creation depends + on boot1.out, which we already have. + The rule for its creation is a bit terse, but the important + thing is that the output, boot2.h, is + something like this: +sys/boot/i386/boot2/boot2.h: +#define XREADORG 0x725 + +Recall that boot1 was relocated + (i.e copied from 0x7c00 to + 0x700). Now this relocation will make + sense, because as we will see, the + BTX server reclaims some memory, including + where boot1 was originally loaded. + However, it needs access to boot1's + xread function; this function, according + to the output of boot2.h, is at + location 0x725. Indeed, the + BTX server uses the + xread function from the relocated + boot1's code. This function is now + accesible from within the boot2 + client. + +Having boot2.h, we next build + boot2.s from + boot2.h, boot2.c + and /usr/src/sys/boot/common/ufsread.c. + The rule for this is to compile the code in + boot2.c into assembly + code. The next rule assembles boot2.s + creating the object file boot2.o. + After this, the following rule directs the linker to + link various files (crt0.o, + boot2.o and sio.o). + Note that the output file, boot2.out, + is linked to execute at address + 0x2000. Recall that + boot2 will be executed in + user mode, within a special user segment set up by the + BTX server. This segment starts at + 0xa000. Also, remember that the + boot2 portion of + boot was copied by + boot1 into address + 0xc000, that is, offset + 0x2000 from the start of the user segment, + so boot2 will work properly when we + transfer control to it. Next, boot2.bin + is created from boot2.out by stripping + its symbols and format information; boot2.bin is a + raw. Now, note that a file + boot2.ldr is created as a 512-byte file + full. + + <literal>boot2</literal> Stage + + The code implementing boot2 resides in + sys/boot/i386/boot2/, and the executable + itself is in /boot. The files + boot0 and boot2 that + are in /boot are not used by the bootstrap, + but by utilities such as boot0cfg. + The actual position for boot0 is in the + MBR. For boot2 it is the beginning of a + bootable &os; slice. These locations are not under the + filesystem's control, so they are invisible to commands like + ls. + + The main task for boot2 is to load the + file /boot/loader, which is the third stage + in the bootstrapping procedure. The code in + boot2 cannot use any services like + open() and read(), + since the kernel is not yet loaded. It must scan the harddisk, + knowing about the filesystem structure, find the file + /boot/loader, read it into memory using a + BIOS service, and then pass the execution to the loader's entry + point. + + Besides that, boot2 prompts for user + input so the loader can be booted from different disk, unit, + slice and partition. + + The boot2 binary is created in special + way: + + sys/boot/i386/boot2/Makefile: +boot2.ld: boot2.ldr boot2.bin ${BTXKERN} + btxld -v -E ${ORG2} -f bin -b ${BTXKERN} -l boot2.ldr \ -o ${.TARGET} -P 1 boot2.bin BTX @@ -440,7 +1351,7 @@ nbyte) are used to read the content of a file into memory. /boot/loader is an ELF binary, but where the ELF header is prepended with a.out's struct - exec structure. load() scans the + exec structure. load() scans the loader's ELF header, loading the content of /boot/loader into memory, and passing the execution to the loader's entry: @@ -449,10 +1360,13 @@ __exec((caddr_t)addr, RB_BOOTINFO | (opts & RBX_MASK), MAKEBOOTDEV(dev_maj[dsk.type], 0, dsk.slice, dsk.unit, dsk.part), 0, 0, 0, VTOP(&bootinfo)); + + + - <application>loader</application> Stage + <literal>loader</literal> Stage loader is a BTX client as well. I will not describe it here in detail, there is a comprehensive @@ -703,7 +1617,7 @@ virtual address for this example would just be the value of EIP. Segment registers such as CS, DS etc are the selectors, i.e., indexes, into GDT (to be more precise, an index is not a - selector itself, but the INDEX field of a selector). FreeBSD's + selector itself, but the INDEX field of a selector). &os;'s GDT holds descriptors for 15 selectors per CPU: sys/i386/i386/machdep.c: @@ -911,7 +1825,7 @@ structure, and that is what the second __asm is. The third __asm instruction marks the end of a - section. If a directive with the same section name occurred + section. If a directive with the same section name occurred before, the content, i.e., the 32-bit value, will be appended to the existing section, so forming an array of 32-bit pointers. Index: driverbasics/chapter.xml =================================================================== --- driverbasics/chapter.xml (revision 43469) +++ driverbasics/chapter.xml (working copy) @@ -13,7 +13,6 @@ JörgWunschBased on intro(4) manual page by - Introduction >Release-Note: >Audit-Trail: >Unformatted: