aboutsummaryrefslogtreecommitdiffstats
path: root/mbr
diff options
context:
space:
mode:
Diffstat (limited to 'mbr')
-rw-r--r--mbr/oldmbr.asm229
1 files changed, 229 insertions, 0 deletions
diff --git a/mbr/oldmbr.asm b/mbr/oldmbr.asm
new file mode 100644
index 00000000..31bf1fdf
--- /dev/null
+++ b/mbr/oldmbr.asm
@@ -0,0 +1,229 @@
+; -----------------------------------------------------------------------
+;
+; Copyright 2003-2004 H. Peter Anvin - All Rights Reserved
+;
+; Permission is hereby granted, free of charge, to any person
+; obtaining a copy of this software and associated documentation
+; files (the "Software"), to deal in the Software without
+; restriction, including without limitation the rights to use,
+; copy, modify, merge, publish, distribute, sublicense, and/or
+; sell copies of the Software, and to permit persons to whom
+; the Software is furnished to do so, subject to the following
+; conditions:
+;
+; The above copyright notice and this permission notice shall
+; be included in all copies or substantial portions of the Software.
+;
+; THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+; EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+; OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+; NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+; HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+; WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+; FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+; OTHER DEALINGS IN THE SOFTWARE.
+;
+; -----------------------------------------------------------------------
+
+;
+; 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.
+;
+
+%include "bios.inc"
+
+;
+; Note: The MBR is actually loaded at 0:7C00h, but we quickly move it down to
+; 0600h.
+;
+ section .text
+ 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
+ and al,al
+ jz .now
+ mov ah,0Eh ; TTY output
+ mov bh,[BIOS_page] ; Current page
+ mov bl,07h
+ 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. Location 440 is known to
+; have a 4-byte attempt-at-unique-ID for some OSes.
+;
+
+PartitionTable equ $$+446 ; Start of partition table
+
+;
+; BSS data; put at 800h
+;
+DriveNo equ 0800h