- Create KD branch. All debugging support is removed in this branch (no symbols,...
[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 mov bx, 0x8000 ; bx = load address
336 mov si, di ; restore file pointer
337 mov cx, 0xFFFF ; load the whole file
338 call getfssec ; get the whole file
339
340 %ifdef DEBUG_MESSAGES
341 mov si, startldr_msg
342 call writemsg
343 call crlf
344 %endif
345
346 mov dl, [DriveNo] ; dl = boot drive
347 mov dh, 0 ; dh = boot partition
348 jmp 0:0x8000 ; jump into OSLoader
349
350
351
352 ;
353 ; searchdir:
354 ;
355 ; Open a file
356 ;
357 ; On entry:
358 ; DS:DI = filename
359 ; If successful:
360 ; ZF clear
361 ; SI = file pointer
362 ; DX:AX or EAX = file length in bytes
363 ; If unsuccessful
364 ; ZF set
365 ;
366
367 ;
368 ; searchdir_iso is a special entry point for ISOLINUX only. In addition
369 ; to the above, searchdir_iso passes a file flag mask in AL. This is useful
370 ; for searching for directories.
371 ;
372 alloc_failure:
373 xor ax,ax ; ZF <- 1
374 ret
375
376 searchdir:
377 xor al,al
378 searchdir_iso:
379 mov [ISOFlags],al
380 call allocate_file ; Temporary file structure for directory
381 jnz alloc_failure
382 push es
383 push ds
384 pop es ; ES = DS
385 mov si,CurDir
386 cmp byte [di],'\' ; If filename begins with slash
387 jne .not_rooted
388 inc di ; Skip leading slash
389 mov si,RootDir ; Reference root directory instead
390 .not_rooted:
391 mov eax,[si+dir_clust]
392 mov [bx+file_left],eax
393 mov eax,[si+dir_lba]
394 mov [bx+file_sector],eax
395 mov edx,[si+dir_len]
396
397 .look_for_slash:
398 mov ax,di
399 .scan:
400 mov cl,[di]
401 inc di
402 and cl,cl
403 jz .isfile
404 cmp cl,'\'
405 jne .scan
406 mov [di-1],byte 0 ; Terminate at directory name
407 mov cl,02h ; Search for directory
408 xchg cl,[ISOFlags]
409 push di
410 push cx
411 push word .resume ; Where to "return" to
412 push es
413 .isfile:
414 xchg ax,di
415
416 .getsome:
417 ; Get a chunk of the directory
418 mov si,trackbuf
419 pushad
420 xchg bx,si
421 mov cx,1 ; load one sector
422 call getfssec
423 popad
424
425 .compare:
426 movzx eax, byte [si] ; Length of directory entry
427 cmp al, 33
428 jb .next_sector
429 mov cl, [si+25]
430 xor cl, [ISOFlags]
431 test cl, byte 8Eh ; Unwanted file attributes!
432 jnz .not_file
433 pusha
434 movzx cx, byte [si+32] ; File identifier length
435 add si, byte 33 ; File identifier offset
436 call iso_compare_names
437 popa
438 je .success
439 .not_file:
440 sub edx, eax ; Decrease bytes left
441 jbe .failure
442 add si, ax ; Advance pointer
443
444 .check_overrun:
445 ; Did we finish the buffer?
446 cmp si, trackbuf+trackbufsize
447 jb .compare ; No, keep going
448
449 jmp short .getsome ; Get some more directory
450
451 .next_sector:
452 ; Advance to the beginning of next sector
453 lea ax, [si+SECTORSIZE-1]
454 and ax, ~(SECTORSIZE-1)
455 sub ax, si
456 jmp short .not_file ; We still need to do length checks
457
458 .failure:
459 %ifdef DEBUG_MESSAGES
460 mov si, findfail_msg
461 call writemsg
462 call crlf
463 %endif
464 xor eax, eax ; ZF = 1
465 mov [bx+file_sector], eax
466 pop es
467 ret
468
469 .success:
470 mov eax, [si+2] ; Location of extent
471 mov [bx+file_sector], eax
472 mov eax, [si+10] ; Data length
473 push eax
474 add eax, SECTORSIZE-1
475 shr eax, SECTORSIZE_LG2
476 mov [bx+file_left], eax
477 pop eax
478 mov edx, eax
479 shr edx, 16
480 and bx, bx ; ZF = 0
481 mov si, bx
482 pop es
483 ret
484
485 .resume:
486 ; We get here if we were only doing part of a lookup
487 ; This relies on the fact that .success returns bx == si
488 xchg edx, eax ; Directory length in edx
489 pop cx ; Old ISOFlags
490 pop di ; Next filename pointer
491
492 mov byte [di-1], '\' ; restore the backslash in the filename
493
494 mov [ISOFlags], cl ; Restore the flags
495 jz .failure ; Did we fail? If so fail for real!
496 jmp .look_for_slash ; Otherwise, next level
497
498 ;
499 ; allocate_file: Allocate a file structure
500 ;
501 ; If successful:
502 ; ZF set
503 ; BX = file pointer
504 ; In unsuccessful:
505 ; ZF clear
506 ;
507 allocate_file:
508 push cx
509 mov bx, Files
510 mov cx, MAX_OPEN
511 .check:
512 cmp dword [bx], byte 0
513 je .found
514 add bx, open_file_t_size ; ZF = 0
515 loop .check
516 ; ZF = 0 if we fell out of the loop
517 .found:
518 pop cx
519 ret
520
521 ;
522 ; iso_compare_names:
523 ; Compare the names DS:SI and DS:DI and report if they are
524 ; equal from an ISO 9660 perspective. SI is the name from
525 ; the filesystem; CX indicates its length, and ';' terminates.
526 ; DI is expected to end with a null.
527 ;
528 ; Note: clobbers AX, CX, SI, DI; assumes DS == ES == base segment
529 ;
530 iso_compare_names:
531 ; First, terminate and canonicalize input filename
532 push di
533 mov di, ISOFileName
534 .canon_loop:
535 jcxz .canon_end
536 lodsb
537 dec cx
538 cmp al, ';'
539 je .canon_end
540 and al, al
541 je .canon_end
542 stosb
543 cmp di, ISOFileNameEnd-1 ; Guard against buffer overrun
544 jb .canon_loop
545 .canon_end:
546 cmp di, ISOFileName
547 jbe .canon_done
548 cmp byte [di-1], '.' ; Remove terminal dots
549 jne .canon_done
550 dec di
551 jmp short .canon_end
552 .canon_done:
553 mov [di], byte 0 ; Null-terminate string
554 pop di
555 mov si, ISOFileName
556 .compare:
557 lodsb
558 mov ah, [di]
559 inc di
560 and ax, ax
561 jz .success ; End of string for both
562 and al, al ; Is either one end of string?
563 jz .failure ; If so, failure
564 and ah, ah
565 jz .failure
566 or ax, 2020h ; Convert to lower case
567 cmp al, ah
568 je .compare
569 .failure:
570 and ax, ax ; ZF = 0 (at least one will be nonzero)
571 .success:
572 ret
573
574
575
576
577
578
579
580 ;
581 ; getfssec: Get multiple clusters from a file, given the file pointer.
582 ;
583 ; On entry:
584 ; ES:BX -> Buffer
585 ; SI -> File pointer
586 ; CX -> Cluster count; 0FFFFh = until end of file
587 ; On exit:
588 ; SI -> File pointer (or 0 on EOF)
589 ; CF = 1 -> Hit EOF
590 ;
591 getfssec:
592 cmp cx, [si+file_left]
593 jna .ok_size
594 mov cx, [si+file_left]
595
596 .ok_size:
597 mov bp, cx
598 push cx
599 push si
600 mov eax, [si+file_sector]
601 call getlinsec
602 xor ecx, ecx
603 pop si
604 pop cx
605
606 add [si+file_sector], ecx
607 sub [si+file_left], ecx
608 ja .not_eof ; CF = 0
609
610 xor ecx, ecx
611 mov [si+file_sector], ecx ; Mark as unused
612 xor si,si
613 stc
614
615 .not_eof:
616 ret
617
618
619
620 ; INT 13h, AX=4B01h, DL=<passed in value> failed.
621 ; Try to scan the entire 80h-FFh from the end.
622 spec_query_failed:
623 mov si,spec_err_msg
624 call writemsg
625
626 mov dl, 0FFh
627 .test_loop:
628 pusha
629 mov ax, 4B01h
630 mov si, spec_packet
631 mov byte [si], 13 ; Size of buffer
632 int 13h
633 popa
634 jc .still_broken
635
636 mov si, maybe_msg
637 call writemsg
638 mov al, dl
639 call writehex2
640 call crlf
641
642 cmp byte [sp_drive], dl
643 jne .maybe_broken
644
645 ; Okay, good enough...
646 mov si, alright_msg
647 call writemsg
648 mov [DriveNo], dl
649 .found_drive:
650 jmp found_drive
651
652 ; Award BIOS 4.51 apparently passes garbage in sp_drive,
653 ; but if this was the drive number originally passed in
654 ; DL then consider it "good enough"
655 .maybe_broken:
656 cmp byte [DriveNo], dl
657 je .found_drive
658
659 .still_broken:
660 dec dx
661 cmp dl, 80h
662 jnb .test_loop
663
664 fatal_error:
665 mov si, nothing_msg
666 call writemsg
667
668 .norge:
669 jmp short .norge
670
671
672
673 ; Information message (DS:SI) output
674 ; Prefix with "isolinux: "
675 ;
676 writemsg:
677 push ax
678 push si
679 mov si, isolinux_str
680 call writestr
681 pop si
682 call writestr
683 pop ax
684 ret
685
686 ;
687 ; crlf: Print a newline
688 ;
689 crlf:
690 mov si, crlf_msg
691 ; Fall through
692
693 ;
694 ; writestr: write a null-terminated string to the console, saving
695 ; registers on entry.
696 ;
697 writestr:
698 pushfd
699 pushad
700 .top:
701 lodsb
702 and al, al
703 jz .end
704 call writechr
705 jmp short .top
706 .end:
707 popad
708 popfd
709 ret
710
711
712 ;
713 ; writehex[248]: Write a hex number in (AL, AX, EAX) to the console
714 ;
715 writehex2:
716 pushfd
717 pushad
718 shl eax, 24
719 mov cx, 2
720 jmp short writehex_common
721 writehex4:
722 pushfd
723 pushad
724 shl eax, 16
725 mov cx, 4
726 jmp short writehex_common
727 writehex8:
728 pushfd
729 pushad
730 mov cx, 8
731 writehex_common:
732 .loop:
733 rol eax, 4
734 push eax
735 and al, 0Fh
736 cmp al, 10
737 jae .high
738 .low:
739 add al, '0'
740 jmp short .ischar
741 .high:
742 add al, 'A'-10
743 .ischar:
744 call writechr
745 pop eax
746 loop .loop
747 popad
748 popfd
749 ret
750
751 ;
752 ; Write a character to the screen. There is a more "sophisticated"
753 ; version of this in the subsequent code, so we patch the pointer
754 ; when appropriate.
755 ;
756
757 writechr:
758 pushfd
759 pushad
760 mov ah, 0Eh
761 xor bx, bx
762 int 10h
763 popad
764 popfd
765 ret
766
767 ;
768 ; Get one sector. Convenience entry point.
769 ;
770 getonesec:
771 mov bp, 1
772 ; Fall through to getlinsec
773
774 ;
775 ; Get linear sectors - EBIOS LBA addressing, 2048-byte sectors.
776 ;
777 ; Note that we can't always do this as a single request, because at least
778 ; Phoenix BIOSes has a 127-sector limit. To be on the safe side, stick
779 ; to 32 sectors (64K) per request.
780 ;
781 ; Input:
782 ; EAX - Linear sector number
783 ; ES:BX - Target buffer
784 ; BP - Sector count
785 ;
786 getlinsec:
787 mov si,dapa ; Load up the DAPA
788 mov [si+4],bx
789 mov bx,es
790 mov [si+6],bx
791 mov [si+8],eax
792 .loop2:
793 push bp ; Sectors left
794 cmp bp,[MaxTransfer]
795 jbe .bp_ok
796 mov bp,[MaxTransfer]
797 .bp_ok:
798 mov [si+2],bp
799 push si
800 mov dl,[DriveNo]
801 mov ah,42h ; Extended Read
802 call xint13
803 pop si
804 pop bp
805 movzx eax,word [si+2] ; Sectors we read
806 add [si+8],eax ; Advance sector pointer
807 sub bp,ax ; Sectors left
808 shl ax,SECTORSIZE_LG2-4 ; 2048-byte sectors -> segment
809 add [si+6],ax ; Advance buffer pointer
810 and bp,bp
811 jnz .loop2
812 mov eax,[si+8] ; Next sector
813 ret
814
815 ; INT 13h with retry
816 xint13:
817 mov byte [RetryCount], retry_count
818 .try:
819 pushad
820 int 13h
821 jc .error
822 add sp, byte 8*4 ; Clean up stack
823 ret
824 .error:
825 mov [DiskError], ah ; Save error code
826 popad
827 dec byte [RetryCount]
828 jz .real_error
829 push ax
830 mov al,[RetryCount]
831 mov ah,[dapa+2] ; Sector transfer count
832 cmp al,2 ; Only 2 attempts left
833 ja .nodanger
834 mov ah,1 ; Drop transfer size to 1
835 jmp short .setsize
836 .nodanger:
837 cmp al,retry_count-2
838 ja .again ; First time, just try again
839 shr ah,1 ; Otherwise, try to reduce
840 adc ah,0 ; the max transfer size, but not to 0
841 .setsize:
842 mov [MaxTransfer],ah
843 mov [dapa+2],ah
844 .again:
845 pop ax
846 jmp .try
847
848 .real_error:
849 mov si, diskerr_msg
850 call writemsg
851 mov al, [DiskError]
852 call writehex2
853 mov si, ondrive_str
854 call writestr
855 mov al, dl
856 call writehex2
857 call crlf
858 ; Fall through to kaboom
859
860 ;
861 ; kaboom: write a message and bail out. Wait for a user keypress,
862 ; then do a hard reboot.
863 ;
864 kaboom:
865 mov ax, cs
866 mov ds, ax
867 mov es, ax
868 mov fs, ax
869 mov gs, ax
870 sti
871 mov si, err_bootfailed
872 call writestr
873 call getchar
874 cli
875 mov word [BIOS_magic], 0 ; Cold reboot
876 jmp 0F000h:0FFF0h ; Reset vector address
877
878 getchar:
879 .again:
880 mov ah, 1 ; Poll keyboard
881 int 16h
882 jz .again
883 .kbd:
884 xor ax, ax ; Get keyboard input
885 int 16h
886 .func_key:
887 ret
888
889
890 ;
891 ; pollchar: check if we have an input character pending (ZF = 0)
892 ;
893 pollchar:
894 pushad
895 mov ah,1 ; Poll keyboard
896 int 16h
897 popad
898 ret
899
900
901
902 isolinux_banner db CR, LF, 'Loading IsoBoot...', CR, LF, 0
903 copyright_str db ' Copyright (C) 1994-2002 H. Peter Anvin', CR, LF, 0
904 presskey_msg db 'Press any key to boot from CD', 0
905 dot_msg db '.',0
906
907 %ifdef DEBUG_MESSAGES
908 startup_msg: db 'Starting up, DL = ', 0
909 spec_ok_msg: db 'Loaded spec packet OK, drive = ', 0
910 secsize_msg: db 'Sector size appears to be ', 0
911 rootloc_msg: db 'Root directory location: ', 0
912 rootlen_msg: db 'Root directory length: ', 0
913 rootsect_msg: db 'Root directory length(sectors): ', 0
914 fileloc_msg: db 'SETUPLDR.SYS location: ', 0
915 filelen_msg: db 'SETUPLDR.SYS length: ', 0
916 filesect_msg: db 'SETUPLDR.SYS length(sectors): ', 0
917 findfail_msg: db 'Failed to find file!', 0
918 startldr_msg: db 'Starting SETUPLDR.SYS', 0
919 %endif
920
921 nosecsize_msg: db 'Failed to get sector size, assuming 0800', CR, LF, 0
922 spec_err_msg: db 'Loading spec packet failed, trying to wing it...', CR, LF, 0
923 maybe_msg: db 'Found something at drive = ', 0
924 alright_msg: db 'Looks like it might be right, continuing...', CR, LF, 0
925 nothing_msg: db 'Failed to locate CD-ROM device; boot failed.', CR, LF, 0
926 isolinux_str db 'IsoBoot: ', 0
927 crlf_msg db CR, LF, 0
928 diskerr_msg: db 'Disk error ', 0
929 ondrive_str: db ', drive ', 0
930 err_bootfailed db CR, LF, 'Boot failed: press a key to retry...'
931 isolinux_dir db '\LOADER', 0
932 no_dir_msg db 'Could not find the LOADER directory.', CR, LF, 0
933 isolinux_bin db 'SETUPLDR.SYS', 0
934 no_isolinux_msg db 'Could not find SETUPLDR.SYS.', CR, LF, 0
935
936 ;
937 ; El Torito spec packet
938 ;
939 align 8, db 0
940 spec_packet: db 13h ; Size of packet
941 sp_media: db 0 ; Media type
942 sp_drive: db 0 ; Drive number
943 sp_controller: db 0 ; Controller index
944 sp_lba: dd 0 ; LBA for emulated disk image
945 sp_devspec: dw 0 ; IDE/SCSI information
946 sp_buffer: dw 0 ; User-provided buffer
947 sp_loadseg: dw 0 ; Load segment
948 sp_sectors: dw 0 ; Sector count
949 sp_chs: db 0,0,0 ; Simulated CHS geometry
950 sp_dummy: db 0 ; Scratch, safe to overwrite
951
952 ;
953 ; EBIOS drive parameter packet
954 ;
955 align 8, db 0
956 drive_params: dw 30 ; Buffer size
957 dp_flags: dw 0 ; Information flags
958 dp_cyl: dd 0 ; Physical cylinders
959 dp_head: dd 0 ; Physical heads
960 dp_sec: dd 0 ; Physical sectors/track
961 dp_totalsec: dd 0,0 ; Total sectors
962 dp_secsize: dw 0 ; Bytes per sector
963 dp_dpte: dd 0 ; Device Parameter Table
964 dp_dpi_key: dw 0 ; 0BEDDh if rest valid
965 dp_dpi_len: db 0 ; DPI len
966 db 0
967 dw 0
968 dp_bus: times 4 db 0 ; Host bus type
969 dp_interface: times 8 db 0 ; Interface type
970 db_i_path: dd 0,0 ; Interface path
971 db_d_path: dd 0,0 ; Device path
972 db 0
973 db_dpi_csum: db 0 ; Checksum for DPI info
974
975 ;
976 ; EBIOS disk address packet
977 ;
978 align 8, db 0
979 dapa: dw 16 ; Packet size
980 .count: dw 0 ; Block count
981 .off: dw 0 ; Offset of buffer
982 .seg: dw 0 ; Segment of buffer
983 .lba: dd 0 ; LBA (LSW)
984 dd 0 ; LBA (MSW)
985
986 alignb 4, db 0
987 MaxTransfer dw 2 ;32 ; Max sectors per transfer
988
989 times 2046-($-$$) db 0 ; Pad to file offset 2046
990 dw 0aa55h ; BootSector signature