Home | History | Annotate | Download | only in mbr
      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