Sophie

Sophie

distrib > Mandriva > 2010.1 > x86_64 > by-pkgid > 965e33040dd61030a94f0eb89877aee8 > files > 3405

howto-html-en-20080722-2mdv2010.1.noarch.rpm

<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
>&#13;   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
>&#13;<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
>&#13;<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 &#62;=
         *   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"
>&#13;     IA-32 Intel Architecture Software Developer's Manual</A
>
     (Vol.3. Ch.5.8.3. Masking Exceptions and Interrupts When Switching Stacks).
    </P
><P
>&#13;     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
>&#13;<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&#62;=disksizes+4) break;     // if (i&#62;=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
>&#13;     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
>&#13;     <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
>&#13;<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 = &#38;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
>&#13;     <EM
>bvmlinux (head.o, misc.o, piggy.o)</EM
> will be loaded
     at 0x100000, <EM
>syssize</EM
>*16 bytes.
    </P
><P
>&#13;<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
>&#13;     <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
>&#13;<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
>&#13;     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 &#38; 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 &#62;&#62; 4);  // how many 16-bytes read
#endif
                if (AX &#62; 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 &#60;&#60; 9);            // 1 sector = 2^9 bytes
                if (CX overflow &#38;&#38; CX!=0) {     // &#62; 64KB
                        AX = (-BX) &#62;&#62; 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 &#38;= 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 &#38;&#38; 9;
        if (BX overflow) {              // &#62; 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
>&#13;     <EM
>setup.S:bootsect_helper()</EM
> is only used by
     <EM
>bootsect.S:read_it()</EM
>.
    </P
><P
>&#13;     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
>&#13;<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 &#62;&#62; 4;
                *(byte*)(&#38;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*)(&#38;bootsect_dst_base+2)++;
        }
bootsect_ex:
        // have the number of moved frames (16-bytes) in AX
        AH = *(byte*)(&#38;bootsect_dst_base+2) &#60;&#60; 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
>&#13;     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
>&#13;     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
>&#13;     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
>&#13;    <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"
>&#13;        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"
>&#13;        Ralf Brown's Interrupt List</A
></P
></LI
></UL
>
    As &#60;IA-32 Intel Architecture Software Developer's Manual&#62;
    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"
>&nbsp;</TD
><TD
WIDTH="33%"
ALIGN="right"
VALIGN="top"
>linux/arch/i386/boot/setup.S</TD
></TR
></TABLE
></DIV
></BODY
></HTML
>