Fix DOS interrupt error messages
[syslinux.git] / mbr / oldmbr.asm
blob26fb022b6ae21e3e4f42fb311e0d60726266afe8
1 ; -----------------------------------------------------------------------
3 ; Copyright 2003-2008 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 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
95 ; Now look for one (and only one) active partition.
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
108 cmp ax,byte 1 ; Better be only one
109 jnz not_one_partition
112 ; Now we have the active partition partition information in DS:DI.
113 ; Check to see if we support EBIOS.
115 mov dl,[DriveNo]
116 mov ax,4100h
117 mov bx,055AAh
118 xor cx,cx
119 xor dh,dh
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
128 ; We have EBIOS. Load the boot sector using LBA.
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
140 ; No EBIOS. Load the boot sector using CHS.
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]
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
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
166 ; Verify that we have a boot sector, jump
168 cmp word [7C00h+510],0AA55h
169 jne missing_os
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.)
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
197 align 4, db 0 ; Begin data area
200 ; EBIOS disk address packet
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)
210 ; CHS information
211 SecPerCyl: dw 0 ; Heads*Sectors
212 Sectors: dw 0
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
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.
225 PartitionTable equ $$+446 ; Start of partition table
228 ; BSS data; put at 800h
230 DriveNo equ 0800h