免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 3883 | 回复: 1
打印 上一主题 下一主题

Linux 386 boot代码分析 (2) setup.txt head.txt [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2003-02-08 20:49 |只看该作者 |倒序浏览
看到好文章为什么不能跟大家分享呢?

下面是我整理过的出自http://www.linuxforum.net/的好文章。
原文作者:feiyunw 和 raoxianhong

---------------------------------------------------------------------------
读代码前先看看 raoxianhong  的中文版setup.txt  :
---------------------------------------------------------------------------
1、按规定得有个头,所以一开始是惯用的JMP;
2、头里边内容很丰富,具体用法走着瞧;
3、自我检测,不知道有什么用,防伪造?防篡改?
4、如果装载程序不对,只好死掉!以下终于走入正题;
5、获取内存容量(使用了三种办法,其中的E820和E801看不明白,int 15倒是老朋友了--应该是上个世纪80年代末认识的了,真佩服十年过去了,情意依旧,不过遇上一些不守规矩的BIOS,不知道还行不行);
6、将键盘重复键的重复率设为最大,灵敏一点?
7、检测硬盘,不懂,放这里干什么?
8、检测MCA总线(不要问我这是什么);
9、检测PS/2鼠标,用int 11,只是不知道为何放这里;
10、检测电源管理BIOS;唉,书到用时方恨少,不懂的太多了,真不好意思;不过也没有关系, 不懂的就别去动它就行了;以下要进入内核了;
11、 在进入保护模式之前,可以调用一个你提供的试模式下的过程,让你最后在看她一眼,当然你要是不提供,那就有个默认的,无非是塞住耳朵闭上眼睛禁止任何中断,包括著名的NMI ;
12、设置保护模式起动后的例程地址, 你可以写自己的例程,但不是代替而是把它加在setup提供的例程的前面(显示一个小鸭子?);
13、如果内核是zImage, 将它移动到0x10000处;
14、如果自己不在0x90000处,则移动到0x90000处;
15、建立idt, gdt表;
16、启动A20;
17、屏住呼吸,屏闭所有中断;
18、启动!movw $1, %ax ; lmsw %ax; 好已经进入保护模式下,马上进行局部调整;
19、jmpi 0x100000, __KERNEL_CS,终于进入内核;


---------------------------------------------------------------------------
下面是 feiyunw  的代码分析:
---------------------------------------------------------------------------

  1. ////////////////////////////////////////////////////////////////////
  2. // setup.txt
  3. // Copyright(C) 2001, Feiyun Wang
  4. ////////////////////////////////////////////////////////////////////
  5. // analysis on linux/arch/i386/boot/setup.S (for Linux 2.2.17)
  6. ////////////////////////////////////////////////////////////////////

  7. ////////////////////////////////////////////////////////////////////
  8. // export the margin tags for .text, .data and .bss
  9. {
  10.         .text
  11. begtext:

  12.         .data
  13. begdata:

  14.         .bss
  15. begbss:
  16. }

  17. ////////////////////////////////////////////////////////////////////
  18.         .text
  19. start()
  20.         SYSSEG = 0x1000
  21.         SETUPSEG = 0x9020
  22.         modelist = end of .text:
  23. {
  24.         // if loaded by bootsect.S,
  25.         //      you can assume CS=SETUPSEG (=0x9020), otherwise...
  26.         goto start_of_setup();

  27. /*
  28. http://lxr.linux.no/source/Documentation/i386/boot.txt
  29. Offset/Size  Proto   Name            Meaning
  30. 01F1/1  ALL     setup_sects     The size of the setup in sectors
  31. 01F2/2  ALL     root_flags      If set, the root is mounted readonly
  32. 01F4/2  ALL     syssize         DO NOT USE - for bootsect.S use only
  33. 01F6/2  ALL     swap_dev        DO NOT USE - obsolete
  34. 01F8/2  ALL     ram_size        DO NOT USE - for bootsect.S use only
  35. 01FA/2  ALL     vid_mode        Video mode control
  36. 01FC/2  ALL     root_dev        Default root device number
  37. 01FE/2  ALL     boot_flag       0xAA55 magic number
  38. 0200/2  2.00+   jump            Jump instruction
  39. 0202/4  2.00+   header          Magic signature "HdrS"
  40. 0206/2  2.00+   version         Boot protocol version supported
  41. 0208/4  2.00+   realmode_swtch  Boot loader hook
  42. 020C/4  2.00+   start_sys_seg   Points to kernel version string
  43. 0210/1  2.00+   type_of_loader  Boot loader identifier
  44. 0211/1  2.00+   loadflags       Boot protocol option flags
  45. 0212/2  2.00+   setup_move_size Move to high memory size (used with hooks)
  46. 0214/4  2.00+   code32_start    Boot loader hook
  47. 0218/4  2.00+   ramdisk_image   initrd load address (set by boot loader)
  48. 021C/4  2.00+   ramdisk_size    initrd size (set by boot loader)
  49. 0220/4  2.00+   bootsect_kludge DO NOT USE - for bootsect.S use only
  50. 0224/4  2.01+   heap_end_ptr    Free memory after setup end
  51. 0226/2  N/A     pad1            Unused
  52. 0228/4  2.02+   cmd_line_ptr    32-bit pointer to the kernel command line
  53. */
  54.         .ascii  "HdrS"
  55.         .word   0x0201
  56. realmode_swtch: // boot loader hook
  57.         .word   0, 0
  58. start_sys_seg:  // pointer to kernel version string
  59.         .word   SYSSEG
  60.         .word   kernel_version
  61. type_of_loader:
  62.         .byte   0
  63. loadflags:
  64. #ifndef __BIG_KERNEL__
  65.         .byte   0x00
  66. #else
  67.         .byte   LOADED_HIGH = 1
  68. #endif
  69. setup_move_size:
  70.         .word  0x8000
  71. code32_start:   // boot loader hook
  72. #ifndef __BIG_KERNEL__
  73.         .long   0x1000
  74. #else
  75.         .long   0x100000
  76. #endif
  77. ramdisk_image:  // initrd load address (set by boot loader)
  78.         .long   0
  79. ramdisk_size:   // initrd size (set by boot loader)
  80.         .long   0
  81. bootsect_kludge:        // DO NOT USE - for bootsect.S use only
  82.         .word   bootsect_helper(), SETUPSEG
  83. heap_end_ptr:   // free memory after setup end
  84.         .word   modelist+1024
  85. }

  86. ////////////////////////////////////////////////////////////////////
  87. // check signature to see if all code loaded
  88. start_of_setup()
  89. {
  90.         // get disk type, bootlin depends on this
  91.         // http://www.ctyme.com/intr/rb-0639.htm
  92.         int13h/AH=15h(AL=0, DL=0x81);

  93. #ifdef SAFE_RESET_DISK_CONTROLLER
  94.         int13h/AH=0(AL=0, DL=0x80);     // reset hd0
  95. #endif

  96.         // check signature at the end of setup code
  97.         if (setup_sig1!=SIG1 || setup_sig2!=SIG2) {
  98.                 // since size of setup may >; 4 sectors,
  99.                 //      the rest code may be loaded at SYSSEG
  100.                 goto bad_sig;
  101.         }
  102.         goto goodsig1;
  103. }

  104. ////////////////////////////////////////////////////////////////////
  105. // some small functions
  106. prtstr() { /* ... print ASCIIz string at DS:SI */}
  107. prtsp2() { /* ... print double space */ }
  108. prtspc() { /* ... print single space */ }
  109. prtchr() { /* ... print ASCII AL */ }
  110. beep() { /* ... beep */ }

  111. ////////////////////////////////////////////////////////////////////
  112. goodsig1() { goto goodsig; }    // making near jumps

  113. ////////////////////////////////////////////////////////////////////
  114. // move rest setup code from SYSSEG:0 to CS:0800
  115. // TODO: it won't work if image loaded at 0x100000?
  116. bad_sig()
  117.         DELTA_INITSEG = 0x0020 (= SETUPSEG - INITSEG)
  118.         SYSSEG = 0x1000
  119. {
  120.         BX = (CS-DELTA_INITSEG):[497];          // i.e. setup_sects
  121.         // first 4 sectors have been loaded
  122.         CX = (BX - 4) << 8;                     // rest code in words
  123.         start_sys_seg = (CX >;>; 3) + SYSSEG;     // real system code start

  124.         move SYSSEG:0 to CS:0800 (CX*2 bytes);

  125.         if (setup_sig1!=SIG1 || setup_sig2!=SIG2) {
  126.                 prtstr("No setup signature found ...");
  127.                 halt;
  128.         }
  129. }

  130. ////////////////////////////////////////////////////////////////////
  131. // check if loader compatible with image
  132. good_sig()
  133.         LOADHIGH = 1
  134. {
  135.         if ((loadflags & LOADHIGH) && (!type_of_loader)) {
  136.                 // Nope, old loader want to load big kernel
  137.                 prtstr("Wrong loader:  giving up.");
  138.                 halt;
  139.         }
  140. }

  141. ////////////////////////////////////////////////////////////////////
  142. // get memory size
  143. // set the keyboard repeat rate to max
  144. // check video adapter
  145. // get hd0 & hd1 data
  146. // check for Micro Channel (MCA) bus
  147. // check for PS/2 pointing device
  148. // check for APM BIOS
  149. // move code to INITSEG/SETUPSEG
  150. // load IDT and GDT
  151. // enable and test A20
  152. // reset coprocessor
  153. // reprogram the interrupts
  154. // switch to protected mode
  155. // goto KERNEL
  156. loader_ok()
  157.         SETUPSET = 0x9020
  158.         INITSEG = 0x9000
  159.         DELTA_INITSEG = 0x20
  160. {
  161.         // DS = CS - DELTA_INITSEG when entering this function

  162.         // get memory size
  163. #ifndef STANDARD_MEMORY_BIOS_CALL
  164.         (double word)DS:[0x1E0] = 0;
  165.         try {
  166.                 // get memory size for >;64M configurations
  167.                 // http://www.ctyme.com/intr/rb-1739.htm
  168.                 int15h/AX=E801h;
  169.                 //      AX = extended memory between 1M and 16M, in KB
  170.                 //      BX = extended memory above 16M, in 64K blocks
  171.                 (double word)DS:[0x1E0] = ((EBX & 0xFFFF) << 6)
  172.                         + (EAX & 0xFFFF);
  173.         }
  174. #else
  175.         (double word)DS:[0x1E0] = 0;
  176. #endif

  177.         // get extended memory size
  178.         // http://www.ctyme.com/intr/rb-1529.htm
  179.         int15h/AH=88h;
  180.         DS:[2] = AX;    // KB of contiguous memory from 100000h

  181.         // set the keyboard repeat rate to max
  182.         // http://www.ctyme.com/intr/rb-1757.htm
  183.         int16h/AX=0305h(BX=0);

  184.         // check video adapter and its parameters, see video.S
  185.         video();

  186.         // get hd0 & hd1 data
  187.         // http://www.ctyme.com/intr/rb-6135.htm
  188.         // http://www.ctyme.com/intr/rb-6184.htm
  189.         //      pointers in 0:0104 & 0:0118 respectively
  190.         move hd0 data to CS-DELTA_INITSEG:0080 (16 bytes);
  191.         move hd1 data to CS-DELTA_INITSEG:0090 (16 bytes);

  192.         // get disk type, check if hd1 exists
  193.         // http://www.ctyme.com/intr/rb-0639.htm
  194.         int13h/AH=15h(AL=0, DL=0x81);
  195.         if (failed || AH!=03h) {        // AH=03h if is a hard disk
  196.                 clear CS-DELTA_INITSEG:0090 (16 bytes);
  197.         }

  198.         // check for Micro Channel (MCA) bus
  199.         DS:[0xA0] = 0;    // set table length to 0
  200.         try {
  201.                 // get system configuration
  202.                 // http://www.ctyme.com/intr/rb-1594.htm
  203.                 int15h/AH=C0h;  // ES:BX = ROM configuration table
  204.                 move ROM configuration table to CS-DELTA_INITSEG:00A0;
  205.                 //      first 16 bytes only
  206.         }

  207.         // check PS/2 pointing device
  208.         DS:[0x1FF] = 0;
  209.         // get equipment list
  210.         // http://www.ctyme.com/intr/rb-0575.htm
  211.         int11h();
  212.         if (has psmouse) {
  213.                 DS:[0x1FF] = 0xAA;
  214.         }

  215. #ifdef CONFIG_APM
  216.         // check for APM BIOS

  217.         DS:[0x40] = 0;
  218.         // Advanced Power Management v1.0+ - installation check
  219.         // http://www.ctyme.com/intr/rb-1394.htm
  220.         int15h/AX=5300h(BX=0);
  221.         // check both CF and BX for APM support
  222.         if (APM && 32-bit protected mode interface supported) {
  223.                 int15h/AX=5304h(BX=0);  // disconnect interface
  224.                 try {
  225.                         // clear return values first
  226.                         clear EBX, CX, DX, ESI, DI;
  227.                         // connect 32bit protect mode APM interface
  228.                         // http://www.ctyme.com/intr/rb-1397.htm
  229.                         int15h/AX=5303h(BX=0);
  230.                         if (supported) {
  231.                                 DS:[0x42] = 32-bit code segment base address;
  232.                                 DS:[0x44] = offset of entry point;
  233.                                 DS:[0x48] = 16-bit code segment base address;
  234.                                 DS:[0x4A] = 16-bit data segment base address;
  235.                                 DS:[0x4E] = APM BIOS code segment length;
  236.                                 DS:[0x52] = APM BIOS data segment length;
  237.                                 int15h/AX=5300h(BX=0);  // check again
  238.                                 if (APM supported) {
  239.                                         INITSET:[0x40] = APM version;
  240.                                         INITSET:[0x4C] = APM flags;
  241.                                 }
  242.                                 else {  // should not happen
  243.                                         // disconnect interface
  244.                                         int15h/AX=5304h(BX=0);
  245.                                 }
  246.                         }
  247.                         else {
  248.                                 // clear 32bit support
  249.                                 INITSET:[0x4C] &= ~0x0002;
  250.                         }
  251.                 }
  252.         }
  253. #endif

  254.         // call mode switch
  255.         if (realmode_swtch) {
  256.                 far realmode_swtch();   // mode switch hook
  257.         }
  258.         else {
  259.                 far default_switch();   // see below
  260.         }

  261.         // set code32: 0x100000 for big kernel,  otherwise 0x1000
  262.         (double word) code32 = code32_start;
  263.         if (!(loadflags & LOADED_HIGH)) {
  264.                 // normal low loaded zImage
  265.                 move start_sys_seg:0 to (0100:0 ... CS-DELTA_INITSEG:0);
  266.                 //      move 0x1000 bytes each time
  267.         }
  268.         if (CS!=SETUPSEG) {
  269.                 cli;    // disable interrupts

  270.                 // store new SS in DX
  271.                 DX = SS;
  272.                 AX = CS - DELTA_INITSEG;
  273.                 if (DX>;=AX) {
  274.                         DX = DX + INITSEG - AX; // i.e. SS-CS+SETUPSEG
  275.                 }

  276.                 // move CS-DELTA_INITSEG:0 to INITSEG:0 (setup_move_size bytes)
  277.                 // TODO: why not do this in one step?
  278.                 ES = INITSEG;
  279.                 move _DOWNWARD_ from CS-DELTA_INITSEG:setup_move_size-1 to
  280.                         (INITSEG:setup_move_size-1
  281.                         ... INITSEG:move_self_here+0x200);
  282.                 // setup_move_size-move_self_here-0x200 bytes
  283.                 // INITSEG:move_self_here+0x200 = SETUPSEG:move_self_here
  284.                 goto SETUPSEG:move_self_here;
  285. move_self_here:
  286.                 move the rest to INITSEG:move_self_here+0x200-1 ... INITSEG:0;
  287.                 // move_self_here+0x200 bytes
  288.                 DS = SETUPSEG;
  289.                 SS = DX;
  290.         }
  291.         // CS==SETUPSEG is true now

  292.         // Protected Mode Basics
  293.         // http://x86.ddj.com/articles/pmbasics/tspec_a1_doc.htm

  294.         lidt    idt_48; // load idt with 0, 0;
  295.         // new code added here in Linux 2.4
  296.         lgdt    gdt_48; // load gdt with whatever appropriate;

  297.         // enable A20
  298.         empty_8042();
  299.         outportb(0x64, 0xD1);   // command write
  300.         empty_8042();
  301.         outportb(0x60, 0xDF);   // A20 on
  302.         empty_8042();

  303. #define TEST_ADDR 0x7C

  304.         // test A20
  305.         GS = AX = 0xFFFF;
  306.         BX = 0:[TEST_ADDR];
  307.         do {
  308.                 0:[TEST_ADDR] = ++AX;
  309.         } while (AX==GS:[TEST_ADDR+0x10]);
  310.         0:[TEST_ADDR] = BX;

  311.         // reset coprocessor
  312.         outportb(0xF0, 0);
  313.         delay();
  314.         outportb(0xF1, 0);
  315.         delay();

  316.         // reprogram the interrupts
  317.         outportb(0x20, 0x11);   // initialize 8259A-1
  318.         delay();
  319.         outportb(0xA0, 0x11);   // initialize 8259A-2
  320.         delay();
  321.         outportb(0x21, 0x20);   // start of hardware int's (0x20)
  322.         delay();
  323.         outportb(0xA1, 0x28);   // start of hardware int's 2 (0x28)
  324.         delay();
  325.         outportb(0x21, 0x04);   // 8259-1 is master
  326.         delay();
  327.         outportb(0xA1, 0x02);   // 8259-2 is slave
  328.         delay();
  329.         outportb(0x21, 0x01);   // 8086 mode
  330.         delay();
  331.         outportb(0xA1, 0x01);   // 8086 mode
  332.         delay();
  333.         outportb(0xA1, 0xFF);   // mask off all interrupts for now
  334.         delay();
  335.         outportb(0x21, 0xFB);   // mask all irq's but irq2, which is cascaded

  336.         // protected mode!
  337.         mov     ax, #1;
  338.         lmsw    ax;
  339.         jmp     flush_instr;
  340. flush_instr:
  341.         xor     bx, bx;
  342. }

  343. ////////////////////////////////////////////////////////////////////
  344. {
  345.         db      0x66, 0xea
  346. code32:
  347.         dd      0x1000
  348.         dw      __KERNEL_CS     // 0x10, defined in asm-i386/segment.h
  349. //      goto 10:1000 or 10:100000

  350. kernel_version:
  351.         .ascii  UTS_RELEASE     // defined in makefile
  352.         .ascii  "("
  353.         .ascii  LINUX_COMPILE_BY
  354.         .ascii  "@"
  355.         .ascii  LINUX_COMPILE_HOST
  356.         .ascii  ")"
  357.         .ascii  UTS_VERSION
  358.         db      0
  359. }

  360. ////////////////////////////////////////////////////////////////////
  361. // default real mode switch routine
  362. far default_switch()
  363. {
  364.         cli;
  365.         outportb(0x70, 0x80);   // disable NMI
  366. }

  367. ////////////////////////////////////////////////////////////////////
  368. // get called when using bootsect loader _AND_ have bzImage to load
  369. far bootsect_helper(ES)
  370. {
  371.         if (bootsect_es==0) {
  372.                 type_of_loader = 0x20;  // bootsect-loader, version 0
  373.                 AX = ES >;>; 4;
  374.                 CS:[bootsect_src_base+2] = AH;
  375.                 bootsect_es = ES;
  376.                 AX = ES - SYSSEG;
  377.         }
  378.         else {
  379.                 if (BX==0) {       // 64K aligned
  380.                         // copy extended memory
  381.                         // http://www.ctyme.com/intr/rb-1527.htm
  382.                         try {
  383.                                 int15h/AX=87h(CX=0x8000,
  384.                                         ES:SI=CS:bootsect_gdt);
  385.                         }
  386.                         catch {
  387. bootsect_panic:
  388.                                 prtstr("INT15 refuses to access high memory."
  389.                                         " Giving up.");
  390.                                 halt;
  391.                         }
  392.                         ES = bootsect_es;
  393.                         CS:[bootsect_dst_base+2]++;
  394.                 }
  395.                 AH = CS:[bootsect_dst_base+2] << 4;
  396.                 AL = 0;
  397.         }
  398. }

  399. ////////////////////////////////////////////////////////////////////
  400. {
  401. bootsect_gdt:
  402.         .word   0, 0, 0, 0
  403.         .word   0, 0, 0, 0
  404. bootsect_src:
  405.         .word   0xFFFF
  406. bootsect_src_base:
  407.         .byte   0, 0, 1         ! base = 0x010000
  408.         .byte   0x93            ! typbyte
  409.         .word   0               ! limit16, base24 =0
  410. bootsect_dst:
  411.         .word   0xFFFF
  412. bootsect_dst_base:
  413.         .byte   0, 0, 0x10      ! base = 0x100000
  414.         .byte   0x93            ! typbyte
  415.         .word   0               ! limit16, base24 =0
  416.         .word   0, 0, 0, 0      ! used by BIOS
  417.         .word   0, 0, 0, 0
  418. bootsect_es:
  419.         .word   0
  420. }

  421. ////////////////////////////////////////////////////////////////////
  422. // check that the keyboard command queue is empty
  423. empty_8042()
  424. {
  425.         timeout = 0xFFFFFF;             // local variable
  426.         for (;;) {
  427.                 if (--timeout==0) return;
  428.                 delay();
  429.                 inportb(0x64, AL);      // 8042 status port
  430.                 if (AL & 1) {           // output buffer
  431.                         delay();
  432.                         inportb(0x60, .);
  433.                         continue;
  434.                 }
  435.                 if (!(AL & 2)) return;  // input buffer
  436.         }
  437. }

  438. ////////////////////////////////////////////////////////////////////
  439. // read the CMOS clock, return the seconds in AL
  440. gettime()
  441. {
  442.         // get real-time clock time
  443.         // http://www.ctyme.com/intr/rb-2273.htm
  444.         int1Ah/AH=02h();        // DH = seconds (in BCD)
  445.         AL = DH & 0x0F;
  446.         AH = DH >;>; 4;
  447.         AAD;
  448. }

  449. ////////////////////////////////////////////////////////////////////
  450. delay() { /* needed after doing I/O */ }

  451. ////////////////////////////////////////////////////////////////////
  452. {
  453. gdt:
  454.         .word   0,0,0,0         ! dummy
  455.         .word   0,0,0,0         ! unused

  456.         .word   0xFFFF          ! 4Gb - (0x100000*0x1000 = 4Gb)
  457.         .word   0x0000          ! base address=0
  458.         .word   0x9A00          ! code read/exec
  459.         .word   0x00CF          ! granularity=4096, 386 (+5th nibble of limit)

  460.         .word   0xFFFF          ! 4Gb - (0x100000*0x1000 = 4Gb)
  461.         .word   0x0000          ! base address=0
  462.         .word   0x9200          ! data read/write
  463.         .word   0x00CF          ! granularity=4096, 386 (+5th nibble of limit)
  464. idt_48:
  465.         .word   0               ! idt limit=0
  466.         .word   0, 0            ! idt base=0L
  467. gdt_48:
  468.         .word   0x800           ! gdt limit=2048, 256 GDT entries
  469.         .word   512+gdt, 0x9    ! gdt base = 0x9XXXX
  470.         // +512 because of bootsect
  471. }

  472. ////////////////////////////////////////////////////////////////////
  473. // Included video setup & detection code "video.S"
  474. /*
  475. Positions of various video parameters passed to the kernel
  476.         (see also include/linux/tty.h)
  477. CS-DELTA_INITSEG segment
  478. #define PARAM_CURSOR_POS        0x00
  479. #define PARAM_VIDEO_PAGE        0x04
  480. #define PARAM_VIDEO_MODE        0x06
  481. #define PARAM_VIDEO_COLS        0x07
  482. #define PARAM_VIDEO_EGA_BX      0x0a
  483. #define PARAM_VIDEO_LINES       0x0e
  484. #define PARAM_HAVE_VGA          0x0f
  485. #define PARAM_FONT_POINTS       0x10
  486. #define PARAM_LFB_WIDTH         0x12
  487. #define PARAM_LFB_HEIGHT        0x14
  488. #define PARAM_LFB_DEPTH         0x16
  489. #define PARAM_LFB_BASE          0x18
  490. #define PARAM_LFB_SIZE          0x1c
  491. #define PARAM_LFB_LINELENGTH    0x24
  492. #define PARAM_LFB_COLORS        0x26
  493. #define PARAM_VESAPM_SEG        0x2e
  494. #define PARAM_VESAPM_OFF        0x30
  495. #define PARAM_LFB_PAGES         0x32
  496. */
  497. video()
  498. {
  499.         FS = DS;
  500.         DS = ES = CS;
  501.         GS = 0;
  502.         basic_detect();

  503. #ifdef CONFIG_VIDEO_SELECT
  504.         if (FS:[0x1FA]!=ASK_VGA) {
  505.                 // ASK_VGA=0xFFFD, defined in asm-i386/boot.h
  506.                 mode_set();
  507.                 if (failed) {
  508.                         prtstr("You passed an undefined mode number.");
  509.                 }
  510.         }
  511.         else {
  512.                 mode_menu();
  513.         }

  514. #ifdef CONFIG_VIDEO_RETAIN
  515.         restore_screen();
  516. #endif

  517. #endif

  518.         mode_params();
  519. }

  520. ////////////////////////////////////////////////////////////////////
  521.         SIG1 = 0xAA55
  522.         SIG2 = 0x5A5A
  523. {
  524. setup_sig1:     .word   SIG1
  525. setup_sig2:     .word   SIG2
  526. modelist:

  527.         .text
  528. endtext:

  529.         .data
  530. enddata:

  531.         .bss
  532. endbss:
  533. }

  534. ////////////////////////////////////////////////////////////////////
  535. // end of file

复制代码


---------------------------------------------------------------------------
再看 feiyunw  的代码分析:
---------------------------------------------------------------------------

  1. ////////////////////////////////////////////////////////////////////
  2. // head.txt
  3. // Copyright(C) 2001, Feiyun Wang
  4. ////////////////////////////////////////////////////////////////////
  5. // analysis on linux/arch/i386/kernel/head.S (for Linux 2.2.17)
  6. ////////////////////////////////////////////////////////////////////

  7. ////////////////////////////////////////////////////////////////////
  8. startup_32()
  9.         __KERNEL_DS = 0x18;
  10.         CL_MAGIC = 0xA33F;
  11.         CL_MAGIC_ADDR = 0x90020;
  12.         CL_BASE_ADDR = 0x90000;
  13.         CL_OFFSET = 0x90022;
  14. {
  15.         cld;
  16.         DS = ES = FS = GS = __KERNEL_DS (= 0x18);

  17. #ifdef __SMP__
  18.         if (BX) {
  19.                 CR4 |= mmu_cr4_features-__PAGE_OFFSET;
  20.                 // mmu_cr4_features defined in arch/i386/mm/init.c
  21.                 // __PAGE_OFFSET defined in include/asm-i386/page.h
  22.         }
  23. #endif

  24.         CR3 = 0x101000;                // page table pointer
  25.         CR0 |= 0x80000000;        // set PG bit

  26.         SS:ESP = stack_start;

  27. #ifdef __SMP__
  28.         if (BX) {
  29.                 EFLAG = 0;
  30.                 goto checkCPUtype;
  31.         }
  32. #endif

  33.         clear BSS (__bss_start .. _end);
  34.         setup_idt();
  35.         EFLAGS = 0;
  36.         move 0x90000 to empty_zero_page (i.e. 0x5000) (2 KByte);
  37.         clear empty_zero_page+2K (2 KByte);

  38.         if (CL_MAGIC==*(CL_MAGIC_ADDR)) {
  39.                 move *(CL_OFFSET)+CL_BASE_ADDR to empty_zero_page+2K (2 KByte);
  40.         }
  41. }

  42. ////////////////////////////////////////////////////////////////////
  43. checkCPUtype()
  44.         global variables: ready
  45.         // see include/asm-i386/processor.h struct cpuinfo_x86
  46.         // boot_cpu_data defined in arch/i386/kernel/setup.c
  47.         struct cpuinfo_x86 boot_cpu_data;
  48.         __KERNEL_DS = 0x18;
  49. {
  50.         X86_CPUID = -1;

  51.         X86 = 3;
  52.         save original EFLAGS;
  53.         check AC bit in EFLAGS;
  54.         if (AC bit not changed) goto is386;

  55.         X86 = 4;
  56.         check ID bit in EFLAGS;
  57.         restore original EFLAGS;
  58.         if (ID bit not changed) goto is486;

  59.         // get CPU info,
  60.         // <>; Vol.2 P.3-110
  61.         CPUID(EAX=0);
  62.         X86_CPUID = EAX;
  63.         X86_VENDOR_ID = EBX;
  64.         *((&X86_VENDOR_ID)+4) = ECX;
  65.         *((&X86_VENDOR_ID)+8) = EDX;
  66.         if (!EAX) goto is486;

  67.         CPUID(EAX=1);
  68.         CL = AL;
  69.         X86 = AH & 0x0f;                // family
  70.         X86_MODEL = (AL & 0xf0) >;>; 4;        // model
  71.         X86_MASK = AL & 0x0f;                // stepping id
  72.         X86_CAPABILITY = EDX;                // feature

  73. is486:
  74.         // save PG, PE & ET, set AM, WP, NE & MP
  75.         EAX = (CR0 & 0x80000011) | 0x50022;
  76.         goto 2f;
  77. is386:
  78.         restore original EFLAGS;
  79.         // save PG, PE & ET, set MP
  80.         EAX = (CR0 & 0x80000011) | 0x02;
  81. 2f:
  82.         CR0 = EAX;
  83.         check_x87();

  84. #ifdef __SMP__
  85.         if (ready) {
  86.                 CR4 |= 0x10;        // set PSE, turn on 4 MByte pages
  87.                 CR3 = CR3;
  88.         }
  89.         ready++;
  90. #endif;

  91.         lgdt gdt_descr;
  92.         lidt idt_descr;
  93.         DS = ES = FS = GS = __KERNEL_DS (= 0x18);

  94. #ifdef __SMP__
  95.         SS = __KERNEL_DS (= 0x18);
  96. #else
  97.         SS:ESP = stack_start;
  98. #endif

  99.         lldt 0;
  100.         cld;
  101.         start_kernel();
  102.         halt;
  103. }

  104. ////////////////////////////////////////////////////////////////////
  105. {
  106. #ifdef __SMP__
  107. ready:        .byte 0;
  108. #endif
  109. }

  110. ////////////////////////////////////////////////////////////////////
  111. check_x87()
  112. {
  113.         X86_HARD_MATH = 0;
  114.         clts;
  115.         fninit;
  116.         fstsw ax;
  117.         if (al) {
  118.                 // no coprocessor, set EM;
  119.                 // TODO; why not use |=?
  120.                 cr0 ^= 0x04;
  121.         }
  122.         else {
  123.                 X86_HARD_MATH = 1;
  124.                 fsetpm;                // 0xDB, 0xE4
  125.         }
  126. }

  127. ////////////////////////////////////////////////////////////////////
  128. setup_idt()
  129. {
  130.         edx = &ignore_int;
  131.         eax = __KERNEL_CS << 16;
  132.         ax = dx;
  133.         dx = 0x8E00;        // interrupt gate, dpl = 0, present

  134.         set all entries in idt_table to eax:edx;        // 256*8 Bytes
  135. }

  136. ////////////////////////////////////////////////////////////////////
  137. {
  138. stack_start:
  139.         .long init_task_union+8192;
  140.         .long __KERNEL_DS;
  141. }

  142. ////////////////////////////////////////////////////////////////////
  143. ignore_init()
  144. {
  145.         printk("Unknown interrupt\n");
  146. }

  147. ////////////////////////////////////////////////////////////////////
  148. {
  149.         NR_TASKS = 512;                // defined in include/linux/tasks.h
  150.         IDT_ENTRIES = 256;
  151.         GDT_ENTRIES = 12+2*NR_TASKS;

  152.         .word 0;
  153. idt_descr:
  154.         .word IDT_ENTRIES*8-1;
  155. idt:
  156.         .long idt_table;

  157.         .word 0;
  158. gdt_descr:
  159.         .word GDT_ENTRIES*8-1;
  160. gdt:
  161.         .long gdt_table;
  162. }

  163. ////////////////////////////////////////////////////////////////////
  164. {
  165.         .org 0x1000;
  166. swapper_pg_dir:
  167.         .long 0x00102007;
  168.         .fill __USER_PGD_PTRS-1, 4, 0;                // 767 entries
  169.         .long 0x00102007;
  170.         .fill __KERNEL_PGD_PTRS-1, 4, 0;        // 255 entries

  171.         .org 0x2000;
  172. pg0:
  173.         // ...

  174.         .org 0x3000;
  175. empty_bad_page:

  176.         .org 0x4000;
  177. empty_bad_page_table:

  178.         .org 0x5000;
  179. empty_zero_page:

  180.         .org 0x6000;
  181. .data
  182. gdt_table:
  183.         .quad 0x0000000000000000;        // null
  184.         .quad 0x0000000000000000;        // not used
  185.         .quad 0x00cf9a000000ffff;        // 0x10 kernel 4GB code at 0x00000000
  186.         .quad 0x00cf92000000ffff;        // 0x18 kernel 4GB data at 0x00000000
  187.         .quad 0x00cffa000000ffff;        // 0x20 user 4GB code at 0x00000000
  188.         .quad 0x00cff2000000ffff;        // 0x28 user 4GB data at 0x00000000
  189.         .quad 0x0000000000000000;        // not used
  190.         .quad 0x0000000000000000;        // not used

  191.         .quad 0x0040920000000000;        // 0x40 APM setup for bad BIOS
  192.         .quad 0x00409a0000000000;        // 0x48 APM CS code
  193.         .quad 0x00009a0000000000;        // 0x50 APM CS 16 code (16 bit)
  194.         .quad 0x0040920000000000;        // 0x58 APM DS data
  195.         .fill 2*NR_TASKS, 8, 0;

  196. .section .text.lock
  197. stext_lock:
  198. }

  199. ////////////////////////////////////////////////////////////////////
  200. // end of file

复制代码

论坛徽章:
1
荣誉版主
日期:2011-11-23 16:44:17
2 [报告]
发表于 2003-03-12 00:28 |只看该作者

Linux 386 boot代码分析 (2) setup.txt head.txt

北京雪夜,好,为什么不继续了呢?
论坛,其实大家应该随心所欲的写些东西了,斑竹认为呢?
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP