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