| #- |
| # Copyright (c) 2007 Yahoo!, Inc. |
| # All rights reserved. |
| # Written by: John Baldwin <jhb@FreeBSD.org> |
| # |
| # Redistribution and use in source and binary forms, with or without |
| # modification, are permitted provided that the following conditions |
| # are met: |
| # 1. Redistributions of source code must retain the above copyright |
| # notice, this list of conditions and the following disclaimer. |
| # 2. Redistributions in binary form must reproduce the above copyright |
| # notice, this list of conditions and the following disclaimer in the |
| # documentation and/or other materials provided with the distribution. |
| # 3. Neither the name of the author nor the names of any co-contributors |
| # may be used to endorse or promote products derived from this software |
| # without specific prior written permission. |
| # |
| # THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND |
| # ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
| # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
| # ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE |
| # FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL |
| # DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS |
| # OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) |
| # HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT |
| # LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY |
| # OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF |
| # SUCH DAMAGE. |
| # |
| # $FreeBSD$ |
| # |
| # Partly from: src/sys/boot/i386/mbr/mbr.s 1.7 |
| |
| # A 512 byte PMBR boot manager to read a boot program and run it. |
| # The embedded MBR is set up for PMBR and default bootblock sector |
| # is hardcoded to 256 and size 1. The actual values are supposed to be |
| # updated by installboot. |
| |
| .set LOAD,0x7c00 # Load address |
| .set EXEC,0x600 # Execution address |
| .set MAGIC,0xaa55 # Magic: bootable |
| .set SECSIZE,0x200 # Size of a single disk sector |
| .set DISKSIG,440 # Disk signature offset |
| .set STACK,EXEC+SECSIZE*4 # Stack address |
| .set DPBUF,STACK |
| |
| .set NHRDRV,0x475 # Number of hard drives |
| |
| .globl start # Entry point |
| .code16 |
| .text |
| |
| start: jmp real_code |
| .fill 0x3c,0x1,0x90 # fill with nop to ease disasm |
| # |
| # BIOS Parameter Block. Reserved space from 0xb to 0x3e, the FAT32 BPB |
| # is 60 (3Ch) bytes. |
| # |
| . = start + 0x3e |
| |
| # |
| # Setup the segment registers for flat addressing and setup the stack. |
| # |
| real_code: cld # String ops inc |
| xorw %ax,%ax # Zero |
| movw %ax,%es # Address |
| movw %ax,%ds # data |
| movw %ax,%ss # Set up |
| movw $STACK,%sp # stack |
| # |
| # Relocate ourself to a lower address so that we have more room to load |
| # other sectors. |
| # |
| movw $main-EXEC+LOAD,%si # Source |
| movw $main,%di # Destination |
| movw $SECSIZE-(main-start),%cx # Byte count |
| rep # Relocate |
| movsb # code |
| # |
| # Jump to the relocated code. |
| # |
| jmp main-LOAD+EXEC # To relocated code |
| # |
| # Validate drive number in %dl. |
| # |
| main: cmpb $0x80,%dl # Drive valid? |
| jb main.1 # No |
| movb NHRDRV,%dh # Calculate the highest |
| addb $0x80,%dh # drive number available |
| cmpb %dh,%dl # Within range? |
| jb main.2 # Yes |
| main.1: movb $0x80,%dl # Assume drive 0x80 |
| # |
| # Load stage2 and start it. location and size is written by installboot |
| # and if size is 0, we can not do anything... |
| # |
| main.2: movw stage2_size, %ax |
| cmpw $0, %ax |
| je err_noboot # the stage2 size is not set |
| pushw %dx # save drive |
| movb $0x41, %ah # check extensions |
| movw $0x55aa, %bx |
| int $0x13 |
| popw %dx # restore drive |
| jc err_rd # need lba mode for now |
| cmpw $0xaa55, %bx # chs support is not |
| jne err_rd # implemented. |
| movw $stage2_sector, %si # pointer to lba |
| movw $LOAD/16,%bx # set buffer segment |
| movw %bx,%es |
| xorw %bx,%bx # and offset |
| load_boot: push %si # Save %si |
| call read |
| pop %si # Restore |
| decw stage2_size # stage2_size-- |
| jnz next_boot |
| boot: mov %bx,%es # Reset %es to zero |
| jmp LOAD # Jump to boot code |
| next_boot: incl (%si) # Next LBA |
| adcl $0,4(%si) |
| mov %es,%ax # Adjust segment for next |
| addw $SECSIZE/16,%ax # sector |
| mov %ax,%es # |
| jmp load_boot |
| # |
| # Load a sector (64-bit LBA at %si) from disk %dl into %es:%bx by creating |
| # a EDD packet on the stack and passing it to the BIOS. Trashes %ax and %si. |
| # |
| read: pushl 0x4(%si) # Set the LBA |
| pushl 0x0(%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 |
| int $0x13 # Call the BIOS |
| add $0x10,%sp # Restore stack |
| jc err_rd # If error |
| ret |
| # |
| # Various error message entry points. |
| # |
| err_rd: movw $msg_rd,%si # "I/O error loading |
| jmp putstr # boot loader" |
| |
| err_noboot: movw $msg_noboot,%si # "Missing boot |
| jmp putstr # loader" |
| # |
| # 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_rd: .asciz "I/O error" |
| msg_noboot: .asciz "No boot loader" |
| |
| nop |
| mbr_version: .byte 1, 1 # 1.1 |
| .align 4 |
| stage2_size: .word 1 # bootblock size in sectors |
| stage2_sector: .quad 256 # lba of bootblock |
| disk_uuid: .quad 0 # uuid |
| .quad 0 |
| |
| # this is the end of the code block we can use, next is space for |
| # signature, partition table 4 entries and signature. |
| .org DISKSIG,0x1b8 # |
| sig: .long 0 # OS Disk Signature |
| .word 0 # "Unknown" in PMBR |
| |
| partbl: .byte 0x00 # non-bootable |
| .byte 0x00 # head 0 |
| .byte 0x02 # sector |
| .byte 0x00 # cylinder |
| .byte 0xEE # ID |
| .byte 0xFF # ending head |
| .byte 0xFF # ending sector |
| .byte 0xFF # ending cylinder |
| .long 0x00000001 # starting LBA |
| .long 0xFFFFFFFF # size |
| .fill 0x10,0x3,0x0 # other 3 entries |
| .word MAGIC # Magic number |