Adding upstream version 3.35.
[syslinux-debian/hramrach.git] / mbr.asm
blob31bf1fdfe181e9eaa941b014dc22ca3c4cde558e
1 ; -----------------------------------------------------------------------
3 ; Copyright 2003-2004 H. Peter Anvin - All Rights Reserved
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:
14 ; The above copyright notice and this permission notice shall
15 ; be included in all copies or substantial portions of the Software.
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.
26 ; -----------------------------------------------------------------------
29 ; mbr.asm
31 ; Simple Master Boot Record, including support for EBIOS extensions.
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.
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.
41 ; This MBR should be "8086-clean", i.e. not require a 386.
44 %include "bios.inc"
47 ; Note: The MBR is actually loaded at 0:7C00h, but we quickly move it down to
48 ; 0600h.
50 section .text
51 cpu 8086
52 org 0600h
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
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.
74 jmp 0:next ; Jump to copy at 0600h
76 next:
77 mov [DriveNo], dl ; Drive number stored in DL
79 ; Check for CHS parameters. This doesn't work on floppy disks,
80 ; but for an MBR we don't care.
82 mov ah,08h ; Get drive parameters
83 int 13h
84 xor ax,ax
85 mov al,dh
86 inc ax ; From 0-based to count
87 mov [Heads],ax
88 and cl,3Fh ; Max sector number
89 mov [Sectors],cl
90 ; Note: we actually don't care about the number of
91 ; cylinders, since that's the highest-order division
94 ; Now look for one (and only one) active partition.
96 mov si,PartitionTable
97 xor ax,ax
98 mov cx,4
99 checkpartloop:
100 test byte [si],80h
101 jz .notactive
102 inc ax
103 mov di,si
104 .notactive: add si,byte 16
105 loop checkpartloop
107 cmp ax,byte 1 ; Better be only one
108 jnz not_one_partition
111 ; Now we have the active partition partition information in DS:DI.
112 ; Check to see if we support EBIOS.
114 mov dl,[DriveNo]
115 mov ax,4100h
116 mov bx,055AAh
117 xor cx,cx
118 xor dh,dh
120 int 13h
121 jc no_ebios
122 cmp bx,0AA55h
123 jne no_ebios
124 test cl,1 ; LBA device access
125 jz no_ebios
127 ; We have EBIOS. Load the boot sector using LBA.
129 push di
130 mov si,dapa
131 mov bx,[di+8] ; Copy the block address
132 mov [si+8],bx
133 mov bx,[di+10]
134 mov [si+10],bx
135 mov dl,[DriveNo]
136 mov ah,42h ; Extended Read
137 jmp short common_tail
139 ; No EBIOS. Load the boot sector using CHS.
141 no_ebios:
142 push di
143 mov ax,[di+8]
144 mov dx,[di+10]
145 div word [Sectors]
146 inc dx
147 mov cx,dx ; Sector #
148 xor dx,dx
149 div word [Heads]
150 ; DX = head #, AX = cylinder #
151 mov ch,al
152 shr ax,1
153 shr ax,1
154 and al,0C0h
155 or cl,al
156 mov dh,dl ; Head #
157 mov dl,[DriveNo]
158 mov bx,7C00h
159 mov ax,0201h ; Read one sector
160 common_tail:
161 int 13h
162 jc disk_error
163 pop si ; DS:SI -> partition table entry
165 ; Verify that we have a boot sector, jump
167 cmp word [7C00h+510],0AA55h
168 jne missing_os
170 jmp 0:7C00h ; Jump to boot sector; far
171 ; jump is speculation barrier
172 ; (Probably not neecessary, but
173 ; there is plenty of space.)
175 not_one_partition:
176 ja too_many_os
177 missing_os:
178 mov si,missing_os_msg
179 jmp short die
180 too_many_os:
181 disk_error:
182 mov si,bad_disk_msg
183 die:
184 .msgloop:
185 lodsb
186 and al,al
187 jz .now
188 mov ah,0Eh ; TTY output
189 mov bh,[BIOS_page] ; Current page
190 mov bl,07h
191 int 10h
192 jmp short .msgloop
193 .now:
194 jmp short .now
196 align 4, db 0 ; Begin data area
199 ; EBIOS disk address packet
201 dapa:
202 dw 16 ; Packet size
203 .count: dw 1 ; Block count
204 .off: dw 7C00h ; Offset of buffer
205 .seg: dw 0 ; Segment of buffer
206 .lba: dd 0 ; LBA (LSW)
207 dd 0 ; LBA (MSW)
209 ; CHS information
210 Heads: dw 0
211 Sectors: dw 0
213 ; Error messages
214 missing_os_msg db 'Missing operating system', 13, 10, 0
215 bad_disk_msg db 'Operating system loading error', 13, 10, 0
218 ; Maximum MBR size: 446 bytes; end-of-boot-sector signature also needed.
219 ; Note that some operating systems (NT, DR-DOS) put additional stuff at
220 ; the end of the MBR, so shorter is better. Location 440 is known to
221 ; have a 4-byte attempt-at-unique-ID for some OSes.
224 PartitionTable equ $$+446 ; Start of partition table
227 ; BSS data; put at 800h
229 DriveNo equ 0800h