1#- 2# Copyright (c) 2007 Yahoo!, Inc. 3# All rights reserved. 4# Written by: John Baldwin <jhb@FreeBSD.org> 5# 6# Redistribution and use in source and binary forms, with or without 7# modification, are permitted provided that the following conditions 8# are met: 9# 1. Redistributions of source code must retain the above copyright 10# notice, this list of conditions and the following disclaimer. 11# 2. Redistributions in binary form must reproduce the above copyright 12# notice, this list of conditions and the following disclaimer in the 13# documentation and/or other materials provided with the distribution. 14# 3. Neither the name of the author nor the names of any co-contributors 15# may be used to endorse or promote products derived from this software 16# without specific prior written permission. 17# 18# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 19# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 20# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 21# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 22# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 23# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 24# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 25# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 26# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 27# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 28# SUCH DAMAGE. 29# 30# $FreeBSD$ 31# 32# Partly from: src/sys/boot/i386/mbr/mbr.s 1.7 33 34# A 512 byte PMBR boot manager to read a boot program and run it. 35# The embedded MBR is set up for PMBR and default bootblock sector 36# is hardcoded to 256 and size 1. The actual values are supposed to be 37# updated by installboot. 38 39 .set LOAD,0x7c00 # Load address 40 .set EXEC,0x600 # Execution address 41 .set MAGIC,0xaa55 # Magic: bootable 42 .set SECSIZE,0x200 # Size of a single disk sector 43 .set DISKSIG,440 # Disk signature offset 44 .set STACK,EXEC+SECSIZE*4 # Stack address 45 .set DPBUF,STACK 46 47 .set NHRDRV,0x475 # Number of hard drives 48 49 .globl start # Entry point 50 .code16 51 .text 52 53start: jmp real_code 54 .fill 0x3c,0x1,0x90 # fill with nop to ease disasm 55# 56# BIOS Parameter Block. Reserved space from 0xb to 0x3e, the FAT32 BPB 57# is 60 (3Ch) bytes. 58# 59 . = start + 0x3e 60 61# 62# Setup the segment registers for flat addressing and setup the stack. 63# 64real_code: cld # String ops inc 65 xorw %ax,%ax # Zero 66 movw %ax,%es # Address 67 movw %ax,%ds # data 68 movw %ax,%ss # Set up 69 movw $STACK,%sp # stack 70# 71# Relocate ourself to a lower address so that we have more room to load 72# other sectors. 73# 74 movw $main-EXEC+LOAD,%si # Source 75 movw $main,%di # Destination 76 movw $SECSIZE-(main-start),%cx # Byte count 77 rep # Relocate 78 movsb # code 79# 80# Jump to the relocated code. 81# 82 jmp main-LOAD+EXEC # To relocated code 83# 84# Validate drive number in %dl. 85# 86main: cmpb $0x80,%dl # Drive valid? 87 jb main.1 # No 88 movb NHRDRV,%dh # Calculate the highest 89 addb $0x80,%dh # drive number available 90 cmpb %dh,%dl # Within range? 91 jb main.2 # Yes 92main.1: movb $0x80,%dl # Assume drive 0x80 93# 94# Load stage2 and start it. location and size is written by installboot 95# and if size is 0, we can not do anything... 96# 97main.2: movw stage2_size, %ax 98 cmpw $0, %ax 99 je err_noboot # the stage2 size is not set 100 pushw %dx # save drive 101 movb $0x41, %ah # check extensions 102 movw $0x55aa, %bx 103 int $0x13 104 popw %dx # restore drive 105 jc err_rd # need lba mode for now 106 cmpw $0xaa55, %bx # chs support is not 107 jne err_rd # implemented. 108 movw $stage2_sector, %si # pointer to lba 109 movw $LOAD/16,%bx # set buffer segment 110 movw %bx,%es 111 xorw %bx,%bx # and offset 112load_boot: push %si # Save %si 113 call read 114 pop %si # Restore 115 decw stage2_size # stage2_size-- 116 jnz next_boot 117boot: mov %bx,%es # Reset %es to zero 118 jmp LOAD # Jump to boot code 119next_boot: incl (%si) # Next LBA 120 adcl $0,4(%si) 121 mov %es,%ax # Adjust segment for next 122 addw $SECSIZE/16,%ax # sector 123 mov %ax,%es # 124 jmp load_boot 125# 126# Load a sector (64-bit LBA at %si) from disk %dl into %es:%bx by creating 127# a EDD packet on the stack and passing it to the BIOS. Trashes %ax and %si. 128# 129read: pushl 0x4(%si) # Set the LBA 130 pushl 0x0(%si) # address 131 pushw %es # Set the address of 132 pushw %bx # the transfer buffer 133 pushw $0x1 # Read 1 sector 134 pushw $0x10 # Packet length 135 movw %sp,%si # Packer pointer 136 movw $0x4200,%ax # BIOS: LBA Read from disk 137 int $0x13 # Call the BIOS 138 add $0x10,%sp # Restore stack 139 jc err_rd # If error 140 ret 141# 142# Various error message entry points. 143# 144err_rd: movw $msg_rd,%si # "I/O error loading 145 jmp putstr # boot loader" 146 147err_noboot: movw $msg_noboot,%si # "Missing boot 148 jmp putstr # loader" 149# 150# Output an ASCIZ string to the console via the BIOS. 151# 152putstr.0: movw $0x7,%bx # Page:attribute 153 movb $0xe,%ah # BIOS: Display 154 int $0x10 # character 155putstr: lodsb # Get character 156 testb %al,%al # End of string? 157 jnz putstr.0 # No 158putstr.1: jmp putstr.1 # Await reset 159 160msg_rd: .asciz "I/O error" 161msg_noboot: .asciz "No boot loader" 162 163 nop 164mbr_version: .byte 1, 1 # 1.1 165 .align 4 166stage2_size: .word 1 # bootblock size in sectors 167stage2_sector: .quad 256 # lba of bootblock 168disk_uuid: .quad 0 # uuid 169 .quad 0 170 171# this is the end of the code block we can use, next is space for 172# signature, partition table 4 entries and signature. 173 .org DISKSIG,0x1b8 # 174sig: .long 0 # OS Disk Signature 175 .word 0 # "Unknown" in PMBR 176 177partbl: .byte 0x00 # non-bootable 178 .byte 0x00 # head 0 179 .byte 0x02 # sector 180 .byte 0x00 # cylinder 181 .byte 0xEE # ID 182 .byte 0xFF # ending head 183 .byte 0xFF # ending sector 184 .byte 0xFF # ending cylinder 185 .long 0x00000001 # starting LBA 186 .long 0xFFFFFFFF # size 187 .fill 0x10,0x3,0x0 # other 3 entries 188 .word MAGIC # Magic number 189