[BOOTSECTORS]
[reactos.git] / reactos / boot / freeldr / bootsect / isobtrt.asm
1 ; ****************************************************************************
2 ;
3 ; isolinux.asm
4 ;
5 ; A program to boot Linux kernels off a CD-ROM using the El Torito
6 ; boot standard in "no emulation" mode, making the entire filesystem
7 ; available. It is based on the SYSLINUX boot loader for MS-DOS
8 ; floppies.
9 ;
10 ; Copyright (C) 1994-2001 H. Peter Anvin
11 ;
12 ; This program is free software; you can redistribute it and/or modify
13 ; it under the terms of the GNU General Public License as published by
14 ; the Free Software Foundation, Inc., 675 Mass Ave, Cambridge MA 02139,
15 ; USA; either version 2 of the License, or (at your option) any later
16 ; version; incorporated herein by reference.
17 ;
18 ; ****************************************************************************
19 ;
20 ; THIS FILE IS A MODIFIED VERSION OF ISOLINUX.ASM
21 ; MODIFICATION DONE BY MICHAEL K TER LOUW
22 ; LAST UPDATED 3-9-2002
23 ; SEE "COPYING" FOR INFORMATION ABOUT THE LICENSE THAT APPLIES TO THIS RELEASE
24 ;
25 ; ****************************************************************************
26 ;
27 ; This file is a modified version of ISOLINUX.ASM.
28 ; Modification done by Eric Kohl
29 ; Last update 04-25-2002
30 ;
31 ; ****************************************************************************
32 ;
33 ; This file is a modified version of ISOLINUX.ASM.
34 ; (for ReactOS regression testing)
35 ; Modification done by Christoph von Wittich
36 ; Last update 08-27-2006
37 ;
38 ; ****************************************************************************
39
40
41 ; Note: The Makefile builds one version with DEBUG_MESSAGES automatically.
42 ;%define DEBUG_MESSAGES ; Uncomment to get debugging messages
43
44
45 ; ---------------------------------------------------------------------------
46 ; BEGIN THE BIOS/CODE/DATA SEGMENT
47 ; ---------------------------------------------------------------------------
48
49 absolute 0400h
50 serial_base resw 4 ; Base addresses for 4 serial ports
51 absolute 0413h
52 BIOS_fbm resw 1 ; Free Base Memory (kilobytes)
53 absolute 046Ch
54 BIOS_timer resw 1 ; Timer ticks
55 absolute 0472h
56 BIOS_magic resw 1 ; BIOS reset magic
57 absolute 0484h
58 BIOS_vidrows resb 1 ; Number of screen rows
59
60 ;
61 ; Memory below this point is reserved for the BIOS and the MBR
62 ;
63 absolute 1000h
64 trackbuf resb 8192 ; Track buffer goes here
65 trackbufsize equ $-trackbuf
66 ; trackbuf ends at 3000h
67
68 struc open_file_t
69 file_sector resd 1 ; Sector pointer (0 = structure free)
70 file_left resd 1 ; Number of sectors left
71 endstruc
72
73 struc dir_t
74 dir_lba resd 1 ; Directory start (LBA)
75 dir_len resd 1 ; Length in bytes
76 dir_clust resd 1 ; Length in clusters
77 endstruc
78
79
80 MAX_OPEN_LG2 equ 2 ; log2(Max number of open files)
81 MAX_OPEN equ (1 << MAX_OPEN_LG2)
82 SECTORSIZE_LG2 equ 11 ; 2048 bytes/sector (El Torito requirement)
83 SECTORSIZE equ (1 << SECTORSIZE_LG2)
84 CR equ 13 ; Carriage Return
85 LF equ 10 ; Line Feed
86 retry_count equ 6 ; How patient are we with the BIOS?
87
88
89
90 absolute 5000h ; Here we keep our BSS stuff
91
92 DriveNo resb 1 ; CD-ROM BIOS drive number
93 DiskError resb 1 ; Error code for disk I/O
94 RetryCount resb 1 ; Used for disk access retries
95 TimeoutCount resb 1 ; Timeout counter
96 ISOFlags resb 1 ; Flags for ISO directory search
97 RootDir resb dir_t_size ; Root directory
98 CurDir resb dir_t_size ; Current directory
99 ISOFileName resb 64 ; ISO filename canonicalization buffer
100 ISOFileNameEnd equ $
101
102
103 alignb open_file_t_size
104 Files resb MAX_OPEN*open_file_t_size
105
106
107
108 section .text
109 org 7000h
110
111 start:
112 cli ; Disable interrupts
113 xor ax, ax ; ax = segment zero
114 mov ss, ax ; Initialize stack segment
115 mov sp, start ; Set up stack
116 mov ds, ax ; Initialize other segment registers
117 mov es, ax
118 mov fs, ax
119 mov gs, ax
120 sti ; Enable interrupts
121 cld ; Increment pointers
122
123 mov cx, 2048 >> 2 ; Copy the bootsector
124 mov si, 0x7C00 ; from 0000:7C00
125 mov di, 0x7000 ; to 0000:7000
126 rep movsd ; copy the program
127 jmp 0:relocate ; jump into relocated code
128
129 relocate:
130 ; Display the banner and copyright
131 %ifdef DEBUG_MESSAGES
132 mov si, isolinux_banner ; si points to hello message
133 call writestr ; display the message
134 mov si,copyright_str
135 call writestr
136 %endif
137
138 ; check if there is a mbr on the hdd if so boot from it
139
140 pusha
141 mov ax, 0201h
142 mov dx, 0080h
143 mov cx, 0001h
144 mov bx, trackbuf
145 int 13h
146 popa
147 jc .boot_cdrom ; could not read hdd
148
149 push ax
150 mov ax, word [trackbuf+510]
151 cmp ax, 0
152 je .boot_cdrom ; no boot sector found (hopefully there are no weird bootsectors which begin with 0)
153 pop ax
154
155 .boot_harddisk:
156 call crlf
157
158 ; Boot first harddisk (drive 0x80)
159 mov ax, 0201h
160 mov dx, 0080h
161 mov cx, 0001h
162 mov bx, 7C00h
163 int 13h
164 jnc .go_hd
165 jmp kaboom
166 .go_hd:
167 mov ax, cs
168 mov ds, ax
169 mov es, ax
170 mov fs, ax
171 mov gs, ax
172 mov dx, 0080h
173
174 jmp 0:0x7C00
175
176 .boot_cdrom:
177 ; Save and display the boot drive number
178 mov [DriveNo], dl
179 %ifdef DEBUG_MESSAGES
180 mov si, startup_msg
181 call writemsg
182 mov al, dl
183 call writehex2
184 call crlf
185 %endif
186
187 ; Now figure out what we're actually doing
188 ; Note: use passed-in DL value rather than 7Fh because
189 ; at least some BIOSes will get the wrong value otherwise
190 mov ax, 4B01h ; Get disk emulation status
191 mov dl, [DriveNo]
192 mov si, spec_packet
193 int 13h
194 jc near spec_query_failed ; Shouldn't happen (BIOS bug)
195 mov dl, [DriveNo]
196 cmp [sp_drive], dl ; Should contain the drive number
197 jne near spec_query_failed
198
199 %ifdef DEBUG_MESSAGES
200 mov si, spec_ok_msg
201 call writemsg
202 mov al, byte [sp_drive]
203 call writehex2
204 call crlf
205 %endif
206
207 found_drive:
208 ; Get drive information
209 mov ah, 48h
210 mov dl, [DriveNo]
211 mov si, drive_params
212 int 13h
213 jnc params_ok
214
215 ; mov si, nosecsize_msg No use in reporting this
216 ; call writemsg
217
218 params_ok:
219 ; Check for the sector size (should be 2048, but
220 ; some BIOSes apparently think we're 512-byte media)
221 ;
222 ; FIX: We need to check what the proper behaviour
223 ; is for getlinsec when the BIOS thinks the sector
224 ; size is 512!!! For that, we need such a BIOS, though...
225 %ifdef DEBUG_MESSAGES
226 mov si, secsize_msg
227 call writemsg
228 mov ax, [dp_secsize]
229 call writehex4
230 call crlf
231 %endif
232
233
234 ;
235 ; Clear Files structures
236 ;
237 mov di, Files
238 mov cx, (MAX_OPEN*open_file_t_size)/4
239 xor eax, eax
240 rep stosd
241
242 ;
243 ; Now, we need to sniff out the actual filesystem data structures.
244 ; mkisofs gave us a pointer to the primary volume descriptor
245 ; (which will be at 16 only for a single-session disk!); from the PVD
246 ; we should be able to find the rest of what we need to know.
247 ;
248 get_fs_structures:
249 mov eax, 16 ; Primary Volume Descriptor (sector 16)
250 mov bx, trackbuf
251 call getonesec
252
253 mov eax, [trackbuf+156+2]
254 mov [RootDir+dir_lba],eax
255 mov [CurDir+dir_lba],eax
256 %ifdef DEBUG_MESSAGES
257 mov si, rootloc_msg
258 call writemsg
259 call writehex8
260 call crlf
261 %endif
262
263 mov eax,[trackbuf+156+10]
264 mov [RootDir+dir_len],eax
265 mov [CurDir+dir_len],eax
266 %ifdef DEBUG_MESSAGES
267 mov si, rootlen_msg
268 call writemsg
269 call writehex8
270 call crlf
271 %endif
272 add eax,SECTORSIZE-1
273 shr eax,SECTORSIZE_LG2
274 mov [RootDir+dir_clust],eax
275 mov [CurDir+dir_clust],eax
276 %ifdef DEBUG_MESSAGES
277 mov si, rootsect_msg
278 call writemsg
279 call writehex8
280 call crlf
281 %endif
282
283 ; Look for the "REACTOS" directory, and if found,
284 ; make it the current directory instead of the root
285 ; directory.
286 mov di,isolinux_dir
287 mov al,02h ; Search for a directory
288 call searchdir_iso
289 jnz .dir_found
290 mov si,no_dir_msg
291 call writemsg
292 jmp kaboom
293
294 .dir_found:
295 mov [CurDir+dir_len],eax
296 mov eax,[si+file_left]
297 mov [CurDir+dir_clust],eax
298 xor eax,eax ; Free this file pointer entry
299 xchg eax,[si+file_sector]
300 mov [CurDir+dir_lba],eax
301
302
303 mov di, isolinux_bin ; di points to Isolinux filename
304 call searchdir ; look for the file
305 jnz .isolinux_opened ; got the file
306 mov si, no_isolinux_msg ; si points to error message
307 call writemsg ; display the message
308 jmp kaboom ; fail boot
309
310 .isolinux_opened:
311 mov di, si ; save file pointer
312
313 %ifdef DEBUG_MESSAGES
314 mov si, filelen_msg
315 call writemsg
316 call writehex8
317 call crlf
318 %endif
319
320 mov ecx, eax ; calculate sector count
321 shr ecx, 11
322 test eax, 0x7FF
323 jz .full_sector
324 inc ecx
325 .full_sector:
326
327 %ifdef DEBUG_MESSAGES
328 mov eax, ecx
329 mov si, filesect_msg
330 call writemsg
331 call writehex8
332 call crlf
333 %endif
334
335 ; use high segment, as some bios can fail, when offset is too big
336 mov bx, 0x0F80 ; FREELDR_BASE / 16 ; es = load segment
337 mov es, bx
338 xor ebx, ebx ; bx = load offset
339 mov si, di ; restore file pointer
340 mov cx, 0xFFFF ; load the whole file
341 call getfssec ; get the whole file
342
343 %ifdef DEBUG_MESSAGES
344 mov si, startldr_msg
345 call writemsg
346 call crlf
347 %endif
348
349 mov dl, [DriveNo] ; dl = boot drive
350 mov dh, 0 ; dh = boot partition
351
352 ; Transfer execution to the bootloader
353 ;ljmp16 0, FREELDR_BASE
354 db 0xEA
355 dw 0xF800
356 dw 0
357
358 ;
359 ; searchdir:
360 ;
361 ; Open a file
362 ;
363 ; On entry:
364 ; DS:DI = filename
365 ; If successful:
366 ; ZF clear
367 ; SI = file pointer
368 ; DX:AX or EAX = file length in bytes
369 ; If unsuccessful
370 ; ZF set
371 ;
372
373 ;
374 ; searchdir_iso is a special entry point for ISOLINUX only. In addition
375 ; to the above, searchdir_iso passes a file flag mask in AL. This is useful
376 ; for searching for directories.
377 ;
378 alloc_failure:
379 xor ax,ax ; ZF <- 1
380 ret
381
382 searchdir:
383 xor al,al
384 searchdir_iso:
385 mov [ISOFlags],al
386 call allocate_file ; Temporary file structure for directory
387 jnz alloc_failure
388 push es
389 push ds
390 pop es ; ES = DS
391 mov si,CurDir
392 cmp byte [di],'\' ; If filename begins with slash
393 jne .not_rooted
394 inc di ; Skip leading slash
395 mov si,RootDir ; Reference root directory instead
396 .not_rooted:
397 mov eax,[si+dir_clust]
398 mov [bx+file_left],eax
399 mov eax,[si+dir_lba]
400 mov [bx+file_sector],eax
401 mov edx,[si+dir_len]
402
403 .look_for_slash:
404 mov ax,di
405 .scan:
406 mov cl,[di]
407 inc di
408 and cl,cl
409 jz .isfile
410 cmp cl,'\'
411 jne .scan
412 mov [di-1],byte 0 ; Terminate at directory name
413 mov cl,02h ; Search for directory
414 xchg cl,[ISOFlags]
415 push di
416 push cx
417 push word .resume ; Where to "return" to
418 push es
419 .isfile:
420 xchg ax,di
421
422 .getsome:
423 ; Get a chunk of the directory
424 mov si,trackbuf
425 pushad
426 xchg bx,si
427 mov cx,1 ; load one sector
428 call getfssec
429 popad
430
431 .compare:
432 movzx eax, byte [si] ; Length of directory entry
433 cmp al, 33
434 jb .next_sector
435 mov cl, [si+25]
436 xor cl, [ISOFlags]
437 test cl, byte 8Eh ; Unwanted file attributes!
438 jnz .not_file
439 pusha
440 movzx cx, byte [si+32] ; File identifier length
441 add si, byte 33 ; File identifier offset
442 call iso_compare_names
443 popa
444 je .success
445 .not_file:
446 sub edx, eax ; Decrease bytes left
447 jbe .failure
448 add si, ax ; Advance pointer
449
450 .check_overrun:
451 ; Did we finish the buffer?
452 cmp si, trackbuf+trackbufsize
453 jb .compare ; No, keep going
454
455 jmp short .getsome ; Get some more directory
456
457 .next_sector:
458 ; Advance to the beginning of next sector
459 lea ax, [si+SECTORSIZE-1]
460 and ax, ~(SECTORSIZE-1)
461 sub ax, si
462 jmp short .not_file ; We still need to do length checks
463
464 .failure:
465 %ifdef DEBUG_MESSAGES
466 mov si, findfail_msg
467 call writemsg
468 call crlf
469 %endif
470 xor eax, eax ; ZF = 1
471 mov [bx+file_sector], eax
472 pop es
473 ret
474
475 .success:
476 mov eax, [si+2] ; Location of extent
477 mov [bx+file_sector], eax
478 mov eax, [si+10] ; Data length
479 push eax
480 add eax, SECTORSIZE-1
481 shr eax, SECTORSIZE_LG2
482 mov [bx+file_left], eax
483 pop eax
484 mov edx, eax
485 shr edx, 16
486 and bx, bx ; ZF = 0
487 mov si, bx
488 pop es
489 ret
490
491 .resume:
492 ; We get here if we were only doing part of a lookup
493 ; This relies on the fact that .success returns bx == si
494 xchg edx, eax ; Directory length in edx
495 pop cx ; Old ISOFlags
496 pop di ; Next filename pointer
497
498 mov byte [di-1], '\' ; restore the backslash in the filename
499
500 mov [ISOFlags], cl ; Restore the flags
501 jz .failure ; Did we fail? If so fail for real!
502 jmp .look_for_slash ; Otherwise, next level
503
504 ;
505 ; allocate_file: Allocate a file structure
506 ;
507 ; If successful:
508 ; ZF set
509 ; BX = file pointer
510 ; In unsuccessful:
511 ; ZF clear
512 ;
513 allocate_file:
514 push cx
515 mov bx, Files
516 mov cx, MAX_OPEN
517 .check:
518 cmp dword [bx], byte 0
519 je .found
520 add bx, open_file_t_size ; ZF = 0
521 loop .check
522 ; ZF = 0 if we fell out of the loop
523 .found:
524 pop cx
525 ret
526
527 ;
528 ; iso_compare_names:
529 ; Compare the names DS:SI and DS:DI and report if they are
530 ; equal from an ISO 9660 perspective. SI is the name from
531 ; the filesystem; CX indicates its length, and ';' terminates.
532 ; DI is expected to end with a null.
533 ;
534 ; Note: clobbers AX, CX, SI, DI; assumes DS == ES == base segment
535 ;
536 iso_compare_names:
537 ; First, terminate and canonicalize input filename
538 push di
539 mov di, ISOFileName
540 .canon_loop:
541 jcxz .canon_end
542 lodsb
543 dec cx
544 cmp al, ';'
545 je .canon_end
546 and al, al
547 je .canon_end
548 stosb
549 cmp di, ISOFileNameEnd-1 ; Guard against buffer overrun
550 jb .canon_loop
551 .canon_end:
552 cmp di, ISOFileName
553 jbe .canon_done
554 cmp byte [di-1], '.' ; Remove terminal dots
555 jne .canon_done
556 dec di
557 jmp short .canon_end
558 .canon_done:
559 mov [di], byte 0 ; Null-terminate string
560 pop di
561 mov si, ISOFileName
562 .compare:
563 lodsb
564 mov ah, [di]
565 inc di
566 and ax, ax
567 jz .success ; End of string for both
568 and al, al ; Is either one end of string?
569 jz .failure ; If so, failure
570 and ah, ah
571 jz .failure
572 or ax, 2020h ; Convert to lower case
573 cmp al, ah
574 je .compare
575 .failure:
576 and ax, ax ; ZF = 0 (at least one will be nonzero)
577 .success:
578 ret
579
580
581
582
583
584
585
586 ;
587 ; getfssec: Get multiple clusters from a file, given the file pointer.
588 ;
589 ; On entry:
590 ; ES:BX -> Buffer
591 ; SI -> File pointer
592 ; CX -> Cluster count; 0FFFFh = until end of file
593 ; On exit:
594 ; SI -> File pointer (or 0 on EOF)
595 ; CF = 1 -> Hit EOF
596 ;
597 getfssec:
598 cmp cx, [si+file_left]
599 jna .ok_size
600 mov cx, [si+file_left]
601
602 .ok_size:
603 mov bp, cx
604 push cx
605 push si
606 mov eax, [si+file_sector]
607 call getlinsec
608 xor ecx, ecx
609 pop si
610 pop cx
611
612 add [si+file_sector], ecx
613 sub [si+file_left], ecx
614 ja .not_eof ; CF = 0
615
616 xor ecx, ecx
617 mov [si+file_sector], ecx ; Mark as unused
618 xor si,si
619 stc
620
621 .not_eof:
622 ret
623
624
625
626 ; INT 13h, AX=4B01h, DL=<passed in value> failed.
627 ; Try to scan the entire 80h-FFh from the end.
628 spec_query_failed:
629 mov si,spec_err_msg
630 call writemsg
631
632 mov dl, 0FFh
633 .test_loop:
634 pusha
635 mov ax, 4B01h
636 mov si, spec_packet
637 mov byte [si], 13 ; Size of buffer
638 int 13h
639 popa
640 jc .still_broken
641
642 mov si, maybe_msg
643 call writemsg
644 mov al, dl
645 call writehex2
646 call crlf
647
648 cmp byte [sp_drive], dl
649 jne .maybe_broken
650
651 ; Okay, good enough...
652 mov si, alright_msg
653 call writemsg
654 mov [DriveNo], dl
655 .found_drive:
656 jmp found_drive
657
658 ; Award BIOS 4.51 apparently passes garbage in sp_drive,
659 ; but if this was the drive number originally passed in
660 ; DL then consider it "good enough"
661 .maybe_broken:
662 cmp byte [DriveNo], dl
663 je .found_drive
664
665 .still_broken:
666 dec dx
667 cmp dl, 80h
668 jnb .test_loop
669
670 fatal_error:
671 mov si, nothing_msg
672 call writemsg
673
674 .norge:
675 jmp short .norge
676
677
678
679 ; Information message (DS:SI) output
680 ; Prefix with "isolinux: "
681 ;
682 writemsg:
683 push ax
684 push si
685 mov si, isolinux_str
686 call writestr
687 pop si
688 call writestr
689 pop ax
690 ret
691
692 ;
693 ; crlf: Print a newline
694 ;
695 crlf:
696 mov si, crlf_msg
697 ; Fall through
698
699 ;
700 ; writestr: write a null-terminated string to the console, saving
701 ; registers on entry.
702 ;
703 writestr:
704 pushfd
705 pushad
706 .top:
707 lodsb
708 and al, al
709 jz .end
710 call writechr
711 jmp short .top
712 .end:
713 popad
714 popfd
715 ret
716
717
718 ;
719 ; writehex[248]: Write a hex number in (AL, AX, EAX) to the console
720 ;
721 writehex2:
722 pushfd
723 pushad
724 shl eax, 24
725 mov cx, 2
726 jmp short writehex_common
727 writehex4:
728 pushfd
729 pushad
730 shl eax, 16
731 mov cx, 4
732 jmp short writehex_common
733 writehex8:
734 pushfd
735 pushad
736 mov cx, 8
737 writehex_common:
738 .loop:
739 rol eax, 4
740 push eax
741 and al, 0Fh
742 cmp al, 10
743 jae .high
744 .low:
745 add al, '0'
746 jmp short .ischar
747 .high:
748 add al, 'A'-10
749 .ischar:
750 call writechr
751 pop eax
752 loop .loop
753 popad
754 popfd
755 ret
756
757 ;
758 ; Write a character to the screen. There is a more "sophisticated"
759 ; version of this in the subsequent code, so we patch the pointer
760 ; when appropriate.
761 ;
762
763 writechr:
764 pushfd
765 pushad
766 mov ah, 0Eh
767 xor bx, bx
768 int 10h
769 popad
770 popfd
771 ret
772
773 ;
774 ; Get one sector. Convenience entry point.
775 ;
776 getonesec:
777 mov bp, 1
778 ; Fall through to getlinsec
779
780 ;
781 ; Get linear sectors - EBIOS LBA addressing, 2048-byte sectors.
782 ;
783 ; Note that we can't always do this as a single request, because at least
784 ; Phoenix BIOSes has a 127-sector limit. To be on the safe side, stick
785 ; to 32 sectors (64K) per request.
786 ;
787 ; Input:
788 ; EAX - Linear sector number
789 ; ES:BX - Target buffer
790 ; BP - Sector count
791 ;
792 getlinsec:
793 mov si,dapa ; Load up the DAPA
794 mov [si+4],bx
795 mov bx,es
796 mov [si+6],bx
797 mov [si+8],eax
798 .loop2:
799 push bp ; Sectors left
800 cmp bp,[MaxTransfer]
801 jbe .bp_ok
802 mov bp,[MaxTransfer]
803 .bp_ok:
804 mov [si+2],bp
805 push si
806 mov dl,[DriveNo]
807 mov ah,42h ; Extended Read
808 call xint13
809 pop si
810 pop bp
811 movzx eax,word [si+2] ; Sectors we read
812 add [si+8],eax ; Advance sector pointer
813 sub bp,ax ; Sectors left
814 shl ax,SECTORSIZE_LG2-4 ; 2048-byte sectors -> segment
815 add [si+6],ax ; Advance buffer pointer
816 and bp,bp
817 jnz .loop2
818 mov eax,[si+8] ; Next sector
819 ret
820
821 ; INT 13h with retry
822 xint13:
823 mov byte [RetryCount], retry_count
824 .try:
825 pushad
826 int 13h
827 jc .error
828 add sp, byte 8*4 ; Clean up stack
829 ret
830 .error:
831 mov [DiskError], ah ; Save error code
832 popad
833 dec byte [RetryCount]
834 jz .real_error
835 push ax
836 mov al,[RetryCount]
837 mov ah,[dapa+2] ; Sector transfer count
838 cmp al,2 ; Only 2 attempts left
839 ja .nodanger
840 mov ah,1 ; Drop transfer size to 1
841 jmp short .setsize
842 .nodanger:
843 cmp al,retry_count-2
844 ja .again ; First time, just try again
845 shr ah,1 ; Otherwise, try to reduce
846 adc ah,0 ; the max transfer size, but not to 0
847 .setsize:
848 mov [MaxTransfer],ah
849 mov [dapa+2],ah
850 .again:
851 pop ax
852 jmp .try
853
854 .real_error:
855 mov si, diskerr_msg
856 call writemsg
857 mov al, [DiskError]
858 call writehex2
859 mov si, ondrive_str
860 call writestr
861 mov al, dl
862 call writehex2
863 call crlf
864 ; Fall through to kaboom
865
866 ;
867 ; kaboom: write a message and bail out. Wait for a user keypress,
868 ; then do a hard reboot.
869 ;
870 kaboom:
871 mov ax, cs
872 mov ds, ax
873 mov es, ax
874 mov fs, ax
875 mov gs, ax
876 sti
877 mov si, err_bootfailed
878 call writestr
879 call getchar
880 cli
881 mov word [BIOS_magic], 0 ; Cold reboot
882 jmp 0F000h:0FFF0h ; Reset vector address
883
884 getchar:
885 .again:
886 mov ah, 1 ; Poll keyboard
887 int 16h
888 jz .again
889 .kbd:
890 xor ax, ax ; Get keyboard input
891 int 16h
892 .func_key:
893 ret
894
895
896 isolinux_banner db CR, LF, 'Loading IsoBoot...', CR, LF, 0
897 copyright_str db ' (C) 1994-2002 H. Peter Anvin', CR, LF, 0
898 presskey_msg db 'Press any key to boot from CD', 0
899 dot_msg db '.',0
900
901 %ifdef DEBUG_MESSAGES
902 startup_msg: db 'Starting up, DL = ', 0
903 spec_ok_msg: db 'Loaded spec packet OK, drive = ', 0
904 secsize_msg: db 'Sector size appears to be ', 0
905 rootloc_msg: db 'Root directory location: ', 0
906 rootlen_msg: db 'Root directory length: ', 0
907 rootsect_msg: db 'Root directory length(sectors): ', 0
908 fileloc_msg: db 'SETUPLDR.SYS location: ', 0
909 filelen_msg: db 'SETUPLDR.SYS length: ', 0
910 filesect_msg: db 'SETUPLDR.SYS length(sectors): ', 0
911 findfail_msg: db 'Failed to find file!', 0
912 startldr_msg: db 'Starting SETUPLDR.SYS', 0
913 %endif
914
915 ; nosecsize_msg: db 'Failed to get sector size, assuming 0800', CR, LF, 0
916 spec_err_msg: db 'Loading spec packet failed, trying to wing it...', CR, LF, 0
917 maybe_msg: db 'Found something at drive = ', 0
918 alright_msg: db 'Looks like it might be right, continuing...', CR, LF, 0
919 nothing_msg: db 'Failed to locate CD-ROM device; boot failed.', CR, LF, 0
920 isolinux_str db 'IsoBoot: ', 0
921 crlf_msg db CR, LF, 0
922 diskerr_msg: db 'Disk error ', 0
923 ondrive_str: db ', drive ', 0
924 err_bootfailed db CR, LF, 'Boot failed: press a key to retry...'
925 isolinux_dir db '\LOADER', 0
926 no_dir_msg db 'Could not find the LOADER directory.', CR, LF, 0
927 isolinux_bin db 'SETUPLDR.SYS', 0
928 no_isolinux_msg db 'Could not find SETUPLDR.SYS.', CR, LF, 0
929
930 ;
931 ; El Torito spec packet
932 ;
933 align 8, db 0
934 spec_packet: db 13h ; Size of packet
935 sp_media: db 0 ; Media type
936 sp_drive: db 0 ; Drive number
937 sp_controller: db 0 ; Controller index
938 sp_lba: dd 0 ; LBA for emulated disk image
939 sp_devspec: dw 0 ; IDE/SCSI information
940 sp_buffer: dw 0 ; User-provided buffer
941 sp_loadseg: dw 0 ; Load segment
942 sp_sectors: dw 0 ; Sector count
943 sp_chs: db 0,0,0 ; Simulated CHS geometry
944 sp_dummy: db 0 ; Scratch, safe to overwrite
945
946 ;
947 ; EBIOS drive parameter packet
948 ;
949 align 8, db 0
950 drive_params: dw 30 ; Buffer size
951 dp_flags: dw 0 ; Information flags
952 dp_cyl: dd 0 ; Physical cylinders
953 dp_head: dd 0 ; Physical heads
954 dp_sec: dd 0 ; Physical sectors/track
955 dp_totalsec: dd 0,0 ; Total sectors
956 dp_secsize: dw 0 ; Bytes per sector
957 dp_dpte: dd 0 ; Device Parameter Table
958 dp_dpi_key: dw 0 ; 0BEDDh if rest valid
959 dp_dpi_len: db 0 ; DPI len
960 db 0
961 dw 0
962 dp_bus: times 4 db 0 ; Host bus type
963 dp_interface: times 8 db 0 ; Interface type
964 db_i_path: dd 0,0 ; Interface path
965 db_d_path: dd 0,0 ; Device path
966 db 0
967 db_dpi_csum: db 0 ; Checksum for DPI info
968
969 ;
970 ; EBIOS disk address packet
971 ;
972 align 8, db 0
973 dapa: dw 16 ; Packet size
974 .count: dw 0 ; Block count
975 .off: dw 0 ; Offset of buffer
976 .seg: dw 0 ; Segment of buffer
977 .lba: dd 0 ; LBA (LSW)
978 dd 0 ; LBA (MSW)
979
980 alignb 4, db 0
981 MaxTransfer dw 2 ;32 ; Max sectors per transfer
982
983 times 2046-($-$$) db 0 ; Pad to file offset 2046
984 dw 0aa55h ; BootSector signature