2 # Copyright (c) 2007 Yahoo!, Inc.
4 # Written by: John Baldwin <jhb@FreeBSD.org>
6 # Redistribution and use in source and binary forms, with or without
7 # modification, are permitted provided that the following conditions
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.
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
32 # Partly from: src/sys/boot/i386/mbr/mbr.s 1.7
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.
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
47 .set NHRDRV,0x475 # Number of hard drives
49 .globl start # Entry point
54 .fill 0x3c,0x1,0x90 # fill with nop to ease disasm
56 # BIOS Parameter Block. Reserved space from 0xb to 0x3e, the FAT32 BPB
62 # Setup the segment registers for flat addressing and setup the stack.
64 real_code
: cld
# String ops inc
66 movw
%ax
,%es
# Address
69 movw $STACK
,%sp
# stack
71 # Relocate ourself to a lower address so that we have more room to load
74 movw $main-EXEC+LOAD
,%si
# Source
75 movw $main
,%di
# Destination
76 movw $SECSIZE-
(main-start
),%cx
# Byte count
80 # Jump to the relocated code.
82 jmp main-LOAD+EXEC
# To relocated code
84 # Validate drive number in %dl.
86 main
: cmpb $
0x80,%dl
# Drive valid?
88 movb NHRDRV
,%dh
# Calculate the highest
89 addb $
0x80,%dh
# drive number available
90 cmpb
%dh
,%dl
# Within range?
92 main.1
: movb $
0x80,%dl
# Assume drive 0x80
94 # Load stage2 and start it. location and size is written by installboot
95 # and if size is 0, we can not do anything...
97 main.2
: movw stage2_size
, %ax
99 je err_noboot
# the stage2 size is not set
100 pushw
%dx
# save drive
101 movb $
0x41, %ah
# check extensions
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
111 xorw
%bx
,%bx
# and offset
112 load_boot
: push
%si
# Save %si
115 decw stage2_size
# stage2_size--
117 boot
: mov
%bx
,%es
# Reset %es to zero
118 jmp LOAD
# Jump to boot code
119 next_boot
: incl
(%si
) # Next LBA
121 mov
%es
,%ax
# Adjust segment for next
122 addw $SECSIZE
/16,%ax
# sector
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.
129 read
: 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
142 # Various error message entry points.
144 err_rd
: movw $msg_rd
,%si
# "I/O error loading
145 jmp putstr
# boot loader"
147 err_noboot
: movw $msg_noboot
,%si
# "Missing boot
150 # Output an ASCIZ string to the console via the BIOS.
152 putstr.0
: movw $
0x7,%bx
# Page:attribute
153 movb $
0xe,%ah
# BIOS: Display
154 int $
0x10 # character
155 putstr
: lodsb
# Get character
156 testb
%al
,%al
# End of string?
158 putstr.1
: jmp putstr.1
# Await reset
160 msg_rd
: .asciz "I/O error"
161 msg_noboot
: .asciz "No boot loader"
164 mbr_version
: .byte 1, 1 # 1.1
166 stage2_size
: .word 1 # bootblock size in sectors
167 stage2_sector
: .quad 256 # lba of bootblock
168 disk_uuid
: .quad 0 # uuid
171 # this is the end of the code block we can use, next is space for
172 # signature, partition table 4 entries and signature.
174 sig
: .long 0 # OS Disk Signature
175 .word 0 # "Unknown" in PMBR
177 partbl
: .byte 0x00 # non-bootable
180 .byte 0x00 # cylinder
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