GRUB2及启动过程详解(5)

2019-04-16 00:04

* 注意,BIOS在把控制权交给MBR前,会在DL中设置正确的Bit位,表明MBR来源 * DL = 00h 1st floppy disk(“drive A:”) * DL = 01h 2nd floppy disk(“drive B:”) * DL = 80h 1st hard disk * DL = 81h 2nd hard disk

* 因为我们是磁盘加载的MBR,所以我们dl里面存的是0x80。 * 下面这段应为来自官方源代码注释

* This is a workaround for buggy BIOSes which don't pass boot * drive correctly. If GRUB is installed into a HDD, check if * DL is masked correctly. If not, assume that the BIOS passed * a bogus value and set DL to 0x80, since this is the only * possible boot drive. If GRUB is installed into a floppy, * this does nothing (only jump).

* 意思是有些BIOS类型并没有正确的设置DL寄存器,我们检测是否DL置了0x80bit位 * 如过不是,我们手工设置为DL为0x80

* 注意test 相当于用and(位与)判断,实际上是测试Bit位是否被置上 */

00007C68 F6C280 test dl,0x80 00007C6B 7405 jz 0x7c72

/* 如果DL不在区间0-0x0f and 0x80-0x8f. 那么需要设置DL为0x80 * 如果DL在区间0x10-0x7f,那么不需要设置DL为0x80 */

00007C6D F6C270 test dl,0x70 00007C70 7402 jz 0x7c74 00007C72 B280 mov dl,0x80 00007C74 EA797C0000 jmp word 0x0:0x7c79

/* ax清零,ds赋值0,ss赋值0 */

00007C79 31C0 xor ax,ax 00007C7B 8ED8 mov ds,ax 00007C7D 8ED0 mov ss,ax

/*设置堆栈:设置了实模式下的堆栈段地址(栈顶位置) 0x2000*/

00007C7F BC0020 mov sp,0x2000

/*恢复中断 再次安全*/

00007C82 FB sti

/* 从内存0x7c64读入AL, 在0x7c64,我们值为0xFF, 比较两个数为相等 * 那么不执行0x7c8a

* 这里只是检查我们是否有forced disk reference */

00007C83 A0647C mov al,[0x7c64] 00007C86 3CFF cmp al,0xff

00007C88 7402 jz 0x7c8c 00007C8A 88C2 mov dl,al

7.2.3. Step3 判断硬盘是否支持LBA还是只支持CHS

/*在前面我们介绍了CHS及LBA, 这两种对硬盘读寻址有很大不同

*在加载后续GRUB2 core.img的前,我们必须判断硬盘是否支持LBA还是只支持CHS*/

/* save drive reference first thing! */

00007C8C 52 push dx

/* set %si to the disk address packet */

00007C8D BE057C mov si,0x7c05

/* 调用BIOS INT13功能,检查硬盘是否支持LBA

* 通过 BIOS 调用 INT 0x13 来确定是否支持扩展,LBA 扩展功能分两个子集 , 如下 : 第一个子集提供了访问大硬盘所必须的功能 , 包括:

**************************************************************** 1.检查扩展是否存在 : ah = 41h , bx = 0x55aa , dl = drive( 0×80 ~ 0xff ) 2.扩展读 : ah = 42h 3.扩展写 : ah = 43h 4.校验扇区 : ah = 44h 5.扩展定位 : ah = 47h 6.取得驱动器参数 : ah = 48h

**************************************************************** 第二个子集提供了对软件控制驱动器锁定和弹出的支持 ,包括:

**************************************************************** 1.检查扩展 : ah = 41h 2.锁定/解锁驱动器 : ah = 45h 3.弹出驱动器 : ah = 46h 4.取得驱动器参数 : ah = 48h 5.取得扩展驱动器改变状态: ah = 49h

****************************************************************

我们采用的是ah=41h,bx=0x55aa,dl=0x80,所以是检查扩展是否存在。这个操作会改变 CF标志位的值。如果支持LBA,那么CF=0,否则CF=1。 */

00007C90 B441 mov ah,0x41 00007C92 BBAA55 mov bx,0x55aa 00007C95 CD13 int 0x13

/*

* %dl may have been clobbered by INT 13, AH=41H. * This happens, for example, with AST BIOS 1.04. */

00007C97 5A pop dx 00007C98 52 push dx

/*

* 下面的三个跳转语句都到0x7cd8位置,那个位置是CHS部分 * 有下面几种情况

* 1) 探查结果 CF=1(0x7c99 jc 0x7cd8),二话不说,跳转到CHS模式

* 2) CF=0是否就采用LBA呢?也不一定,还需要判断bx==0x55aa,如果不等则CHS模式 * 3)有一个FORCE_LBA Byte(INT13返回寄存器cx中),如果这个位是1,那么直接采用LBA MODE */

00007C99 723D jc 0x7cd8 00007C9B 81FB55AA cmp bx,0xaa55 00007C9F 7537 jnz 0x7cd8 00007CA1 83E101 and cx,byte +0x1 00007CA4 7432 jz 0x7cd8

/* 由于现在硬盘都是LBA模式,这里我们就不在对CHS模式介绍了,直接进入LBA*/

7.2.4. Step4 采用LBA加载core.img第一个扇区

/* 对于BIOS LBA读来说,最重要的是设置SI所在内存块的值

由si及其偏移量指向的内存保存着磁盘参数块

SI在上面7.2.3中被设置为0x7c05,根据下面的偏移量来设置 如下:

****************************************************************** 偏移 地址

大小

位数

描述

值 0x10 0x00 0x01

00h 0x7c05 BYTE 8 01h 0x7c06 BYTE 8 02h 0x7c07 WORD 16 04h 0x7c09 DWORD 32 08h 0x7c0d QWORD 64

数据块的大小 (10h or 18h) 保留,必须为0

传输数据块数,传输完成后保存传输的块数 传输时的数据缓存地址

0x7000:[0x0000]

起始绝对扇区号(即起始扇区的LBA号码) 0x01

****************************************************************** 下面的很多代码都是在初始化SI 所指向的内存

注意[si+0x4]表示的是 segment:offset pointer to the memory buffer to which sectors will be transferred (note that x86 is little-endian: if declaring the segment and offset separately, the offset must be declared before the segment) */

/* 下面这个首先把内存中si+0x4的位置,传输数据时的数据缓存地址 * 也就是0x7c09~0x7c0a 16bit置为0 */

00007CA6 31C0 xor ax,ax 00007CA8 894404 mov [si+0x4],ax

/* AX现在值为0x0001*/

00007CAB 40 inc ax

/* set the mode to non-zero 也就是把内存[si-1]0x7c04的值置为1 * (也就是mode被置1,表示LBA扩展读;如果是0,就是CHS寻址读) */

00007CAC 8844FF mov [si-0x1],al

/* 把内存0x7c07-0x7c08 16bit 的值置为1

* 也就是需要传输数据块数,这里我们将要传输core.img中第一个扇区 */

00007CAF 894402 mov [si+0x2],ax

/* the size and the reserved byte * 把内存0x7c05的值置为0x10 (固定) * 把内存0x7c06的值置为0x00 (固定)*/

00007CB2 C7041000 mov word [si],0x10

/* the absolute address 起始绝对扇区号(即起始扇区的LBA-1号码) 0x7c0d ~ 0x7c11 32bit: 内存0x7c5c值为01 00 00 00 0x7c12 ~ 0x7c15 32bit: 内存0x7c60 值为 00 00 00 00

*最后就是制定LBA地址为LBA1,也就是第二个扇区,在前面我么说了这个/

00007CB6 668B1E5C7C mov ebx,[0x7c5c] 00007CBB 66895C08 mov [si+0x8],ebx 00007CBF 668B1E607C mov ebx,[0x7c60] 00007CC4 66895C0C mov [si+0xc],ebx

/* the segment of buffer address 传输时的数据缓存地址 * 也就是0x7c0b~0x7c0c 16bit置为0x7000 * 0x7c09~0x7c0a 16bit置为在前面已经被置为0 * 数据缓存地址为 :0x7000:[0x0000]

* 注意0x7000为段地址,偏移为0x0000,实际物力地址将是0x70000 */

00007CC8 C744060070 mov word [si+0x6],0x7000

/*

* 调用BIOS功能\ * 从硬盘读指定扇区到内存中

* 参数如下 %ah = 0x42 (在上面一节中2.扩展读: ah = 42h) * * * * */

%dl = drive number (在7.2.2中已经被置为 0x80) %ds:%si = segment:offset of disk address packet (DS在7.2.2中已经被初始化为0, SI在上面被置为0x7c05) %al = 0x0 成功; err code on failure

* 返回:

00007CCD B442 mov ah,0x42 00007CCF CD13 int 0x13

/* LBA 扩展读失败,可能不支持LBA,跳转采用CHS方式 */

00007CD1 7205 jc 0x7cd8

/* 进入下一步,准备拷贝刚读入的core.img第一个扇区数据到指定位置 */

00007CD3 BB0070 mov bx,0x7000 00007CD6 EB76 jmp short 0x7d4e

/* 总结,上面这段这么多的汇编代码就是完成一个功能:

调用BIOS INT14 ah=0x42 把硬盘LBA-1的512字节传输到内存0x7000:[0x0000]位置 注意:0x7000:[0x0000]实际上是段地址:[段内偏移]实际地址为 0x70000 */

7.2.5. Step5 拷贝core.img第一个扇区到内存指定位置

/*

* We need to save %cx and %si because the startup code in * kernel uses them without initializing them. */

00007D4E 60 pushaw 00007D4F 1E push ds

/* 循环256次:0x100*/

00007D50 B90001 mov cx,0x100

/* bx 在上面被置为0x7000, 也就是从硬盘拷贝过来的地址*/

00007D53 8EDB mov ds,bx 00007D55 31F6 xor si,si

/* di 是我们目标地址0x8000, 也就是core.img要从这个位置开始执行*/

00007D57 BF0080 mov di,0x8000

/* 初始化es为0*/

00007D5A 8EC6 mov es,si

/* 重复前固定操作,清除方向标志位*/

00007D5C FC cld

/* 开始循环 move string word

ds:[si] (0x7000:[0x0000])移到es:[di](0x0000:[0x8000]) 一次一个word,也就是2 byte,循环256次共512byte*/

00007D5D F3A5 rep movsw

00007D5F 1F pop ds 00007D60 61 popaw

/* 总结,上面这段这么多的汇编代码就是完成一个功能:


GRUB2及启动过程详解(5).doc 将本文的Word文档下载到电脑 下载失败或者文档不完整,请联系客服人员解决!

下一篇:110kV线路断线故障分析专题报告

相关阅读
本类排行
× 注册会员免费下载(下载后可以自由复制和排版)

马上注册会员

注:下载文档有可能“只有目录或者内容不全”等情况,请下载之前注意辨别,如果您已付费且无法下载或内容有问题,请联系我们协助你处理。
微信: QQ: