Magellan Linux

Contents of /trunk/mkinitrd-magellan/isolinux/isolinux.asm

Parent Directory Parent Directory | Revision Log Revision Log


Revision 532 - (show annotations) (download)
Sat Sep 1 22:45:15 2007 UTC (16 years, 8 months ago) by niro
File size: 41054 byte(s)
-import if magellan mkinitrd; it is a fork of redhats mkinitrd-5.0.8 with all magellan patches and features; deprecates magellan-src/mkinitrd

1 ; -*- fundamental -*- (asm-mode sucks)
2 ; $Id: isolinux.asm,v 1.1 2007-09-01 22:44:04 niro Exp $
3 ; ****************************************************************************
4 ;
5 ; isolinux.asm
6 ;
7 ; A program to boot Linux kernels off a CD-ROM using the El Torito
8 ; boot standard in "no emulation" mode, making the entire filesystem
9 ; available. It is based on the SYSLINUX boot loader for MS-DOS
10 ; floppies.
11 ;
12 ; Copyright (C) 1994-2005 H. Peter Anvin
13 ;
14 ; This program is free software; you can redistribute it and/or modify
15 ; it under the terms of the GNU General Public License as published by
16 ; the Free Software Foundation, Inc., 53 Temple Place Ste 330,
17 ; Boston MA 02111-1307, USA; either version 2 of the License, or
18 ; (at your option) any later version; incorporated herein by reference.
19 ;
20 ; ****************************************************************************
21
22 %define IS_ISOLINUX 1
23 %include "macros.inc"
24 %include "config.inc"
25 %include "kernel.inc"
26 %include "bios.inc"
27 %include "tracers.inc"
28 %include "layout.inc"
29
30 ;
31 ; Some semi-configurable constants... change on your own risk.
32 ;
33 my_id equ isolinux_id
34 FILENAME_MAX_LG2 equ 8 ; log2(Max filename size Including final null)
35 FILENAME_MAX equ (1 << FILENAME_MAX_LG2)
36 NULLFILE equ 0 ; Zero byte == null file name
37 NULLOFFSET equ 0 ; Position in which to look
38 retry_count equ 6 ; How patient are we with the BIOS?
39 %assign HIGHMEM_SLOP 128*1024 ; Avoid this much memory near the top
40 MAX_OPEN_LG2 equ 6 ; log2(Max number of open files)
41 MAX_OPEN equ (1 << MAX_OPEN_LG2)
42 SECTOR_SHIFT equ 11 ; 2048 bytes/sector (El Torito requirement)
43 SECTOR_SIZE equ (1 << SECTOR_SHIFT)
44
45 ;
46 ; This is what we need to do when idle
47 ;
48 %macro RESET_IDLE 0
49 ; Nothing
50 %endmacro
51 %macro DO_IDLE 0
52 ; Nothing
53 %endmacro
54
55 ;
56 ; The following structure is used for "virtual kernels"; i.e. LILO-style
57 ; option labels. The options we permit here are `kernel' and `append
58 ; Since there is no room in the bottom 64K for all of these, we
59 ; stick them at vk_seg:0000 and copy them down before we need them.
60 ;
61 struc vkernel
62 vk_vname: resb FILENAME_MAX ; Virtual name **MUST BE FIRST!**
63 vk_rname: resb FILENAME_MAX ; Real name
64 vk_appendlen: resw 1
65 alignb 4
66 vk_append: resb max_cmd_len+1 ; Command line
67 alignb 4
68 vk_end: equ $ ; Should be <= vk_size
69 endstruc
70
71 ;
72 ; Segment assignments in the bottom 640K
73 ; 0000h - main code/data segment (and BIOS segment)
74 ;
75 real_mode_seg equ 3000h
76 vk_seg equ 2000h ; Virtual kernels
77 xfer_buf_seg equ 1000h ; Bounce buffer for I/O to high mem
78 comboot_seg equ real_mode_seg ; COMBOOT image loading zone
79
80 ;
81 ; File structure. This holds the information for each currently open file.
82 ;
83 struc open_file_t
84 file_sector resd 1 ; Sector pointer (0 = structure free)
85 file_left resd 1 ; Number of sectors left
86 endstruc
87
88 %ifndef DEPEND
89 %if (open_file_t_size & (open_file_t_size-1))
90 %error "open_file_t is not a power of 2"
91 %endif
92 %endif
93
94 struc dir_t
95 dir_lba resd 1 ; Directory start (LBA)
96 dir_len resd 1 ; Length in bytes
97 dir_clust resd 1 ; Length in clusters
98 endstruc
99
100 ; ---------------------------------------------------------------------------
101 ; BEGIN CODE
102 ; ---------------------------------------------------------------------------
103
104 ;
105 ; Memory below this point is reserved for the BIOS and the MBR
106 ;
107 section .earlybss
108 trackbufsize equ 8192
109 trackbuf resb trackbufsize ; Track buffer goes here
110 getcbuf resb trackbufsize
111 ; ends at 4800h
112
113 section .bss
114 alignb 4
115 ISOFileName resb 64 ; ISO filename canonicalization buffer
116 ISOFileNameEnd equ $
117 CurDir resb dir_t_size ; Current directory
118 RootDir resb dir_t_size ; Root directory
119 FirstSecSum resd 1 ; Checksum of bytes 64-2048
120 ImageDwords resd 1 ; isolinux.bin size, dwords
121 InitStack resd 1 ; Initial stack pointer (SS:SP)
122 DiskSys resw 1 ; Last INT 13h call
123 ImageSectors resw 1 ; isolinux.bin size, sectors
124 DiskError resb 1 ; Error code for disk I/O
125 DriveNo resb 1 ; CD-ROM BIOS drive number
126 ISOFlags resb 1 ; Flags for ISO directory search
127 RetryCount resb 1 ; Used for disk access retries
128
129 _spec_start equ $
130
131 ;
132 ; El Torito spec packet
133 ;
134
135 alignb 8
136 spec_packet: resb 1 ; Size of packet
137 sp_media: resb 1 ; Media type
138 sp_drive: resb 1 ; Drive number
139 sp_controller: resb 1 ; Controller index
140 sp_lba: resd 1 ; LBA for emulated disk image
141 sp_devspec: resw 1 ; IDE/SCSI information
142 sp_buffer: resw 1 ; User-provided buffer
143 sp_loadseg: resw 1 ; Load segment
144 sp_sectors: resw 1 ; Sector count
145 sp_chs: resb 3 ; Simulated CHS geometry
146 sp_dummy: resb 1 ; Scratch, safe to overwrite
147
148 ;
149 ; EBIOS drive parameter packet
150 ;
151 alignb 8
152 drive_params: resw 1 ; Buffer size
153 dp_flags: resw 1 ; Information flags
154 dp_cyl: resd 1 ; Physical cylinders
155 dp_head: resd 1 ; Physical heads
156 dp_sec: resd 1 ; Physical sectors/track
157 dp_totalsec: resd 2 ; Total sectors
158 dp_secsize: resw 1 ; Bytes per sector
159 dp_dpte: resd 1 ; Device Parameter Table
160 dp_dpi_key: resw 1 ; 0BEDDh if rest valid
161 dp_dpi_len: resb 1 ; DPI len
162 resb 1
163 resw 1
164 dp_bus: resb 4 ; Host bus type
165 dp_interface: resb 8 ; Interface type
166 db_i_path: resd 2 ; Interface path
167 db_d_path: resd 2 ; Device path
168 resb 1
169 db_dpi_csum: resb 1 ; Checksum for DPI info
170
171 ;
172 ; EBIOS disk address packet
173 ;
174 alignb 8
175 dapa: resw 1 ; Packet size
176 .count: resw 1 ; Block count
177 .off: resw 1 ; Offset of buffer
178 .seg: resw 1 ; Segment of buffer
179 .lba: resd 2 ; LBA (LSW, MSW)
180
181 ;
182 ; Spec packet for disk image emulation
183 ;
184 alignb 8
185 dspec_packet: resb 1 ; Size of packet
186 dsp_media: resb 1 ; Media type
187 dsp_drive: resb 1 ; Drive number
188 dsp_controller: resb 1 ; Controller index
189 dsp_lba: resd 1 ; LBA for emulated disk image
190 dsp_devspec: resw 1 ; IDE/SCSI information
191 dsp_buffer: resw 1 ; User-provided buffer
192 dsp_loadseg: resw 1 ; Load segment
193 dsp_sectors: resw 1 ; Sector count
194 dsp_chs: resb 3 ; Simulated CHS geometry
195 dsp_dummy: resb 1 ; Scratch, safe to overwrite
196
197 alignb 4
198 _spec_end equ $
199 _spec_len equ _spec_end - _spec_start
200
201 alignb open_file_t_size
202 Files resb MAX_OPEN*open_file_t_size
203
204 ;
205 ; Constants for the xfer_buf_seg
206 ;
207 ; The xfer_buf_seg is also used to store message file buffers. We
208 ; need two trackbuffers (text and graphics), plus a work buffer
209 ; for the graphics decompressor.
210 ;
211 xbs_textbuf equ 0 ; Also hard-coded, do not change
212 xbs_vgabuf equ trackbufsize
213 xbs_vgatmpbuf equ 2*trackbufsize
214
215 section .text
216 ;;
217 ;; Primary entry point. Because BIOSes are buggy, we only load the first
218 ;; CD-ROM sector (2K) of the file, so the number one priority is actually
219 ;; loading the rest.
220 ;;
221 StackBuf equ $
222
223 bootsec equ $
224
225 _start: ; Far jump makes sure we canonicalize the address
226 cli
227 jmp 0:_start1
228 times 8-($-$$) nop ; Pad to file offset 8
229
230 ; This table hopefully gets filled in by mkisofs using the
231 ; -boot-info-table option. If not, the values in this
232 ; table are default values that we can use to get us what
233 ; we need, at least under a certain set of assumptions.
234 bi_pvd: dd 16 ; LBA of primary volume descriptor
235 bi_file: dd 0 ; LBA of boot file
236 bi_length: dd 0xdeadbeef ; Length of boot file
237 bi_csum: dd 0xdeadbeef ; Checksum of boot file
238 bi_reserved: times 10 dd 0xdeadbeef ; Reserved
239
240 _start1: mov [cs:InitStack],sp ; Save initial stack pointer
241 mov [cs:InitStack+2],ss
242 xor ax,ax
243 mov ss,ax
244 mov sp,StackBuf ; Set up stack
245 mov ds,ax
246 mov es,ax
247 mov fs,ax
248 mov gs,ax
249 sti
250
251 cld
252 ; Show signs of life
253 mov si,syslinux_banner
254 call writestr
255 %ifdef DEBUG_MESSAGES
256 mov si,copyright_str
257 call writestr
258 %endif
259
260 ;
261 ; Before modifying any memory, get the checksum of bytes
262 ; 64-2048
263 ;
264 initial_csum: xor edi,edi
265 mov si,_start1
266 mov cx,(SECTOR_SIZE-64) >> 2
267 .loop: lodsd
268 add edi,eax
269 loop .loop
270 mov [FirstSecSum],edi
271
272 mov [DriveNo],dl
273 %ifdef DEBUG_MESSAGES
274 mov si,startup_msg
275 call writemsg
276 mov al,dl
277 call writehex2
278 call crlf
279 %endif
280 ;
281 ; Initialize spec packet buffers
282 ;
283 mov di,_spec_start
284 mov cx,_spec_len >> 2
285 xor eax,eax
286 rep stosd
287
288 ; Initialize length field of the various packets
289 mov byte [spec_packet],13h
290 mov byte [drive_params],30
291 mov byte [dapa],16
292 mov byte [dspec_packet],13h
293
294 ; Other nonzero fields
295 inc word [dsp_sectors]
296
297 ; Now figure out what we're actually doing
298 ; Note: use passed-in DL value rather than 7Fh because
299 ; at least some BIOSes will get the wrong value otherwise
300 mov ax,4B01h ; Get disk emulation status
301 mov dl,[DriveNo]
302 mov si,spec_packet
303 int 13h
304 jc award_hack ; changed for BrokenAwardHack
305 mov dl,[DriveNo]
306 cmp [sp_drive],dl ; Should contain the drive number
307 jne spec_query_failed
308
309 %ifdef DEBUG_MESSAGES
310 mov si,spec_ok_msg
311 call writemsg
312 mov al,byte [sp_drive]
313 call writehex2
314 call crlf
315 %endif
316
317 found_drive:
318 ; Alright, we have found the drive. Now, try to find the
319 ; boot file itself. If we have a boot info table, life is
320 ; good; if not, we have to make some assumptions, and try
321 ; to figure things out ourselves. In particular, the
322 ; assumptions we have to make are:
323 ; - single session only
324 ; - only one boot entry (no menu or other alternatives)
325
326 cmp dword [bi_file],0 ; Address of code to load
327 jne found_file ; Boot info table present :)
328
329 %ifdef DEBUG_MESSAGES
330 mov si,noinfotable_msg
331 call writemsg
332 %endif
333
334 ; No such luck. See if the the spec packet contained one.
335 mov eax,[sp_lba]
336 and eax,eax
337 jz set_file ; Good enough
338
339 %ifdef DEBUG_MESSAGES
340 mov si,noinfoinspec_msg
341 call writemsg
342 %endif
343
344 ; No such luck. Get the Boot Record Volume, assuming single
345 ; session disk, and that we're the first entry in the chain
346 mov eax,17 ; Assumed address of BRV
347 mov bx,trackbuf
348 call getonesec
349
350 mov eax,[trackbuf+47h] ; Get boot catalog address
351 mov bx,trackbuf
352 call getonesec ; Get boot catalog
353
354 mov eax,[trackbuf+28h] ; First boot entry
355 ; And hope and pray this is us...
356
357 ; Some BIOSes apparently have limitations on the size
358 ; that may be loaded (despite the El Torito spec being very
359 ; clear on the fact that it must all be loaded.) Therefore,
360 ; we load it ourselves, and *bleep* the BIOS.
361
362 set_file:
363 mov [bi_file],eax
364
365 found_file:
366 ; Set up boot file sizes
367 mov eax,[bi_length]
368 sub eax,SECTOR_SIZE-3
369 shr eax,2 ; bytes->dwords
370 mov [ImageDwords],eax ; boot file dwords
371 add eax,(2047 >> 2)
372 shr eax,9 ; dwords->sectors
373 mov [ImageSectors],ax ; boot file sectors
374
375 mov eax,[bi_file] ; Address of code to load
376 inc eax ; Don't reload bootstrap code
377 %ifdef DEBUG_MESSAGES
378 mov si,offset_msg
379 call writemsg
380 call writehex8
381 call crlf
382 %endif
383
384 ; Just in case some BIOSes have problems with
385 ; segment wraparound, use the normalized address
386 mov bx,((7C00h+2048) >> 4)
387 mov es,bx
388 xor bx,bx
389 mov bp,[ImageSectors]
390 %ifdef DEBUG_MESSAGES
391 push ax
392 mov si,size_msg
393 call writemsg
394 mov ax,bp
395 call writehex4
396 call crlf
397 pop ax
398 %endif
399 call getlinsec
400
401 push ds
402 pop es
403
404 %ifdef DEBUG_MESSAGES
405 mov si,loaded_msg
406 call writemsg
407 %endif
408
409 ; Verify the checksum on the loaded image.
410 verify_image:
411 mov si,7C00h+2048
412 mov bx,es
413 mov ecx,[ImageDwords]
414 mov edi,[FirstSecSum] ; First sector checksum
415 .loop es lodsd
416 add edi,eax
417 dec ecx
418 jz .done
419 and si,si
420 jnz .loop
421 ; SI wrapped around, advance ES
422 add bx,1000h
423 mov es,bx
424 jmp short .loop
425 .done: mov ax,ds
426 mov es,ax
427 cmp [bi_csum],edi
428 je integrity_ok
429
430 mov si,checkerr_msg
431 call writemsg
432 jmp kaboom
433
434 integrity_ok:
435 %ifdef DEBUG_MESSAGES
436 mov si,allread_msg
437 call writemsg
438 %endif
439 jmp all_read ; Jump to main code
440
441 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
442 ;; Start of BrokenAwardHack --- 10-nov-2002 Knut_Petersen@t-online.de
443 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
444 ;;
445 ;; There is a problem with certain versions of the AWARD BIOS ...
446 ;; the boot sector will be loaded and executed correctly, but, because the
447 ;; int 13 vector points to the wrong code in the BIOS, every attempt to
448 ;; load the spec packet will fail. We scan for the equivalent of
449 ;;
450 ;; mov ax,0201h
451 ;; mov bx,7c00h
452 ;; mov cx,0006h
453 ;; mov dx,0180h
454 ;; pushf
455 ;; call <direct far>
456 ;;
457 ;; and use <direct far> as the new vector for int 13. The code above is
458 ;; used to load the boot code into ram, and there should be no reason
459 ;; for anybody to change it now or in the future. There are no opcodes
460 ;; that use encodings relativ to IP, so scanning is easy. If we find the
461 ;; code above in the BIOS code we can be pretty sure to run on a machine
462 ;; with an broken AWARD BIOS ...
463 ;;
464 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
465 ;;
466 %ifdef DEBUG_MESSAGES ;;
467 ;;
468 award_notice db "Trying BrokenAwardHack first ...",CR,LF,0 ;;
469 award_not_orig db "BAH: Original Int 13 vector : ",0 ;;
470 award_not_new db "BAH: Int 13 vector changed to : ",0 ;;
471 award_not_succ db "BAH: SUCCESS",CR,LF,0 ;;
472 award_not_fail db "BAH: FAILURE" ;;
473 award_not_crlf db CR,LF,0 ;;
474 ;;
475 %endif ;;
476 ;;
477 award_oldint13 dd 0 ;;
478 award_string db 0b8h,1,2,0bbh,0,7ch,0b9h,6,0,0bah,80h,1,09ch,09ah ;;
479 ;;
480 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
481 award_hack: mov si,spec_err_msg ; Moved to this place from
482 call writemsg ; spec_query_faild
483 ;
484 %ifdef DEBUG_MESSAGES ;
485 ;
486 mov si,award_notice ; display our plan
487 call writemsg ;
488 mov si,award_not_orig ; display original int 13
489 call writemsg ; vector
490 %endif ;
491 mov eax,[13h*4] ;
492 mov [award_oldint13],eax ;
493 ;
494 %ifdef DEBUG_MESSAGES ;
495 ;
496 call writehex8 ;
497 mov si,award_not_crlf ;
498 call writestr ;
499 %endif ;
500 push es ; save ES
501 mov ax,0f000h ; ES = BIOS Seg
502 mov es,ax ;
503 cld ;
504 xor di,di ; start at ES:DI = f000:0
505 award_loop: push di ; save DI
506 mov si,award_string ; scan for award_string
507 mov cx,7 ; length of award_string = 7dw
508 repz cmpsw ; compare
509 pop di ; restore DI
510 jcxz award_found ; jmp if found
511 inc di ; not found, inc di
512 jno award_loop ;
513 ;
514 award_failed: pop es ; No, not this way :-((
515 award_fail2: ;
516 ;
517 %ifdef DEBUG_MESSAGES ;
518 ;
519 mov si,award_not_fail ; display failure ...
520 call writemsg ;
521 %endif ;
522 mov eax,[award_oldint13] ; restore the original int
523 or eax,eax ; 13 vector if there is one
524 jz spec_query_failed ; and try other workarounds
525 mov [13h*4],eax ;
526 jmp spec_query_failed ;
527 ;
528 award_found: mov eax,[es:di+0eh] ; load possible int 13 addr
529 pop es ; restore ES
530 ;
531 cmp eax,[award_oldint13] ; give up if this is the
532 jz award_failed ; active int 13 vector,
533 mov [13h*4],eax ; otherwise change 0:13h*4
534 ;
535 ;
536 %ifdef DEBUG_MESSAGES ;
537 ;
538 push eax ; display message and
539 mov si,award_not_new ; new vector address
540 call writemsg ;
541 pop eax ;
542 call writehex8 ;
543 mov si,award_not_crlf ;
544 call writestr ;
545 %endif ;
546 mov ax,4B01h ; try to read the spec packet
547 mov dl,[DriveNo] ; now ... it should not fail
548 mov si,spec_packet ; any longer
549 int 13h ;
550 jc award_fail2 ;
551 ;
552 %ifdef DEBUG_MESSAGES ;
553 ;
554 mov si,award_not_succ ; display our SUCCESS
555 call writemsg ;
556 %endif ;
557 jmp found_drive ; and leave error recovery code
558 ;
559 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
560 ;; End of BrokenAwardHack ---- 10-nov-2002 Knut_Petersen@t-online.de
561 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
562
563
564 ; INT 13h, AX=4B01h, DL=<passed in value> failed.
565 ; Try to scan the entire 80h-FFh from the end.
566
567 spec_query_failed:
568
569 ; some code moved to BrokenAwardHack
570
571 mov dl,0FFh
572 .test_loop: pusha
573 mov ax,4B01h
574 mov si,spec_packet
575 mov byte [si],13 ; Size of buffer
576 int 13h
577 popa
578 jc .still_broken
579
580 mov si,maybe_msg
581 call writemsg
582 mov al,dl
583 call writehex2
584 call crlf
585
586 cmp byte [sp_drive],dl
587 jne .maybe_broken
588
589 ; Okay, good enough...
590 mov si,alright_msg
591 call writemsg
592 mov [DriveNo],dl
593 .found_drive: jmp found_drive
594
595 ; Award BIOS 4.51 apparently passes garbage in sp_drive,
596 ; but if this was the drive number originally passed in
597 ; DL then consider it "good enough"
598 .maybe_broken:
599 cmp byte [DriveNo],dl
600 je .found_drive
601
602 .still_broken: dec dx
603 cmp dl, 80h
604 jnb .test_loop
605
606 ; No spec packet anywhere. Some particularly pathetic
607 ; BIOSes apparently don't even implement function
608 ; 4B01h, so we can't query a spec packet no matter
609 ; what. If we got a drive number in DL, then try to
610 ; use it, and if it works, then well...
611 mov dl,[DriveNo]
612 cmp dl,81h ; Should be 81-FF at least
613 jb fatal_error ; If not, it's hopeless
614
615 ; Write a warning to indicate we're on *very* thin ice now
616 mov si,nospec_msg
617 call writemsg
618 mov al,dl
619 call writehex2
620 call crlf
621 mov si,trysbm_msg
622 call writemsg
623 jmp .found_drive ; Pray that this works...
624
625 fatal_error:
626 mov si,nothing_msg
627 call writemsg
628
629 .norge: jmp short .norge
630
631 ; Information message (DS:SI) output
632 ; Prefix with "isolinux: "
633 ;
634 writemsg: push ax
635 push si
636 mov si,isolinux_str
637 call writestr
638 pop si
639 call writestr
640 pop ax
641 ret
642
643 ;
644 ; Write a character to the screen. There is a more "sophisticated"
645 ; version of this in the subsequent code, so we patch the pointer
646 ; when appropriate.
647 ;
648
649 writechr:
650 jmp near writechr_simple ; 3-byte jump
651
652 writechr_simple:
653 pushfd
654 pushad
655 mov ah,0Eh
656 xor bx,bx
657 int 10h
658 popad
659 popfd
660 ret
661
662 ;
663 ; Get one sector. Convenience entry point.
664 ;
665 getonesec:
666 mov bp,1
667 ; Fall through to getlinsec
668
669 ;
670 ; Get linear sectors - EBIOS LBA addressing, 2048-byte sectors.
671 ;
672 ; Note that we can't always do this as a single request, because at least
673 ; Phoenix BIOSes has a 127-sector limit. To be on the safe side, stick
674 ; to 32 sectors (64K) per request.
675 ;
676 ; Input:
677 ; EAX - Linear sector number
678 ; ES:BX - Target buffer
679 ; BP - Sector count
680 ;
681 getlinsec:
682 mov si,dapa ; Load up the DAPA
683 mov [si+4],bx
684 mov bx,es
685 mov [si+6],bx
686 mov [si+8],eax
687 .loop:
688 push bp ; Sectors left
689 cmp bp,[MaxTransfer]
690 jbe .bp_ok
691 mov bp,[MaxTransfer]
692 .bp_ok:
693 mov [si+2],bp
694 push si
695 mov dl,[DriveNo]
696 mov ah,42h ; Extended Read
697 call xint13
698 pop si
699 pop bp
700 movzx eax,word [si+2] ; Sectors we read
701 add [si+8],eax ; Advance sector pointer
702 sub bp,ax ; Sectors left
703 shl ax,SECTOR_SHIFT-4 ; 2048-byte sectors -> segment
704 add [si+6],ax ; Advance buffer pointer
705 and bp,bp
706 jnz .loop
707 mov eax,[si+8] ; Next sector
708 ret
709
710 ; INT 13h with retry
711 xint13: mov byte [RetryCount],retry_count
712 .try: pushad
713 int 13h
714 jc .error
715 add sp,byte 8*4 ; Clean up stack
716 ret
717 .error:
718 mov [DiskError],ah ; Save error code
719 popad
720 mov [DiskSys],ax ; Save system call number
721 dec byte [RetryCount]
722 jz .real_error
723 push ax
724 mov al,[RetryCount]
725 mov ah,[dapa+2] ; Sector transfer count
726 cmp al,2 ; Only 2 attempts left
727 ja .nodanger
728 mov ah,1 ; Drop transfer size to 1
729 jmp short .setsize
730 .nodanger:
731 cmp al,retry_count-2
732 ja .again ; First time, just try again
733 shr ah,1 ; Otherwise, try to reduce
734 adc ah,0 ; the max transfer size, but not to 0
735 .setsize:
736 mov [MaxTransfer],ah
737 mov [dapa+2],ah
738 .again:
739 pop ax
740 jmp .try
741
742 .real_error: mov si,diskerr_msg
743 call writemsg
744 mov al,[DiskError]
745 call writehex2
746 mov si,oncall_str
747 call writestr
748 mov ax,[DiskSys]
749 call writehex4
750 mov si,ondrive_str
751 call writestr
752 mov al,dl
753 call writehex2
754 call crlf
755 ; Fall through to kaboom
756
757 ;
758 ; kaboom: write a message and bail out. Wait for a user keypress,
759 ; then do a hard reboot.
760 ;
761 kaboom:
762 lss sp,[cs:StackPtr]
763 mov ax,cs
764 mov ds,ax
765 mov es,ax
766 mov fs,ax
767 mov gs,ax
768 sti
769 mov si,err_bootfailed
770 call cwritestr
771 call getchar
772 cli
773 mov word [BIOS_magic],0 ; Cold reboot
774 jmp 0F000h:0FFF0h ; Reset vector address
775
776 ; -----------------------------------------------------------------------------
777 ; Common modules needed in the first sector
778 ; -----------------------------------------------------------------------------
779
780 %include "writestr.inc" ; String output
781 writestr equ cwritestr
782 %include "writehex.inc" ; Hexadecimal output
783
784 ; -----------------------------------------------------------------------------
785 ; Data that needs to be in the first sector
786 ; -----------------------------------------------------------------------------
787
788 syslinux_banner db CR, LF, 'ISOLINUX ', version_str, ' ', date, ' ', 0
789 copyright_str db ' Copyright (C) 1994-', year, ' H. Peter Anvin'
790 db CR, LF, 0
791 isolinux_str db 'isolinux: ', 0
792 %ifdef DEBUG_MESSAGES
793 startup_msg: db 'Starting up, DL = ', 0
794 spec_ok_msg: db 'Loaded spec packet OK, drive = ', 0
795 secsize_msg: db 'Sector size appears to be ', 0
796 offset_msg: db 'Loading main image from LBA = ', 0
797 size_msg: db 'Sectors to load = ', 0
798 loaded_msg: db 'Loaded boot image, verifying...', CR, LF, 0
799 verify_msg: db 'Image checksum verified.', CR, LF, 0
800 allread_msg db 'Main image read, jumping to main code...', CR, LF, 0
801 %endif
802 noinfotable_msg db 'No boot info table, assuming single session disk...', CR, LF, 0
803 noinfoinspec_msg db 'Spec packet missing LBA information, trying to wing it...', CR, LF, 0
804 spec_err_msg: db 'Loading spec packet failed, trying to wing it...', CR, LF, 0
805 maybe_msg: db 'Found something at drive = ', 0
806 alright_msg: db 'Looks like it might be right, continuing...', CR, LF, 0
807 nospec_msg db 'Extremely broken BIOS detected, last ditch attempt with drive = ', 0
808 nothing_msg: db 'Failed to locate CD-ROM device; boot failed.', CR, LF
809 trysbm_msg db 'See http://syslinux.zytor.com/sbm for more information.', CR, LF, 0
810 diskerr_msg: db 'Disk error ', 0
811 oncall_str: db ', AX = ',0
812 ondrive_str: db ', drive ', 0
813 checkerr_msg: db 'Image checksum error, sorry...', CR, LF, 0
814
815 err_bootfailed db CR, LF, 'Boot failed: press a key to retry...'
816 bailmsg equ err_bootfailed
817 crlf_msg db CR, LF
818 null_msg db 0
819
820 alignb 4, db 0
821 StackPtr dw StackBuf, 0 ; SS:SP for stack reset
822 MaxTransfer dw 32 ; Max sectors per transfer
823
824 rl_checkpt equ $ ; Must be <= 800h
825
826 rl_checkpt_off equ ($-$$)
827 ;%ifndef DEPEND
828 ;%if rl_checkpt_off > 0x800
829 ;%error "Sector 0 overflow"
830 ;%endif
831 ;%endif
832
833 ; ----------------------------------------------------------------------------
834 ; End of code and data that have to be in the first sector
835 ; ----------------------------------------------------------------------------
836
837 all_read:
838 ;
839 ; Initialize screen (if we're using one)
840 ;
841 ; Now set up screen parameters
842 call adjust_screen
843
844 ; Wipe the F-key area
845 mov al,NULLFILE
846 mov di,FKeyName
847 mov cx,10*(1 << FILENAME_MAX_LG2)
848 rep stosb
849
850 ; Patch the writechr routine to point to the full code
851 mov word [writechr+1], writechr_full-(writechr+3)
852
853 ; Tell the user we got this far...
854 %ifndef DEBUG_MESSAGES ; Gets messy with debugging on
855 mov si,copyright_str
856 call writestr
857 %endif
858
859 ; Test tracers
860 TRACER 'T'
861 TRACER '>'
862
863 ;
864 ; Common initialization code
865 ;
866 %include "init.inc"
867 %include "cpuinit.inc"
868
869 ;
870 ; Now we're all set to start with our *real* business. First load the
871 ; configuration file (if any) and parse it.
872 ;
873 ; In previous versions I avoided using 32-bit registers because of a
874 ; rumour some BIOSes clobbered the upper half of 32-bit registers at
875 ; random. I figure, though, that if there are any of those still left
876 ; they probably won't be trying to install Linux on them...
877 ;
878 ; The code is still ripe with 16-bitisms, though. Not worth the hassle
879 ; to take'm out. In fact, we may want to put them back if we're going
880 ; to boot ELKS at some point.
881 ;
882
883 ;
884 ; Now, we need to sniff out the actual filesystem data structures.
885 ; mkisofs gave us a pointer to the primary volume descriptor
886 ; (which will be at 16 only for a single-session disk!); from the PVD
887 ; we should be able to find the rest of what we need to know.
888 ;
889 get_fs_structures:
890 mov eax,[bi_pvd]
891 mov bx,trackbuf
892 call getonesec
893
894 mov eax,[trackbuf+156+2]
895 mov [RootDir+dir_lba],eax
896 mov [CurDir+dir_lba],eax
897 %ifdef DEBUG_MESSAGES
898 mov si,dbg_rootdir_msg
899 call writemsg
900 call writehex8
901 call crlf
902 %endif
903 mov eax,[trackbuf+156+10]
904 mov [RootDir+dir_len],eax
905 mov [CurDir+dir_len],eax
906 add eax,SECTOR_SIZE-1
907 shr eax,SECTOR_SHIFT
908 mov [RootDir+dir_clust],eax
909 mov [CurDir+dir_clust],eax
910
911 ; Look for an isolinux directory, and if found,
912 ; make it the current directory instead of the root
913 ; directory.
914 mov di,boot_dir ; Search for /boot/isolinux
915 mov al,02h
916 call searchdir_iso
917 jnz .found_dir
918 mov di,isolinux_dir
919 mov al,02h ; Search for /isolinux
920 call searchdir_iso
921 jz .no_isolinux_dir
922 .found_dir:
923 mov [CurDir+dir_len],eax
924 mov eax,[si+file_left]
925 mov [CurDir+dir_clust],eax
926 xor eax,eax ; Free this file pointer entry
927 xchg eax,[si+file_sector]
928 mov [CurDir+dir_lba],eax
929 %ifdef DEBUG_MESSAGES
930 push si
931 mov si,dbg_isodir_msg
932 call writemsg
933 pop si
934 call writehex8
935 call crlf
936 %endif
937 .no_isolinux_dir:
938
939 ;
940 ; Locate the configuration file
941 ;
942 load_config:
943 %ifdef DEBUG_MESSAGES
944 mov si,dbg_config_msg
945 call writemsg
946 %endif
947
948 mov di,isolinux_cfg
949 call open
950 jz no_config_file ; Not found or empty
951
952 %ifdef DEBUG_MESSAGES
953 mov si,dbg_configok_msg
954 call writemsg
955 %endif
956
957 ;
958 ; Now we have the config file open. Parse the config file and
959 ; run the user interface.
960 ;
961 %include "ui.inc"
962
963 ;
964 ; Linux kernel loading code is common.
965 ;
966 %include "runkernel.inc"
967
968 ;
969 ; COMBOOT-loading code
970 ;
971 %include "comboot.inc"
972 %include "com32.inc"
973 %include "cmdline.inc"
974
975 ;
976 ; Boot sector loading code
977 ;
978 %include "bootsect.inc"
979
980 ;
981 ; Enable disk emulation. The kind of disk we emulate is dependent on the size of
982 ; the file: 1200K, 1440K or 2880K floppy, otherwise harddisk.
983 ;
984 is_disk_image:
985 TRACER CR
986 TRACER LF
987 TRACER 'D'
988 TRACER ':'
989
990 shl edx,16
991 mov dx,ax ; Set EDX <- file size
992 mov di,img_table
993 mov cx,img_table_count
994 mov eax,[si+file_sector] ; Starting LBA of file
995 mov [dsp_lba],eax ; Location of file
996 mov byte [dsp_drive], 0 ; 00h floppy, 80h hard disk
997 .search_table:
998 TRACER 't'
999 mov eax,[di+4]
1000 cmp edx,[di]
1001 je .type_found
1002 add di,8
1003 loop .search_table
1004
1005 ; Hard disk image. Need to examine the partition table
1006 ; in order to deduce the C/H/S geometry. Sigh.
1007 .hard_disk_image:
1008 TRACER 'h'
1009 cmp edx,512
1010 jb .bad_image
1011
1012 mov bx,trackbuf
1013 mov cx,1 ; Load 1 sector
1014 call getfssec
1015
1016 cmp word [trackbuf+510],0aa55h ; Boot signature
1017 jne .bad_image ; Image not bootable
1018
1019 mov cx,4 ; 4 partition entries
1020 mov di,trackbuf+446 ; Start of partition table
1021
1022 xor ax,ax ; Highest sector(al) head(ah)
1023
1024 .part_scan:
1025 cmp byte [di+4], 0
1026 jz .part_loop
1027 lea si,[di+1]
1028 call .hs_check
1029 add si,byte 4
1030 call .hs_check
1031 .part_loop:
1032 add di,byte 16
1033 loop .part_scan
1034
1035 push eax ; H/S
1036 push edx ; File size
1037 mov bl,ah
1038 xor bh,bh
1039 inc bx ; # of heads in BX
1040 xor ah,ah ; # of sectors in AX
1041 cwde ; EAX[31:16] <- 0
1042 mul bx
1043 shl eax,9 ; Convert to bytes
1044 ; Now eax contains the number of bytes per cylinder
1045 pop ebx ; File size
1046 xor edx,edx
1047 div ebx
1048 and edx,edx
1049 jz .no_remainder
1050 inc eax ; Fractional cylinder...
1051 ; Now (e)ax contains the number of cylinders
1052 .no_remainder: cmp eax,1024
1053 jna .ok_cyl
1054 mov ax,1024 ; Max possible #
1055 .ok_cyl: dec ax ; Convert to max cylinder no
1056 pop ebx ; S(bl) H(bh)
1057 shl ah,6
1058 or bl,ah
1059 xchg ax,bx
1060 shl eax,16
1061 mov ah,bl
1062 mov al,4 ; Hard disk boot
1063 mov byte [dsp_drive], 80h ; Drive 80h = hard disk
1064
1065 .type_found:
1066 TRACER 'T'
1067 mov bl,[sp_media]
1068 and bl,0F0h ; Copy controller info bits
1069 or al,bl
1070 mov [dsp_media],al ; Emulation type
1071 shr eax,8
1072 mov [dsp_chs],eax ; C/H/S geometry
1073 mov ax,[sp_devspec] ; Copy device spec
1074 mov [dsp_devspec],ax
1075 mov al,[sp_controller] ; Copy controller index
1076 mov [dsp_controller],al
1077
1078 TRACER 'V'
1079 call vgaclearmode ; Reset video
1080
1081 mov ax,4C00h ; Enable emulation and boot
1082 mov si,dspec_packet
1083 mov dl,[DriveNo]
1084 lss sp,[InitStack]
1085 TRACER 'X'
1086
1087 int 13h
1088
1089 ; If this returns, we have problems
1090 .bad_image:
1091 mov si,err_disk_image
1092 call cwritestr
1093 jmp enter_command
1094
1095 ;
1096 ; Look for the highest seen H/S geometry
1097 ; We compute cylinders separately
1098 ;
1099 .hs_check:
1100 mov bl,[si] ; Head #
1101 cmp bl,ah
1102 jna .done_track
1103 mov ah,bl ; New highest head #
1104 .done_track: mov bl,[si+1]
1105 and bl,3Fh ; Sector #
1106 cmp bl,al
1107 jna .done_sector
1108 mov al,bl
1109 .done_sector: ret
1110
1111 ;
1112 ; Boot a specified local disk. AX specifies the BIOS disk number; or
1113 ; 0xFFFF in case we should execute INT 18h ("next device.")
1114 ;
1115 local_boot:
1116 call vgaclearmode
1117 lss sp,[cs:Stack] ; Restore stack pointer
1118 xor dx,dx
1119 mov ds,dx
1120 mov es,dx
1121 mov fs,dx
1122 mov gs,dx
1123 mov si,localboot_msg
1124 call writestr
1125 cmp ax,-1
1126 je .int18
1127
1128 ; Load boot sector from the specified BIOS device and jump to it.
1129 mov dl,al
1130 xor dh,dh
1131 push dx
1132 xor ax,ax ; Reset drive
1133 call xint13
1134 mov ax,0201h ; Read one sector
1135 mov cx,0001h ; C/H/S = 0/0/1 (first sector)
1136 mov bx,trackbuf
1137 call xint13
1138 pop dx
1139 cli ; Abandon hope, ye who enter here
1140 mov si,trackbuf
1141 mov di,07C00h
1142 mov cx,512 ; Probably overkill, but should be safe
1143 rep movsd
1144 lss sp,[cs:InitStack]
1145 jmp 0:07C00h ; Jump to new boot sector
1146
1147 .int18:
1148 int 18h ; Hope this does the right thing...
1149 jmp kaboom ; If we returned, oh boy...
1150
1151 ;
1152 ; Abort loading code
1153 ;
1154 %include "abort.inc"
1155
1156 ;
1157 ; searchdir:
1158 ;
1159 ; Open a file
1160 ;
1161 ; On entry:
1162 ; DS:DI = filename
1163 ; If successful:
1164 ; ZF clear
1165 ; SI = file pointer
1166 ; DX:AX or EAX = file length in bytes
1167 ; If unsuccessful
1168 ; ZF set
1169 ;
1170 ; Assumes CS == DS == ES, and trashes BX and CX.
1171 ;
1172 ; searchdir_iso is a special entry point for ISOLINUX only. In addition
1173 ; to the above, searchdir_iso passes a file flag mask in AL. This is useful
1174 ; for searching for directories.
1175 ;
1176 alloc_failure:
1177 xor ax,ax ; ZF <- 1
1178 ret
1179
1180 searchdir:
1181 xor al,al
1182 searchdir_iso:
1183 mov [ISOFlags],al
1184 TRACER 'S'
1185 call allocate_file ; Temporary file structure for directory
1186 jnz alloc_failure
1187 push es
1188 push ds
1189 pop es ; ES = DS
1190 mov si,CurDir
1191 cmp byte [di],'/' ; If filename begins with slash
1192 jne .not_rooted
1193 inc di ; Skip leading slash
1194 mov si,RootDir ; Reference root directory instead
1195 .not_rooted:
1196 mov eax,[si+dir_clust]
1197 mov [bx+file_left],eax
1198 mov eax,[si+dir_lba]
1199 mov [bx+file_sector],eax
1200 mov edx,[si+dir_len]
1201
1202 .look_for_slash:
1203 mov ax,di
1204 .scan:
1205 mov cl,[di]
1206 inc di
1207 and cl,cl
1208 jz .isfile
1209 cmp cl,'/'
1210 jne .scan
1211 mov [di-1],byte 0 ; Terminate at directory name
1212 mov cl,02h ; Search for directory
1213 xchg cl,[ISOFlags]
1214
1215 push di ; Save these...
1216 push cx
1217
1218 ; Create recursion stack frame...
1219 push word .resume ; Where to "return" to
1220 push es
1221 .isfile: xchg ax,di
1222
1223 .getsome:
1224 ; Get a chunk of the directory
1225 ; This relies on the fact that ISOLINUX doesn't change SI
1226 mov si,trackbuf
1227 TRACER 'g'
1228 pushad
1229 xchg bx,si
1230 mov cx,[BufSafe]
1231 call getfssec
1232 popad
1233
1234 .compare:
1235 movzx eax,byte [si] ; Length of directory entry
1236 cmp al,33
1237 jb .next_sector
1238 TRACER 'c'
1239 mov cl,[si+25]
1240 xor cl,[ISOFlags]
1241 test cl, byte 8Eh ; Unwanted file attributes!
1242 jnz .not_file
1243 pusha
1244 movzx cx,byte [si+32] ; File identifier length
1245 add si,byte 33 ; File identifier offset
1246 TRACER 'i'
1247 call iso_compare_names
1248 popa
1249 je .success
1250 .not_file:
1251 sub edx,eax ; Decrease bytes left
1252 jbe .failure
1253 add si,ax ; Advance pointer
1254
1255 .check_overrun:
1256 ; Did we finish the buffer?
1257 cmp si,trackbuf+trackbufsize
1258 jb .compare ; No, keep going
1259
1260 jmp short .getsome ; Get some more directory
1261
1262 .next_sector:
1263 ; Advance to the beginning of next sector
1264 lea ax,[si+SECTOR_SIZE-1]
1265 and ax,~(SECTOR_SIZE-1)
1266 sub ax,si
1267 jmp short .not_file ; We still need to do length checks
1268
1269 .failure: xor eax,eax ; ZF = 1
1270 mov [bx+file_sector],eax
1271 pop es
1272 ret
1273
1274 .success:
1275 mov eax,[si+2] ; Location of extent
1276 mov [bx+file_sector],eax
1277 mov eax,[si+10] ; Data length
1278 push eax
1279 add eax,SECTOR_SIZE-1
1280 shr eax,SECTOR_SHIFT
1281 mov [bx+file_left],eax
1282 pop eax
1283 mov edx,eax
1284 shr edx,16
1285 and bx,bx ; ZF = 0
1286 mov si,bx
1287 pop es
1288 ret
1289
1290 .resume: ; We get here if we were only doing part of a lookup
1291 ; This relies on the fact that .success returns bx == si
1292 xchg edx,eax ; Directory length in edx
1293 pop cx ; Old ISOFlags
1294 pop di ; Next filename pointer
1295 mov byte [di-1], '/' ; Restore slash
1296 mov [ISOFlags],cl ; Restore the flags
1297 jz .failure ; Did we fail? If so fail for real!
1298 jmp .look_for_slash ; Otherwise, next level
1299
1300 ;
1301 ; allocate_file: Allocate a file structure
1302 ;
1303 ; If successful:
1304 ; ZF set
1305 ; BX = file pointer
1306 ; In unsuccessful:
1307 ; ZF clear
1308 ;
1309 allocate_file:
1310 TRACER 'a'
1311 push cx
1312 mov bx,Files
1313 mov cx,MAX_OPEN
1314 .check: cmp dword [bx], byte 0
1315 je .found
1316 add bx,open_file_t_size ; ZF = 0
1317 loop .check
1318 ; ZF = 0 if we fell out of the loop
1319 .found: pop cx
1320 ret
1321
1322 ;
1323 ; iso_compare_names:
1324 ; Compare the names DS:SI and DS:DI and report if they are
1325 ; equal from an ISO 9660 perspective. SI is the name from
1326 ; the filesystem; CX indicates its length, and ';' terminates.
1327 ; DI is expected to end with a null.
1328 ;
1329 ; Note: clobbers AX, CX, SI, DI; assumes DS == ES == base segment
1330 ;
1331
1332 iso_compare_names:
1333 ; First, terminate and canonicalize input filename
1334 push di
1335 mov di,ISOFileName
1336 .canon_loop: jcxz .canon_end
1337 lodsb
1338 dec cx
1339 cmp al,';'
1340 je .canon_end
1341 and al,al
1342 je .canon_end
1343 stosb
1344 cmp di,ISOFileNameEnd-1 ; Guard against buffer overrun
1345 jb .canon_loop
1346 .canon_end:
1347 cmp di,ISOFileName
1348 jbe .canon_done
1349 cmp byte [di-1],'.' ; Remove terminal dots
1350 jne .canon_done
1351 dec di
1352 jmp short .canon_end
1353 .canon_done:
1354 mov [di],byte 0 ; Null-terminate string
1355 pop di
1356 mov si,ISOFileName
1357 .compare:
1358 lodsb
1359 mov ah,[di]
1360 inc di
1361 and ax,ax
1362 jz .success ; End of string for both
1363 and al,al ; Is either one end of string?
1364 jz .failure ; If so, failure
1365 and ah,ah
1366 jz .failure
1367 or ax,2020h ; Convert to lower case
1368 cmp al,ah
1369 je .compare
1370 .failure: and ax,ax ; ZF = 0 (at least one will be nonzero)
1371 .success: ret
1372
1373 ;
1374 ; mangle_name: Mangle a filename pointed to by DS:SI into a buffer pointed
1375 ; to by ES:DI; ends on encountering any whitespace.
1376 ;
1377 ; This verifies that a filename is < FILENAME_MAX characters,
1378 ; doesn't contain whitespace, zero-pads the output buffer,
1379 ; and removes trailing dots and redundant slashes,
1380 ; so "repe cmpsb" can do a compare, and the
1381 ; path-searching routine gets a bit of an easier job.
1382 ;
1383 mangle_name:
1384 push bx
1385 xor ax,ax
1386 mov cx,FILENAME_MAX-1
1387 mov bx,di
1388
1389 .mn_loop:
1390 lodsb
1391 cmp al,' ' ; If control or space, end
1392 jna .mn_end
1393 cmp al,ah ; Repeated slash?
1394 je .mn_skip
1395 xor ah,ah
1396 cmp al,'/'
1397 jne .mn_ok
1398 mov ah,al
1399 .mn_ok stosb
1400 .mn_skip: loop .mn_loop
1401 .mn_end:
1402 cmp bx,di ; At the beginning of the buffer?
1403 jbe .mn_zero
1404 cmp byte [di-1],'.' ; Terminal dot?
1405 je .mn_kill
1406 cmp byte [di-1],'/' ; Terminal slash?
1407 jne .mn_zero
1408 .mn_kill: dec di ; If so, remove it
1409 inc cx
1410 jmp short .mn_end
1411 .mn_zero:
1412 inc cx ; At least one null byte
1413 xor ax,ax ; Zero-fill name
1414 rep stosb
1415 pop bx
1416 ret ; Done
1417
1418 ;
1419 ; unmangle_name: Does the opposite of mangle_name; converts a DOS-mangled
1420 ; filename to the conventional representation. This is needed
1421 ; for the BOOT_IMAGE= parameter for the kernel.
1422 ; NOTE: A 13-byte buffer is mandatory, even if the string is
1423 ; known to be shorter.
1424 ;
1425 ; DS:SI -> input mangled file name
1426 ; ES:DI -> output buffer
1427 ;
1428 ; On return, DI points to the first byte after the output name,
1429 ; which is set to a null byte.
1430 ;
1431 unmangle_name: call strcpy
1432 dec di ; Point to final null byte
1433 ret
1434
1435 ;
1436 ; getfssec: Get multiple clusters from a file, given the file pointer.
1437 ;
1438 ; On entry:
1439 ; ES:BX -> Buffer
1440 ; SI -> File pointer
1441 ; CX -> Cluster count
1442 ; On exit:
1443 ; SI -> File pointer (or 0 on EOF)
1444 ; CF = 1 -> Hit EOF
1445 ;
1446 getfssec:
1447 TRACER 'F'
1448
1449 push ds
1450 push cs
1451 pop ds ; DS <- CS
1452
1453 movzx ecx,cx
1454 cmp ecx,[si+file_left]
1455 jna .ok_size
1456 mov ecx,[si+file_left]
1457 .ok_size:
1458
1459 mov bp,cx
1460 push cx
1461 push si
1462 mov eax,[si+file_sector]
1463 TRACER 'l'
1464 call getlinsec
1465 xor ecx,ecx
1466 pop si
1467 pop cx
1468
1469 add [si+file_sector],ecx
1470 sub [si+file_left],ecx
1471 ja .not_eof ; CF = 0
1472
1473 xor ecx,ecx
1474 mov [si+file_sector],ecx ; Mark as unused
1475 xor si,si
1476 stc
1477
1478 .not_eof:
1479 pop ds
1480 TRACER 'f'
1481 ret
1482
1483 ; -----------------------------------------------------------------------------
1484 ; Common modules
1485 ; -----------------------------------------------------------------------------
1486
1487 %include "getc.inc" ; getc et al
1488 %include "conio.inc" ; Console I/O
1489 %include "parseconfig.inc" ; High-level config file handling
1490 %include "parsecmd.inc" ; Low-level config file handling
1491 %include "bcopy32.inc" ; 32-bit bcopy
1492 %include "loadhigh.inc" ; Load a file into high memory
1493 %include "font.inc" ; VGA font stuff
1494 %include "graphics.inc" ; VGA graphics
1495 %include "highmem.inc" ; High memory sizing
1496 %include "strcpy.inc" ; strcpy()
1497 %include "rawcon.inc" ; Console I/O w/o using the console functions
1498
1499 ; -----------------------------------------------------------------------------
1500 ; Begin data section
1501 ; -----------------------------------------------------------------------------
1502
1503 section .data
1504
1505 boot_prompt db 'boot: ', 0
1506 wipe_char db BS, ' ', BS, 0
1507 err_notfound db 'Could not find kernel image: ',0
1508 err_notkernel db CR, LF, 'Invalid or corrupt kernel image.', CR, LF, 0
1509 err_noram db 'It appears your computer has less than '
1510 asciidec dosram_k
1511 db 'K of low ("DOS")'
1512 db CR, LF
1513 db 'RAM. Linux needs at least this amount to boot. If you get'
1514 db CR, LF
1515 db 'this message in error, hold down the Ctrl key while'
1516 db CR, LF
1517 db 'booting, and I will take your word for it.', CR, LF, 0
1518 err_badcfg db 'Unknown keyword in config file.', CR, LF, 0
1519 err_noparm db 'Missing parameter in config file.', CR, LF, 0
1520 err_noinitrd db CR, LF, 'Could not find ramdisk image: ', 0
1521 err_nohighmem db 'Not enough memory to load specified kernel.', CR, LF, 0
1522 err_highload db CR, LF, 'Kernel transfer failure.', CR, LF, 0
1523 err_oldkernel db 'Cannot load a ramdisk with an old kernel image.'
1524 db CR, LF, 0
1525 err_notdos db ': attempted DOS system call', CR, LF, 0
1526 err_comlarge db 'COMBOOT image too large.', CR, LF, 0
1527 err_bssimage db 'BSS images not supported.', CR, LF, 0
1528 err_a20 db CR, LF, 'A20 gate not responding!', CR, LF, 0
1529 notfound_msg db 'not found', CR, LF, 0
1530 localboot_msg db 'Booting from local disk...', CR, LF, 0
1531 cmdline_msg db 'Command line: ', CR, LF, 0
1532 ready_msg db 'Ready.', CR, LF, 0
1533 trying_msg db 'Trying to load: ', 0
1534 crlfloading_msg db CR, LF ; Fall through
1535 loading_msg db 'Loading ', 0
1536 dotdot_msg db '.'
1537 dot_msg db '.', 0
1538 fourbs_msg db BS, BS, BS, BS, 0
1539 aborted_msg db ' aborted.', CR, LF, 0
1540 crff_msg db CR, FF, 0
1541 default_str db 'default', 0
1542 default_len equ ($-default_str)
1543 boot_dir db '/boot' ; /boot/isolinux
1544 isolinux_dir db '/isolinux', 0
1545 ConfigName equ $
1546 isolinux_cfg db 'isolinux.cfg', 0
1547 err_disk_image db 'Cannot load disk image (invalid file)?', CR, LF, 0
1548
1549 %ifdef DEBUG_MESSAGES
1550 dbg_rootdir_msg db 'Root directory at LBA = ', 0
1551 dbg_isodir_msg db 'isolinux directory at LBA = ', 0
1552 dbg_config_msg db 'About to load config file...', CR, LF, 0
1553 dbg_configok_msg db 'Configuration file opened...', CR, LF, 0
1554 %endif
1555 ;
1556 ; Command line options we'd like to take a look at
1557 ;
1558 ; mem= and vga= are handled as normal 32-bit integer values
1559 initrd_cmd db 'initrd='
1560 initrd_cmd_len equ 7
1561
1562 ;
1563 ; Config file keyword table
1564 ;
1565 %include "keywords.inc"
1566
1567 ;
1568 ; Extensions to search for (in *forward* order).
1569 ;
1570 align 4, db 0
1571 exten_table: db '.cbt' ; COMBOOT (specific)
1572 db '.img' ; Disk image
1573 db '.bin' ; CD boot sector
1574 db '.com' ; COMBOOT (same as DOS)
1575 db '.c32' ; COM32
1576 exten_table_end:
1577 dd 0, 0 ; Need 8 null bytes here
1578
1579 ;
1580 ; Floppy image table
1581 ;
1582 align 4, db 0
1583 img_table_count equ 3
1584 img_table:
1585 dd 1200*1024 ; 1200K floppy
1586 db 1 ; Emulation type
1587 db 80-1 ; Max cylinder
1588 db 15 ; Max sector
1589 db 2-1 ; Max head
1590
1591 dd 1440*1024 ; 1440K floppy
1592 db 2 ; Emulation type
1593 db 80-1 ; Max cylinder
1594 db 18 ; Max sector
1595 db 2-1 ; Max head
1596
1597 dd 2880*1024 ; 2880K floppy
1598 db 3 ; Emulation type
1599 db 80-1 ; Max cylinder
1600 db 36 ; Max sector
1601 db 2-1 ; Max head
1602
1603 ;
1604 ; Misc initialized (data) variables
1605 ;
1606
1607 ;
1608 ; Variables that are uninitialized in SYSLINUX but initialized here
1609 ;
1610 ; **** ISOLINUX:: We may have to make this flexible, based on what the
1611 ; **** BIOS expects our "sector size" to be.
1612 ;
1613 alignb 4, db 0
1614 BufSafe dw trackbufsize/SECTOR_SIZE ; Clusters we can load into trackbuf
1615 BufSafeSec dw trackbufsize/SECTOR_SIZE ; = how many sectors?
1616 BufSafeBytes dw trackbufsize ; = how many bytes?
1617 EndOfGetCBuf dw getcbuf+trackbufsize ; = getcbuf+BufSafeBytes
1618 %ifndef DEPEND
1619 %if ( trackbufsize % SECTOR_SIZE ) != 0
1620 %error trackbufsize must be a multiple of SECTOR_SIZE
1621 %endif
1622 %endif