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 76next: 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 100checkpartloop: 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; 142no_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 161common_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 176not_one_partition: 177 ja too_many_os 178missing_os: 179 mov si,missing_os_msg 180 jmp short die 181too_many_os: 182disk_error: 183 mov si,bad_disk_msg 184die: 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; 202dapa: 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 211SecPerCyl: dw 0 ; Heads*Sectors 212Sectors: dw 0 213 214; Error messages 215missing_os_msg db 'Missing operating system', 13, 10, 0 216bad_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 225PartitionTable equ $$+446 ; Start of partition table 226 227; 228; BSS data; put at 800h 229; 230DriveNo equ 0800h 231