]>
Commit | Line | Data |
---|---|---|
14c7c974 A |
1 | ; Copyright (c) 1999 Apple Computer, Inc. All rights reserved. |
2 | ; | |
3 | ; @APPLE_LICENSE_HEADER_START@ | |
4 | ; | |
5 | ; Portions Copyright (c) 1999 Apple Computer, Inc. All Rights | |
6 | ; Reserved. This file contains Original Code and/or Modifications of | |
7 | ; Original Code as defined in and that are subject to the Apple Public | |
8 | ; Source License Version 1.1 (the "License"). You may not use this file | |
9 | ; except in compliance with the License. Please obtain a copy of the | |
10 | ; License at http://www.apple.com/publicsource and read it before using | |
11 | ; this file. | |
12 | ; | |
13 | ; The Original Code and all software distributed under the License are | |
14 | ; distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER | |
15 | ; EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, | |
16 | ; INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, | |
17 | ; FITNESS FOR A PARTICULAR PURPOSE OR NON- INFRINGEMENT. Please see the | |
18 | ; License for the specific language governing rights and limitations | |
19 | ; under the License. | |
20 | ; | |
21 | ; @APPLE_LICENSE_HEADER_END@ | |
22 | ; | |
23 | ; Boot Loader: boot0 | |
24 | ; | |
25 | ; A small boot sector program written in x86 assembly whose only | |
26 | ; responsibility is to locate the booter partition, load the | |
27 | ; booter into memory, and jump to the booter's entry point. | |
28 | ; The booter partition can be a primary or a logical partition. | |
29 | ; But the booter partition must reside within the 8GB limit | |
30 | ; imposed by CHS addressing + translation. | |
31 | ; | |
32 | ; This boot loader can be placed at any of the following places: | |
33 | ; * Master Boot Record (MBR) | |
34 | ; * Boot sector of an extended partition | |
35 | ; * Boot sector of a primary partition | |
36 | ; * Boot sector of a logical partition | |
37 | ; | |
38 | ; In order to coexist with a fdisk partition table (64 bytes), and | |
39 | ; leave room for a two byte signature (0xAA55) in the end, boot0 is | |
40 | ; restricted to 446 bytes (512 - 64 - 2). If boot0 did not have to | |
41 | ; live in the MBR, then we would have 510 bytes to play with. | |
42 | ; | |
43 | ; boot0 is always loaded by the BIOS or another first level booter | |
44 | ; to 0:7C00h. | |
45 | ; | |
46 | ; This code is written for the NASM assembler. | |
47 | ; nasm boot0.s -o boot0 | |
48 | ||
75b89a82 | 49 | |
14c7c974 A |
50 | ;-------------------------------------------------------------------------- |
51 | ; Constants. | |
52 | ||
53 | FLOPPY EQU 0x00 ; floppy dev number | |
54 | HDISK EQU 0x80 ; hard drive dev number | |
55 | DEBUG EQU 0 ; enable debugging output | |
56 | ||
57 | BOOTSEG EQU 0x0 ; our sole segment | |
58 | BOOTSP EQU 0xFFF0 ; stack pointer | |
59 | BOOTLOAD EQU 0x7C00 ; booter load address | |
60 | BOOTRELOC EQU 0xE000 ; booter is relocated here | |
61 | BOOTSIG EQU 0xAA55 ; booter signature | |
62 | ||
75b89a82 A |
63 | BOOT2_SIZE EQU 112 ; load this many blocks for boot2 |
64 | BOOT2_ADDR EQU 0x0200 ; where to load boot2 | |
65 | BOOT2_SEG EQU 0x2000 | |
14c7c974 A |
66 | |
67 | %IF BOOTDEV = FLOPPY | |
75b89a82 | 68 | DRIVE_NUM EQU FLOPPY ; floppy drive |
14c7c974 | 69 | %ELSE |
75b89a82 | 70 | DRIVE_NUM EQU HDISK ; "C" drive |
14c7c974 A |
71 | %ENDIF |
72 | SECTOR_BYTES EQU 512 ; sector size in bytes | |
73 | ||
74 | BUF_MBR EQU 0x1000 ; memory buffer for MBR | |
75 | BUF_EXT EQU 0x1200 ; memory buffer for extended partition | |
76 | ||
77 | TABLE_MAIN EQU BUF_MBR + 0x1be ; location of main partition table | |
78 | TABLE_EXT EQU BUF_EXT + 0x1be ; location of ext partition table | |
79 | ENTRY_SIZE EQU 16 ; size of each fdisk partition entry | |
80 | TYPE_BOOT EQU 0xab ; partition type we are looking for | |
81 | TYPE_EXT EQU 0x05 ; extended partition type | |
82 | TYPE_EXT_1 EQU 0x0f ; Windows extended partition | |
83 | TYPE_EXT_2 EQU 0x85 ; Linux extended partition | |
84 | EXT_LEVELS_MAX EQU 128 ; max extended partition levels | |
85 | ||
86 | ||
87 | ;-------------------------------------------------------------------------- | |
88 | ; Start of text segment. | |
89 | ||
90 | SEGMENT .text | |
91 | ||
92 | ORG 0xE000 ; must match BOOTRELOC | |
93 | ||
94 | ;-------------------------------------------------------------------------- | |
95 | ; Loaded at 0:7c00h. | |
96 | ; | |
97 | start | |
98 | ; Set up the stack to grow down from BOOTSEG:BOOTSP. | |
99 | ; Interrupts should be off while the stack is being manipulated. | |
100 | ; | |
101 | cli ; interrupts off | |
102 | mov ax, BOOTSEG ; | |
103 | mov ss, ax ; ss <- BOOTSEG | |
104 | mov sp, BOOTSP ; sp <- BOOTSP | |
105 | sti ; reenable interrupts | |
106 | ||
107 | ; Relocate the booter code from DS:SI to ES:DI, | |
108 | ; or from 0:7C00h to BOOTSEG:BOOTRELOC. | |
109 | ; | |
110 | mov es, ax ; es <- BOOTSEG | |
75b89a82 A |
111 | mov ds, ax ; ds <- BOOTSEG |
112 | ||
14c7c974 A |
113 | mov si, BOOTLOAD ; si <- BOOTLOAD (source) |
114 | mov di, BOOTRELOC ; di <- BOOTRELOC (destination) | |
115 | ; | |
116 | cld ; auto-increment SI and/or DI registers | |
117 | mov cx, 256 ; copy 256 words (512 bytes) | |
118 | repnz movsw ; repeat string move (word) operation | |
119 | ||
120 | ; Code relocated, jump to start_reloc in relocated location. | |
121 | ; | |
122 | jmp BOOTSEG:start_reloc | |
123 | ||
124 | ;-------------------------------------------------------------------------- | |
125 | ; Start execution from the relocated location. | |
126 | ; | |
127 | start_reloc | |
14c7c974 A |
128 | mov al, '=' ; indicate execution start |
129 | call putchar | |
130 | ||
131 | ; Get disk parameters (CHS) using INT13/F8 call. | |
132 | ; | |
133 | mov dl, DRIVE_NUM ; boot drive is drive C | |
134 | mov ah, 8 ; Read Disk Driver Parameter function | |
135 | int 0x13 | |
136 | and cl, 0x3f ; sectors/track | |
137 | mov [max_sectors], cl | |
138 | mov [max_heads], dh | |
139 | jc error | |
140 | ||
141 | mov al, '>' ; indicate INT13/F8 success | |
142 | call putchar | |
143 | ||
14c7c974 A |
144 | ; Since this code may not always reside in the MBR, we will always |
145 | ; start by loading the MBR to BUF_MBR. | |
146 | ; | |
147 | mov WORD [chs_cx], 0x0001 ; cyl = 0, sect = 1 | |
148 | mov BYTE [chs_dx + 1], 0 ; head = 0 | |
149 | xor cx, cx ; skip 0 sectors | |
150 | mov ax, 1 ; read 1 sector | |
151 | mov bx, BUF_MBR ; load buffer | |
152 | call load | |
153 | jc error | |
154 | ||
155 | mov di, TABLE_MAIN ; argument for find_booter | |
156 | cmp WORD [di + 64], BOOTSIG ; correct signature found? | |
157 | jne error ; Oops! no signature! | |
158 | mov bl, TYPE_BOOT ; look for this partition type | |
159 | mov bh, 0 ; initial nesting level is 0 | |
160 | call find_booter | |
161 | ||
162 | error | |
163 | mov si, load_error | |
164 | call message | |
165 | hang_1 | |
166 | jmp hang_1 | |
167 | ||
168 | ;-------------------------------------------------------------------------- | |
169 | ; Locate the booter partition and load the booter. | |
170 | ; | |
171 | ; Arguments: | |
172 | ; di - pointer to fdisk partition table. | |
173 | ; bl - partition type to look for. | |
174 | ; | |
175 | ; The following registers are modified: | |
176 | ; ax, bh | |
177 | ; | |
178 | find_booter | |
179 | push cx | |
180 | push si | |
181 | ||
182 | mov si, di ; si <- pointer to partition table | |
183 | mov cx, 4 ; 4 partition entries per table | |
184 | ||
185 | find_booter_pri | |
186 | ; | |
187 | ; Hunt for a fdisk partition type that matches the value in bl. | |
188 | ; | |
189 | %IF DEBUG | |
190 | mov al, bh ; log partition type seen | |
191 | call putspace | |
192 | mov al, [si + 4] | |
193 | call display_byte | |
194 | %ENDIF | |
195 | ||
196 | cmp BYTE [si + 4], bl ; Is this the booter partition? | |
197 | je load_booter ; yes, load the booter | |
198 | ||
199 | add si, ENTRY_SIZE ; si <- next partition entry | |
200 | loop find_booter_pri ; loop while cx is not zero | |
201 | ||
202 | ; No primary (or perhaps logical) booter partition found in the | |
203 | ; current partition table. Restart and look for extended partitions. | |
204 | ; | |
205 | mov si, di ; si <- pointer to partition table | |
206 | mov cx, 4 ; 4 partition entries per table | |
207 | ||
208 | find_booter_ext | |
209 | ; | |
210 | ; Look for extended partition entries in the partition table. | |
211 | ; | |
212 | %IF DEBUG | |
213 | mov al, bh ; log partition type seen | |
214 | call putspace | |
215 | mov al, 'E' | |
216 | call putchar | |
217 | mov al, [si + 4] | |
218 | call display_byte | |
219 | %ENDIF | |
220 | ||
221 | cmp BYTE [si + 4], TYPE_EXT ; Is this an extended partition? | |
222 | je find_booter_ext_2 ; yes, load its partition table | |
223 | ||
224 | cmp BYTE [si + 4], TYPE_EXT_1 ; Is this an extended partition? | |
225 | je find_booter_ext_2 ; yes, load its partition table | |
75b89a82 | 226 | |
14c7c974 A |
227 | cmp BYTE [si + 4], TYPE_EXT_2 ; Is this an extended partition? |
228 | je find_booter_ext_2 ; yes, load its partition table | |
229 | ||
230 | find_booter_ext_1 | |
231 | ; | |
232 | ; si is not pointing to an extended partition entry, | |
233 | ; try the next entry in the partition table. | |
234 | ; | |
235 | add si, ENTRY_SIZE ; si <- next partition entry | |
236 | loop find_booter_ext ; loop while cx is not zero | |
237 | ||
238 | jmp find_booter_end ; give up | |
239 | ||
240 | find_booter_ext_2 | |
241 | cmp bh, EXT_LEVELS_MAX | |
242 | ja find_booter_end ; in too deep! | |
243 | ||
244 | inc bh ; increment nesting level counter | |
245 | ||
246 | ; Prepare the arguments for the load function call to | |
247 | ; load the extended partition table into memory. | |
248 | ; Note that si points to the extended partition entry. | |
249 | ; | |
250 | mov ax, [si] ; DH/DL | |
251 | mov [chs_dx], ax | |
252 | mov ax, [si + 2] ; CH/CL | |
253 | mov [chs_cx], ax | |
254 | pusha | |
255 | xor cx, cx ; skip 0 sectors | |
256 | mov ax, 1 ; read 1 sector | |
257 | mov bx, BUF_EXT ; load to BUF_EXT | |
258 | call load | |
259 | popa | |
260 | ||
261 | jc find_booter_ext_3 ; bail out if load failed | |
262 | ||
263 | mov di, TABLE_EXT ; di <- pointer to new partition table | |
264 | cmp WORD [di + 64], BOOTSIG | |
265 | jne find_booter_ext_3 ; OhOh! no signature! | |
266 | ||
267 | call find_booter ; recursion... | |
268 | ||
269 | find_booter_ext_3 | |
270 | dec bh ; decrement nesting level counter | |
271 | ||
272 | ; If we got here, then we know there isn't a booter | |
273 | ; partition linked from this partition entry. | |
274 | ||
275 | test bh, bh ; if we are at level 0, then | |
276 | jz find_booter_ext_1 ; look for next extended partition entry | |
277 | ||
278 | find_booter_end | |
279 | pop si | |
280 | pop cx | |
281 | ret | |
282 | ||
283 | ;-------------------------------------------------------------------------- | |
284 | ; Yeah! Found the booter partition. The first sector in this partition | |
285 | ; is reserved for the boot sector code (us). So load the booter | |
286 | ; starting from the second sector in the partition, then jump to the | |
287 | ; start of the booter. | |
288 | ; | |
289 | load_booter | |
290 | mov ax, [si] ; DH/DL | |
291 | mov [chs_dx], ax | |
292 | mov ax, [si + 2] ; CH/CL | |
293 | mov [chs_cx], ax | |
294 | ||
295 | mov cx, 1 ; skip the initial boot sector | |
296 | mov ax, BOOT2_SIZE ; read BOOT2_SIZE sectors | |
75b89a82 A |
297 | mov bx, BOOT2_SEG |
298 | mov es, bx | |
14c7c974 A |
299 | mov bx, BOOT2_ADDR ; where to place boot2 code |
300 | call load ; load it... | |
301 | ||
75b89a82 A |
302 | xor edx, edx |
303 | mov dl, DRIVE_NUM ; argument for boot2 | |
304 | ||
305 | jmp BOOT2_SEG:BOOT2_ADDR ; there is no going back now! | |
14c7c974 A |
306 | |
307 | ;-------------------------------------------------------------------------- | |
308 | ; Load sectors from disk using INT13/F2 call. The sectors are loaded | |
309 | ; one sector at a time to avoid any BIOS bugs, and eliminate | |
310 | ; complexities with crossing track boundaries, and other gotchas. | |
311 | ; | |
312 | ; Arguments: | |
313 | ; cx - number of sectors to skip | |
314 | ; ax - number of sectors to read | |
315 | ; bx - pointer to the memory buffer (must not cross a segment boundary) | |
316 | ; [chs_cx][chs_dx] - CHS starting position | |
317 | ; | |
318 | ; Returns: | |
319 | ; CF = 0 success | |
320 | ; CF = 1 error | |
321 | ; | |
322 | ; The caller must save any registers it needs. | |
323 | ; | |
324 | load | |
325 | jcxz load_sectors | |
326 | call next_sector ; [chs_cx][chs_dx] <- next sector | |
327 | loop load | |
328 | ||
329 | load_sectors | |
330 | mov cx, ax ; cx <- number of sectors to read | |
331 | ||
332 | load_loop | |
333 | call read_sector ; load a single sector | |
334 | jc load_exit ; abort if carry flag is set | |
335 | add bx, SECTOR_BYTES ; increment buffer pointer | |
336 | call next_sector ; [chs_cx][chs_dx] <- next sector | |
337 | loop load_loop | |
338 | clc ; successful exit | |
339 | load_exit | |
340 | ret | |
341 | ||
342 | ;-------------------------------------------------------------------------- | |
343 | ; Read a single sector from the hard disk. | |
344 | ; | |
345 | ; Arguments: | |
346 | ; [chs_cx][chs_dx] - CHS starting position | |
75b89a82 A |
347 | ; es:bx - pointer to the sector memory buffer |
348 | ; (must not cross a segment boundary) | |
14c7c974 A |
349 | ; |
350 | ; Returns: | |
351 | ; CF = 0 success | |
352 | ; CF = 1 error | |
353 | ; | |
354 | ; Caller's cx register is preserved. | |
355 | ; | |
356 | read_sector | |
357 | push cx | |
358 | mov cx, 5 ; try 5 times to read the sector | |
359 | ||
360 | read_sector_1 | |
361 | mov bp, cx ; save cx | |
362 | ||
363 | mov cx, [chs_cx] | |
364 | mov dx, [chs_dx] | |
365 | mov dl, DRIVE_NUM ; drive number | |
366 | mov ax, 0x0201 ; Func 2, read 1 sector | |
367 | int 0x13 ; read sector | |
368 | jnc read_sector_ok ; CF = 0 indicates success | |
369 | ||
370 | mov al, '*' ; sector read error indicator | |
371 | call putchar | |
372 | ||
373 | xor ax, ax ; Reset the drive and retry the read | |
374 | int 0x13 | |
375 | ||
376 | mov cx, bp | |
377 | loop read_sector_1 ; retry while cx is not zero | |
378 | ||
379 | stc ; set carry flag to indicate error | |
380 | pop cx | |
381 | ret | |
382 | ||
383 | read_sector_ok | |
384 | mov al, '.' ; successful sector read indicator | |
385 | call putchar | |
386 | clc ; success, clear carry flag | |
387 | pop cx | |
388 | ret | |
389 | ||
390 | ;-------------------------------------------------------------------------- | |
391 | ; Given the current CHS position stored in [chs_cx][chs_dx], update | |
392 | ; it so that the value in [chs_cx][chs_dx] points to the following | |
393 | ; sector. | |
394 | ; | |
395 | ; Arguments: | |
396 | ; [chs_cx][chs_dx] - CHS position | |
397 | ; | |
398 | ; [max_sectors] and [max_heads] must be valid. | |
399 | ; | |
400 | ; Caller's ax and bx registers are preserved. | |
401 | ; | |
402 | next_sector | |
403 | push ax | |
404 | push bx | |
405 | ||
406 | ; Extract the CHS values from the packed register values in memory. | |
407 | ; | |
408 | mov al, [chs_cx] | |
409 | and al, 0x3f ; al <- sector number (1-63) | |
410 | ||
411 | mov bx, [chs_cx] | |
412 | rol bl, 2 | |
413 | ror bx, 8 | |
414 | and bx, 0x03ff ; bx <- cylinder number | |
415 | ||
416 | mov ah, [chs_dx + 1] ; ah <- head number | |
417 | ||
418 | inc al ; Increment CHS by one sector. | |
419 | cmp al, [max_sectors] | |
420 | jbe next_sector_done | |
421 | ||
422 | inc ah | |
423 | cmp ah, [max_heads] | |
424 | jbe next_sector_new_head | |
425 | ||
426 | inc bx | |
427 | ||
428 | next_sector_new_cyl | |
429 | xor ah, ah ; head number starts at 0 | |
430 | ||
431 | next_sector_new_head | |
432 | mov al, 1 ; sector number starts at 1 | |
433 | ||
434 | next_sector_done | |
435 | ; Reassemble the CHS values back into the packed representation | |
436 | ; in memory. | |
437 | ; | |
438 | mov [chs_cx + 1], bl ; lower 8-bits of the 10-bit cylinder | |
439 | ror bh, 2 | |
440 | or bh, al | |
441 | mov [chs_cx], bh ; cylinder & sector number | |
442 | mov [chs_dx + 1], ah ; head number | |
443 | ||
444 | pop bx | |
445 | pop ax | |
446 | ret | |
447 | ||
448 | ;-------------------------------------------------------------------------- | |
449 | ; Write a string to the console. | |
450 | ; | |
451 | ; Arguments: | |
452 | ; ds:si pointer to a NULL terminated string. | |
453 | ; | |
454 | ; The following registers are modified: | |
455 | ; ax, bx, si | |
456 | ; | |
457 | message | |
458 | mov bx, 1 ; bh=0, bl=1 (blue) | |
459 | cld ; increment SI after each lodsb call | |
460 | message_loop | |
461 | lodsb ; load a byte from DS:SI into al | |
462 | cmp al, 0 ; Is it a NULL? | |
463 | je message_done ; yes, all done | |
464 | mov ah, 0xE ; bios INT10 Func 0xE | |
465 | int 0x10 ; bios display a byte in tty mode | |
466 | jmp short message_loop | |
467 | message_done | |
468 | ret | |
469 | ||
470 | ;-------------------------------------------------------------------------- | |
471 | ; Write a ASCII character to the console. | |
472 | ; | |
473 | ; Arguments: | |
474 | ; al contains the ASCII character printed. | |
475 | ; | |
476 | putchar | |
477 | push bx | |
478 | mov bx, 1 ; bh=0, bl=1 (blue) | |
479 | mov ah, 0x0e ; bios int 10, function 0xe | |
480 | int 0x10 ; bios display a byte in tty mode | |
481 | pop bx | |
482 | ret | |
483 | ||
484 | %IF DEBUG | |
485 | ;========================================================================== | |
486 | ; DEBUG FUNCTION START | |
487 | ; | |
488 | ; If DEBUG is set to 1, this booter will become too large for the MBR, | |
489 | ; but it will still be less than 510 bytes, which is fine for a partition's | |
490 | ; boot sector. | |
491 | ;========================================================================== | |
492 | ||
493 | ;-------------------------------------------------------------------------- | |
494 | ; Write a variable number of spaces to the console. | |
495 | ; | |
496 | ; Arguments: | |
497 | ; al number to spaces to display | |
498 | ; | |
499 | putspace | |
500 | push cx | |
501 | xor cx, cx | |
502 | mov cl, al ; use cx as the loop counter | |
503 | mov al, ' ' ; character to print | |
504 | putspace_loop | |
505 | jcxz putspace_done | |
506 | call putchar | |
507 | loop putspace_loop | |
508 | putspace_done | |
509 | pop cx | |
510 | ret | |
511 | ||
512 | ;-------------------------------------------------------------------------- | |
513 | ; Write the hex byte value to the console. | |
514 | ; | |
515 | ; Arguments: | |
516 | ; al contains the byte to be displayed. e.g. if al is 0x3f, then 3F | |
517 | ; will be displayed on screen. | |
518 | ; | |
519 | display_byte | |
520 | push ax | |
521 | ror al, 4 | |
522 | call display_nibble ; display upper nibble | |
523 | pop ax | |
524 | call display_nibble ; display lower nibble | |
525 | ; | |
526 | mov ax, 10 ; display carriage return | |
527 | call putchar | |
528 | mov ax, 13 | |
529 | call putchar | |
530 | ret | |
531 | ||
532 | display_nibble | |
533 | and al, 0x0f | |
534 | add al, '0' | |
535 | cmp al, '9' | |
536 | jna display_nibble_1 | |
537 | add al, 'A' - '9' - 1 | |
538 | display_nibble_1 | |
539 | call putchar | |
540 | ret | |
541 | ||
542 | ;========================================================================== | |
543 | ; DEBUG FUNCTION END | |
544 | ;========================================================================== | |
545 | %ENDIF | |
546 | ||
547 | ; Disk parameters gathered through INT13/F8 call. | |
548 | ; | |
549 | max_sectors db 0 ; number of sectors per track | |
550 | max_heads db 0 ; number of heads | |
551 | ||
552 | ; Parameters to our load function. | |
553 | ; | |
554 | chs_cx dw 0x0001 ; cx register for INT13/F2 call | |
555 | chs_dx dw 0x0000 ; dx register for INT13/F2 call | |
556 | ||
557 | ;-------------------------------------------------------------------------- | |
558 | ; NULL terminated strings. | |
559 | ; | |
560 | load_error db 10, 13, 'Load Error', 0 | |
561 | ||
562 | ;-------------------------------------------------------------------------- | |
563 | ; Pad the rest of the 512 byte sized booter with zeroes. The last | |
564 | ; two bytes is the mandatory boot sector signature. | |
565 | ; | |
566 | ; If the booter code becomes too large, then nasm will complain | |
567 | ; that the 'times' argument is negative. | |
568 | ||
569 | pad_boot | |
75b89a82 | 570 | times 446-($-$$) db 0 |
14c7c974 A |
571 | |
572 | %IF BOOTDEV = FLOPPY | |
573 | ;-------------------------------------------------------------------------- | |
574 | ; Put fake partition entries for the bootable floppy image | |
575 | ; | |
75b89a82 A |
576 | part1bootid db 0x80 ; first partition active |
577 | part1head db 0x00 ; head # | |
578 | part1sect db 0x02 ; sector # (low 6 bits) | |
579 | part1cyl db 0x00 ; cylinder # (+ high 2 bits of above) | |
580 | part1systid db 0xab ; Apple boot partition | |
581 | times 3 db 0x00 ; ignore head/cyl/sect #'s | |
582 | part1relsect dd 0x00000001 ; start at sector 1 | |
583 | part1numsect dd 0x00000080 ; 64K for booter | |
584 | part2bootid db 0x00 ; not active | |
585 | times 3 db 0x00 ; ignore head/cyl/sect #'s | |
586 | part2systid db 0xa8 ; Apple UFS partition | |
587 | times 3 db 0x00 ; ignore head/cyl/sect #'s | |
588 | part2relsect dd 0x00000082 ; start after booter | |
589 | ; part2numsect dd 0x00000abe ; 1.44MB - 65K | |
590 | part2numsect dd 0x000015fe ; 2.88MB - 65K | |
14c7c974 A |
591 | %ENDIF |
592 | ||
593 | pad_table_and_sig | |
594 | times 510-($-$$) db 0 | |
595 | dw BOOTSIG | |
596 | ||
597 | END |