1/* 2 * Copyright (c) 1999 Robert Nordier 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms are freely 6 * permitted provided that the above copyright notice and this 7 * paragraph and the following disclaimer are duplicated in all 8 * such forms. 9 * 10 * This software is provided "AS IS" and without any express or 11 * implied warranties, including, without limitation, the implied 12 * warranties of merchantability and fitness for a particular 13 * purpose. 14 * 15 * 16 * $FreeBSD: src/sys/boot/i386/mbr/mbr.s,v 1.6 2000/06/27 20:04:10 jhb Exp $ 17 * $DragonFly: src/sys/boot/pc32/mbr/mbr.s,v 1.3 2003/11/10 06:08:36 dillon Exp $ 18 */ 19 20/* 21 * A 512 byte MBR boot manager that simply boots the active partition. 22 */ 23 24 .set LOAD,0x7c00 # Load address 25 .set EXEC,0x600 # Execution address 26 .set PT_OFF,0x1be # Partition table 27 .set MAGIC,0xaa55 # Magic: bootable 28 29 .set NHRDRV,0x475 # Number of hard drives 30 31 .globl start # Entry point 32 .code16 33 34/* 35 * Setup the segment registers for flat addressing and setup the stack. 36 */ 37start: cld # String ops inc 38 xorw %ax,%ax # Zero 39 movw %ax,%es # Address 40 movw %ax,%ds # data 41 movw %ax,%ss # Set up 42 movw $LOAD,%sp # stack 43/* 44 * Relocate ourself to a lower address so that we are out of the way when 45 * we load in the bootstrap from the partition to boot. 46 */ 47 movw $main-EXEC+LOAD,%si # Source 48 movw $main,%di # Destination 49 movw $0x200-(main-start),%cx # Byte count 50 rep # Relocate 51 movsb # code 52/* 53 * Jump to the relocated code. 54 */ 55 jmp main-LOAD+EXEC # To relocated code 56/* 57 * Scan the partition table looking for an active entry. Note that %ch is 58 * zero from the repeated string instruction above. We save the offset of 59 * the active partition in %si and scan the entire table to ensure that only 60 * one partition is marked active. 61 */ 62main: xorw %si,%si # No active partition 63 movw $partbl,%bx # Partition table 64 movb $0x4,%cl # Number of entries 65main.1: cmpb %ch,(%bx) # Null entry? 66 je main.2 # Yes 67 jg err_pt # If 0x1..0x7f 68 testw %si,%si # Active already found? 69 jnz err_pt # Yes 70 movw %bx,%si # Point to active 71main.2: addb $0x10,%bl # Till 72 loop main.1 # done 73 testw %si,%si # Active found? 74 jnz main.3 # Yes 75 int $0x18 # BIOS: Diskless boot 76/* 77 * Ok, we've found a possible active partition. Check to see that the drive 78 * is a valid hard drive number. 79 */ 80main.3: cmpb $0x80,%dl # Drive valid? 81 jb main.4 # No 82 movb NHRDRV,%dh # Calculate the highest 83 addb $0x80,%dh # drive number available 84 cmpb %dh,%dl # Within range? 85 jb main.5 # Yes 86main.4: movb (%si),%dl # Load drive 87/* 88 * Ok, now that we have a valid drive and partition entry, load the CHS from 89 * the partition entry and read the sector from the disk. 90 */ 91main.5: movw %sp,%di # Save stack pointer 92 movb 0x1(%si),%dh # Load head 93 movw 0x2(%si),%cx # Load cylinder:sector 94 movw $LOAD,%bx # Transfer buffer 95#ifdef AVOID_PACKET_MODE 96 cmpb $0xff,%dh # Might we need to use LBA? 97 jnz main.7 # No. 98 cmpw $0xffff,%cx # Do we need to use LBA? 99 jnz main.7 # No. 100#endif 101 pushw %cx # Save %cx 102 pushw %bx # Save %bx 103 movw $0x55aa,%bx # Magic 104 movb $0x41,%ah # BIOS: EDD extensions 105 int $0x13 # present? 106 jc main.6 # No. 107 cmpw $0xaa55,%bx # Magic ok? 108 jne main.6 # No. 109 testb $0x1,%cl # Packet mode present? 110 jz main.6 # No. 111 popw %bx # Restore %bx 112 pushl $0x0 # Set the LBA 113 pushl 0x8(%si) # address 114 pushw %es # Set the address of 115 pushw %bx # the transfer buffer 116 pushw $0x1 # Read 1 sector 117 pushw $0x10 # Packet length 118 movw %sp,%si # Packer pointer 119 movw $0x4200,%ax # BIOS: LBA Read from disk 120 jmp main.8 # Skip the CHS setup 121main.6: popw %bx # Restore %bx 122 popw %cx # Restore %cx 123main.7: movw $0x201,%ax # BIOS: Read from disk 124main.8: int $0x13 # Call the BIOS 125 movw %di,%sp # Restore stack 126 jc err_rd # If error 127/* 128 * Now that we've loaded the bootstrap, check for the 0xaa55 signature. If it 129 * is present, execute the bootstrap we just loaded. 130 */ 131 cmpw $MAGIC,0x1fe(%bx) # Bootable? 132 jne err_os # No 133 jmp *%bx # Invoke bootstrap 134/* 135 * Various error message entry points. 136 */ 137err_pt: movw $msg_pt,%si # "Invalid partition 138 jmp putstr # table" 139 140err_rd: movw $msg_rd,%si # "Error loading 141 jmp putstr # operating system" 142 143err_os: movw $msg_os,%si # "Missing operating 144 jmp putstr # system" 145/* 146 * Output an ASCIZ string to the console via the BIOS. 147 */ 148putstr.0: movw $0x7,%bx # Page:attribute 149 movb $0xe,%ah # BIOS: Display 150 int $0x10 # character 151putstr: lodsb # Get character 152 testb %al,%al # End of string? 153 jnz putstr.0 # No 154putstr.1: jmp putstr.1 # Await reset 155 156msg_pt: .asciz "Invalid partition table" 157msg_rd: .asciz "Error loading operating system" 158msg_os: .asciz "Missing operating system" 159 160 .org PT_OFF 161 162partbl: .fill 0x10,0x4,0x0 # Partition table 163 .word MAGIC # Magic number 164