blob: 968da1a3817e2044f321144b4610e16aa759dc6b [file] [log] [blame]
FILE_LICENCE ( GPL2_OR_LATER )
#define BOOT_SEG 0x07c0
#define EXEC_SEG 0x0100
#define STACK_SEG 0x0200
#define STACK_SIZE 0x2000
.text
.arch i386
.section ".prefix", "awx", @progbits
.code16
/*
* Find active partition
*
* Parameters:
* %dl : BIOS drive number
* %bp : Active partition handler routine
*/
find_active_partition:
/* Set up stack at STACK_SEG:STACK_SIZE */
movw $STACK_SEG, %ax
movw %ax, %ss
movw $STACK_SIZE, %sp
/* Relocate self to EXEC_SEG */
pushw $BOOT_SEG
popw %ds
pushw $EXEC_SEG
popw %es
xorw %si, %si
xorw %di, %di
movw $0x200, %cx
rep movsb
ljmp $EXEC_SEG, $1f
1: pushw %ds
popw %es
pushw %cs
popw %ds
/* Check for LBA extensions */
movb $0x41, %ah
movw $0x55aa, %bx
stc
int $0x13
jc 1f
cmpw $0xaa55, %bx
jne 1f
movw $read_lba, read_sectors
1:
/* Read and process root partition table */
xorb %dh, %dh
movw $0x0001, %cx
xorl %esi, %esi
xorl %edi, %edi
call process_table
/* Print failure message */
movw $10f, %si
jmp boot_error
10: .asciz "Could not locate active partition\r\n"
/*
* Print failure message and boot next device
*
* Parameters:
* %si : Failure string
*/
boot_error:
cld
movw $0x0007, %bx
movb $0x0e, %ah
1: lodsb
testb %al, %al
je 99f
int $0x10
jmp 1b
99: /* Boot next device */
int $0x18
/*
* Process partition table
*
* Parameters:
* %dl : BIOS drive number
* %dh : Head
* %cl : Sector (bits 0-5), high two bits of cylinder (bits 6-7)
* %ch : Low eight bits of cylinder
* %esi:%edi : LBA address
* %bp : Active partition handler routine
*
* Returns:
* CF set on error
*/
process_table:
pushal
call read_boot_sector
jc 99f
movw $446, %bx
1: call process_partition
addw $16, %bx
cmpw $510, %bx
jne 1b
99: popal
ret
/*
* Process partition
*
* Parameters:
* %dl : BIOS drive number
* %dh : Head
* %cl : Sector (bits 0-5), high two bits of cylinder (bits 6-7)
* %ch : Low eight bits of cylinder
* %esi:%edi : LBA address
* %bx : Offset within partition table
* %bp : Active partition handler routine
*/
process_partition:
pushal
/* Load C/H/S values from partition entry */
movb %es:1(%bx), %dh
movw %es:2(%bx), %cx
/* Update LBA address from partition entry */
addl %es:8(%bx), %edi
adcl $0, %esi
/* Check active flag */
testb $0x80, %es:(%bx)
jz 1f
call read_boot_sector
jc 99f
jmp *%bp
1: /* Check for extended partition */
movb %es:4(%bx), %al
cmpb $0x05, %al
je 2f
cmpb $0x0f, %al
je 2f
cmpb $0x85, %al
jne 99f
2: call process_table
99: popal
/* Reload original partition table */
call read_boot_sector
ret
/*
* Read single sector to %es:0000 and verify 0x55aa signature
*
* Parameters:
* %dl : BIOS drive number
* %dh : Head
* %cl : Sector (bits 0-5), high two bits of cylinder (bits 6-7)
* %ch : Low eight bits of cylinder
* %esi:%edi : LBA address
*
* Returns:
* CF set on error
*/
read_boot_sector:
pushw %ax
movw $1, %ax
call *read_sectors
jc 99f
cmpw $0xaa55, %es:(510)
je 99f
stc
99: popw %ax
ret
/*
* Read sectors to %es:0000
*
* Parameters:
* %dl : BIOS drive number
* %dh : Head
* %cl : Sector (bits 0-5), high two bits of cylinder (bits 6-7)
* %ch : Low eight bits of cylinder
* %esi:%edi : LBA address
* %ax : Number of sectors (max 127)
*
* Returns:
* CF set on error
*/
read_sectors: .word read_chs
read_chs:
/* Read sectors using C/H/S address */
pushal
xorw %bx, %bx
movb $0x02, %ah
stc
int $0x13
sti
popal
ret
read_lba:
/* Read sectors using LBA address */
pushal
movw %ax, (lba_desc + 2)
pushw %es
popw (lba_desc + 6)
movl %edi, (lba_desc + 8)
movl %esi, (lba_desc + 12)
movw $lba_desc, %si
movb $0x42, %ah
int $0x13
popal
ret
lba_desc:
.byte 0x10
.byte 0
.word 1
.word 0x0000
.word 0x0000
.long 0, 0