From 3c2d50e5de17ce79f9f99763d7823dd460e5213d Mon Sep 17 00:00:00 2001 From: Michael Brown Date: Thu, 5 Jul 2007 00:21:01 +0100 Subject: [PATCH] Added active partition locator, and simple MBR built using it. --- src/arch/i386/prefix/bootpart.S | 189 ++++++++++++++++++++++++++++++++ src/arch/i386/prefix/mbr.S | 13 +++ 2 files changed, 202 insertions(+) create mode 100644 src/arch/i386/prefix/bootpart.S create mode 100644 src/arch/i386/prefix/mbr.S diff --git a/src/arch/i386/prefix/bootpart.S b/src/arch/i386/prefix/bootpart.S new file mode 100644 index 00000000..87104f59 --- /dev/null +++ b/src/arch/i386/prefix/bootpart.S @@ -0,0 +1,189 @@ +#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 + /* 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 + movw $(20f-10f), %cx +1: movw $0x0007, %bx + movb $0x0e, %ah + lodsb + int $0x10 + loop 1b + /* Boot next device */ + int $0x18 +10: .ascii "Could not locate active partition\r\n" +20: + +/* + * 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 + movw $446, %bx +1: call read_sector + jc 99f + 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_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 + ret + +/* + * Read single sector to 0000:7c00 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_sector: + pushal + /* Check for LBA extensions */ + call check_lba + jnc read_lba +read_chs: + /* Read sector using C/H/S address */ + movw $0x0201, %ax + xorw %bx, %bx + stc + int $0x13 + sti + jmp 99f +read_lba: + /* Read sector using LBA address */ + movb $0x42, %ah + movl %esi, (lba_desc + 12) + movl %edi, (lba_desc + 8) + movw $lba_desc, %si + int $0x13 +99: /* Check for 55aa signature */ + jc 99f + cmpw $0xaa55, %es:(510) + je 99f + stc +99: popal + ret + +lba_desc: + .byte 0x10 + .byte 0 + .word 1 + .word 0x0000 + .word 0x07c0 + .long 0, 0 + +/* + * Check for LBA extensions + * + * Parameters: + * %dl : BIOS drive number + * + * Returns: + * CF clear if LBA extensions supported + */ +check_lba: + pushal + movb $0x41, %ah + movw $0x55aa, %bx + stc + int $0x13 + jc 99f + cmpw $0xaa55, %bx + je 99f + stc +99: popal + ret diff --git a/src/arch/i386/prefix/mbr.S b/src/arch/i386/prefix/mbr.S new file mode 100644 index 00000000..adfe2041 --- /dev/null +++ b/src/arch/i386/prefix/mbr.S @@ -0,0 +1,13 @@ + .text + .arch i386 + .section ".prefix", "awx", @progbits + .code16 + .org 0 + +mbr: + movw $exec_sector, %bp + jmp find_active_partition +exec_sector: + ljmp $0x0000, $0x7c00 + +#include "bootpart.S"