GRUB2及启动过程详解(7)

2019-04-16 00:04

/* 参照下表设置

SI在上面7.2.3中被设置为0x7c05,根据下表设置

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

大小

位数

描述

值 0x10 0x00 0x67

00h 0x7c05 BYTE 8 01h 0x7c06 BYTE 8 02h 0x7c07 WORD 16 04h 0x7c09 DWORD 32 08h 0x7c0d QWORD 64 /* 大小和保留 设置为0x0010

00008034 C7041000 mov word [si],0x10

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

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

0x7000:[0x0000]

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

******************************************************************/

/* 传输的数据块数放ax中,在这个例子中为0x67 */

00008038 894402 mov [si+0x2],ax

/* 硬盘拷贝的起始扇区为LBA-2 ebx, ecx在前面已经设置过*/

0000803B 66895C08 mov [si+0x8],ebx 0000803F 66894C0C mov [si+0xc],ecx

/* 依然拷贝到内存0x7000:[0x0000]处地址*/

00008043 C744060070 mov word [si+0x6],0x7000 00008048 50 push ax /*保存ax=0x67 */ 00008049 C744040000 mov word [si+0x4],0x0

/*

* BIOS call \ * Call with %ah = 0x42 * * * */

0000804E B442 mov ah,0x42 00008050 CD13 int 0x13

%dl = drive number

%ds:%si = segment:offset of disk address packet %al = 0x0 on success; err code on failure

* Return:

/* 如果读取错误,跳转到0x8105进行处理,在这里就不做介绍 */

00008052 0F82AF00 jc word 0x8105

/* 准备拷贝buffer */

00008056 BB0070 mov bx,0x7000 00008059 EB66 jmp short 0x80c1

/* 注意,也许一次没有从硬盘读取完,还需要继续读取,但是下次读取硬盘必须等待buffer 拷贝结束*/

7.3.1.3. Step3) 拷贝缓冲区

/* 注意,从硬盘读取的数据放在0x70000位置, 我们需要拷贝到一个区域*/ /* load addresses for copy from disk buffer to destination * [di+0xa]=0x81f4+0xa=0x81fe初始化内存存放为 20 08 * es 寄存器第一次值为0x0820 /

000080C1 8E450A mov es,[di+0xa]

/* 恢复 %ax =0x67*/

000080C4 58 pop ax

/* 计算下一个可能目标地址 (presuming512 byte sectors!) */

000080C5 C1E005 shl ax,byte 0x5/* shift %ax five bits to the left 0x67 */ 000080C8 01450A add [di+0xa],ax /* 更新[di+0xa]位0x8200 */

/* 保存地址寄存器 */

000080CB 60 pushaw 000080CC 1E push ds

/* 计算拷贝的长度 */

000080CD C1E003 shl ax,byte 0x3 /* ax X 8*/ 000080D0 89C1 mov cx,ax

000080D2 31FF xor di,di /* 目的地址置0 */ 000080D4 31F6 xor si,si /* 源地址置0 */

000080D6 8EDB mov ds,bx /* 恢复原段地址: 0x7000 */

/* 开始拷贝从 ds:[si] 0x7000:[0x0000])处拷贝到es:[di]0x0820:[0x0000]处 起始物力地址为0x70000,目的物理地址为0x8200

注意: es=0x0820为段地址, 转化为物理地址需要左移4bit*/

000080D8 FC cld 000080D9 F3A5 rep movsw

/* restore addressing regs and print a dot with correct DS

(MSG modifies SI, which is saved, and unused AX and BX) */

000080DB 1F pop ds

000080DC BE1B81 mov si,0x811b /*打印message*/ 000080DF E85700 call word 0x8139 000080E2 61 popaw

/* 检查是否还有剩余的硬盘扇区需要读写不,如果需要,返回Step2)继续读取 * step2) 的运行地址为0x800f */

000080E3 837D0800 cmp word [di+0x8],byte +0x0

000080E7 0F8524FF jnz word 0x800f

/* update position to load from 并跳转到bootloop

* 在step1) 初始化中我们继续判断 是否还需要读取剩余的扇区,如果没有那么进入下一步/

000080EB 83EF0C sub di,byte +0xc 000080EE E916FF jmp word 0x8007

7.3.1.4. Step4) Bootit: core.img

000080F1 BE1D81 mov si,0x811d /*打印message*/ 000080F4 E84200 call word 0x8139

/*跳转到 8200并开始执行, 8200地址为core.img的运行地址*/

000080F7 5A pop dx

000080F8 EA00820000 jmp word 0x0:0x8200

7.3.1.5. 总结

diskboot.img把LBA2到LBA67的core.img全部读入到内存0x8200位置, 这部分LBA2-LBA67内容分为两个内容:

1) 开始部分是start_raw.S的代码

2) 后一部分是压缩的GRUB2核心代码 后面进入GRUB2 startup部分

7.3.2. GRUB2 core Startup

在diskboot.img完成任务后,后面的工作又core.img中的Startup接手,startup分为两个部分:

Startup_raw Startup

为了节约时间,这部分代码我们不再进行反汇编讲解,而是直接从官方网站直接取得代码。 大伙可以登录官方网站 http://www.gnu.org/software/grub/ 并可以直接使用git下载代码

git clone git://git.savannah.gnu.org/grub.git

7.3.2.1. Startup_raw

这段代码位置:grub-core/boot/i386/pc/Startup_raw.S

依然为汇编语言,官方代码采用AT&T风格的汇编语言编写

/*

* 这段代码Startup_raw.S必须加载到0x0:0x8200. */

7.3.2.1.1. Step1) 初始化

/*首先需要 设置数据段、堆栈段和扩展段寄存器,以及栈指针。*/

cli

/* we're not safe here! */

/* set up %ds, %ss, and %es */ xorw %ax, %ax movw %ax, %ds movw %ax, %ss movw

%ax, %es

/* set up the real mode/BIOS stack */ movl $GRUB_MEMORY_MACHINE_REAL_STACK, ?p movl

?p, %esp

sti

/* we're safe again */

7.3.2.1.2. Step2) 进入保护模式

/*进行一些准备工作后开始进入保护模式

* real_to_prot 这个函数的代码在 grub-core/kern/i386/realmode .S中 。

/* save the boot drive */

*/

movb %dl, LOCAL(boot_drive)

/* reset disk system (%ah = 0) */ int $0x13

/* transition to protected mode */ calll real_to_prot

7.3.2.1.3. Step3) 解压核心代码

#ifdef ENABLE_LZMA

/* GRUB_MEMORY_MACHINE_DECOMPRESSION_ADDR 定义为0x100000. 在memory.h中*/

/* 因为core.img有 32K限制,对core.img进行压缩是非常有必要的 解压后的核心最开始放在0x00100000处,esi寄存器的值就是核心代码的地址 */

movl movl movl

$GRUB_MEMORY_MACHINE_DECOMPRESSION_ADDR, íi $decompressor_end, %esi $LOCAL(decompressor_end), %esi

#ifdef __APPLE__ #else #endif

pushl íi movl leal

LOCAL (uncompressed_size), ìx (íi, ìx), ?x

/* Don't remove this push: it's an argument. */ push ìx call

_LzmaDecodeA

pop ìx

/* _LzmaDecodeA clears DF, so no need to run cld */ popl

%esi

#endif

7.3.2.1.4. Step3) 跳转核心代码

在上面的指令中:

esi寄存器的值就是核心代码的地址:0x00100000 Edx:启动设备 movl movl movl movl

LOCAL(boot_dev), íx $prot_to_real, íi $real_to_prot, ìx $LOCAL(realidt), êx

jmp *%esi


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

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

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

马上注册会员

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