                     LINUX/I386 ֡ȥץȥ
                     ----------------------------

                    H. Peter Anvin <hpa@zytor.com>
                        ǽ 2002-01-01

i386 ץåȥեǤϡLinux ͥ¿ʣʥ֡Ȥδ
ѤƤޤϰˤϡͥ뼫Ȥưǽ᡼ˤ
Ȥ˾˲äʣ PC ΥǥȤŪ¦̤
äơڤӡץڥ졼ƥ󥰥ƥȤƤΥꥢ⡼ DOS 
¾ξǤˤ PC ȳδԤѲˤäƿʲƤޤ

ߤǤϡͤĤΥС Linux/i386 ֡ȥץȥ뤬¸ߤޤ

Ťͥ:
    zImage/Image ΥݡȤΤߡΥͥˤϥޥɥ饤
    饵ݡȤƤʤΤ⤢ޤ

ץȥ 2.00:
    (ͥ 1.3.73) ֡ȥȥ֤ͥϢȤȤ뤿η
    줿ˡ˲äơbzImage  initrd ΥݡȤɲäޤ
    Υåȥåΰ褬߲ǽǤ뤳ȤȤƲꤷƤ
    ޤsetup.S Ϻֲǽˤʤޤ

ץȥ 2.01:
    (ͥ 1.3.76) ҡץСٹɲäޤ

ץȥ 2.02:
    (ͥ 2.4.0-test3-pre3) ޥɥ饤ץȥ롣
    ¤򲼤ޤΥåȥåΰ񤭤ʤȤ
    ꡢSMM ⤷ 32 ӥå BIOS ȥݥȤ EBDA 
    륷ƥǤ⡢˥֡ȤǤ褦ˤʤޤzImage Ͽ侩
    ޤ󤬡ݡȤƤޤ

ץȥ 2.03:
    (ͥ 2.4.18-pre1) ͭ initrd ɥ쥹κǾ̤򡢥֡ȥ
    Ū˼Ǥ褦ˤޤ


**** 쥤

Image ⤷ zImage ͥѤ륫ͥνΥ
ޥåפϡŵŪˤϼΤ褦ˤʤäƤޤ



£ɣϣѤͽѤߡԲġBIOS EBDA ѤͽѤ

åҡסޥɥ饤󡡨ͥΥꥢ⡼ɥɤ

ͥ륻åȥåסͥΥꥢ⡼ɥ

ͥ֡ȥͥΥ쥬֡ȥ

ץƥȥ⡼ɥͥ롡ͥ륤᡼ʬ

֡ȥ ֡ȥȥݥ 0000:7C00

ͣ£ҡ£ɣϣѤͽѤߡ

ŵŪˤϣͣ£Ҥѡ

£ɣϣӤˤѤΤߡ



bzImage ѤȤץƥȥ⡼ɥͥ 0x100000 ("
") ˺֤졢ͥΥꥢ⡼ɥ֥å (֡ȥ
åȥåסå/ҡ)ϡ0x10000 ̥νλ֤
֤ʤФɤˤǤֲǽȤƤޤԱˤ⡢ץȥ
2.00 ȥץȥ 2.01 ϡ0x9XXXX ΥϰϤ˥ޥɥ饤
¸ߤ뤳Ȥ׵ᤷΥϰϤϽưͥˤäư
ƾ񤭤ޤץȥ 2.02 Ǥϡ褷Ƥޤ

"" ֡ȥ̥κǹ̥ݥȡ
ǽʸ¤㤯ݤĤȤ˾ޤȤǤʤʤ顢 BIOS 
ˤϡ̥ξ¶᤯ˡĥ BIOS ǡΰȸƤФ뤫ʤ
礭̤Υ֤Τ⤢뤫Ǥ֡ȥϡ"INT 12h"
BIOS Ȥäơ̥꤬ɤ줯餤ѤǤ뤫ǧʤ
Фʤޤ

Աˤ INT 12h ­򸡽Фˤϡ֡ȥ
桼˥顼åФ餤ΤȤǤޤ󡣤Τᡢ
֡ȥϡŪ˲ǽʸ¤ꡢǤʤΰ褦
߷פ٤Ǥ0x90000 ȤؤΥǡߤɬפȤ
zImage ͥŤ bzImage ͥΤᡢ֡ȥ 0x9A000
ΥȤʤ褦ˤʤФʤޤ¿ BIOS
ΰ˲ƤޤΤǤ


**** ꥢ⡼ɥͥإå

ʸ⡢ڤӡͥ֡ȥΤɤΰ֤ˤƤ⡢
""  512 ХȤΤȤǤǥμºݤΥȤ
طޤ

Linux ͥɤǽΥƥåפǤϡꥢ⡼ɥ
(֡ȥȥåȥåץ) ɤեå 0x01f1 
¸ߤ벼Υإå򸡺ʤФʤޤ󡣥֡ȥϺǽ
ĤΥ (1K) ɤ줫֡ȥåץ
Ĵ٤뤳ȤǤޤꥢ⡼ɥɤϹפ 32K ޤǲǽǤ

إåϼΤ褦ˤʤäƤޤ

եå ץȥ ̾            ̣
/

01F1/1     ALL        setup_sects     ñ̤ΥåȥåפΥ
01F2/2     ALL        root_flags      åȤƤС꡼ɥ꡼ root ޥȤ
01F4/2     ALL        syssize         Բġbootsect.S ˤѤΤߡ
01F6/2     ALL        swap_dev        Բġobsolete.
01F8/2     ALL        ram_size        Բġbootsect.S ˤѤΤߡ
01FA/2     ALL        vid_mode        ӥǥ⡼
01FC/2     ALL        root_dev        ǥեȤΥ롼ȥǥХֹ
01FE/2     ALL        boot_flag       ޥåʥС 0xAA55
0200/2     2.00+      jump            ̿
0202/4     2.00+      header          ޥåʥС "HdrS"
0206/2     2.00+      version         ݡȤ֡ȥץȥΥС
0208/4     2.00+      realmode_swtch  ֡ȥեå ()
020C/2     2.00+      start_sys       ̥ (0x1000) (obsolete)
020E/2     2.00+      kernel_version  ͥСʸؤΥݥ
0210/1     2.00+      type_of_loader  ֡ȥ̻
0211/1     2.00+      loadflags       ֡ȥץȥ롦ץե饰
0212/2     2.00+      setup_move_size ̥ꥵذư (եåȶ˻)
0214/4     2.00+      code32_start    ֡ȥեå ()
0218/4     2.00+      ramdisk_image   initrd ɥɥ쥹 (֡ȥˤꥻåȤ)
021C/4     2.00+      ramdisk_size    initrd  (֡ȥˤꥻåȤ)
0220/4     2.00+      bootsect_kludge Բġbootsect.S ˤѤΤߡ
0224/2     2.01+      heap_end_ptr    åȥå׽λְʹߤΥե꡼
0226/2     N/A        pad1            ̤
0228/4     2.02+      cmd_line_ptr    ͥ륳ޥɥ饤ؤ 32 ӥåȥݥ
022C/4     2.03+      initrd_addr_max ͭ initrd ɥ쥹κǾ

ߴΤᡢsetup_sects եɤ 0 ξˤϡºݤͤ
4 Ȥʤޤ

եå 0x202 ΰ֤˥ޥåʥС "HdrS" (0x53726448) ȯ
Ǥʤ硢֡ȥץȥΥС "Ť" ǤŤͥ
ɤȤˤϡΥѥ᡼ꤵޤ

        ᡼ = zImage
        initrd ̤ݡ
        ꥢ⡼ɥͥ 0x90000 ֤ʤФʤʤ

ʳʤС"version" եɤϥץȥΥСޤ
ޤ㤨СץȥС 2.01 ϡ0x0201 򤳤Υեɤ
ޤǤޤإåΥեɤ򥻥åȤȤˤϡΥץ
ȥСǥݡȤƤեɤΤߤ򥻥åȤ褦
ʤФʤޤ

"kernel_version" եɤϡ⤷⥼ʳͤåȤƤ硢
ͤɤǤ̥뽪ü줿ͥСֹʸؤΥݥ
󥿤Ǥꡢͤ 0x200 ̤Ǥ桼ФƥͥСɽ
ΤѤǤޤͤ (0x200*setup_sects) ̤ǤʤФʤ
ޤ󡣤ȤСͤ 0x1c00 ˥åȤƤ硢ͥС
ֹʸϥͥե 0x1e00 ˤޤϡ
"setup_sects" եɤ 14 ʾͤޤǤˤΤߡͭ
ͤȤʤޤ

ۤȤɤΥ֡ȥϡñˤΥåȥɥ쥹˥ͥľ
ɤǤ礦Τ褦ʥ֡ȥϡإåΤۤȤɤ
եɤˤĤƤϡ뤳ȤˤĤƿۤɬפϤޤ
ȤϤΤΡΥեɤʤФʤޤ

  vid_mode:
        ̤ʥޥɥ饤󥪥ץפ򻲾ȤƤ

  type_of_loader:
        ֡ȥ˳ƺѤߤ ID (ɽ򻲾) ϡ0xTV
        򥻥åȤޤǡT ϥ֡ȥμ̻ҡV ϥС
        ֹǤ

        ƺѤߥ֡ȥ ID:
        0 LILO
        1 Loadlin
        2 bootsect-loader
        3 SYSLINUX
        4 EtherBoot

        ֡ȥ ID ƤƤ餦ɬפϡ<hpa@zytor.com>
        Ϣ򤪴ꤤޤ

  loadflags, heap_end_ptr:
        ץȥС 2.01 ʾʤСåȥåץҡפ
        եåȥߥåȤ head_end_ptr 졢loadflags  0x80
        ӥå (CAN_USE_HEAP) 򥻥åȤޤheap_end_ptr ϡå
        åפγϰ (եå 0x0200) а֤Ǥ

  setup_move_size:
        ץȥ 2.00 ⤷ 2.01 ȤäƤȤꥢ⡼
        ͥ뤬 0x90000 ˥ɤʤʤСꥢ⡼ɥͥ
        ǥ󥰥ǡΤۤɤ˰ưޤ
        ꥢ⡼ɥͥ뼫Τ¾ɲäΥǡ (ͥ륳ޥ
        饤ʤ) ưˤϡΥեɤޤ

  ramdisk_image, ramdisk_size:
        ֡ȥ RAM ǥ (initrd) ɤƤ硢
        RAM ǥǡؤ 32 ӥåȥݥ󥿤 ramdisk_image 
        åȤ RAM ǥǡΥ ramdisk_size 
        åȤޤ

        initrd ŵŪˤϡΤǤ¤̤֤٤
        Ǥʤʤ顢ʤСưͥν
        ˤäƾ񤭤Ƥޤ⤷ʤǤʤ顢
        initrd_addr_max եɤǻꤵ륢ɥ쥹֤
        ƤϤޤinitrd ϾʤȤ 4K ڡñ̤ǥ饤
        Ƥ٤Ǥ

  cmd_line_ptr:
        ץȥС 2.02 ʾʤСϡͥ륳ޥ
        饤ؤ 32 ӥåȥݥ󥿤Ǥͥ륳ޥɥ饤ϡ
        åȥå׽λ֤ 0xA0000 δ֤ʤСɤˤǤ֤
        ȤǤޤȤ֡ȥޥɥ饤򥵥ݡȤ
        ʤǤ⡢ΥեɤʤФʤޤ󡣤Τ褦
        ˤϡʸؤ褦ˤޤ (⤷ϡɤΤ
        ʸ "auto" ؤ褦ˤ뤳ȤǤ) Υեɤ
        ޤޤǤȡͥϡ֡ȥץȥ 2.02+ 򥵥ݡ
        ƤʤȲꤷƤޤޤ

  ramdisk_max:
        initrd Ƥΰκ祢ɥ쥹Ǥ֡ȥץȥ
        2.02 ˤϤΥեɤϤʤ祢ɥ쥹 0x37FFFFFF
        Ǥ(Υɥ쥹ϰ˻ȤХȤκǾ̥ɥ쥹Ȥ
        ƤޤΤǡRAM ǥԤä 131072 ХȤ
        Υեɤ 0x37FFFFFF ξ硢RAM ǥ 0x37FE0000
        鳫Ϥ뤳ȤǤޤ


**** ͥ륳ޥɥ饤

ͥ륳ޥɥ饤ϡ֡ȥͥϢȤ뤿νפ
ˡȤʤäƤƤޤĤΥץϡ֡ȥȤˤط
Ƥޤ "̤ʥޥɥ饤󥪥ץ" 򻲾ȤƤ

ͥ륳ޥɥ饤ϡ̥뽪ü줿Ĺ 255 ޤǤʸ󡢥ץ饹
ǸΥ̥Ǥ

֡ȥץȥС 2.02 ʹߤʤСͥ륳ޥɥ饤
ɥ쥹ϡإåե cmd_line_ptr Ϳޤ ()

ץȥС 2.02 Ť硢ͥ륳ޥɥ饤
ΥץȥѤϤޤ

        եå 0x0020 ()  "cmd_line_magic" ˡޥå
        ʥС 0xA33F ޤ

        եå 0x0022 ()  "cmd_line_offset" ˡͥ
        ޥɥ饤ΥեåȤޤ (ꥢ⡼ɥͥ
        ϰ֤Ф) 

        ͥ륳ޥɥ饤 setup_move_size ǥС
        ϰϤˤʤФʤʤΤǡΥեɤĴɬפ
        ޤ


**** ֡

ȤơΥꥢ⡼ɥȥ쥤Ȥꤷޤ

        0x0000-0x7FFF   ꥢ⡼ɥͥ
        0x8000-0x8FFF   åȥҡ
        0x9000-0x90FF   ͥ륳ޥɥ饤

Υ֡ȥϡإå˲ΥեɤʤФʤޤ

        unsigned long base_ptr; /* ꥢ⡼ɥȤΥ١ɥ쥹 */

        if ( setup_sects == 0 ) {
                setup_sects = 4;
        }

        if ( protocol >= 0x0200 ) {
                type_of_loader = <type code>;
                if ( loading_initrd ) {
                        ramdisk_image = <initrd_address>;
                        ramdisk_size = <initrd_size>;
                }
                if ( protocol >= 0x0201 ) {
                        heap_end_ptr = 0x9000 - 0x200;
                        loadflags |= 0x80; /* CAN_USE_HEAP */
                }
                if ( protocol >= 0x0202 ) {
                        cmd_line_ptr = base_ptr + 0x9000;
                } else {
                        cmd_line_magic  = 0xA33F;
                        cmd_line_offset = 0x9000;
                        setup_move_size = 0x9100;
                }
        } else {
                /* ȤƤŤͥ */

                cmd_line_magic  = 0xA33F;
                cmd_line_offset = 0x9000;

                /* ȤƤŤͥϡΥꥢ⡼ɥɤ
                   0x90000 ˥ɤʤФʤʤ */

                if ( base_ptr != 0x90000 ) {
                        /* ꥢ⡼ɥͥ򥳥ԡ */
                        memcpy(0x90000, base_ptr, (setup_sects+1)*512);
                        /* ޥɥ饤򥳥ԡ */
                        memcpy(0x99000, base_ptr+0x9000, 256);

                        base_ptr = 0x90000;             /* ֤줿 */
                }

                /* 32K ޤǥ򥯥ꥢ뤳Ȥ侩 */
                memset(0x90000 + (setup_sects+1)*512, 0,
                       (64-(setup_sects+1))*512);
        }


**** ͥλĤʬɤ

ꥢ⡼ɥͥϥͥեΥեå (setup_sects+1)*512
Ϥޤޤ (ٽҤ٤ޤ setup_sects  0 ΤȤϡºݤͤ 4
Ǥ)ꥢ⡼ɥͥϡImage/zImage ͥʤХɥ쥹
0x10000 ˡbzImage ͥʤ 0x100000 ˥ɤʤФʤޤ

ץȥ뤬 2.00 ʾǡloadflags եɤ 0x01 ӥå (LOAD_HIGH)
åȤƤʤСͥ bzImage Ǥ

        is_bzImage = (protocol >= 0x0200) && (loadflags & 0x01);
        load_address = is_bzImage ? 0x100000 : 0x10000;

Image/zImage ͥϡ512K ΥޤǲǽʤΤǡ0x10000  0x90000
ϰϤȤȤȤդƤϡΥͥ뤬
ꥢ⡼ʬ 0x90000 ˥ɤȤȤʤѤ׵Ǥ
Ȥ̣ޤbzImage Υͥϡä¿ν󶡤ޤ


**** ̤ʥޥɥ饤󥪥ץ

֡ȥˤä󶡤륳ޥɥ饤󤬥桼ˤäϤ
ʤС桼ϲ˼ޥɥ饤󥪥ץư뤳Ȥ
Ƥ⤫ޤޤ󡣤̾ƤͥˤȤäƼ¼Ū
̣櫓ǤϤʤˤƤ⡢ͥ륳ޥɥ饤󤫤
٤ǤϤޤ󡣥֡ȥѤΥޥɥ饤󥪥ץɲä
ɬפȤ֡ȥκԤϡΥץ󤬡ߤ⤷Ͼ
ͥ륪ץȶ礷ʤ褦ˤ뤿ᡢlinux/Documentation/
kernel-parameters.txt ˡΥץϿ٤Ǥ

  vga=<mode>
        ˤ <mode> ϡ (C εˡǡ10 ʿ8 ʿ
        16 ʿΤ줫) ⤷ϡ"normal" (0xFFFF ̣)
        "ext" (0xFFFE  ̣)"ask" (0xFFFD ̣) Ȥ
        ʸΤ줫Ǥͤϡޥɥ饤Ϥ
        ͥ뤬ѤΤǡvid_mode եɤ˥åȤƤ
        ʤФʤޤ

  mem=<size>
        <size>  C εˡˤǡK, M, G (<<10, <<20, <<30 
        ̣ޤ) ˤĤ뤳ȤǤޤˤꡢ
        ͥ˥νλ֤ޤϡinitrd ֲǽ
        ֤˱ƶͿޤȤΤϡinitrd ϥνλ
        ᤯֤뤫ǤΥץϡͥȥ֡
         ** Ф륪ץǤ뤳ȤդƤ!

  initrd=<file>
        initrd ɤޤ<file> ΰ̣ϡ餫˥֡ȥ
        ¸Ǥꡢ֡ȥ (LILO ʤ) ˤϡΤ褦
        ޥɤäƤʤΤ⤢ޤ

ˡ桼Υޥɥ饤˲ΥץäƤ֡
⤢ޤ

  BOOT_IMAGE=<file>
        ɤ줿֡ȥ᡼ٽҤ٤ޤ<file> ΰ̣ϡ
        餫˥֡ȥ˰¸Ƥޤ

  auto
        桼ˤŪʲʤ˥ͥ뤬֡Ȥ줿

Υץ֡ȥɲä硢桼Ρ⤷
ե졼Υޥɥ饤ˡ *ǽ*
֤뤳Ȥ򶯤侩ޤʤȡ"init=/bin/sh"  "auto"
ץǺ𤷤ƤޤǤ礦


**** ͥ餻

ͥ륨ȥݥȤ˥פ뤳ȤˤꡢͥϥȤޤ
ͥ륨ȥݥȤϡꥢ⡼ɥͥγϰ֤ **
եå 0x20 ΤȤ֤ޤϡ⤷ꥢ⡼ɥͥ
ɤ 0x90000 ˥ɤ硢ͥ륨ȥݥȤ 9020:0000 
ʤ뤳Ȥ̣Ƥޤ

ȥǤϡds = es = ss ϥꥢ⡼ɥͥ륳ɤγϰ (⤷
ɤ 0x90000 ˥ɤƤʤ 0x9000) ؤsp Ŭڤ˥åȤ
̾ϥҡפΥȥåפؤߤ϶ػߤˤޤˡͥ
ΥХݸ뤿ᡢ֡ȥ fs = gs = ds = es = ss ȥåȤ
Ȥ侩ޤ

嵭ǤϡΤ褦ˤ뤳ȤˤʤǤ礦

        /* : "Ť" ͥץȥξ硢base_ptr ϡλ
           0x90000 ǤʤФʤʤΥץ륳ɤ򻲾ȤΤȡ*/

        seg = base_ptr >> 4;

        cli();  /* ߤػߤˤ! */

        /* ꥢ⡼ɥͥ륹å򥻥åȤ */
        _SS = seg;
        _SP = 0x9000;   /* SS ľ SP ɤ! */

        _DS = _ES = _FS = _GS = seg;
        jmp_far(seg+0x20, 0);   /* ͥ餻 */

֡ȥեåԡɥ饤֤˥ʤСͥ餻
˥եåԡ⡼ڤ뤳Ȥ侩ޤȤΤϡͥΥ֡
ȤϳߤػߤΤޤޤˤƤΤǡ⡼դˤʤʤǤ
äˡɤ줿ͥ뤬եåԡɥ饤Ф׵ɥ⥸塼
ȤƻäƤ!


**** ٤ʥ֡Ȼեå

⤷֡ȥäŨŪʴĶ (DOS  LOADLIN ʤ) 
ϡɸŪ׵˽ȤԲǽǤ礦Τ褦
֡ȥϡ⤷åȤƤʤСŬڤʳǥͥ
äƼ¹Ԥ벼˼եåȤäƤ⤫ޤޤ󡣤
եåλѤϡ餯ŪǽʤȤƤΤ߹θ٤Ǥ!

: ƤΥեåϡ¹Ԥˤ %esp, %ebp, %esi, %edi ¸
Ȥ׵ᤵޤ

  realmode_swtch:
        ץƥȥ⡼ɤ˰ܹԤľ˼¹Ԥ 16 ӥåȥꥢ⡼ɤ
        far ֥롼󡣥ǥեȤΥ롼 NMI ̵ˤΤǡ
        ʤΥ롼⤪餯٤Ǥ礦

  code32_start:
        ץƥȥ⡼ɰܹľ塢ͥ *פ*
        32 ӥåȤΥեåȥ⡼ɤΥ롼CS ʳΥȤ
        åȤƤޤ¾ΥȤϡʤȤ
        KERNEL_DS (0x18) ˥åȤʤФʤޤ

        եåλ塢ʤΥ֡ȥ񤭤ˤ
        եɤ˥åȤƤɥ쥹إפʤ
        ʤޤ

------------------------------------------------------------
Ρ JF ץ < http://www.linux.or.jp/JF/ >
   2004/04/11
ԡ    ɧ <takahiko(a)hakubi.co.jp>
ԡ     <morimoto(a)xantia.citroen.org>
           ͸  <setzer(a)mx3.tiki.ne.jp>
             <hng(a)ps.ksky.ne.jp>
           Seiji Kaneko <skaneko(a)a2.mbn.or.jp>
