GRUB0.93 源码阅读分析---新的开始(1)

来源:互联网 发布:mysql decimal 时间 编辑:程序博客网 时间:2024/04/29 18:47

 

一直以来做的东西很杂,现在突然有兴趣研究下开源的sourcecode,计划是从GRUB开始,逐步深入,希望自己能坚持下来。以自己以前的经验,只看不记忘得快,所以了,在这里写点notes。 看一点写一点,很多错误的地方也暂且放过了,以后逐渐更正。在这里,只为记录下学习过程。参考过的资料没有一一列出,谢谢无私奉献的网友们。

-------------------------------------------------------------------------------------------

1. stage1.s记录

-------------------------------------------------------------------------------------------

.globl _start; _start:
 /*
  * _start is loaded at 0x7c00 and is jumped to with CS:IP 0:0x7c00
  */

 /*
  * Beginning of the sector is compatible with the FAT/HPFS BIOS
  * parameter block.
  */

 jmp after_BPB

pgnotes: bios 的int19会将磁盘的第一个扇区读到0x7c00,并且将driver number记录在dx寄存器,然后jump过来;BPB是MBR中的一些固定信息,网上很多文章讲;

 ljmp $0, $ABS(real_start) 

pgnotes: ljmp一下是为了将cs设置为0?(FIXME)

MOV_MEM_TO_AL(ABS(boot_drive)) 

pgnotes:0xa0就是MOV AL,moffs8 ,可参考ia2;

pgnotes: 下面的代码顺着走,现在仅考虑grub安装在HDD上的情况,这样调用int 13 41function后,就顺利走到lba_mode;

 movl %ebx, 8(%si)

pgnotes: this is the starting absolute block number, 这个值是stage2_sector=1;int 13 42function用初始化好的disk address packet,将sector1读出,拷贝到stage2_address=0x8000,jmp过去,就转入stage2/start.S执行了。

-------------------------------------------------------------------------------------------

2. /stage2/start.S记录

-------------------------------------------------------------------------------------------

#ifdef STAGE1_5
# define ABS(x) (x-_start+0x2000)
#else
# define ABS(x) (x-_start+0x8000)

pgnotes:代码一开始就有这几句,全局搜索,无STAGE1_5的define,所以ABS(x)会将相对地址+0x8000等于绝对地址,逆向推理,也可以发现和stage1.s的结尾对应起来了。但以后,需要针对编译好的grub,顺向了解安装后的位置。

 

 

/* this sets up for the first run through "bootloop" */
movw    $ABS(firstlist - BOOTSEC_LISTSIZE), %di

pgnotes:这个语句较关键,firstlist是相对start.S的偏移,可以看程序末尾:

    . = _start + 0x200 - BOOTSEC_LISTSIZE    /*pgnotes:起始位置+一个扇区512字节数-8个字节的list长度*/   
        /* fill the first data listing with the default */
blocklist_default_start:
    .long 2        /* this is the sector start parameter, in logical
               sectors from the start of the disk, sector 0 */

/*pgnotes:4个字节,地址的逻辑扇区号是2,0为起始逻辑扇区号*/
blocklist_default_len:
            /* this is the number of sectors to read */
#ifdef STAGE1_5
    .word 0        /* the command "install" will fill this up */
#else
    .word (STAGE2_SIZE + 511) >> 9/*pgnotes:2个字节,STAGE2_SIZE的所占的扇区长度*/
#endif
blocklist_default_seg:
#ifdef STAGE1_5
    .word 0x220
#else
    .word 0x820    /* this is the segment of the starting address
               to load the data into */    /*pgnotes:2个字节,目标段地址*/
#endif
   
firstlist:    /* this label has to be after the list data!!! */

pgnotes: start.S中主要使用这个list中的值将STAGE2_SIZE大小的内容读出,并用下面的copy_buffer逐步放到0x8200

处,

copy_buffer:   

    /* load addresses for copy from disk buffer to destination */
    movw    6(%di), %es    /* load destination segment */    /*pgnotes:2个字节,目标段地址*/

    /* restore %ax */
    popw    %ax   
   

pgnotes:ax是本次读出的扇区数,popw后左移5bits,加到目标段,这样得到下次copy到的目标段地址*/
最后程序通过ljmp    $0, $0x8200,跳转到被copy的内容处继续运行。
总结: 这两个小程序分别被编译成512字节,代码简单、功能单一,主要用int13来逐步copy跳转。由于自己没有全局的理解,以后再更正可能的错误。