免费注册 查看新帖 |

Chinaunix

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

Linux 386 boot代码分析 (1) bootsect.txt [复制链接]

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

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

---------------------------------------------------------------------------
feiyunw 的开场篇:
---------------------------------------------------------------------------
应lucian_yao的建议,我把我写的初始化分析的文章重贴到文档版。
(原先贴在内核技术版,现在又做了一些修改)
写这些东西是因为当时看程序时找不到类似的东西,干脆就自己写了:


bootsect.txt        linux/arch/i386/boot/bootsect.S
setup.txt        linux/arch/i386/boot/setup.S
head.txt        linux/arch/i386/kernel/head.S

希望对大家学习Linux有帮助。

基于Linux 2.2.17是因为我用Redhat7.0。
当时Redhat7.0用Linux2.2.16,我想17和16的差别比较小,就用了17做分析。

关于版权说明:还不知道使用什么声明比较合适,所以就把Copyright留在文件里了。
我认为GPL适合free software,对这种文档性质的东西可能不太合适。
不过可以参照GPL的“free software”使用这些“free document”。

---------------------------------------------------------------------------
读代码前先看看 raoxianhong 的中文版bootsect.txt :
---------------------------------------------------------------------------
看程序太累,请看中文版的bootsect.txt
1.将自己移动到0x9000:0x0000处,为内核调入留出地址空间;
2.建立运行环境(ss=ds=es=cs=0x9000, sp=0x4000-12),保证起动程序运行;
3.BIOS初始化0x1E号中断为软盘参数表,将它取来保存备用;
4.将setup读到0x9000:0x0200处;
5.测试软盘参数一个磁道有多少个扇区(也没有什么好办法,只能试试36, 18, 15, 9对不对了);
6.打印“Loading”;
7.读入内核到0x1000:0000(如果是bzImage, 则将每个64K移动到0x100000处,在实模式下,只能调用0x15号中断了,这段代码无法放在bootsect中所以只能放在setup中,幸好此时setup已经读入了);
8.到setup去吧

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

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

  7. ////////////////////////////////////////////////////////////////////
  8. #if 0
  9.         int 3;                        // for debugger
  10. #endif

  11. _main()
  12.         BOOTSEG = 0x07C0
  13.         INITSEG = 0x9000
  14. {
  15.         move BOOTSEG:0 to INITSEG:0 (512 bytes);
  16.         goto INITSEG:go;        // CS:IP = INITSEG:go
  17. }

  18. ////////////////////////////////////////////////////////////////////
  19. // prepare disk parameter table
  20. go()
  21.         INITSEG = 0x9000
  22. {
  23.         set SS:SP to INITSEG:3FF4;        // 0x4000-0x0C
  24.         copy disk parameter table (pointer in 0:0078)
  25.                 to INITSEG:3FF4 (12 bytes);
  26.         patch sector count to 36 (offset 4 in parameter table, 1 byte);
  27.         set disk parameter table pointer (0:0078) to INITSEG:3FF4;
  28. }

  29. ////////////////////////////////////////////////////////////////////
  30. // load the setup-sectors directly after the bootblock
  31. load_setup()
  32.         setup_sects = SETUPSECS = 4
  33.         INITSEG = 0x9000
  34. {
  35.         for(;;) {
  36.                 int13h/AH=0(DL=0);      // reset FDC
  37.                 try {
  38.                         // http://www.ctyme.com/intr/rb-0607.htm
  39.                         int13h/AH=02h(AL=setup_sects,
  40.                                 ES:BX=INITSEG:0200,
  41.                                 CX=2, DX=0);
  42.                         break;
  43.                 }
  44.                 catch (disk error) {
  45.                         print_nl();
  46.                         print_hex(SP);
  47.                 }
  48.         }
  49. }

  50. ////////////////////////////////////////////////////////////////////
  51. // get disk drive parameters, specifically sectors#/track
  52. ok_load_setup()
  53.         global variables: disksizes, sectors
  54. {
  55. #if 0
  56.         // get disk drive parameters
  57.         // http://www.ctyme.com/intr/rb-0621.htm
  58.         int13h/AH=08h(DL=0);
  59.         CH = 0;
  60.         // seems not completed yet
  61. #else
  62.         // probe sectors with disksize[] = {36, 18, 15, 9}
  63.         SI = &disksizes;
  64.         for (;;) {
  65.                 sectors = DS:[SI++];
  66.                 if (SI>;=disksizes+4) break;
  67.                 try {
  68.                         int13h/AH=02h(AL=1,
  69.                                 ES:BX=INITSEG:((setup_sects+1)<<9),
  70.                                 CX=sectors, DX=0);
  71.                         break;
  72.                 }
  73.                 catch {
  74.                 }
  75.         }
  76. #endif
  77. }

  78. ////////////////////////////////////////////////////////////////////
  79. // print out "Loading"
  80. // load the system image
  81. // set root_dev
  82. // jump to the setup-routine loaded directly after the bootblock
  83. got_sectors()
  84.         INITSEG = 0x9000
  85.         SYSSEG = 0x1000
  86.         SETUPSEG = 0x9020
  87.         global variable: root_dev
  88. {
  89.         // int10h/AH=03h http://www.ctyme.com/intr/rb-0088.htm
  90.         // int10h/AH=13h http://www.ctyme.com/intr/rb-0210.htm
  91.         print out "Loading";

  92.         read_it(ES=SYSSEG);
  93.         kill_motor();
  94.         print_nl();

  95.         if (!root_dev) {
  96.                 switch (sectors) {
  97.                 case 15: root_dev = 0x0208;        // /dev/ps0 - 1.2Mb
  98.                         break;
  99.                 case 18: root_dev = 0x021C;        // /dev/PS0 - 1.44Mb
  100.                         break;
  101.                 case 36: root_dev = 0x0220;        // /dev/fd0H2880 - 2.88Mb
  102.                         break;
  103.                 default: root_dev = 0x0200;        // /dev/fd0 - autodetect
  104.                         break;
  105.                 }
  106.         }

  107.         goto SETUPSEG:0;
  108.         // see linux/arch/i386/boot/setup.S
  109. }

  110. word sread = 0;                // sectors read of current track
  111. word head = 0;                // current head
  112. word track = 0;                // current track
  113. ////////////////////////////////////////////////////////////////////
  114. // load the system image
  115. read_it(ES)
  116.         setup_sects = SETUPSECS = 4
  117.         SYSSEG = 0x1000
  118.         syssize = SYSSIZE = 0x7F00
  119. {
  120.         sread = setup_sects + 1;        // plus 1 bootsect
  121.         if (ES & 0x0fff) halt;                // not 64KB aligned
  122.         BX = 0;

  123.         for (;;) {
  124. rp_read:
  125. #ifdef __BIG_KERNEL__
  126.                 .word   0x1eff, 0x220;
  127.                 // call far * bootsect_kludge, see setup.S
  128. #else
  129.                 AX = ES - SYSSEG;
  130. #endif
  131.                 if (AX>;syssize) return;

  132. ok1_read:
  133.                 // get proper AL (sectors to read),
  134.                 //      not to across tracks or make BX overflow
  135.                 AX = sectors - sread;
  136.                 CX = BX + (AX << 9);
  137.                 // TODO: I think CX!=0 can be omitted
  138.                 if (CX overflow && CX!=0) {
  139.                         AX = (-BX) >;>; 9;
  140.                 }
  141. ok2_read:
  142.                 read_track(AL, ES:BX);
  143.                 CX = AX;
  144.                 AX += sread;
  145.                 if (AX==sectors) {
  146.                         if (head==1) track++;
  147.                         head = 1 - head;
  148.                         AX = 0;
  149.                 }
  150. ok3_read:
  151.                 sread = AX;
  152.                 BX += CX << 9;
  153.                 if (BX overflow) {
  154.                         ES += 0x1000;
  155.                         BX = 0;
  156.                 }
  157.         }
  158. }

  159. ////////////////////////////////////////////////////////////////////
  160. // read disk with (sread, track, head)
  161. read_track(AL, ES:BX)
  162. {
  163.         for (;;) {
  164.                 printf(".");

  165.                 // set CX, DX according to (sread, track, head)
  166.                 DX = track;
  167.                 CX = sread + 1;
  168.                 CH = DL;

  169.                 DX = head;
  170.                 DH = DL;
  171.                 DX &= 0x0100;

  172.                 try {
  173.                         int13h/AH=02h(AL, ES:BX, CX, DX);
  174.                         return;
  175.                 }
  176.                 catch (disk error) {
  177. bad_rt:
  178.                         print_all();
  179.                         int13h/AH=0h(DL=0);     // reset FDC
  180.                 }
  181.         }
  182. }

  183. ////////////////////////////////////////////////////////////////////
  184. // some small functions
  185. print_all() { /* ... print out error, AX, BX, CX, DX */ }
  186. print_nl() { /* ... print CR LF */ }
  187. print_hex() { /* ... print the word pointed by SS:BP in hex */ }
  188. kill_motor() { outportb(0x3F2, 0); /* turn off floppy drive motor */}

  189. ////////////////////////////////////////////////////////////////////
  190. // global variables for bootsect.S
  191. {
  192. sectors:
  193.         .word 0
  194. disksizes:
  195.         .byte 36, 18, 15, 9
  196. msg1:
  197.         .byte 13, 10
  198.         .ascii "Loading"

  199. /*
  200. http://lxr.linux.no/source/Documentation/i386/boot.txt
  201. Offset/Size  Proto   Name            Meaning
  202. 01F1/1  ALL     setup_sects     The size of the setup in sectors
  203. 01F2/2  ALL     root_flags      If set, the root is mounted readonly
  204. 01F4/2  ALL     syssize         DO NOT USE - for bootsect.S use only
  205. 01F6/2  ALL     swap_dev        DO NOT USE - obsolete
  206. 01F8/2  ALL     ram_size        DO NOT USE - for bootsect.S use only
  207. 01FA/2  ALL     vid_mode        Video mode control
  208. 01FC/2  ALL     root_dev        Default root device number
  209. 01FE/2  ALL     boot_flag       0xAA55 magic number
  210. */
  211. .org 497
  212. setup_sects:
  213.         .byte SETUPSECS
  214. root_flags:
  215.         .word CONFIG_ROOT_RDONLY
  216. syssize:
  217.         .word SYSSIZE
  218. swap_dev:
  219.         .word SWAP_DEV
  220. ram_size:
  221.         .word RAMDISK
  222. vid_mode:
  223.         .word SVGA_MODE
  224. root_dev:
  225.         .word ROOT_DEV
  226. boot_flag:
  227.         .word 0xAA55
  228. }

  229. ////////////////////////////////////////////////////////////////////
  230. // end of file
复制代码

论坛徽章:
0
2 [报告]
发表于 2003-02-13 09:17 |只看该作者

Linux 386 boot代码分析 (1) bootsect.txt

好东西啊!
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

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

清除 Cookies - ChinaUnix - Archiver - WAP - TOP