blob: 5d05d018347b97c0be60f6d4368720fda45136d4 [file] [log] [blame]
; -*- fundamental -*- (asm-mode sucks)
; $Id$
; -----------------------------------------------------------------------
;
; NOT Copyright 2000 H. Peter Anvin
;
; This file is in the public domain. Enjoy. However, I would
; appreciate it if modified versions were marked as such, and
; please don't bug me about any version not released by me.
;
; -----------------------------------------------------------------------
;
; mbr.asm
;
; Simple Master Boot Record, including support for EBIOS extensions.
;
; The MBR lives in front of the boot sector, and is responsible for
; loading the boot sector of the active partition. The EBIOS support
; is needed if the active partition starts beyond cylinder 1024.
;
; This MBR determines all geometry info at runtime. It uses only the
; linear block field in the partition table. It does, however, pass
; the partition table information unchanged to the target OS.
;
; This MBR should be "8086-clean", i.e. not require a 386.
;
;
; Note: The MBR is actually loaded at 0:7C00h, but we quickly move it down to
; 0600h.
;
cpu 8086
org 0600h
_start: cli
xor ax,ax
mov ds,ax
mov es,ax
mov ss,ax
mov sp,7C00h
sti
cld
mov si,sp ; Start address
mov di,0600h ; Destination address
mov cx,512/2
rep movsw
;
; Now, jump to the copy at 0600h so we can load the boot sector at 7C00h.
; Since some BIOSes seem to think 0000:7C00h and 07C0:0000h are the same
; thing, use a far jump to canonicalize the address. This also makes
; sure that it is a code speculation barrier.
;
jmp 0:next ; Jump to copy at 0600h
next:
mov [DriveNo], dl ; Drive number stored in DL
;
; Check for CHS parameters. This doesn't work on floppy disks,
; but for an MBR we don't care.
;
mov ah,08h ; Get drive parameters
int 13h
xor ax,ax
mov al,dh
inc ax ; From 0-based to count
mov [Heads],ax
and cl,3Fh ; Max sector number
mov [Sectors],cl
; Note: we actually don't care about the number of
; cylinders, since that's the highest-order division
;
; Now look for one (and only one) active partition.
;
mov si,PartitionTable
xor ax,ax
mov cx,4
checkpartloop:
test byte [si],80h
jz .notactive
inc ax
mov di,si
.notactive: add si,byte 16
loop checkpartloop
cmp ax,byte 1 ; Better be only one
jnz not_one_partition
;
; Now we have the active partition partition information in DS:DI.
; Check to see if we support EBIOS.
;
mov dl,[DriveNo]
mov ax,4100h
mov bx,055AAh
xor cx,cx
xor dh,dh
stc
int 13h
jc no_ebios
cmp bx,0AA55h
jne no_ebios
test cl,1 ; LBA device access
jz no_ebios
;
; We have EBIOS. Load the boot sector using LBA.
;
push di
mov si,dapa
mov bx,[di+8] ; Copy the block address
mov [si+8],bx
mov bx,[di+10]
mov [si+10],bx
mov dl,[DriveNo]
mov ah,42h ; Extended Read
jmp short common_tail
;
; No EBIOS. Load the boot sector using CHS.
;
no_ebios:
push di
mov ax,[di+8]
mov dx,[di+10]
div word [Sectors]
inc dx
mov cx,dx ; Sector #
xor dx,dx
div word [Heads]
; DX = head #, AX = cylinder #
mov ch,al
shr ax,1
shr ax,1
and al,0C0h
or cl,al
mov dh,dl ; Head #
mov dl,[DriveNo]
mov bx,7C00h
mov ax,0201h ; Read one sector
common_tail:
int 13h
jc disk_error
pop si ; DS:SI -> partition table entry
;
; Verify that we have a boot sector, jump
;
cmp word [7C00h+510],0AA55h
jne missing_os
cli
jmp 0:7C00h ; Jump to boot sector; far
; jump is speculation barrier
; (Probably not neecessary, but
; there is plenty of space.)
not_one_partition:
ja too_many_os
missing_os:
mov si,missing_os_msg
jmp short die
too_many_os:
disk_error:
mov si,bad_disk_msg
die:
.msgloop:
lodsb
xor al,al
jz .now
mov ah,0Eh ; TTY output
mov bx,0007h
int 10h
jmp short .msgloop
.now:
jmp short .now
align 4, db 0 ; Begin data area
;
; EBIOS disk address packet
;
dapa:
dw 16 ; Packet size
.count: dw 1 ; Block count
.off: dw 7C00h ; Offset of buffer
.seg: dw 0 ; Segment of buffer
.lba: dd 0 ; LBA (LSW)
dd 0 ; LBA (MSW)
; CHS information
Heads: dw 0
Sectors: dw 0
; Error messages
missing_os_msg db 'Missing operating system', 13, 10, 0
bad_disk_msg db 'Operating system loading error', 13, 10, 0
;
; Maximum MBR size: 446 bytes; end-of-boot-sector signature also needed.
; Note that some operating systems (NT, DR-DOS) put additional stuff at
; the end of the MBR, so shorter is better.
;
PartitionTable equ $$+446 ; Start of partition table
;
; BSS data; put at 800h
;
DriveNo equ 0800h