/* -----------------------------------------------------------------------
*
- * Copyright 2007 H. Peter Anvin - All Rights Reserved
+ * Copyright 2007-2008 H. Peter Anvin - All Rights Reserved
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation
next:
/* Check to see if we have EBIOS */
pushw %dx /* drive number */
- movw $0x4100, %ax
+ movb $0x41, %ah /* %al == 0 already */
movw $0x55aa, %bx
xorw %cx, %cx
xorb %dh, %dh
shrw %cx /* Bit 0 = fixed disk subset */
jnc 1f
- /* We have EBIOS; patch in a jump to read_sector_ebios */
- movw $0xeb+((read_sector_ebios-read_sector_cbios-2)<< 8), (read_sector_cbios)
+ /* We have EBIOS; patch in the following code at
+ read_sector_cbios: movb $0x42, %ah ; jmp read_common */
+ movl $0xeb42b4+((read_common-read_sector_cbios-4) << 24), \
+ (read_sector_cbios)
1:
popw %dx
int $0x13
andw $0x3f, %cx /* Sector count */
pushw %cx /* Save sectors on the stack */
- xorw %ax, %ax
- pushw %ax /* High word of sectors/cylinder */
- movb %dh, %al /* dh = number of heads */
- incw %ax /* From 0-based to count */
+ movzbw %dh, %ax /* dh = max head */
+ incw %ax /* From 0-based max to count */
mulw %cx /* Heads*sectors -> sectors per cylinder */
- pushw %ax /* Save sectors/cylinder on the stack */
+
+ /* Save sectors/cylinder on the stack */
+ pushw %dx /* High word */
+ pushw %ax /* Low word */
xorl %eax, %eax /* Base */
cdq /* Root (%edx <- 0) */
call scan_partition_table
/* If we get here, we have no OS */
- jmp missing_os
+missing_os:
+ call error
+ .ascii "Missing operating system.\r\n"
/*
* read_sector: read a single sector pointed to by %eax to 0x7c00.
*/
read_sector:
pushal
- movw %sp, %si
xorl %edx, %edx
movw $bootsec, %bx
+ pushl %edx /* MSW of LBA */
+ pushl %eax /* LSW of LBA */
+ pushw %es /* Buffer segment */
+ pushw %bx /* Buffer offset */
+ pushw $1 /* Sector count */
+ pushw $16 /* Size of packet */
+ movw %sp, %si
+
+ /* This chunk is skipped if we have ebios */
+ /* Do not clobber %eax before this chunk! */
+ /* This also relies on %bx and %edx as set up above. */
read_sector_cbios:
divl (secpercyl)
shlb $6, %ah
xchgw %dx, %ax
divb (sectors)
movb %al, %dh
- incb %ah
orb %ah, %cl
+ incw %cx /* Sectors are 1-based */
movw $0x0201, %ax
- jmp read_common
-read_sector_ebios:
- pushl %edx /* MSW of LBA */
- pushl %eax /* LSW of LBA */
- pushw %es /* Buffer segment */
- pushw %bx /* Buffer offset */
- pushw $1 /* Sector count */
- pushw $16 /* Size of packet */
- movb $0x42, %ah
+
read_common:
movb (driveno), %dl
int $0x13
- movw %si, %sp
+ addw $16, %sp /* Drop DAPA */
popal
ret
* read_partition_table:
* Read a partition table (pointed to by %eax), and copy
* the partition table into the ptab buffer.
+ *
* Clobbers %si, %di, and %cx, other registers preserved.
+ * %cx = 0 on exit.
+ *
+ * On error, CF is set and ptab is overwritten with junk.
*/
ptab = _start+446
read_partition_table:
call read_sector
- jc 20f
movw $bootsec+446, %si
movw $ptab, %di
movw $(16*4/2), %cx
rep ; movsw
-20:
ret
/*
jns too_many_active
/* No active partitions found, look for extended partitions */
- popw %bx /* %bx <- ptab */
popw %cx /* %cx <- 4 */
+ popw %bx /* %bx <- ptab */
7:
movb 4(%bx), %al
cmpb $0x0f, %al /* 0x0f = Win9x extended */
popal
ret
+too_many_active:
+ call error
+ .ascii "Multiple active partitions.\r\n"
+
/*
* boot: invoke the actual bootstrap. (%si) points to the partition
* table entry, and 28(%bp) has the partition table base.
jc disk_error
cmpw $0xaa55, (bootsec+510)
jne missing_os /* Not a valid boot sector */
- movw $driveno, %sp
+ movw $driveno, %sp /* driveno == bootsec-6 */
popw %dx /* dl -> drive number */
popw %di /* es:di -> $PnP vector */
popw %es
cli
- jmp bootsec
+ jmpw *%sp /* %sp == bootsec */
-/*
- * error messages
- */
-missing_os:
- movw $missing_os_msg, %si
- jmp error
disk_error:
- movw $disk_error_msg, %si
- jmp error
-too_many_active:
- movw $too_many_active_msg, %si
- /* jmp error */
+ call error
+ .ascii "Operating system load error.\r\n"
+/*
+ * Print error messages. This is invoked with "call", with the
+ * error message at the return address.
+ */
error:
+ popw %si
2:
lodsb
- andb %al, %al
- jz 3f
movb $0x0e, %ah
movb (BIOS_page), %bh
movb $0x07, %bl
- int $0x10
- jmp 2b
-3:
+ int $0x10 /* May destroy %bp */
+ cmpb $10, %al /* Newline? */
+ jne 2b
+
int $0x18 /* Boot failure */
- jmp . /* Die */
-
-missing_os_msg:
- .ascii "Missing operating system."
- .byte 0
-disk_error_msg:
- .ascii "Operating system load error."
- .byte 0
-too_many_active_msg:
- .ascii "Multiple active partitions."
- .byte 0
+die:
+ hlt
+ jmp die