#define ABS(x) (x-_start+0x7c00) //计算物理地址,不依赖编译器
#define MSG(x) movw $ABS(x), %si; call message
#define MOV_MEM_TO_AL(x) .byte 0xa0; .word x //这个不用管它,只是为了实现兼容性用了机器码
.file "stage1.S"
jmp after_BPB
nop /* do I care about this ??? */
mode:
.byte 0
disk_address_packet:
sectors:
.long 0
heads:
.long 0
cylinders:
.word 0
sector_start:
.byte 0
head_start:
.byte 0
cylinder_start:
.word 0
/* more space... */
* End of BIOS parameter block.
*/
.byte COMPAT_VERSION_MAJOR, COMPAT_VERSION_MINOR
boot_drive:
.byte GRUB_INVALID_DRIVE /* the disk to load stage2 from */
force_lba:
.byte 0
stage2_address:
.word 0x8000
stage2_sector:
.long 1
stage2_segment:
.word 0x800
cli /* we're not safe here! */
jmp 1f
testb $0x80, %dl
jnz 1f
movb $0x80, %dl
1:
* ljmp to the next instruction because some bogus BIOSes
* jump to 07C0:0000 instead of 0000:7C00.
*/
ljmp $0, $ABS(real_start) /*cs = 0*/
xorw %ax, %ax
movw %ax, %ds
movw %ax, %ss
movw $STAGE1_STACKSEG, %sp /*STAGE1_STACKSEG = 0x2000*/
* Check if we have a forced disk reference here
*/
MOV_MEM_TO_AL(ABS(boot_drive)) /* movb ABS(boot_drive), %al */
cmpb $GRUB_INVALID_DRIVE, %al /* 如果boot_drive=0xff,则表示从默认的位置加载stage2
* 如果不是默认,把驱动器号保存在dl中
*/
je 1f
movb %al, %dl
1:
/* save drive reference first thing! */
pushw %dx /*不是默认的话,保存才是有用的,否则没用*/
MSG(notification_string)
testb $STAGE1_BIOS_HD_FLAG, %dl /*如果是软盘,即STAGE1_STACKSEG=0,直接跳入chs模式*/
jz chs_mode
/* check if LBA is supported */
movb $0x41, %ah /*此时dl=80,ah=41h,bx=0x55aa,int 13h 检测第一块硬盘的CF位*/
movw $0x55aa, %bx /*即检查是否支持LBA寻址,不支持则CF=1*/
int $0x13
*AH 41h = function number for extensions check
*DL drive index (e.g. 1st HDD = 80h)
*BX 55AAh
*CF Set On Not Present, Clear If Present
* %dl may have been clobbered by INT 13, AH=41H.
* This happens, for example, with AST BIOS 1.04.
*/
popw %dx
pushw %dx
jc chs_mode
cmpw $0xaa55, %bx /*测试后,正常情况下bx=0xaa55*/
jne chs_mode
MOV_MEM_TO_AL(ABS(force_lba)) /* movb ABS(force_lba), %al */
testb %al, %al
jnz lba_mode
andw $1, %cx /*CX Interface support bitmask:
jz chs_mode
lba_mode:
/* save the total number of sectors */
movl 0x10(%si), %ecx /*这是在干什么*/
movw $ABS(disk_address_packet), %si /* si指向BIOS的参数*/
movb $1, -1(%si)
movl ABS(stage2_sector), %ebx
movw $0x0010, (%si) /**/
movw $1, 2(%si)
/* the absolute address (low 32 bits) */
movl %ebx, 8(%si)
movw $STAGE1_BUFFERSEG, 6(%si)
movw %ax, 4(%si)
movl %eax, 12(%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
*/
int $0x13
jc chs_mode
jmp copy_buffer
chs_mode:
/*
* Determine the hard disk geometry from the BIOS!
* We do this first, so that LS-120 IDE floppies work correctly.
*/
movb $8, %ah
int $0x13 /*INT 13h AH=08h: Read Drive Parameters AH Return Code
*DL number of hard disk drives
*DH logical last index of heads = number_of - 1 (because index starts with 0)
*CX logical last index of cylinders = number_of - 1 (because index starts with 0)
*/
jnc final_init /* CF Set On Error, Clear If No Error */
/*
* The call failed, so maybe use the floppy probe instead.
*/
testb $STAGE1_BIOS_HD_FLAG, %dl
jz floppy_probe
jmp hd_probe_error
movw $ABS(sectors), %si
movb $0, -1(%si)
/* save number of heads */
xorl %eax, %eax
movb %dh, %al
incw %ax
movl %eax, 4(%si)
movb %cl, %dl
shlw $2, %dx
movb %ch, %al
movb %dh, %ah
incw %ax
movw %ax, 8(%si)
movb %dl, %al
shrb $2, %al
movl %eax, (%si)
/* load logical sector start (bottom half) */
movl ABS(stage2_sector), %eax
xorl %edx, %edx
divl (%si)
movb %dl, 10(%si)
divl 4(%si) /* divide by number of heads */
/* save head start */
movb %dl, 11(%si)
movw %ax, 12(%si)
cmpw 8(%si), %ax
jge geometry_error
* This is the loop for taking care of BIOS geometry translation (ugh!)
*/
movb 13(%si), %dl
movb 10(%si), %cl /* get sector */
from 1-N, not 0-(N-1) ) */
orb %dl, %cl /* composite together */
movb 12(%si), %ch /* sector+hcyl in cl, cylinder in ch */
popw %dx
/* head number */
movb 11(%si), %dh
* BIOS call "INT 0x13 Function 0x2" to read sectors from disk into memory
* Call with %ah = 0x2
* %al = number of sectors
* %ch = cylinder
* %cl = sector (bits 6-7 are high bits of "cylinder")
* %dh = head
* %dl = drive (0x80 for hard disk, 0x0 for floppy disk)
* %es:%bx = segment:offset of buffer
* Return:
* %al = 0x0 on success; err code on failure
*/
movw %bx, %es /* load %es segment with disk buffer */
movw $0x0201, %ax /* function 2 */
int $0x13
copy_buffer:
movw ABS(stage2_segment), %es
* We need to save %cx and %si because the startup code in
* stage2 uses them without initializing them.
*/
pusha
pushw %ds
movw $0x100, %cx
movw %bx, %ds
xorw %si, %si
xorw %di, %di
cld
rep
movsw
popa
jmp *(stage2_address)
* BIOS Geometry translation error (past the end of the disk geometry!).
*/
geometry_error:
MSG(geometry_error_string)
jmp general_error
* Disk probe failure.
*/
hd_probe_error:
MSG(hd_probe_error_string)
jmp general_error
* Read error on the disk.
*/
read_error:
MSG(read_error_string)
MSG(general_error_string)
stop: jmp stop
geometry_error_string: .string "Geom"
hd_probe_error_string: .string "Hard Disk"
read_error_string: .string "Read"
general_error_string: .string " Error"
* message: write the string pointed to by %si
*
* WARNING: trashes %si, %ax, and %bx
*/
* Use BIOS "int 10H Function 0Eh" to write character in teletype mode
* %ah = 0xe %al = character
* %bh = page %bl = foreground color (graphics modes)
*/
1:
movw $0x0001, %bx
movb $0xe, %ah
int $0x10 /* display a byte */
message:
lodsb
cmpb $0, %al
jne 1b /* if not end of string, jmp to display */
ret
* Windows NT breaks compatibility by embedding a magic
* number here.
*/
nt_magic:
.long 0
.word 0
* This is where an MBR would go if on a hard disk. The code
* here isn't even referenced unless we're on a floppy. Kinda
* sneaky, huh?
*/
. = _start + STAGE1_PARTSTART
.byte 36, 18, 15, 9, 0%3
5703



被折叠的 条评论
为什么被折叠?



