968 lines
21 KiB
HTML
968 lines
21 KiB
HTML
<HTML
|
|
><HEAD
|
|
><TITLE
|
|
>linux/arch/i386/boot/bootsect.S</TITLE
|
|
><META
|
|
NAME="GENERATOR"
|
|
CONTENT="Modular DocBook HTML Stylesheet Version 1.7"><LINK
|
|
REL="HOME"
|
|
TITLE="Linux i386 Boot Code HOWTO"
|
|
HREF="index.html"><LINK
|
|
REL="PREVIOUS"
|
|
TITLE="Linux Makefiles"
|
|
HREF="makefiles.html"><LINK
|
|
REL="NEXT"
|
|
TITLE="linux/arch/i386/boot/setup.S"
|
|
HREF="setup.html"></HEAD
|
|
><BODY
|
|
CLASS="sect1"
|
|
BGCOLOR="#FFFFFF"
|
|
TEXT="#000000"
|
|
LINK="#0000FF"
|
|
VLINK="#840084"
|
|
ALINK="#0000FF"
|
|
><DIV
|
|
CLASS="NAVHEADER"
|
|
><TABLE
|
|
SUMMARY="Header navigation table"
|
|
WIDTH="100%"
|
|
BORDER="0"
|
|
CELLPADDING="0"
|
|
CELLSPACING="0"
|
|
><TR
|
|
><TH
|
|
COLSPAN="3"
|
|
ALIGN="center"
|
|
>Linux i386 Boot Code HOWTO</TH
|
|
></TR
|
|
><TR
|
|
><TD
|
|
WIDTH="10%"
|
|
ALIGN="left"
|
|
VALIGN="bottom"
|
|
><A
|
|
HREF="makefiles.html"
|
|
ACCESSKEY="P"
|
|
>Prev</A
|
|
></TD
|
|
><TD
|
|
WIDTH="80%"
|
|
ALIGN="center"
|
|
VALIGN="bottom"
|
|
></TD
|
|
><TD
|
|
WIDTH="10%"
|
|
ALIGN="right"
|
|
VALIGN="bottom"
|
|
><A
|
|
HREF="setup.html"
|
|
ACCESSKEY="N"
|
|
>Next</A
|
|
></TD
|
|
></TR
|
|
></TABLE
|
|
><HR
|
|
ALIGN="LEFT"
|
|
WIDTH="100%"></DIV
|
|
><DIV
|
|
CLASS="sect1"
|
|
><H1
|
|
CLASS="sect1"
|
|
><A
|
|
NAME="bootsect"
|
|
></A
|
|
>3. linux/arch/i386/boot/bootsect.S</H1
|
|
><P
|
|
> Given that we are booting up <EM
|
|
>bzImage</EM
|
|
>, which is
|
|
composed of <EM
|
|
>bbootsect</EM
|
|
>, <EM
|
|
>bsetup</EM
|
|
>
|
|
and <EM
|
|
>bvmlinux (head.o, misc.o, piggy.o)</EM
|
|
>,
|
|
the first floppy sector, <EM
|
|
>bbootsect</EM
|
|
> (512 bytes),
|
|
which is compiled from <TT
|
|
CLASS="filename"
|
|
>linux/arch/i386/boot/bootsect.S</TT
|
|
>,
|
|
is loaded by BIOS to 07C0:0.
|
|
The reset of <EM
|
|
>bzImage</EM
|
|
> (<EM
|
|
>bsetup</EM
|
|
>
|
|
and <EM
|
|
>bvmlinux</EM
|
|
>) has not been loaded yet.
|
|
</P
|
|
><DIV
|
|
CLASS="sect2"
|
|
><H2
|
|
CLASS="sect2"
|
|
><A
|
|
NAME="move_bootsect"
|
|
></A
|
|
>3.1. Move Bootsect</H2
|
|
><P
|
|
> <TABLE
|
|
BORDER="0"
|
|
BGCOLOR="#E0E0E0"
|
|
WIDTH="100%"
|
|
><TR
|
|
><TD
|
|
><FONT
|
|
COLOR="#000000"
|
|
><PRE
|
|
CLASS="programlisting"
|
|
>SETUPSECTS = 4 /* default nr of setup-sectors */
|
|
BOOTSEG = 0x07C0 /* original address of boot-sector */
|
|
INITSEG = DEF_INITSEG (0x9000) /* we move boot here - out of the way */
|
|
SETUPSEG = DEF_SETUPSEG (0x9020) /* setup starts here */
|
|
SYSSEG = DEF_SYSSEG (0x1000) /* system loaded at 0x10000 (65536) */
|
|
SYSSIZE = DEF_SYSSIZE (0x7F00) /* system size: # of 16-byte clicks */
|
|
/* to be loaded */
|
|
ROOT_DEV = 0 /* ROOT_DEV is now written by "build" */
|
|
SWAP_DEV = 0 /* SWAP_DEV is now written by "build" */
|
|
|
|
.code16
|
|
.text
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
_start:
|
|
{
|
|
// move ourself from 0x7C00 to 0x90000 and jump there.
|
|
move BOOTSEG:0 to INITSEG:0 (512 bytes);
|
|
goto INITSEG:go;
|
|
}</PRE
|
|
></FONT
|
|
></TD
|
|
></TR
|
|
></TABLE
|
|
>
|
|
<EM
|
|
>bbootsect</EM
|
|
> has been moved to INITSEG:0 (0x9000:0).
|
|
Now we can forget BOOTSEG.
|
|
</P
|
|
></DIV
|
|
><DIV
|
|
CLASS="sect2"
|
|
><H2
|
|
CLASS="sect2"
|
|
><A
|
|
NAME="get_disk_para"
|
|
></A
|
|
>3.2. Get Disk Parameters</H2
|
|
><P
|
|
> <TABLE
|
|
BORDER="0"
|
|
BGCOLOR="#E0E0E0"
|
|
WIDTH="100%"
|
|
><TR
|
|
><TD
|
|
><FONT
|
|
COLOR="#000000"
|
|
><PRE
|
|
CLASS="programlisting"
|
|
>///////////////////////////////////////////////////////////////////////////////
|
|
// prepare stack and disk parameter table
|
|
go:
|
|
{
|
|
SS:SP = INITSEG:3FF4; // put stack at INITSEG:0x4000-12
|
|
/* 0x4000 is an arbitrary value >=
|
|
* length of bootsect + length of setup + room for stack;
|
|
* 12 is disk parm size. */
|
|
copy disk parameter (pointer in 0:0078) to INITSEG:3FF4 (12 bytes);
|
|
// <A
|
|
HREF="http://www.ctyme.com/intr/rb-2445.htm"
|
|
TARGET="_top"
|
|
>int1E: SYSTEM DATA - DISKETTE PARAMETERS</A
|
|
>
|
|
patch sector count to 36 (offset 4 in parameter table, 1 byte);
|
|
set disk parameter table pointer (0:0078, int1E) to INITSEG:3FF4;
|
|
}</PRE
|
|
></FONT
|
|
></TD
|
|
></TR
|
|
></TABLE
|
|
>
|
|
Make sure SP is initialized immediately after SS register.
|
|
The recommended method of modifying SS is to use "lss" instruction
|
|
according to
|
|
<A
|
|
HREF="http://developer.intel.com/design/pentium4/manuals/"
|
|
TARGET="_top"
|
|
> IA-32 Intel Architecture Software Developer's Manual</A
|
|
>
|
|
(Vol.3. Ch.5.8.3. Masking Exceptions and Interrupts When Switching Stacks).
|
|
</P
|
|
><P
|
|
> Stack operations, such as push and pop, will be OK now.
|
|
First 12 bytes of disk parameter have been copied to INITSEG:3FF4.
|
|
</P
|
|
><P
|
|
> <TABLE
|
|
BORDER="0"
|
|
BGCOLOR="#E0E0E0"
|
|
WIDTH="100%"
|
|
><TR
|
|
><TD
|
|
><FONT
|
|
COLOR="#000000"
|
|
><PRE
|
|
CLASS="programlisting"
|
|
>///////////////////////////////////////////////////////////////////////////////
|
|
// get disk drive parameters, specifically number of sectors/track.
|
|
char disksizes[] = {36, 18, 15, 9};
|
|
int sectors;
|
|
{
|
|
SI = disksizes; // i = 0;
|
|
do {
|
|
probe_loop:
|
|
sectors = DS:[SI++]; // sectors = disksizes[i++];
|
|
if (SI>=disksizes+4) break; // if (i>=4) break;
|
|
int13/AH=02h(AL=1, ES:BX=INITSEG:0200, CX=sectors, DX=0);
|
|
// <A
|
|
HREF="http://www.ctyme.com/intr/rb-0607.htm"
|
|
TARGET="_top"
|
|
>int13/AH=02h: DISK - READ SECTOR(S) INTO MEMORY</A
|
|
>
|
|
} while (failed to read sectors);
|
|
}</PRE
|
|
></FONT
|
|
></TD
|
|
></TR
|
|
></TABLE
|
|
>
|
|
"lodsb" loads a byte from DS:[SI] to AL and increases SI automatically.
|
|
</P
|
|
><P
|
|
> The number of sectors per track has been saved in variable
|
|
<EM
|
|
>sectors</EM
|
|
>.
|
|
</P
|
|
></DIV
|
|
><DIV
|
|
CLASS="sect2"
|
|
><H2
|
|
CLASS="sect2"
|
|
><A
|
|
NAME="load_setup"
|
|
></A
|
|
>3.3. Load Setup Code</H2
|
|
><P
|
|
> <EM
|
|
>bsetup</EM
|
|
> (<EM
|
|
>setup_sects</EM
|
|
> sectors)
|
|
will be loaded right after <EM
|
|
>bbootsect</EM
|
|
>, i.e. SETUPSEG:0.
|
|
Note that INITSEG:0200==SETUPSEG:0 and
|
|
<EM
|
|
>setup_sects</EM
|
|
> has been changed
|
|
by <B
|
|
CLASS="command"
|
|
>tools/build</B
|
|
> to match
|
|
<EM
|
|
>bsetup</EM
|
|
> size
|
|
in <A
|
|
HREF="makefiles.html#i386_tools_build.c"
|
|
>Section 2.6</A
|
|
>.
|
|
</P
|
|
><P
|
|
> <TABLE
|
|
BORDER="0"
|
|
BGCOLOR="#E0E0E0"
|
|
WIDTH="100%"
|
|
><TR
|
|
><TD
|
|
><FONT
|
|
COLOR="#000000"
|
|
><PRE
|
|
CLASS="programlisting"
|
|
>///////////////////////////////////////////////////////////////////////////////
|
|
got_sectors:
|
|
word sread; // sectors read for current track
|
|
char setup_sects; // overwritten by tools/build
|
|
{
|
|
print out "Loading";
|
|
/* <A
|
|
HREF="http://www.ctyme.com/intr/rb-0088.htm"
|
|
TARGET="_top"
|
|
>int10/AH=03h(BH=0): VIDEO - GET CURSOR POSITION AND SIZE</A
|
|
>
|
|
* <A
|
|
HREF="http://www.ctyme.com/intr/rb-0210.htm"
|
|
TARGET="_top"
|
|
>int10/AH=13h(AL=1, BH=0, BL=7, CX=9, DH=DL=0, ES:BP=INITSEG:$msg1):</A
|
|
>
|
|
* <A
|
|
HREF="http://www.ctyme.com/intr/rb-0210.htm"
|
|
TARGET="_top"
|
|
>VIDEO - WRITE STRING</A
|
|
> */
|
|
|
|
// load setup-sectors directly after the moved bootblock (at 0x90200).
|
|
SI = &sread; // using SI to index sread, head and track
|
|
sread = 1; // the boot sector has already been read
|
|
|
|
int13/AH=00h(DL=0); // <A
|
|
HREF="http://www.ctyme.com/intr/rb-0605.htm"
|
|
TARGET="_top"
|
|
>reset FDC</A
|
|
>
|
|
|
|
BX = 0x0200; // read bsetup right after bbootsect (512 bytes)
|
|
do {
|
|
next_step:
|
|
/* to prevent cylinder crossing reading,
|
|
* calculate how many sectors to read this time */
|
|
uint16 pushw_ax = AX = MIN(sectors-sread, setup_sects);
|
|
no_cyl_crossing:
|
|
read_track(AL, ES:BX); // AX is not modified
|
|
// set ES:BX, sread, head and track for next read_track()
|
|
set_next(AX);
|
|
setup_sects -= pushw_ax; // rest - for next step
|
|
} while (setup_sects);
|
|
}</PRE
|
|
></FONT
|
|
></TD
|
|
></TR
|
|
></TABLE
|
|
>
|
|
SI is set to the address of <EM
|
|
>sread</EM
|
|
> to index
|
|
variables <EM
|
|
>sread</EM
|
|
>, <EM
|
|
>head</EM
|
|
> and
|
|
<EM
|
|
>track</EM
|
|
>, as they are contiguous in memory.
|
|
Check <A
|
|
HREF="bootsect.html#read_disk"
|
|
>Section 3.6</A
|
|
> for read_track() and set_next() details.
|
|
</P
|
|
></DIV
|
|
><DIV
|
|
CLASS="sect2"
|
|
><H2
|
|
CLASS="sect2"
|
|
><A
|
|
NAME="load_compressed"
|
|
></A
|
|
>3.4. Load Compressed Image</H2
|
|
><P
|
|
> <EM
|
|
>bvmlinux (head.o, misc.o, piggy.o)</EM
|
|
> will be loaded
|
|
at 0x100000, <EM
|
|
>syssize</EM
|
|
>*16 bytes.
|
|
</P
|
|
><P
|
|
> <TABLE
|
|
BORDER="0"
|
|
BGCOLOR="#E0E0E0"
|
|
WIDTH="100%"
|
|
><TR
|
|
><TD
|
|
><FONT
|
|
COLOR="#000000"
|
|
><PRE
|
|
CLASS="programlisting"
|
|
>///////////////////////////////////////////////////////////////////////////////
|
|
// load vmlinux/bvmlinux (head.o, misc.o, piggy.o)
|
|
{
|
|
read_it(ES=SYSSEG);
|
|
kill_motor(); // turn off floppy drive motor
|
|
print_nl(); // print CR LF
|
|
}</PRE
|
|
></FONT
|
|
></TD
|
|
></TR
|
|
></TABLE
|
|
>
|
|
Check <A
|
|
HREF="bootsect.html#read_disk"
|
|
>Section 3.6</A
|
|
> for read_it() details.
|
|
If we are booting up <EM
|
|
>zImage</EM
|
|
>,
|
|
<EM
|
|
>vmlinux</EM
|
|
> is loaded at 0x10000 (SYSSEG:0).
|
|
</P
|
|
><P
|
|
> <EM
|
|
>bzImage (bbootsect, bsetup, bvmlinux)</EM
|
|
> is
|
|
in the memory as a whole now.
|
|
</P
|
|
></DIV
|
|
><DIV
|
|
CLASS="sect2"
|
|
><H2
|
|
CLASS="sect2"
|
|
><A
|
|
NAME="go_setup"
|
|
></A
|
|
>3.5. Go Setup</H2
|
|
><P
|
|
> <TABLE
|
|
BORDER="0"
|
|
BGCOLOR="#E0E0E0"
|
|
WIDTH="100%"
|
|
><TR
|
|
><TD
|
|
><FONT
|
|
COLOR="#000000"
|
|
><PRE
|
|
CLASS="programlisting"
|
|
>///////////////////////////////////////////////////////////////////////////////
|
|
// check which root-device to use and jump to setup.S
|
|
int root_dev; // overwritten by tools/build
|
|
{
|
|
if (!root_dev) {
|
|
switch (sectors) {
|
|
case 15: root_dev = 0x0208; // /dev/ps0 - 1.2Mb
|
|
break;
|
|
case 18: root_dev = 0x021C; // /dev/PS0 - 1.44Mb
|
|
break;
|
|
case 36: root_dev = 0x0220; // /dev/fd0H2880 - 2.88Mb
|
|
break;
|
|
default: root_dev = 0x0200; // /dev/fd0 - auto detect
|
|
break;
|
|
}
|
|
}
|
|
|
|
// jump to the setup-routine loaded directly after the bootblock
|
|
goto SETUPSEG:0;
|
|
}</PRE
|
|
></FONT
|
|
></TD
|
|
></TR
|
|
></TABLE
|
|
>
|
|
It passes control to <EM
|
|
>bsetup</EM
|
|
>.
|
|
See <EM
|
|
>linux/arch/i386/boot/setup.S:start</EM
|
|
> in
|
|
<A
|
|
HREF="setup.html"
|
|
>Section 4</A
|
|
>.
|
|
</P
|
|
></DIV
|
|
><DIV
|
|
CLASS="sect2"
|
|
><H2
|
|
CLASS="sect2"
|
|
><A
|
|
NAME="read_disk"
|
|
></A
|
|
>3.6. Read Disk</H2
|
|
><P
|
|
> The following functions are used to load <EM
|
|
>bsetup</EM
|
|
>
|
|
and <EM
|
|
>bvmlinux</EM
|
|
> from disk.
|
|
Note that <EM
|
|
>syssize</EM
|
|
> has been changed
|
|
by <B
|
|
CLASS="command"
|
|
>tools/build</B
|
|
> in
|
|
<A
|
|
HREF="makefiles.html#i386_tools_build.c"
|
|
>Section 2.6</A
|
|
> too.
|
|
<TABLE
|
|
BORDER="0"
|
|
BGCOLOR="#E0E0E0"
|
|
WIDTH="100%"
|
|
><TR
|
|
><TD
|
|
><FONT
|
|
COLOR="#000000"
|
|
><PRE
|
|
CLASS="programlisting"
|
|
>sread: .word 0 # sectors read of current track
|
|
head: .word 0 # current head
|
|
track: .word 0 # current track
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
// load the system image at address SYSSEG:0
|
|
read_it(ES=SYSSEG)
|
|
int syssize; /* system size in 16-bytes,
|
|
* overwritten by tools/build */
|
|
{
|
|
if (ES & 0x0fff) die; // not 64KB aligned
|
|
|
|
BX = 0;
|
|
for (;;) {
|
|
rp_read:
|
|
#ifdef __BIG_KERNEL__
|
|
bootsect_helper(ES:BX);
|
|
/* INITSEG:0220==SETUPSEG:0020 is bootsect_kludge,
|
|
* which contains pointer SETUPSEG:bootsect_helper().
|
|
* This function initializes some data structures
|
|
* when it is called for the first time,
|
|
* and moves SYSSEG:0 to 0x100000, 64KB each time,
|
|
* in the following calls.
|
|
* See <A
|
|
HREF="bootsect.html#bootsect_helper"
|
|
>Section 3.7</A
|
|
>. */
|
|
#else
|
|
AX = ES - SYSSEG + ( BX >> 4); // how many 16-bytes read
|
|
#endif
|
|
if (AX > syssize) return; // everything loaded
|
|
ok1_read:
|
|
/* Get proper AL (sectors to read) for this time
|
|
* to prevent cylinder crossing reading and BX overflow. */
|
|
AX = sectors - sread;
|
|
CX = BX + (AX << 9); // 1 sector = 2^9 bytes
|
|
if (CX overflow && CX!=0) { // > 64KB
|
|
AX = (-BX) >> 9;
|
|
}
|
|
ok2_read:
|
|
read_track(AL, ES:BX);
|
|
set_next(AX);
|
|
}
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
// read disk with parameters (sread, track, head)
|
|
read_track(AL sectors, ES:BX destination)
|
|
{
|
|
for (;;) {
|
|
printf(".");
|
|
// <A
|
|
HREF="http://www.ctyme.com/intr/rb-0106.htm"
|
|
TARGET="_top"
|
|
>int10/AH=0Eh: VIDEO - TELETYPE OUTPUT</A
|
|
>
|
|
|
|
// set CX, DX according to (sread, track, head)
|
|
DX = track;
|
|
CX = sread + 1;
|
|
CH = DL;
|
|
|
|
DX = head;
|
|
DH = DL;
|
|
DX &= 0x0100;
|
|
|
|
int13/AH=02h(AL, ES:BX, CX, DX);
|
|
// <A
|
|
HREF="http://www.ctyme.com/intr/rb-0607.htm"
|
|
TARGET="_top"
|
|
>int13/AH=02h: DISK - READ SECTOR(S) INTO MEMORY</A
|
|
>
|
|
if (read disk success) return;
|
|
// "addw $8, %sp" is to cancel previous 4 "pushw" operations.
|
|
bad_rt:
|
|
print_all(); // print error code, AX, BX, CX and DX
|
|
int13/AH=00h(DL=0); // <A
|
|
HREF="http://www.ctyme.com/intr/rb-0605.htm"
|
|
TARGET="_top"
|
|
>reset FDC</A
|
|
>
|
|
}
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
// set ES:BX, sread, head and track for next read_track()
|
|
set_next(AX sectors_read)
|
|
{
|
|
CX = AX; // sectors read
|
|
AX += sread;
|
|
if (AX==sectors) {
|
|
head = 1 ^ head; // flap head between 0 and 1
|
|
if (head==0) track++;
|
|
ok4_set:
|
|
AX = 0;
|
|
}
|
|
ok3_set:
|
|
sread = AX;
|
|
BX += CX && 9;
|
|
if (BX overflow) { // > 64KB
|
|
ES += 0x1000;
|
|
BX = 0;
|
|
}
|
|
set_next_fn:
|
|
}</PRE
|
|
></FONT
|
|
></TD
|
|
></TR
|
|
></TABLE
|
|
>
|
|
</P
|
|
></DIV
|
|
><DIV
|
|
CLASS="sect2"
|
|
><H2
|
|
CLASS="sect2"
|
|
><A
|
|
NAME="bootsect_helper"
|
|
></A
|
|
>3.7. Bootsect Helper</H2
|
|
><P
|
|
> <EM
|
|
>setup.S:bootsect_helper()</EM
|
|
> is only used by
|
|
<EM
|
|
>bootsect.S:read_it()</EM
|
|
>.
|
|
</P
|
|
><P
|
|
> Because <EM
|
|
>bbootsect</EM
|
|
> and <EM
|
|
>bsetup</EM
|
|
>
|
|
are linked separately, they use offsets relative to
|
|
their own code/data segments.
|
|
We have to "call far" (lcall) for <EM
|
|
>bootsect_helper()</EM
|
|
>
|
|
in different segment, and it must "return far" (lret) then.
|
|
This results in CS change in calling, which makes CS!=DS, and
|
|
we have to use segment modifier to specify variables in
|
|
<TT
|
|
CLASS="filename"
|
|
>setup.S</TT
|
|
>.
|
|
</P
|
|
><P
|
|
> <TABLE
|
|
BORDER="0"
|
|
BGCOLOR="#E0E0E0"
|
|
WIDTH="100%"
|
|
><TR
|
|
><TD
|
|
><FONT
|
|
COLOR="#000000"
|
|
><PRE
|
|
CLASS="programlisting"
|
|
>///////////////////////////////////////////////////////////////////////////////
|
|
// called by bootsect loader when loading bzImage
|
|
bootsect_helper(ES:BX)
|
|
bootsect_es = 0; // defined in setup.S
|
|
type_of_loader = 0; // defined in setup.S
|
|
{
|
|
if (!bootsect_es) { // called for the first time
|
|
type_of_loader = 0x20; // bootsect-loader, version 0
|
|
AX = ES >> 4;
|
|
*(byte*)(&bootsect_src_base+2) = AH;
|
|
bootsect_es = ES;
|
|
AX = ES - SYSSEG;
|
|
return;
|
|
}
|
|
bootsect_second:
|
|
if (!BX) { // 64KB full
|
|
// move from SYSSEG:0 to destination, 64KB each time
|
|
int15/AH=87h(CX=0x8000, ES:SI=CS:bootsect_gdt);
|
|
// <A
|
|
HREF="http://www.ctyme.com/intr/rb-1527.htm"
|
|
TARGET="_top"
|
|
>int15/AH=87h: SYSTEM - COPY EXTENDED MEMORY</A
|
|
>
|
|
if (failed to copy) {
|
|
bootsect_panic() {
|
|
prtstr("INT15 refuses to access high mem, "
|
|
"giving up.");
|
|
bootsect_panic_loop: goto bootsect_panic_loop; // never return
|
|
}
|
|
}
|
|
ES = bootsect_es; // reset ES to always point to 0x10000
|
|
*(byte*)(&bootsect_dst_base+2)++;
|
|
}
|
|
bootsect_ex:
|
|
// have the number of moved frames (16-bytes) in AX
|
|
AH = *(byte*)(&bootsect_dst_base+2) << 4;
|
|
AL = 0;
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
// data used by bootsect_helper()
|
|
bootsect_gdt:
|
|
.word 0, 0, 0, 0
|
|
.word 0, 0, 0, 0
|
|
|
|
bootsect_src:
|
|
.word 0xffff
|
|
|
|
bootsect_src_base:
|
|
.byte 0x00, 0x00, 0x01 # base = 0x010000
|
|
.byte 0x93 # typbyte
|
|
.word 0 # limit16,base24 =0
|
|
|
|
bootsect_dst:
|
|
.word 0xffff
|
|
|
|
bootsect_dst_base:
|
|
.byte 0x00, 0x00, 0x10 # base = 0x100000
|
|
.byte 0x93 # typbyte
|
|
.word 0 # limit16,base24 =0
|
|
.word 0, 0, 0, 0 # BIOS CS
|
|
.word 0, 0, 0, 0 # BIOS DS
|
|
|
|
bootsect_es:
|
|
.word 0
|
|
|
|
bootsect_panic_mess:
|
|
.string "INT15 refuses to access high mem, giving up."</PRE
|
|
></FONT
|
|
></TD
|
|
></TR
|
|
></TABLE
|
|
>
|
|
Note that <EM
|
|
>type_of_loader</EM
|
|
> value is changed.
|
|
It will be referenced in <A
|
|
HREF="setup.html#check_loader"
|
|
>Section 4.3</A
|
|
>.
|
|
</P
|
|
></DIV
|
|
><DIV
|
|
CLASS="sect2"
|
|
><H2
|
|
CLASS="sect2"
|
|
><A
|
|
NAME="bootsect_misc"
|
|
></A
|
|
>3.8. Miscellaneous</H2
|
|
><P
|
|
> The rest are supporting functions, variables
|
|
and part of "real-mode kernel header".
|
|
Note that data is in .text segment as code, thus it can be
|
|
properly initialized when loaded.
|
|
<TABLE
|
|
BORDER="0"
|
|
BGCOLOR="#E0E0E0"
|
|
WIDTH="100%"
|
|
><TR
|
|
><TD
|
|
><FONT
|
|
COLOR="#000000"
|
|
><PRE
|
|
CLASS="programlisting"
|
|
>///////////////////////////////////////////////////////////////////////////////
|
|
// some small functions
|
|
print_all(); /* print error code, AX, BX, CX and DX */
|
|
print_nl(); /* print CR LF */
|
|
print_hex(); /* print the word pointed to by SS:BP in hexadecimal */
|
|
kill_motor() /* turn off floppy drive motor */
|
|
{
|
|
#if 1
|
|
int13/AH=00h(DL=0); // <A
|
|
HREF="http://www.ctyme.com/intr/rb-0605.htm"
|
|
TARGET="_top"
|
|
>reset FDC</A
|
|
>
|
|
#else
|
|
outb(0, 0x3F2); // outb(val, port)
|
|
#endif
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
sectors: .word 0
|
|
disksizes: .byte 36, 18, 15, 9
|
|
msg1: .byte 13, 10
|
|
.ascii "Loading"</PRE
|
|
></FONT
|
|
></TD
|
|
></TR
|
|
></TABLE
|
|
>
|
|
</P
|
|
><P
|
|
> Bootsect trailer, which is a part of "real-mode kernel header",
|
|
begins at offset 497.
|
|
<TABLE
|
|
BORDER="0"
|
|
BGCOLOR="#E0E0E0"
|
|
WIDTH="100%"
|
|
><TR
|
|
><TD
|
|
><FONT
|
|
COLOR="#000000"
|
|
><PRE
|
|
CLASS="programlisting"
|
|
>.org 497
|
|
setup_sects: .byte SETUPSECS // overwritten by tools/build
|
|
root_flags: .word ROOT_RDONLY
|
|
syssize: .word SYSSIZE // overwritten by tools/build
|
|
swap_dev: .word SWAP_DEV
|
|
ram_size: .word RAMDISK
|
|
vid_mode: .word SVGA_MODE
|
|
root_dev: .word ROOT_DEV // overwritten by tools/build
|
|
boot_flag: .word 0xAA55</PRE
|
|
></FONT
|
|
></TD
|
|
></TR
|
|
></TABLE
|
|
>
|
|
</P
|
|
><P
|
|
> This "header" must conform to the layout pattern in
|
|
<TT
|
|
CLASS="filename"
|
|
>linux/Documentation/i386/boot.txt</TT
|
|
>:
|
|
<TABLE
|
|
BORDER="0"
|
|
BGCOLOR="#E0E0E0"
|
|
WIDTH="100%"
|
|
><TR
|
|
><TD
|
|
><FONT
|
|
COLOR="#000000"
|
|
><PRE
|
|
CLASS="programlisting"
|
|
>Offset Proto Name Meaning
|
|
/Size
|
|
01F1/1 ALL setup_sects The size of the setup in sectors
|
|
01F2/2 ALL root_flags If set, the root is mounted readonly
|
|
01F4/2 ALL syssize DO NOT USE - for bootsect.S use only
|
|
01F6/2 ALL swap_dev DO NOT USE - obsolete
|
|
01F8/2 ALL ram_size DO NOT USE - for bootsect.S use only
|
|
01FA/2 ALL vid_mode Video mode control
|
|
01FC/2 ALL root_dev Default root device number
|
|
01FE/2 ALL boot_flag 0xAA55 magic number</PRE
|
|
></FONT
|
|
></TD
|
|
></TR
|
|
></TABLE
|
|
>
|
|
</P
|
|
></DIV
|
|
><DIV
|
|
CLASS="sect2"
|
|
><H2
|
|
CLASS="sect2"
|
|
><A
|
|
NAME="bootsect_ref"
|
|
></A
|
|
>3.9. Reference</H2
|
|
><P
|
|
> <P
|
|
></P
|
|
><UL
|
|
><LI
|
|
><P
|
|
>THE LINUX/I386 BOOT PROTOCOL:
|
|
<TT
|
|
CLASS="filename"
|
|
>linux/Documentation/i386/boot.txt</TT
|
|
></P
|
|
></LI
|
|
><LI
|
|
><P
|
|
><A
|
|
HREF="http://developer.intel.com/design/pentium4/manuals/"
|
|
TARGET="_top"
|
|
> IA-32 Intel Architecture Software Developer's Manual</A
|
|
></P
|
|
></LI
|
|
><LI
|
|
><P
|
|
><A
|
|
HREF="http://www.cs.cmu.edu/~ralf/files.html"
|
|
TARGET="_top"
|
|
> Ralf Brown's Interrupt List</A
|
|
></P
|
|
></LI
|
|
></UL
|
|
>
|
|
As <IA-32 Intel Architecture Software Developer's Manual>
|
|
is widely referenced in this document, I will call it "IA-32 Manual"
|
|
for short.
|
|
</P
|
|
></DIV
|
|
></DIV
|
|
><DIV
|
|
CLASS="NAVFOOTER"
|
|
><HR
|
|
ALIGN="LEFT"
|
|
WIDTH="100%"><TABLE
|
|
SUMMARY="Footer navigation table"
|
|
WIDTH="100%"
|
|
BORDER="0"
|
|
CELLPADDING="0"
|
|
CELLSPACING="0"
|
|
><TR
|
|
><TD
|
|
WIDTH="33%"
|
|
ALIGN="left"
|
|
VALIGN="top"
|
|
><A
|
|
HREF="makefiles.html"
|
|
ACCESSKEY="P"
|
|
>Prev</A
|
|
></TD
|
|
><TD
|
|
WIDTH="34%"
|
|
ALIGN="center"
|
|
VALIGN="top"
|
|
><A
|
|
HREF="index.html"
|
|
ACCESSKEY="H"
|
|
>Home</A
|
|
></TD
|
|
><TD
|
|
WIDTH="33%"
|
|
ALIGN="right"
|
|
VALIGN="top"
|
|
><A
|
|
HREF="setup.html"
|
|
ACCESSKEY="N"
|
|
>Next</A
|
|
></TD
|
|
></TR
|
|
><TR
|
|
><TD
|
|
WIDTH="33%"
|
|
ALIGN="left"
|
|
VALIGN="top"
|
|
>Linux Makefiles</TD
|
|
><TD
|
|
WIDTH="34%"
|
|
ALIGN="center"
|
|
VALIGN="top"
|
|
> </TD
|
|
><TD
|
|
WIDTH="33%"
|
|
ALIGN="right"
|
|
VALIGN="top"
|
|
>linux/arch/i386/boot/setup.S</TD
|
|
></TR
|
|
></TABLE
|
|
></DIV
|
|
></BODY
|
|
></HTML
|
|
> |