syslinux-3.08-2 sources from FC4
[bootcd.git] / syslinux / mbr.asm
1 ; -----------------------------------------------------------------------
2 ;   
3 ;   Copyright 2003-2004 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                 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
92
93 ;
94 ; Now look for one (and only one) active partition.
95 ;
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
106
107                 cmp ax,byte 1                   ; Better be only one
108                 jnz not_one_partition
109
110 ;
111 ; Now we have the active partition partition information in DS:DI.
112 ; Check to see if we support EBIOS.
113 ;
114                 mov dl,[DriveNo]
115                 mov ax,4100h
116                 mov bx,055AAh
117                 xor cx,cx
118                 xor dh,dh
119                 stc
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
126 ;
127 ; We have EBIOS.  Load the boot sector using LBA.
128 ;
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
138 ;
139 ; No EBIOS.  Load the boot sector using CHS.
140 ;
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
164 ;
165 ; Verify that we have a boot sector, jump
166 ;
167                 cmp word [7C00h+510],0AA55h
168                 jne missing_os
169                 cli
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.)
174
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
195
196                 align 4, db 0                   ; Begin data area
197
198 ;
199 ; EBIOS disk address packet
200 ;
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)
208
209 ; CHS information
210 Heads:          dw 0
211 Sectors:        dw 0
212
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
216
217 ;
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.
222 ;
223
224 PartitionTable  equ $$+446                      ; Start of partition table
225
226 ;
227 ; BSS data; put at 800h
228 ;
229 DriveNo         equ 0800h