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