grub boot.S代码分析

bios_grub_mbr

00000000: eb63 9010 8ed0 bc00 b0b8 0000 8ed8 8ec0  .c..............
00000010: fbbe 007c bf00 06b9 0002 f3a4 ea21 0600  ...|.........!..
00000020: 00be be07 3804 750b 83c6 1081 fefe 0775  ....8.u........u
00000030: f3eb 16b4 02b0 01bb 007c b280 8a74 018b  .........|...t..
00000040: 4c02 cd13 ea00 7c00 00eb fe00 0000 0000  L.....|.........
00000050: 0000 0000 0000 0000 0000 0080 0100 0000  ................
00000060: 0000 0000 fffa 9090 f6c2 8074 05f6 c270  ...........t...p
00000070: 7402 b280 ea79 7c00 0031 c08e d88e d0bc  t....y|..1......
00000080: 0020 fba0 647c 3cff 7402 88c2 52bb 1704  . ..d|<.t...R...
00000090: f607 0374 06be 887d e817 01be 057c b441  ...t...}.....|.A
000000a0: bbaa 55cd 135a 5272 3d81 fb55 aa75 3783  ..U..ZRr=..U.u7.
000000b0: e101 7432 31c0 8944 0440 8844 ff89 4402  ..t21..D.@.D..D.
000000c0: c704 1000 668b 1e5c 7c66 895c 0866 8b1e  ....f..\|f.\.f..
000000d0: 607c 6689 5c0c c744 0600 70b4 42cd 1372  `|f.\..D..p.B..r
000000e0: 05bb 0070 eb76 b408 cd13 730d 5a84 d20f  ...p.v....s.Z...
000000f0: 83d0 00be 937d e982 0066 0fb6 c688 64ff  .....}...f....d.
00000100: 4066 8944 040f b6d1 c1e2 0288 e888 f440  @f.D...........@
00000110: 8944 080f b6c2 c0e8 0266 8904 66a1 607c  .D.......f..f.`|
00000120: 6609 c075 4e66 a15c 7c66 31d2 66f7 3488  f..uNf.\|f1.f.4.
00000130: d131 d266 f774 043b 4408 7d37 fec1 88c5  .1.f.t.;D.}7....
00000140: 30c0 c1e8 0208 c188 d05a 88c6 bb00 708e  0........Z....p.
00000150: c331 dbb8 0102 cd13 721e 8cc3 601e b900  .1......r...`...
00000160: 018e db31 f6bf 0080 8ec6 fcf3 a51f 61ff  ...1..........a.
00000170: 265a 7cbe 8e7d eb03 be9d 7de8 3400 bea2  &Z|..}....}.4...
00000180: 7de8 2e00 cd18 ebfe 4752 5542 2000 4765  }.......GRUB .Ge
00000190: 6f6d 0048 6172 6420 4469 736b 0052 6561  om.Hard Disk.Rea
000001a0: 6400 2045 7272 6f72 0d0a 00bb 0100 b40e  d. Error........
000001b0: cd10 ac3c 0075 f4c3 eebd 639d 0000 8020  ...<.u....c....
000001c0: 2100 83fe ffff 0008 0000 00f0 ff09 0000  !...............
000001d0: 0000 0000 0000 0000 0000 0000 0000 0000  ................
000001e0: 0000 0000 0000 0000 0000 0000 0000 0000  ................
000001f0: 0000 0000 0000 0000 0000 0000 0000 55aa  ..............U.

Prepare code

00000000: eb63 90… …

jmp     LOCAL(after_BPB)
nop     /* do I care about this ??? */

00000060: 0000 0000 fffa 9090 …

boot_drive:
	.byte 0xff      /* the disk to load kernel from */
										/* 0xff means use the boot drive */
LOCAL(after_BPB): 
	cli             /* we're not safe here! */
	
	/*
	* 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).
	*/
	.org GRUB_BOOT_MACHINE_DRIVE_CHECK
boot_drive_check:
	jmp     3f      /* grub-setup may overwrite this jump (nop nop)*/ 

LBA mode

disk address packet define

disk_address_packet:
sectors:
        .long   0
heads:
        .long   0
cylinders:
        .word   0
sector_start:
        .byte   0
head_start:
        .byte   0
cylinder_start:
        .word   0

check is support LBA

/* save drive reference first thing! %dx saved boot drive*/
pushw   %dx

/* print a notification message on the screen */
MSG(notification_string)

/* 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

LBA handle

/* The segment of disk buffer. The disk buffer MUST be 32K long and
   cannot straddle a 64K boundary.  in grub/i386/pc/boot.h */
#define GRUB_BOOT_MACHINE_BUFFER_SEG	0x7000
...
#ifndef HYBRID_BOOT
        .org GRUB_BOOT_MACHINE_KERNEL_SECTOR
LOCAL(kernel_sector):
        .long   1
LOCAL(kernel_sector_high):
        .long   0
#endif
...
LOCAL(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    LOCAL(kernel_sector), %ebx
	movl    %ebx, 8(%si)
	movl    LOCAL(kernel_sector_high), %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 read is not supported, so fallback to CHS.  */
	jc      LOCAL(chs_mode)
	
	movw    $GRUB_BOOT_MACHINE_BUFFER_SEG, %bx
	jmp     LOCAL(copy_buffer)
Format of disk address packet:
OffsetSizeDescription
00hBYTEsize of packet (10h or 18h)
01hBYTEreserved (0)
02hWORDnumber of blocks to transfer (max 007Fh for Phoenix EDD)
04hDWORD-> transfer buffer
08hQWORDstarting absolute block number
10hQWORD(EDD-3.0, optional) 64-bit flat address of transfer buffer;used if DWORD at 04h is FFFFh:FFFFh
Result before call “INT 0x13 Function 0x42” (Little endian)
disk_address_packetlengthbyte 0byte 1byte 2byte 3
sectorslong (4)10000100
headerslong (4)00000070
cylindersword (2)0100XXXX
sector_startbyte (1)00XXXXXX
sector_startbyte (1)00XXXXXX
cylinder_startword (2)0000XXXX

Copy buffer data

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     *(LOCAL(kernel_address))

#define GRUB_BOOT_MACHINE_KERNEL_ADDR (GRUB_BOOT_MACHINE_KERNEL_SEG << 4)

GRUB_BOOT_MACHINE_KERNEL_SEG的最终宏定义为
#define GRUB_BOOT_I386_PC_KERNEL_SEG 0x800

因此目的地址GRUB_BOOT_MACHINE_KERNEL_ADDR为0x8000

CLD (CLear Direction flag)

清除方向标志位 ,把标志(flags)寄存器的DF=0,地址指针si、di增加;

STD(SeT Direction flag)的执行结果相反,即置DF的值为1, 地址指针si、di减小;

在执行串操作时,使地址按设置的方式变化

REP

指令的汇编格式:REP (CX)=重复次数

指令的基本功能:

  1. (CX)=0时,串指令执行完毕,否则执行2~4
  2. (CX)<-(CX)-1
  3. 执行串指令(MOVS或STOS)
  4. 重复执行1

MOVSB / MOVSW

指令的基本功能:(ES:DI)<-(DS:SI)

(SI)<-(SI)+/-1(字节)或+/-2(字)

(DI)<-(DI)+/-1(字节)或+/-2(字)

指令对条件码的影响:不影响条件码。

指令的特殊要求:源串必须在数据段中,目的串必须在附加段中,串处理指令隐含的寻址方式是SI和DI寄存器的间接寻址方式。源串允许使用段跨越前缀来指定段。

reference

csdn blog

BIOS Interrups

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值