/* * Copyright (c) 1999 Robert Nordier * All rights reserved. * * Redistribution and use in source and binary forms are freely * permitted provided that the above copyright notice and this * paragraph and the following disclaimer are duplicated in all * such forms. * * This software is provided "AS IS" and without any express or * implied warranties, including, without limitation, the implied * warranties of merchantability and fitness for a particular * purpose. * * * $FreeBSD: src/sys/boot/i386/mbr/mbr.s,v 1.6 2000/06/27 20:04:10 jhb Exp $ * $DragonFly: src/sys/boot/pc32/mbr/mbr.s,v 1.3 2003/11/10 06:08:36 dillon Exp $ */ /* * A 512 byte MBR boot manager that simply boots the active partition. */ .set LOAD,0x7c00 # Load address .set EXEC,0x600 # Execution address .set PT_OFF,0x1be # Partition table .set MAGIC,0xaa55 # Magic: bootable .set NHRDRV,0x475 # Number of hard drives .globl start # Entry point .code16 /* * Setup the segment registers for flat addressing and setup the stack. */ start: cld # String ops inc xorw %ax,%ax # Zero movw %ax,%es # Address movw %ax,%ds # data movw %ax,%ss # Set up movw $LOAD,%sp # stack /* * Relocate ourself to a lower address so that we are out of the way when * we load in the bootstrap from the partition to boot. */ movw $main-EXEC+LOAD,%si # Source movw $main,%di # Destination movw $0x200-(main-start),%cx # Byte count rep # Relocate movsb # code /* * Jump to the relocated code. */ jmp main-LOAD+EXEC # To relocated code /* * Scan the partition table looking for an active entry. Note that %ch is * zero from the repeated string instruction above. We save the offset of * the active partition in %si and scan the entire table to ensure that only * one partition is marked active. */ main: xorw %si,%si # No active partition movw $partbl,%bx # Partition table movb $0x4,%cl # Number of entries main.1: cmpb %ch,(%bx) # Null entry? je main.2 # Yes jg err_pt # If 0x1..0x7f testw %si,%si # Active already found? jnz err_pt # Yes movw %bx,%si # Point to active main.2: addb $0x10,%bl # Till loop main.1 # done testw %si,%si # Active found? jnz main.3 # Yes int $0x18 # BIOS: Diskless boot /* * Ok, we've found a possible active partition. Check to see that the drive * is a valid hard drive number. */ main.3: cmpb $0x80,%dl # Drive valid? jb main.4 # No movb NHRDRV,%dh # Calculate the highest addb $0x80,%dh # drive number available cmpb %dh,%dl # Within range? jb main.5 # Yes main.4: movb (%si),%dl # Load drive /* * Ok, now that we have a valid drive and partition entry, load the CHS from * the partition entry and read the sector from the disk. */ main.5: movw %sp,%di # Save stack pointer movb 0x1(%si),%dh # Load head movw 0x2(%si),%cx # Load cylinder:sector movw $LOAD,%bx # Transfer buffer #ifdef AVOID_PACKET_MODE cmpb $0xff,%dh # Might we need to use LBA? jnz main.7 # No. cmpw $0xffff,%cx # Do we need to use LBA? jnz main.7 # No. #endif pushw %cx # Save %cx pushw %bx # Save %bx movw $0x55aa,%bx # Magic movb $0x41,%ah # BIOS: EDD extensions int $0x13 # present? jc main.6 # No. cmpw $0xaa55,%bx # Magic ok? jne main.6 # No. testb $0x1,%cl # Packet mode present? jz main.6 # No. popw %bx # Restore %bx pushl $0x0 # Set the LBA pushl 0x8(%si) # address pushw %es # Set the address of pushw %bx # the transfer buffer pushw $0x1 # Read 1 sector pushw $0x10 # Packet length movw %sp,%si # Packer pointer movw $0x4200,%ax # BIOS: LBA Read from disk jmp main.8 # Skip the CHS setup main.6: popw %bx # Restore %bx popw %cx # Restore %cx main.7: movw $0x201,%ax # BIOS: Read from disk main.8: int $0x13 # Call the BIOS movw %di,%sp # Restore stack jc err_rd # If error /* * Now that we've loaded the bootstrap, check for the 0xaa55 signature. If it * is present, execute the bootstrap we just loaded. */ cmpw $MAGIC,0x1fe(%bx) # Bootable? jne err_os # No jmp *%bx # Invoke bootstrap /* * Various error message entry points. */ err_pt: movw $msg_pt,%si # "Invalid partition jmp putstr # table" err_rd: movw $msg_rd,%si # "Error loading jmp putstr # operating system" err_os: movw $msg_os,%si # "Missing operating jmp putstr # system" /* * Output an ASCIZ string to the console via the BIOS. */ putstr.0: movw $0x7,%bx # Page:attribute movb $0xe,%ah # BIOS: Display int $0x10 # character putstr: lodsb # Get character testb %al,%al # End of string? jnz putstr.0 # No putstr.1: jmp putstr.1 # Await reset msg_pt: .asciz "Invalid partition table" msg_rd: .asciz "Error loading operating system" msg_os: .asciz "Missing operating system" .org PT_OFF partbl: .fill 0x10,0x4,0x0 # Partition table .word MAGIC # Magic number