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