#include
#define ABS(x) (x-_start+0x7c00) //计算物理地址,不依赖编译器
/* Print message string */
#define MSG(x) movw $ABS(x), %si; call message
/* XXX: binutils-2.9.1.0.x doesn't produce a short opcode for this. */
#define MOV_MEM_TO_AL(x) .byte 0xa0; .word x //这个不用管它,只是为了实现兼容性用了机器码
.file "stage1.S"
.text
.code16
.globl _start; _start:
jmp after_BPB
nop /* do I care about this ??? */
. = _start + 4 //跳过上面两条指令
/* scratch space BIOS参数的定义*/
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... */
. = _start + STAGE1_BPBEND
/*
* End of BIOS parameter block.
*/
/*与启动有关的参数的定义*/
stage1_version:
.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
after_BPB:
/* general setup */
cli /* we're not safe here! */
boot_drive_check: /*这段代码有什么用? jmp 1f 后面的代码能执行吗?我没看明白*/
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*/
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 $STAGE1_STACKSEG, %sp /*STAGE1_STACKSEG = 0x2000*/
sti /* we're safe again */
/*
* 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 /*不是默认的话,保存才是有用的,否则没用*/
/* print a notification message on the screen */
MSG(notification_string)
/* do not probe LBA if the drive is a floppy */
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
/* use CHS if fails */
jc chs_mode
cmpw $0xaa55, %bx /*测试后,正常情况下bx=0xaa55*/
jne chs_mode
/* check if AH=0x42 is supported if FORCE_LBA is zero */
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:
* 1 - Device Access using the packet structure
* 2 - Drive Locking and Ejecting
* 4 - Enhanced Disk Drive Support (EDD)
*/
jz chs_mode
lba_mode:
/* save the total number of sectors */
movl 0x10(%si), %ecx /*这是在干什么*/
/* set %si to the disk address packet */
movw $ABS(disk_address_packet), %si /* si指向BIOS的参数*/
/* set the mode to non-zero mode =1*/
movb $1, -1(%si)
movl ABS(stage2_sector), %ebx
/* the size and the reserved byte */
movw $0x0010, (%si) /**/
/* the blocks */
movw $1, 2(%si)
/* the absolute address (low 32 bits) */
movl %ebx, 8(%si)
/* the segment of buffer address */
movw $STAGE1_BUFFERSEG, 6(%si)
xorl %eax, %eax
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
*/
movb $0x42, %ah
int $0x13
/* LBA read is not supported, so fallback to CHS. */
jc chs_mode
movw $STAGE1_BUFFERSEG, %bx
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
/* Nope, we definitely have a hard disk, and we're screwed. */
jmp hd_probe_error
final_init:
movw $ABS(sectors), %si
/* set the mode to zero */
movb $0, -1(%si)
/* save number of heads */
xorl %eax, %eax
movb %dh, %al
incw %ax
movl %eax, 4(%si)
xorw %dx, %dx
movb %cl, %dl
shlw $2, %dx
movb %ch, %al
movb %dh, %ah
/* save number of cylinders */
incw %ax
movw %ax, 8(%si)
xorw %ax, %ax
movb %dl, %al
shrb $2, %al
/* save number of sectors */
movl %eax, (%si)
setup_sectors:
/* load logical sector start (bottom half) */
movl ABS(stage2_sector), %eax
/* zero %edx */
xorl %edx, %edx
/* divide by number of sectors */
divl (%si)
/* save sector start */
movb %dl, 10(%si)
xorl %edx, %edx /* zero %edx */
divl 4(%si) /* divide by number of heads */
/* save head start */
movb %dl, 11(%si)
/* save cylinder start */
movw %ax, 12(%si)
/* do we need too many cylinders? */
cmpw 8(%si), %ax
jge geometry_error
/*
* This is the loop for taking care of BIOS geometry translation (ugh!)
*/
/* get high bits of cylinder */
movb 13(%si), %dl
shlb $6, %dl /* shift left by 6 bits */
movb 10(%si), %cl /* get sector */
incb %cl /* normalize sector (sectors go
from 1-N, not 0-(N-1) ) */
orb %dl, %cl /* composite together */
movb 12(%si), %ch /* sector+hcyl in cl, cylinder in ch */
/* restore %dx */
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 $STAGE1_BUFFERSEG, %bx
movw %bx, %es /* load %es segment with disk buffer */
xorw %bx, %bx /* %bx = 0, put it at 0 in the segment */
movw $0x0201, %ax /* function 2 */
int $0x13
jc read_error
movw %es, %bx
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
popw %ds
popa
/* boot stage2 */
jmp *(stage2_address)
/* END OF MAIN LOOP */
/*
* 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)
general_error:
MSG(general_error_string)
/* go here when you need to stop the machine hard after an error condition */
stop: jmp stop
notification_string: .string "GRUB "
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.
*/
. = _start + STAGE1_WINDOWS_NT_MAGIC
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?
*/
part_start:
. = _start + STAGE1_PARTSTART
probe_values:
.byte 36, 18, 15, 9, 0%3
阅读(4180) | 评论(0) | 转发(0) |