1 ; ----------------------------------------------------------------------- 2 ; 3 ; Copyright 2003-2008 H. Peter Anvin - All Rights Reserved 4 ; 5 ; Permission is hereby granted, free of charge, to any person 6 ; obtaining a copy of this software and associated documentation 7 ; files (the "Software"), to deal in the Software without 8 ; restriction, including without limitation the rights to use, 9 ; copy, modify, merge, publish, distribute, sublicense, and/or 10 ; sell copies of the Software, and to permit persons to whom 11 ; the Software is furnished to do so, subject to the following 12 ; conditions: 13 ; 14 ; The above copyright notice and this permission notice shall 15 ; be included in all copies or substantial portions of the Software. 16 ; 17 ; THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 18 ; EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES 19 ; OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 20 ; NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT 21 ; HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 22 ; WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 23 ; FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 24 ; OTHER DEALINGS IN THE SOFTWARE. 25 ; 26 ; ----------------------------------------------------------------------- 27 28 ; 29 ; mbr.asm 30 ; 31 ; Simple Master Boot Record, including support for EBIOS extensions. 32 ; 33 ; The MBR lives in front of the boot sector, and is responsible for 34 ; loading the boot sector of the active partition. The EBIOS support 35 ; is needed if the active partition starts beyond cylinder 1024. 36 ; 37 ; This MBR determines all geometry info at runtime. It uses only the 38 ; linear block field in the partition table. It does, however, pass 39 ; the partition table information unchanged to the target OS. 40 ; 41 ; This MBR should be "8086-clean", i.e. not require a 386. 42 ; 43 44 %include "bios.inc" 45 46 ; 47 ; Note: The MBR is actually loaded at 0:7C00h, but we quickly move it down to 48 ; 0600h. 49 ; 50 section .text 51 cpu 8086 52 org 0600h 53 54 _start: cli 55 xor ax,ax 56 mov ds,ax 57 mov es,ax 58 mov ss,ax 59 mov sp,7C00h 60 sti 61 cld 62 mov si,sp ; Start address 63 mov di,0600h ; Destination address 64 mov cx,512/2 65 rep movsw 66 67 ; 68 ; Now, jump to the copy at 0600h so we can load the boot sector at 7C00h. 69 ; Since some BIOSes seem to think 0000:7C00h and 07C0:0000h are the same 70 ; thing, use a far jump to canonicalize the address. This also makes 71 ; sure that it is a code speculation barrier. 72 ; 73 74 jmp 0:next ; Jump to copy at 0600h 75 76 next: 77 mov [DriveNo], dl ; Drive number stored in DL 78 ; 79 ; Check for CHS parameters. This doesn't work on floppy disks, 80 ; but for an MBR we don't care. 81 ; 82 mov ah,08h ; Get drive parameters 83 int 13h 84 and cx,3Fh ; Max sector number 85 mov [Sectors],cx 86 xor ax,ax 87 mov al,dh 88 inc ax ; From 0-based to count 89 mul cx ; Heads*Sectors 90 mov [SecPerCyl],ax 91 ; Note: we actually don't care about the number of 92 ; cylinders, since that's the highest-order division 93 94 ; 95 ; Now look for one (and only one) active partition. 96 ; 97 mov si,PartitionTable 98 xor ax,ax 99 mov cx,4 100 checkpartloop: 101 test byte [si],80h 102 jz .notactive 103 inc ax 104 mov di,si 105 .notactive: add si,byte 16 106 loop checkpartloop 107 108 cmp ax,byte 1 ; Better be only one 109 jnz not_one_partition 110 111 ; 112 ; Now we have the active partition partition information in DS:DI. 113 ; Check to see if we support EBIOS. 114 ; 115 mov dl,[DriveNo] 116 mov ax,4100h 117 mov bx,055AAh 118 xor cx,cx 119 xor dh,dh 120 stc 121 int 13h 122 jc no_ebios 123 cmp bx,0AA55h 124 jne no_ebios 125 test cl,1 ; LBA device access 126 jz no_ebios 127 ; 128 ; We have EBIOS. Load the boot sector using LBA. 129 ; 130 push di 131 mov si,dapa 132 mov bx,[di+8] ; Copy the block address 133 mov [si+8],bx 134 mov bx,[di+10] 135 mov [si+10],bx 136 mov dl,[DriveNo] 137 mov ah,42h ; Extended Read 138 jmp short common_tail 139 ; 140 ; No EBIOS. Load the boot sector using CHS. 141 ; 142 no_ebios: 143 push di 144 mov ax,[di+8] 145 mov dx,[di+10] 146 div word [SecPerCyl] ; AX = cylinder DX = sec in cyl 147 ror ah,1 148 ror ah,1 149 mov cl,ah 150 mov ch,al ; CL = cyl[9:8], CH = cyl[7:0] 151 152 mov ax,dx 153 div byte [Sectors] ; AL = head AH = sector 154 mov dh,al 155 inc ah 156 or cl,ah ; CX = cylinder and sector 157 158 mov dl,[DriveNo] 159 mov bx,7C00h 160 mov ax,0201h ; Read one sector 161 common_tail: 162 int 13h 163 jc disk_error 164 pop si ; DS:SI -> partition table entry 165 ; 166 ; Verify that we have a boot sector, jump 167 ; 168 cmp word [7C00h+510],0AA55h 169 jne missing_os 170 cli 171 jmp 0:7C00h ; Jump to boot sector; far 172 ; jump is speculation barrier 173 ; (Probably not neecessary, but 174 ; there is plenty of space.) 175 176 not_one_partition: 177 ja too_many_os 178 missing_os: 179 mov si,missing_os_msg 180 jmp short die 181 too_many_os: 182 disk_error: 183 mov si,bad_disk_msg 184 die: 185 .msgloop: 186 lodsb 187 and al,al 188 jz .now 189 mov ah,0Eh ; TTY output 190 mov bh,[BIOS_page] ; Current page 191 mov bl,07h 192 int 10h 193 jmp short .msgloop 194 .now: 195 jmp short .now 196 197 align 4, db 0 ; Begin data area 198 199 ; 200 ; EBIOS disk address packet 201 ; 202 dapa: 203 dw 16 ; Packet size 204 .count: dw 1 ; Block count 205 .off: dw 7C00h ; Offset of buffer 206 .seg: dw 0 ; Segment of buffer 207 .lba: dd 0 ; LBA (LSW) 208 dd 0 ; LBA (MSW) 209 210 ; CHS information 211 SecPerCyl: dw 0 ; Heads*Sectors 212 Sectors: dw 0 213 214 ; Error messages 215 missing_os_msg db 'Missing operating system', 13, 10, 0 216 bad_disk_msg db 'Operating system loading error', 13, 10, 0 217 218 ; 219 ; Maximum MBR size: 446 bytes; end-of-boot-sector signature also needed. 220 ; Note that some operating systems (NT, DR-DOS) put additional stuff at 221 ; the end of the MBR, so shorter is better. Location 440 is known to 222 ; have a 4-byte attempt-at-unique-ID for some OSes. 223 ; 224 225 PartitionTable equ $$+446 ; Start of partition table 226 227 ; 228 ; BSS data; put at 800h 229 ; 230 DriveNo equ 0800h 231