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