Source string Read only

(itstool) path: sect1/indexterm
35/350
Context English State
This tells us that <filename>boot1</filename> and <filename>boot2</filename> are needed, and the rule simply concatenates them to produce a single file called <filename>boot</filename>. The rules for creating <filename>boot1</filename> are also quite simple:
boot1: boot1.out
objcopy -S -O binary boot1.out boot1

boot1.out: boot1.o
ld -e start -Ttext 0x7c00 -o boot1.out boot1.o
To apply the rule for creating <filename>boot1</filename>, <filename>boot1.out</filename> must be resolved. This, in turn, depends on the existence of <filename>boot1.o</filename>. This last file is simply the result of assembling our familiar <filename>boot1.S</filename>, without linking. Now, the rule for creating <filename>boot1.out</filename> is applied. This tells us that <filename>boot1.o</filename> should be linked with <literal>start</literal> as its entry point, and starting at address <literal>0x7c00</literal>. Finally, <filename>boot1</filename> is created from <filename>boot1.out</filename> applying the appropriate rule. This rule is the <filename>objcopy</filename> command applied to <filename>boot1.out</filename>. Note the flags passed to <filename>objcopy</filename>: <literal>-S</literal> tells it to strip all relocation and symbolic information; <literal>-O binary</literal> indicates the output format, that is, a simple, unformatted binary file.
Having <filename>boot1</filename>, let us take a look at how <filename>boot2</filename> is constructed:
boot2: boot2.ld
@set -- `ls -l boot2.ld`; x=$$((7680-$$5)); \
echo "$$x bytes available"; test $$x -ge 0
dd if=boot2.ld of=boot2 obs=7680 conv=osync

boot2.ld: boot2.ldr boot2.bin ../btx/btx/btx
btxld -v -E 0x2000 -f bin -b ../btx/btx/btx -l boot2.ldr \
-o boot2.ld -P 1 boot2.bin

boot2.ldr:
dd if=/dev/zero of=boot2.ldr bs=512 count=1

boot2.bin: boot2.out
objcopy -S -O binary boot2.out boot2.bin

boot2.out: ../btx/lib/crt0.o boot2.o sio.o
ld -Ttext 0x2000 -o boot2.out

boot2.o: boot2.s
${CC} ${ACFLAGS} -c boot2.s

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 &gt; 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}` &gt; ${.TARGET}
The mechanism for building <filename>boot2</filename> is far more elaborate. Let us point out the most relevant facts. The dependency list is as follows:
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 file <filename>boot2.h</filename>, but its creation depends on <filename>boot1.out</filename>, which we already have. The rule for its creation is a bit terse, but the important thing is that the output, <filename>boot2.h</filename>, is something like this:
<filename>sys/boot/i386/boot2/boot2.h</filename>
#define XREADORG 0x725
Recall that <filename>boot1</filename> was relocated (i.e., copied from <literal>0x7c00</literal> to <literal>0x700</literal>). This relocation will now make sense, because as we will see, the <acronym>BTX</acronym> server reclaims some memory, including the space where <filename>boot1</filename> was originally loaded. However, the <acronym>BTX</acronym> server needs access to <filename>boot1</filename>'s <literal>xread</literal> function; this function, according to the output of <filename>boot2.h</filename>, is at location <literal>0x725</literal>. Indeed, the <acronym>BTX</acronym> server uses the <literal>xread</literal> function from <filename>boot1</filename>'s relocated code. This function is now accessible from within the <filename>boot2</filename> client.
We next build <filename>boot2.s</filename> from files <filename>boot2.h</filename>, <filename>boot2.c</filename> and <filename>/usr/src/sys/boot/common/ufsread.c</filename>. The rule for this is to compile the code in <filename>boot2.c</filename> (which includes <filename>boot2.h</filename> and <filename>ufsread.c</filename>) into assembly code. Having <filename>boot2.s</filename>, the next rule assembles <filename>boot2.s</filename>, creating the object file <filename>boot2.o</filename>. The next rule directs the linker to link various files (<filename>crt0.o</filename>, <filename>boot2.o</filename> and <filename>sio.o</filename>). Note that the output file, <filename>boot2.out</filename>, is linked to execute at address <literal>0x2000</literal>. Recall that <filename>boot2</filename> will be executed in user mode, within a special user segment set up by the <acronym>BTX</acronym> server. This segment starts at <literal>0xa000</literal>. Also, remember that the <filename>boot2</filename> portion of <filename>boot</filename> was copied to address <literal>0xc000</literal>, that is, offset <literal>0x2000</literal> from the start of the user segment, so <filename>boot2</filename> will work properly when we transfer control to it. Next, <filename>boot2.bin</filename> is created from <filename>boot2.out</filename> by stripping its symbols and format information; boot2.bin is a <emphasis>raw</emphasis> binary. Now, note that a file <filename>boot2.ldr</filename> is created as a 512-byte file full of zeros. This space is reserved for the bsdlabel.
Now that we have files <filename>boot1</filename>, <filename>boot2.bin</filename> and <filename>boot2.ldr</filename>, only the <acronym>BTX</acronym> server is missing before creating the all-in-one <filename>boot</filename> file. The <acronym>BTX</acronym> server is located in <filename>/usr/src/sys/boot/i386/btx/btx</filename>; it has its own <filename>Makefile</filename> with its own set of rules for building. The important thing to notice is that it is also compiled as a <emphasis>raw</emphasis> binary, and that it is linked to execute at address <literal>0x9000</literal>. The details can be found in <filename>/usr/src/sys/boot/i386/btx/btx/Makefile</filename>.
Having the files that comprise the <filename>boot</filename> program, the final step is to <emphasis>merge</emphasis> them. This is done by a special program called <filename>btxld</filename> (source located in <filename>/usr/src/usr.sbin/btxld</filename>). Some arguments to this program include the name of the output file (<filename>boot</filename>), its entry point (<literal>0x2000</literal>) and its file format (raw binary). The various files are finally merged by this utility into the file <filename>boot</filename>, which consists of <filename>boot1</filename>, <filename>boot2</filename>, the <literal>bsdlabel</literal> and the <acronym>BTX</acronym> server. This file, which takes exactly 16 sectors, or 8192 bytes, is what is actually written to the beginning of the FreeBSD slice during installation. Let us now proceed to study the <acronym>BTX</acronym> server program.
The <acronym>BTX</acronym> server prepares a simple environment and switches from 16-bit real mode to 32-bit protected mode, right before passing control to the client. This includes initializing and updating the following data structures:
<primary>virtual v86 mode</primary>
Modifies the <literal>Interrupt Vector Table (IVT)</literal>. The <acronym>IVT</acronym> provides exception and interrupt handlers for Real-Mode code.
The <literal>Interrupt Descriptor Table (IDT)</literal> is created. Entries are provided for processor exceptions, hardware interrupts, two system calls and V86 interface. The IDT provides exception and interrupt handlers for Protected-Mode code.
A <literal>Task-State Segment (TSS)</literal> is created. This is necessary because the processor works in the <emphasis>least</emphasis> privileged level when executing the client (<filename>boot2</filename>), but in the <emphasis>most</emphasis> privileged level when executing the <acronym>BTX</acronym> server.
Real-mode code and data are necessary when switching back to real mode from protected mode, as suggested by the Intel manuals.
The <acronym>GDT</acronym> (Global Descriptor Table) is set up. Entries (descriptors) are provided for supervisor code and data, user code and data, and real-mode code and data. <_:footnote-1/>
Let us now start studying the actual implementation. Recall that <filename>boot1</filename> made a jump to address <literal>0x9010</literal>, the <acronym>BTX</acronym> server's entry point. Before studying program execution there, note that the <acronym>BTX</acronym> server has a special header at address range <literal>0x9000-0x900f</literal>, right before its entry point. This header is defined as follows:
<filename>sys/boot/i386/btx/btx/btx.S</filename>
start: # Start of code
/*
* BTX header.
*/
btx_hdr: .byte 0xeb # Machine ID
.byte 0xe # Header size
.ascii "BTX" # Magic
.byte 0x1 # Major version
.byte 0x2 # Minor version
.byte BTX_FLAGS # Flags
.word PAG_CNT-MEM_ORG&gt;&gt;0xc # Paging control
.word break-start # Text size
.long 0x0 # Entry address
Note the first two bytes are <literal>0xeb</literal> and <literal>0xe</literal>. In the IA-32 architecture, these two bytes are interpreted as a relative jump past the header into the entry point, so in theory, <filename>boot1</filename> could jump here (address <literal>0x9000</literal>) instead of address <literal>0x9010</literal>. Note that the last field in the <acronym>BTX</acronym> header is a pointer to the client's (<filename>boot2</filename>) entry point. This field is patched at link time.
Immediately following the header is the <acronym>BTX</acronym> server's entry point:
/*
* Initialization routine.
*/
init: cli # Disable interrupts
xor %ax,%ax # Zero/segment
mov %ax,%ss # Set up
mov $0x1800,%sp # stack
mov %ax,%es # Address
mov %ax,%ds # data
pushl $0x2 # Clear
popfl # flags
This code disables interrupts, sets up a working stack (starting at address <literal>0x1800</literal>) and clears the flags in the EFLAGS register. Note that the <literal>popfl</literal> instruction pops out a doubleword (4 bytes) from the stack and places it in the EFLAGS register. As the value actually popped is <literal>2</literal>, the EFLAGS register is effectively cleared (IA-32 requires that bit 2 of the EFLAGS register always be 1).
Our next code block clears (sets to <literal>0</literal>) the memory range <literal>0x5e00-0x8fff</literal>. This range is where the various data structures will be created:
/*
* Initialize memory.
*/
mov $0x5e00,%di # Memory to initialize
mov $(0x9000-0x5e00)/2,%cx # Words to zero
rep # Zero-fill
stosw # memory
Recall that <filename>boot1</filename> was originally loaded to address <literal>0x7c00</literal>, so, with this memory initialization, that copy effectively disappeared. However, also recall that <filename>boot1</filename> was relocated to <literal>0x700</literal>, so <emphasis>that</emphasis> copy is still in memory, and the <acronym>BTX</acronym> server will make use of it.

Loading…

No matching activity found.

Browse all component changes

Things to check

Long untranslated

The string has not been translated for a long time

Reset

Multiple failing checks

The translations in several languages have failing checks

Reset

Glossary

English English
No related strings found in the glossary.

Source information

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