Merge remote-tracking branch 'sherbszt/gfxboot32'
[profile/ivi/syslinux.git] / mbr / oldmbr.asm
1 ; -----------------------------------------------------------------------
2 ;
3 ;   Copyright 2003-2008 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                 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
93
94 ;
95 ; Now look for one (and only one) active partition.
96 ;
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
107
108                 cmp ax,byte 1                   ; Better be only one
109                 jnz not_one_partition
110
111 ;
112 ; Now we have the active partition partition information in DS:DI.
113 ; Check to see if we support EBIOS.
114 ;
115                 mov dl,[DriveNo]
116                 mov ax,4100h
117                 mov bx,055AAh
118                 xor cx,cx
119                 xor dh,dh
120                 stc
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
127 ;
128 ; We have EBIOS.  Load the boot sector using LBA.
129 ;
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
139 ;
140 ; No EBIOS.  Load the boot sector using CHS.
141 ;
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]
151
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
157
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
165 ;
166 ; Verify that we have a boot sector, jump
167 ;
168                 cmp word [7C00h+510],0AA55h
169                 jne missing_os
170                 cli
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.)
175
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
196
197                 align 4, db 0                   ; Begin data area
198
199 ;
200 ; EBIOS disk address packet
201 ;
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)
209
210 ; CHS information
211 SecPerCyl:      dw 0                            ; Heads*Sectors
212 Sectors:        dw 0
213
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
217
218 ;
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.
223 ;
224
225 PartitionTable  equ $$+446                      ; Start of partition table
226
227 ;
228 ; BSS data; put at 800h
229 ;
230 DriveNo         equ 0800h