grub学习(1) 第一阶段启动

本文深入探讨了GRUB启动过程中的关键步骤,包括BIOS/UEFI如何将控制权交给GRUB,GRUB如何检查硬盘驱动器并读取第一个扇区,以及如何检测LBA模式支持,并最终将数据读取到内存指定位置。

 

BIOS/UEFI将控制权交过来

作用:读取第一个扇区
    分解:
        先检查控制器是否正确dx
        通过int13是否支持LBA/CHS模式
        通过int13将第一个扇区读取到缓存
        然后将缓存的数据拷贝到预期位置
        跳转到预期的位置,执行第一个扇区的代码

boot.S

	.text

	/* Tell GAS to generate 16-bit instructions so that this code works
	   in real mode. */
	.code16

.globl _start, start;
_start:
start:
	jmp	LOCAL(after_BPB)
	nop	/* do I care about this ??? */

第一次跳转:

/* 啰啰嗦嗦这一堆, 就是保证dl为0x80, 默认为硬盘 */
LOCAL(after_BPB):
	. = _start + GRUB_BOOT_MACHINE_DRIVE_CHECK
	boot_drive_check:
        jmp     3f	/* grub-setup may overwrite this jump */
        testb   $0x80, %dl
        jz      2f
3:
	/* Ignore %dl different from 0-0x0f and 0x80-0x8f.  */
	testb   $0x70, %dl
	jz      1f
2:	
    movb    $0x80, %dl
1:
	/*
	 * ljmp to the next instruction because some bogus BIOSes
	 * jump to 07C0:0000 instead of 0000:7C00.
	 */
	ljmp	$0, $real_start

第二次跳转:

跳转后检测是否支持LBA

real_start:

	/* set up %ds and %ss as offset from 0 */
	xorw	%ax, %ax
	movw	%ax, %ds
	movw	%ax, %ss
	
	/* set up the REAL stack */
	movw	$GRUB_BOOT_MACHINE_STACK_SEG, %sp	//ss:sp 0x0000:0x2000
	
	pushw	%dx //入栈保存, 下面有int调用,防止被破坏
	
	/* set %si to the disk address packet */
	movw	$disk_address_packet, %si

	/* check if LBA is supported */
	movb	$0x41, %ah
	movw	$0x55aa, %bx
	int	$0x13
	
	/* 上述代码的解释如下:
		磁盘扩展探测: INT 13H, AH=41H 
		检测磁盘扩展读(LBA/CHS)支持情况。详细描述如下。
		参数:
		寄存器        描述
		AH=0x41    扩展检测函数序号
		DL        驱动器编号(第一块硬盘为0x80,第二块为0x81,依次类推)
		BX        0x55AA

		结果:
		寄存器        描述
		CF        支持清零,不支持置1
		AH        错误码或者主版本号
		BX        0x55AA
		CX        接口支持掩码
				1 – 使用打包结构体存取设备
				2 – 驱动器加锁和弹出
				4 – 支持增强型磁盘驱动器(EDD)
	*/

封装disk_address_packet,读取第一个扇区

/* 下面还有Int调用, dx再保存一下 */
	popw	%dx
	pushw	%dx
	
lba_mode:
	xorw	%ax, %ax
	movw	%ax, 4(%si)

	incw	%ax
	/* set the mode to non-zero */
	movb	%al, -1(%si)

	/* the blocks */
	movw	%ax, 2(%si)

	/* the size and the reserved byte */
	movw	$0x0010, (%si)

	/* the absolute address */
	movl	kernel_sector, %ebx
	movl	%ebx, 8(%si)
	movl	kernel_sector + 4, %ebx
	movl	%ebx, 12(%si)

	/* the segment of buffer address */
	movw	$GRUB_BOOT_MACHINE_BUFFER_SEG, 6(%si)

/*
 * BIOS call "INT 0x13 Function 0x42" to read sectors from disk into memory
 *	Call with	%ah = 0x42
 *			%dl = drive number
 *			%ds:%si = segment:offset of disk address packet
 *	Return:
 *			%al = 0x0 on success; err code on failure
 */

	movb	$0x42, %ah
	int	$0x13
	/*	上述代码的解释如下:
		LBA模式读: INT 13H, AH=42H 
		LBA模式的读采用打包的数据结构作为参数。
		参数:
		寄存器        描述
		AH=42H    扩展读函数序号
		DL        驱动器编号(第一块硬盘为0x80,第二块为0x81,依次类推)
		DS:SI        segment:offset指针,指向磁盘地址包DAP (Disk Address Packet)

		DAP结构体的格式描述如下:
		偏移量        大小        描述
		00H        1 Byte        DAP大小=16=0x10
		01H        1 Byte        未用,必须置0
		02H~03H    2 Bytes        需要读的扇区数
		(有些BIOS限制不能超过127扇区)
		04H~07H    4 Bytes        segment:offset指针,指向内存缓冲区,读取到的
		扇区内容放置在该缓冲区
		08H~0FH    8 Bytes        需要读的连续扇区的起始扇区编号
		(第一个扇区的编号是0)

		结果:
		寄存器        描述
		CF        失败置1,成功清零
		AH        返回码
		
		读取第一个扇区, 把第一个扇区的数据成功则数据被读到了0x7000:0x0000(内存0x700000)位置
	*/
	
	movw	$GRUB_BOOT_MACHINE_BUFFER_SEG, %bx
	jmp	LOCAL(copy_buffer)

把数据从0x7000:0x0000(内存0x700000)位置拷贝buff到0x0000:0x8000

LOCAL(copy_buffer):
	/*
	 * We need to save %cx and %si because the startup code in
	 * kernel uses them without initializing them.
	 */
	pusha
	pushw	%ds

	movw	$0x100, %cx
	movw	%bx, %ds
	xorw	%si, %si
	movw	$GRUB_BOOT_MACHINE_KERNEL_ADDR, %di
	movw	%si, %es

	cld

	rep
	movsw

	popw	%ds
	popa

	/* boot kernel */
	jmp	*(kernel_address)

深入理解 GNU GRUB - 02 boot.S 2.1 相关BIOS例程
https://blog.csdn.net/cppgp/article/details/6360976

grub2 1.95 源码分析之一 —— boot.S 分析及注释
https://blog.csdn.net/cppgp/article/details/2060146

深入理解 GNU GRUB - 02 boot.S 2.4 boot.S详细注释
https://blog.csdn.net/cppgp/article/details/6361020

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值