]> git.saurik.com Git - apple/boot.git/blob - i386/cdboot/cdboot.s
54226fac9385c792e103403ae912284ae0898823
[apple/boot.git] / i386 / cdboot / cdboot.s
1 ; Copyright (c) 2003 Apple Computer, Inc. All rights reserved.
2 ;
3 ; @APPLE_LICENSE_HEADER_START@
4 ;
5 ; Copyright (c) 1999-2003 Apple Computer, Inc. All Rights Reserved.
6 ;
7 ; This file contains Original Code and/or Modifications of Original Code
8 ; as defined in and that are subject to the Apple Public Source License
9 ; Version 2.0 (the 'License'). You may not use this file except in
10 ; compliance with the License. Please obtain a copy of the License at
11 ; http://www.opensource.apple.com/apsl/ and read it before using this
12 ; file.
13 ;
14 ; The Original Code and all software distributed under the License are
15 ; distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
16 ; EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
17 ; INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
18 ; FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
19 ; Please see the License for the specific language governing rights and
20 ; limitations under the License.
21 ;
22 ; @APPLE_LICENSE_HEADER_END@
23
24 DEBUG EQU 0
25
26 %macro DebugCharMacro 1
27 push ax
28 mov al, %1
29 call putc
30 pop ax
31 %endmacro
32 %macro DebugPauseMacro 0
33 push ax
34 call getc
35 pop ax
36 %endmacro
37
38 %if DEBUG
39 %define DebugChar(x) DebugCharMacro x
40 %define DebugPause(x) DebugPauseMacro
41 %else
42 %define DebugChar(x)
43 %define DebugPause(x)
44 %endif
45
46 kBoot2Sectors EQU 112 ; sectors to load for boot2
47 kBoot2Address EQU 0x0200 ; boot2 load address
48 kBoot2Segment EQU 0x2000 ; boot2 load segment
49
50 kBoot0Stack EQU 0xFFF0 ; boot0 stack pointer
51
52 kReadBuffer EQU 0x1000 ; disk data buffer address
53
54 kVolSectorOffset EQU 0x47 ; offset in buffer of sector number
55 ; in volume descriptor
56 kBootSectorOffset EQU 0x28 ; offset in boot catalog
57 ; of sector number to load boot file
58 kBootCountOffset EQU 0x26 ; offset in boot catalog
59 ; of number of sectors to read
60
61
62 code16
63 ORG 0x7c00
64
65 SEGMENT .text
66
67 start:
68 cli
69 jmp 0:start1
70 times 8-($-$$) nop ; Put boot information table at offset 8
71
72 ; El Torito boot information table, filled in by the
73 ; mkisofs -boot-info-table option, if used.
74 bi_pvd: dd 0 ; LBA of primary volume descriptor
75 bi_file: dd 0 ; LBA of boot file
76 bi_length: dd 0 ; Length of boot file
77 bi_csum: dd 0 ; Checksum of boot file
78 bi_reserved: times 10 dd 0 ; Reserved
79
80 start1:
81 xor ax, ax ; zero %ax
82 mov ss, ax ; setup the
83 mov sp, kBoot0Stack ; stack
84 sti
85 cld ; increment SI after each lodsb call
86 mov ds, ax ; setup the
87 mov es, ax ; data segments
88 ;; BIOS boot drive is in DL
89
90 DebugChar('!')
91 DebugPause()
92
93 %if DEBUG
94 mov eax, [kBoot2LoadAddr]
95 call print_hex
96 call getc
97 %endif
98
99 ;;
100 ;; The BIOS likely didn't load the rest of the booter,
101 ;; so we have to fetch it ourselves.
102 ;;
103 xor ax, ax
104 mov es, ax
105 mov bx, kReadBuffer
106 mov al, 1
107 mov ecx, 17
108 call read_lba
109 jc error
110
111 DebugChar('A')
112
113 mov ecx, [kReadBuffer + kVolSectorOffset]
114 %if DEBUG
115 mov eax, ecx
116 call print_hex
117 DebugPause()
118 %endif
119 mov al, 1
120 call read_lba
121 jc error
122
123 ;; Now we have the boot catalog in the buffer.
124 ;; Really we should look at the validation entry, but oh well.
125
126 DebugChar('B')
127
128 mov ecx, [kReadBuffer + kBootSectorOffset]
129 inc ecx ; skip the first sector which is what we are in
130 %if DEBUG
131 mov eax, ecx
132 call print_hex
133 DebugPause()
134 %endif
135
136 mov ax, kBoot2Segment
137 mov es, ax
138
139 mov al, kBoot2Sectors / 4
140 mov bx, kBoot2Address
141 call read_lba
142 jc error
143
144 DebugChar('C')
145 %if DEBUG
146 mov eax, [es:kBoot2Address]
147 call print_hex
148 DebugPause()
149 %endif
150
151 xor ax, ax
152 mov es, ax
153
154 DebugChar('X')
155 DebugPause()
156
157 ;; Jump to newly-loaded booter
158 jmp kBoot2Segment:kBoot2Address
159
160 error:
161 mov al, 'E'
162 call putc
163 hlt
164
165 ;;
166 ;; Support functions
167 ;;
168
169 ;--------------------------------------------------------------------------
170 ; read_lba - Read sectors from CD using LBA addressing.
171 ;
172 ; Arguments:
173 ; AL = number of 2048-byte sectors to read (valid from 1-127).
174 ; ES:BX = pointer to where the sectors should be stored.
175 ; ECX = sector offset in partition
176 ; DL = drive number (0x80 + unit number)
177 ;
178 ; Returns:
179 ; CF = 0 success
180 ; 1 error
181 ;
182 read_lba:
183 pushad ; save all registers
184 mov bp, sp ; save current SP
185
186 ;
187 ; Create the Disk Address Packet structure for the
188 ; INT13/F42 (Extended Read Sectors) on the stack.
189 ;
190
191 ; push DWORD 0 ; offset 12, upper 32-bit LBA
192 push ds ; For sake of saving memory,
193 push ds ; push DS register, which is 0.
194
195 push ecx
196
197 push es ; offset 6, memory segment
198
199 push bx ; offset 4, memory offset
200
201 xor ah, ah ; offset 3, must be 0
202 push ax ; offset 2, number of sectors
203
204 push WORD 16 ; offset 0-1, packet size
205
206 ;
207 ; INT13 Func 42 - Extended Read Sectors
208 ;
209 ; Arguments:
210 ; AH = 0x42
211 ; DL = drive number (80h + drive unit)
212 ; DS:SI = pointer to Disk Address Packet
213 ;
214 ; Returns:
215 ; AH = return status (sucess is 0)
216 ; carry = 0 success
217 ; 1 error
218 ;
219 ; Packet offset 2 indicates the number of sectors read
220 ; successfully.
221 ;
222 mov si, sp
223 mov ah, 0x42
224 int 0x13
225
226 jnc .exit
227
228 DebugChar('R') ; indicate INT13/F42 error
229
230 ;
231 ; Issue a disk reset on error.
232 ; Should this be changed to Func 0xD to skip the diskette controller
233 ; reset?
234 ;
235 xor ax, ax ; Func 0
236 int 0x13 ; INT 13
237 stc ; set carry to indicate error
238
239 .exit:
240 mov sp, bp ; restore SP
241 popad
242 ret
243
244 ;;
245 ;; Display a single character from AL.
246 ;;
247 putc: pushad
248 mov bx, 0x1 ; attribute for output
249 mov ah, 0xe ; BIOS: put_char
250 int 0x10 ; call BIOS, print char in %al
251 popad
252 ret
253
254 ;;
255 ;; Get a character from the keyboard and return it in AL.
256 ;;
257 getc: mov ah, 0
258 int 0x16
259 ret
260
261 %if DEBUG
262 ;--------------------------------------------------------------------------
263 ; Write the 4-byte value to the console in hex.
264 ;
265 ; Arguments:
266 ; EAX = Value to be displayed in hex.
267 ;
268 print_hex:
269 pushad
270 mov cx, WORD 4
271 bswap eax
272 .loop
273 push ax
274 ror al, 4
275 call print_nibble ; display upper nibble
276 pop ax
277 call print_nibble ; display lower nibble
278 ror eax, 8
279 loop .loop
280
281 mov al, 10 ; carriage return
282 call putc
283 mov al, 13
284 call putc
285 popad
286 ret
287
288 print_nibble:
289 and al, 0x0f
290 add al, '0'
291 cmp al, '9'
292 jna .print_ascii
293 add al, 'A' - '9' - 1
294 .print_ascii:
295 call putc
296 ret
297
298 %endif ; DEBUG
299
300
301
302 ;; Pad this file to a size of 2048 bytes (one CD sector).
303 pad:
304 times 2048-($-$$) db 0
305
306 ;; Location of loaded boot2 code.
307 kBoot2LoadAddr equ $
308
309 END