Try falling back to CBIOS if EBIOS totally fails.
[profile/ivi/syslinux.git] / ldlinux.asm
1 ; -*- fundamental -*- (asm-mode sucks)
2 ; $Id$
3 ; ****************************************************************************
4 ;
5 ;  ldlinux.asm
6 ;
7 ;  A program to boot Linux kernels off an MS-DOS formatted floppy disk.  This
8 ;  functionality is good to have for installation floppies, where it may
9 ;  be hard to find a functional Linux system to run LILO off.
10 ;
11 ;  This program allows manipulation of the disk to take place entirely
12 ;  from MS-LOSS, and can be especially useful in conjunction with the
13 ;  umsdos filesystem.
14 ;
15 ;   Copyright (C) 1994-2005  H. Peter Anvin
16 ;
17 ;  This program is free software; you can redistribute it and/or modify
18 ;  it under the terms of the GNU General Public License as published by
19 ;  the Free Software Foundation, Inc., 53 Temple Place Ste 330,
20 ;  Boston MA 02111-1307, USA; either version 2 of the License, or
21 ;  (at your option) any later version; incorporated herein by reference.
22
23 ; ****************************************************************************
24
25 %ifndef IS_MDSLINUX
26 %define IS_SYSLINUX 1
27 %endif
28 %include "macros.inc"
29 %include "config.inc"
30 %include "kernel.inc"
31 %include "bios.inc"
32 %include "tracers.inc"
33 %include "layout.inc"
34 ;
35 ; Some semi-configurable constants... change on your own risk.
36 ;
37 my_id           equ syslinux_id
38 FILENAME_MAX_LG2 equ 4                  ; log2(Max filename size Including final null)
39 FILENAME_MAX    equ 11                  ; Max mangled filename size
40 NULLFILE        equ ' '                 ; First char space == null filename
41 NULLOFFSET      equ 0                   ; Position in which to look
42 retry_count     equ 16                  ; How patient are we with the disk?
43 %assign HIGHMEM_SLOP 0                  ; Avoid this much memory near the top
44 LDLINUX_MAGIC   equ 0x3eb202fe          ; A random number to identify ourselves with
45
46 MAX_OPEN_LG2    equ 6                   ; log2(Max number of open files)
47 MAX_OPEN        equ (1 << MAX_OPEN_LG2)
48
49 SECTOR_SHIFT    equ 9
50 SECTOR_SIZE     equ (1 << SECTOR_SHIFT)
51
52 ;
53 ; This is what we need to do when idle
54 ;
55 %macro  RESET_IDLE 0
56         ; Nothing
57 %endmacro
58 %macro  DO_IDLE 0
59         ; Nothing
60 %endmacro
61
62 ;
63 ; The following structure is used for "virtual kernels"; i.e. LILO-style
64 ; option labels.  The options we permit here are `kernel' and `append
65 ; Since there is no room in the bottom 64K for all of these, we
66 ; stick them at vk_seg:0000 and copy them down before we need them.
67 ;
68                 struc vkernel
69 vk_vname:       resb FILENAME_MAX       ; Virtual name **MUST BE FIRST!**
70 vk_rname:       resb FILENAME_MAX       ; Real name
71 vk_appendlen:   resw 1
72                 alignb 4
73 vk_append:      resb max_cmd_len+1      ; Command line
74                 alignb 4
75 vk_end:         equ $                   ; Should be <= vk_size
76                 endstruc
77
78 ;
79 ; Segment assignments in the bottom 640K
80 ; Stick to the low 512K in case we're using something like M-systems flash
81 ; which load a driver into low RAM (evil!!)
82 ;
83 ; 0000h - main code/data segment (and BIOS segment)
84 ;
85 real_mode_seg   equ 4000h
86 cache_seg       equ 3000h               ; 64K area for metadata cache
87 vk_seg          equ 2000h               ; Virtual kernels
88 xfer_buf_seg    equ 1000h               ; Bounce buffer for I/O to high mem
89 comboot_seg     equ real_mode_seg       ; COMBOOT image loading zone
90
91 ;
92 ; File structure.  This holds the information for each currently open file.
93 ;
94                 struc open_file_t
95 file_sector     resd 1                  ; Sector pointer (0 = structure free)
96 file_left       resd 1                  ; Number of sectors left
97                 endstruc
98
99 %ifndef DEPEND
100 %if (open_file_t_size & (open_file_t_size-1))
101 %error "open_file_t is not a power of 2"
102 %endif
103 %endif
104
105 ; ---------------------------------------------------------------------------
106 ;   BEGIN CODE
107 ; ---------------------------------------------------------------------------
108
109 ;
110 ; Memory below this point is reserved for the BIOS and the MBR
111 ;
112                 section .earlybss
113 trackbufsize    equ 8192
114 trackbuf        resb trackbufsize       ; Track buffer goes here
115 getcbuf         resb trackbufsize
116                 ; ends at 4800h
117
118                 section .bss
119                 alignb 8
120
121                 ; Expanded superblock
122 SuperInfo       equ $
123                 resq 16                 ; The first 16 bytes expanded 8 times
124 FAT             resd 1                  ; Location of (first) FAT
125 RootDirArea     resd 1                  ; Location of root directory area
126 RootDir         resd 1                  ; Location of root directory proper
127 DataArea        resd 1                  ; Location of data area
128 RootDirSize     resd 1                  ; Root dir size in sectors
129 TotalSectors    resd 1                  ; Total number of sectors
130 EndSector       resd 1                  ; Location of filesystem end
131 ClustSize       resd 1                  ; Bytes/cluster
132 ClustMask       resd 1                  ; Sectors/cluster - 1
133 CopySuper       resb 1                  ; Distinguish .bs versus .bss
134 DriveNumber     resb 1                  ; BIOS drive number
135 ClustShift      resb 1                  ; Shift count for sectors/cluster
136 ClustByteShift  resb 1                  ; Shift count for bytes/cluster
137
138                 alignb open_file_t_size
139 Files           resb MAX_OPEN*open_file_t_size
140
141 ;
142 ; Constants for the xfer_buf_seg
143 ;
144 ; The xfer_buf_seg is also used to store message file buffers.  We
145 ; need two trackbuffers (text and graphics), plus a work buffer
146 ; for the graphics decompressor.
147 ;
148 xbs_textbuf     equ 0                   ; Also hard-coded, do not change
149 xbs_vgabuf      equ trackbufsize
150 xbs_vgatmpbuf   equ 2*trackbufsize
151
152
153                 section .text
154 ;
155 ; Some of the things that have to be saved very early are saved
156 ; "close" to the initial stack pointer offset, in order to
157 ; reduce the code size...
158 ;
159 StackBuf        equ $-44-32             ; Start the stack here (grow down - 4K)
160 PartInfo        equ StackBuf            ; Saved partition table entry
161 FloppyTable     equ PartInfo+16         ; Floppy info table (must follow PartInfo)
162 OrigFDCTabPtr   equ StackBuf-4          ; The high dword on the stack
163
164 ;
165 ; Primary entry point.  Tempting as though it may be, we can't put the
166 ; initial "cli" here; the jmp opcode in the first byte is part of the
167 ; "magic number" (using the term very loosely) for the DOS superblock.
168 ;
169 bootsec         equ $
170                 jmp short start         ; 2 bytes
171                 nop                     ; 1 byte
172 ;
173 ; "Superblock" follows -- it's in the boot sector, so it's already
174 ; loaded and ready for us
175 ;
176 bsOemName       db 'SYSLINUX'           ; The SYS command sets this, so...
177 ;
178 ; These are the fields we actually care about.  We end up expanding them
179 ; all to dword size early in the code, so generate labels for both
180 ; the expanded and unexpanded versions.
181 ;
182 %macro          superb 1
183 bx %+ %1        equ SuperInfo+($-superblock)*8+4
184 bs %+ %1        equ $
185                 zb 1
186 %endmacro
187 %macro          superw 1
188 bx %+ %1        equ SuperInfo+($-superblock)*8
189 bs %+ %1        equ $
190                 zw 1
191 %endmacro
192 %macro          superd 1
193 bx %+ %1        equ $                   ; no expansion for dwords
194 bs %+ %1        equ $
195                 zd 1
196 %endmacro
197 superblock      equ $
198                 superw BytesPerSec
199                 superb SecPerClust
200                 superw ResSectors
201                 superb FATs
202                 superw RootDirEnts
203                 superw Sectors
204                 superb Media
205                 superw FATsecs
206                 superw SecPerTrack
207                 superw Heads
208 superinfo_size  equ ($-superblock)-1    ; How much to expand
209                 superd Hidden
210                 superd HugeSectors
211                 ;
212                 ; This is as far as FAT12/16 and FAT32 are consistent
213                 ;
214                 zb 54                   ; FAT12/16 need 26 more bytes,
215                                         ; FAT32 need 54 more bytes
216 superblock_len  equ $-superblock
217
218 SecPerClust     equ bxSecPerClust
219 ;
220 ; Note we don't check the constraints above now; we did that at install
221 ; time (we hope!)
222 ;
223 start:
224                 cli                     ; No interrupts yet, please
225                 cld                     ; Copy upwards
226 ;
227 ; Set up the stack
228 ;
229                 xor ax,ax
230                 mov ss,ax
231                 mov sp,StackBuf         ; Just below BSS
232                 mov es,ax
233 ;
234 ; DS:SI may contain a partition table entry.  Preserve it for us.
235 ;
236                 mov cx,8                ; Save partition info
237                 mov di,sp
238                 rep movsw
239
240                 mov ds,ax               ; Now we can initialize DS...
241
242 ;
243 ; Now sautee the BIOS floppy info block to that it will support decent-
244 ; size transfers; the floppy block is 11 bytes and is stored in the
245 ; INT 1Eh vector (brilliant waste of resources, eh?)
246 ;
247 ; Of course, if BIOSes had been properly programmed, we wouldn't have
248 ; had to waste precious space with this code.
249 ;
250                 mov bx,fdctab
251                 lfs si,[bx]             ; FS:SI -> original fdctab
252                 push fs                 ; Save on stack in case we need to bail
253                 push si
254
255                 ; Save the old fdctab even if hard disk so the stack layout
256                 ; is the same.  The instructions above do not change the flags
257                 mov [DriveNumber],dl    ; Save drive number in DL
258                 and dl,dl               ; If floppy disk (00-7F), assume no
259                                         ; partition table
260                 js harddisk
261
262 floppy:
263                 mov cl,6                ; 12 bytes (CX == 0)
264                 ; es:di -> FloppyTable already
265                 ; This should be safe to do now, interrupts are off...
266                 mov [bx],di             ; FloppyTable
267                 mov [bx+2],ax           ; Segment 0
268                 fs rep movsw            ; Faster to move words
269                 mov cl,[bsSecPerTrack]  ; Patch the sector count
270                 mov [di-8],cl
271                 ; AX == 0 here
272                 int 13h                 ; Some BIOSes need this
273
274                 jmp short not_harddisk
275 ;
276 ; The drive number and possibly partition information was passed to us
277 ; by the BIOS or previous boot loader (MBR).  Current "best practice" is to
278 ; trust that rather than what the superblock contains.
279 ;
280 ; Would it be better to zero out bsHidden if we don't have a partition table?
281 ;
282 ; Note: di points to beyond the end of PartInfo
283 ;
284 harddisk:
285                 test byte [di-16],7Fh   ; Sanity check: "active flag" should
286                 jnz no_partition        ; be 00 or 80
287                 mov eax,[di-8]          ; Partition offset (dword)
288                 mov [bsHidden],eax
289 no_partition:
290 ;
291 ; Get disk drive parameters (don't trust the superblock.)  Don't do this for
292 ; floppy drives -- INT 13:08 on floppy drives will (may?) return info about
293 ; what the *drive* supports, not about the *media*.  Fortunately floppy disks
294 ; tend to have a fixed, well-defined geometry which is stored in the superblock.
295 ;
296                 ; DL == drive # still
297                 mov ah,08h
298                 int 13h
299                 jc no_driveparm
300                 and ah,ah
301                 jnz no_driveparm
302                 shr dx,8
303                 inc dx                  ; Contains # of heads - 1
304                 mov [bsHeads],dx
305                 and cx,3fh
306                 mov [bsSecPerTrack],cx
307 no_driveparm:
308 not_harddisk:
309 ;
310 ; Ready to enable interrupts, captain
311 ;
312                 sti
313
314 ;
315 ; Do we have EBIOS (EDD)?
316 ;
317 eddcheck:
318                 mov bx,55AAh
319                 mov ah,41h              ; EDD existence query
320                 mov dl,[DriveNumber]
321                 int 13h
322                 jc .noedd
323                 cmp bx,0AA55h
324                 jne .noedd
325                 test cl,1               ; Extended disk access functionality set
326                 jz .noedd
327                 ;
328                 ; We have EDD support...
329                 ;
330                 mov byte [getlinsec.jmp+1],(getlinsec_ebios-(getlinsec.jmp+2))
331 .noedd:
332
333 ;
334 ; Load the first sector of LDLINUX.SYS; this used to be all proper
335 ; with parsing the superblock and root directory; it doesn't fit
336 ; together with EBIOS support, unfortunately.
337 ;
338                 mov eax,[FirstSector]   ; Sector start
339                 mov bx,ldlinux_sys      ; Where to load it
340                 call getonesec
341                 
342                 ; Some modicum of integrity checking
343                 cmp dword [ldlinux_magic+4],LDLINUX_MAGIC^HEXDATE
344                 jne kaboom
345
346                 ; Go for it...
347                 jmp ldlinux_ent
348
349 ;
350 ; getonesec: get one disk sector
351 ;
352 getonesec:
353                 mov bp,1                ; One sector
354                 ; Fall through
355
356 ;
357 ; getlinsec: load a sequence of BP floppy sector given by the linear sector
358 ;            number in EAX into the buffer at ES:BX.  We try to optimize
359 ;            by loading up to a whole track at a time, but the user
360 ;            is responsible for not crossing a 64K boundary.
361 ;            (Yes, BP is weird for a count, but it was available...)
362 ;
363 ;            On return, BX points to the first byte after the transferred
364 ;            block.
365 ;
366 ;            This routine assumes CS == DS, and trashes most registers.
367 ;
368 ; Stylistic note: use "xchg" instead of "mov" when the source is a register
369 ; that is dead from that point; this saves space.  However, please keep
370 ; the order to dst,src to keep things sane.
371 ;
372 getlinsec:
373                 add eax,[bsHidden]              ; Add partition offset
374                 xor edx,edx                     ; Zero-extend LBA (eventually allow 64 bits)
375
376 .jmp:           jmp strict short getlinsec_cbios
377
378 ;
379 ; getlinsec_ebios:
380 ;
381 ; getlinsec implementation for EBIOS (EDD)
382 ;
383 getlinsec_ebios:
384 .loop:
385                 push bp                         ; Sectors left
386 .retry2:
387                 call maxtrans                   ; Enforce maximum transfer size
388                 movzx edi,bp                    ; Sectors we are about to read
389                 mov cx,retry_count
390 .retry:
391
392                 ; Form DAPA on stack
393                 push edx
394                 push eax
395                 push es
396                 push bx
397                 push di
398                 push word 16
399                 mov si,sp
400                 mov dl,[DriveNumber]
401                 mov ah,42h                      ; Extended Read
402                 push ds
403                 push ss
404                 pop ds                          ; DS <- SS
405                 pushad
406                 int 13h
407                 popad
408                 pop ds
409                 lea sp,[si+16]                  ; Remove DAPA
410                 jc .error
411                 pop bp
412                 add eax,edi                     ; Advance sector pointer
413                 sub bp,di                       ; Sectors left
414                 shl di,SECTOR_SHIFT             ; 512-byte sectors
415                 add bx,di                       ; Advance buffer pointer
416                 and bp,bp
417                 jnz .loop
418
419                 ret
420
421 .error:
422                 ; Some systems seem to get "stuck" in an error state when
423                 ; using EBIOS.  Doesn't happen when using CBIOS, which is
424                 ; good, since some other systems get timeout failures
425                 ; waiting for the floppy disk to spin up.
426
427                 pushad                          ; Try resetting the device
428                 xor ax,ax
429                 int 13h
430                 popad
431                 loop .retry                     ; CX-- and jump if not zero
432
433                 shr word [MaxTransfer],1        ; Reduce the transfer size
434                 jnz .retry2
435
436                 ; Total failure.  Try falling back to CBIOS.
437                 mov byte [getlinsec.jmp+1],(getlinsec_cbios-(getlinsec.jmp+2))
438                 mov byte [MaxTransfer],63       ; Max possibe CBIOS transfer
439
440                 pop bp
441                 ; ... fall through ...
442
443 ;
444 ; getlinsec_cbios:
445 ;
446 ; getlinsec implementation for legacy CBIOS
447 ;
448 getlinsec_cbios:
449 .loop:
450                 push edx
451                 push eax
452                 push bp
453                 push bx
454
455                 movzx esi,word [bsSecPerTrack]
456                 movzx edi,word [bsHeads]
457                 ;
458                 ; Dividing by sectors to get (track,sector): we may have
459                 ; up to 2^18 tracks, so we need to use 32-bit arithmetric.
460                 ;
461                 div esi
462                 xor cx,cx
463                 xchg cx,dx              ; CX <- sector index (0-based)
464                                         ; EDX <- 0
465                 ; eax = track #
466                 div edi                 ; Convert track to head/cyl
467
468                 ; We should test this, but it doesn't fit...
469                 ; cmp eax,1023
470                 ; ja .error
471
472                 ;
473                 ; Now we have AX = cyl, DX = head, CX = sector (0-based),
474                 ; BP = sectors to transfer, SI = bsSecPerTrack,
475                 ; ES:BX = data target
476                 ;
477
478                 call maxtrans                   ; Enforce maximum transfer size
479
480                 ; Must not cross track boundaries, so BP <= SI-CX
481                 sub si,cx
482                 cmp bp,si
483                 jna .bp_ok
484                 mov bp,si
485 .bp_ok: 
486
487                 shl ah,6                ; Because IBM was STOOPID
488                                         ; and thought 8 bits were enough
489                                         ; then thought 10 bits were enough...
490                 inc cx                  ; Sector numbers are 1-based, sigh
491                 or cl,ah
492                 mov ch,al
493                 mov dh,dl
494                 mov dl,[DriveNumber]
495                 xchg ax,bp              ; Sector to transfer count
496                 mov ah,02h              ; Read sectors
497                 mov bp,retry_count
498 .retry:
499                 pushad
500                 int 13h
501                 popad
502                 jc .error
503 .resume:
504                 movzx ecx,al            ; ECX <- sectors transferred
505                 shl ax,SECTOR_SHIFT     ; Convert sectors in AL to bytes in AX
506                 pop bx
507                 add bx,ax
508                 pop bp
509                 pop eax
510                 pop edx
511                 add eax,ecx
512                 sub bp,cx
513                 jnz .loop
514                 ret
515
516 .error:
517                 dec bp
518                 jnz .retry
519
520                 xchg ax,bp              ; Sectors transferred <- 0
521                 shr word [MaxTransfer],1
522                 jnz .resume
523                 ; Fall through to disk_error
524         
525 ;
526 ; kaboom: write a message and bail out.
527 ;
528 disk_error:
529 kaboom:
530                 xor si,si
531                 mov ss,si               
532                 mov sp,StackBuf-4       ; Reset stack
533                 mov ds,si               ; Reset data segment
534                 pop dword [fdctab]      ; Restore FDC table
535 .patch:                                 ; When we have full code, intercept here
536                 mov si,bailmsg
537
538                 ; Write error message, this assumes screen page 0
539 .loop:          lodsb
540                 and al,al
541                 jz .done
542                 mov ah,0Eh              ; Write to screen as TTY
543                 mov bx,0007h            ; Attribute
544                 int 10h
545                 jmp short .loop
546 .done:
547                 cbw                     ; AH <- 0
548                 int 16h                 ; Wait for keypress
549                 int 19h                 ; And try once more to boot...
550 .norge:         jmp short .norge        ; If int 19h returned; this is the end
551
552 ;
553 ; Truncate BP to MaxTransfer
554 ;
555 maxtrans:
556                 cmp bp,[MaxTransfer]
557                 jna .ok
558                 mov bp,[MaxTransfer]
559 .ok:            ret
560
561 ;
562 ; Error message on failure
563 ;
564 bailmsg:        db 'Boot error', 0Dh, 0Ah, 0
565
566                 ; This fails if the boot sector overflows
567                 zb 1F8h-($-$$)
568
569 FirstSector     dd 0xDEADBEEF                   ; Location of sector 1
570 MaxTransfer     dw 0x007F                       ; Max transfer size
571 bootsignature   dw 0AA55h
572
573 ;
574 ; ===========================================================================
575 ;  End of boot sector
576 ; ===========================================================================
577 ;  Start of LDLINUX.SYS
578 ; ===========================================================================
579
580 ldlinux_sys:
581
582 syslinux_banner db 0Dh, 0Ah
583 %if IS_MDSLINUX
584                 db 'MDSLINUX '
585 %else
586                 db 'SYSLINUX '
587 %endif
588                 db version_str, ' ', date, ' ', 0
589                 db 0Dh, 0Ah, 1Ah        ; EOF if we "type" this in DOS
590
591                 align 8, db 0
592 ldlinux_magic   dd LDLINUX_MAGIC
593                 dd LDLINUX_MAGIC^HEXDATE
594
595 ;
596 ; This area is patched by the installer.  It is found by looking for
597 ; LDLINUX_MAGIC, plus 8 bytes.
598 ;
599 patch_area:
600 LDLDwords       dw 0            ; Total dwords starting at ldlinux_sys
601 LDLSectors      dw 0            ; Number of sectors - (bootsec+this sec)
602 CheckSum        dd 0            ; Checksum starting at ldlinux_sys
603                                 ; value = LDLINUX_MAGIC - [sum of dwords]
604
605 ; Space for up to 64 sectors, the theoretical maximum
606 SectorPtrs      times 64 dd 0
607
608 ldlinux_ent:
609
610 ; Note that some BIOSes are buggy and run the boot sector at 07C0:0000
611 ; instead of 0000:7C00 and the like.  We don't want to add anything
612 ; more to the boot sector, so it is written to not assume a fixed
613 ; value in CS, but we don't want to deal with that anymore from now
614 ; on.
615 ;
616                 jmp 0:.next
617 .next:
618
619 ;
620 ; Tell the user we got this far
621 ;
622                 mov si,syslinux_banner
623                 call writestr
624
625 ;
626 ; Tell the user if we're using EBIOS or CBIOS
627 ;
628 print_bios:
629                 mov si,bios_name
630                 cmp byte [getlinsec.jmp+1],(getlinsec_ebios-(getlinsec.jmp+2))
631                 jne .cbios
632                 mov byte [si],'E'
633 .cbios:
634                 call writestr
635
636 ;
637 ; Now we read the rest of LDLINUX.SYS.  Don't bother loading the first
638 ; sector again, though.
639 ;
640 load_rest:
641                 mov si,SectorPtrs
642                 mov bx,7C00h+2*SECTOR_SIZE      ; Where we start loading
643                 mov cx,[LDLSectors]
644
645 .get_chunk:
646                 jcxz .done
647                 xor bp,bp
648                 lodsd                           ; First sector of this chunk
649
650                 mov edx,eax
651
652 .make_chunk:
653                 inc bp
654                 dec cx
655                 jz .chunk_ready
656                 inc edx                         ; Next linear sector
657                 cmp [esi],edx                   ; Does it match
658                 jnz .chunk_ready                ; If not, this is it
659                 add esi,4                       ; If so, add sector to chunk
660                 jmp short .make_chunk
661
662 .chunk_ready:
663                 call getlinsecsr
664                 shl bp,SECTOR_SHIFT
665                 add bx,bp
666                 jmp .get_chunk
667
668 .done:
669
670 ;
671 ; All loaded up, verify that we got what we needed.
672 ; Note: the checksum field is embedded in the checksum region, so
673 ; by the time we get to the end it should all cancel out.
674 ;
675 verify_checksum:
676                 mov si,ldlinux_sys
677                 mov cx,[LDLDwords]
678                 mov edx,-LDLINUX_MAGIC
679 .checksum:
680                 lodsd
681                 add edx,eax
682                 loop .checksum
683
684                 and edx,edx                     ; Should be zero
685                 jz all_read                     ; We're cool, go for it!
686
687 ;
688 ; Uh-oh, something went bad...
689 ;
690                 mov si,checksumerr_msg
691                 call writestr
692                 jmp kaboom
693
694 ;
695 ; -----------------------------------------------------------------------------
696 ; Subroutines that have to be in the first sector
697 ; -----------------------------------------------------------------------------
698
699 ;
700 ;
701 ; writestr: write a null-terminated string to the console
702 ;           This assumes we're on page 0.  This is only used for early
703 ;           messages, so it should be OK.
704 ;
705 writestr:
706 .loop:          lodsb
707                 and al,al
708                 jz .return
709                 mov ah,0Eh              ; Write to screen as TTY
710                 mov bx,0007h            ; Attribute
711                 int 10h
712                 jmp short .loop
713 .return:        ret
714
715 ;
716 ; getlinsecsr: save registers, call getlinsec, restore registers
717 ;
718 getlinsecsr:    pushad
719                 call getlinsec
720                 popad
721                 ret
722
723 ;
724 ; Checksum error message
725 ;
726 checksumerr_msg db 'Load error - ', 0   ; Boot failed appended
727
728 ;
729 ; BIOS type string
730 ;
731 bios_name       db 'CBIOS', 0
732
733 ;
734 ; Debug routine
735 ;
736 %ifdef debug
737 safedumpregs:
738                 cmp word [Debug_Magic],0D00Dh
739                 jnz nc_return
740                 jmp dumpregs
741 %endif
742
743 rl_checkpt      equ $                           ; Must be <= 8000h
744
745 rl_checkpt_off  equ ($-$$)
746 %if 0 ; ndef DEPEND
747 %if rl_checkpt_off > 400h
748 %error "Sector 1 overflow"
749 %endif
750 %endif
751
752 ; ----------------------------------------------------------------------------
753 ;  End of code and data that have to be in the first sector
754 ; ----------------------------------------------------------------------------
755
756 all_read:
757 ;
758 ; Let the user (and programmer!) know we got this far.  This used to be
759 ; in Sector 1, but makes a lot more sense here.
760 ;
761                 mov si,copyright_str
762                 call writestr
763
764
765 ;
766 ; Insane hack to expand the superblock to dwords
767 ;
768 expand_super:
769                 xor eax,eax
770                 mov si,superblock
771                 mov di,SuperInfo
772                 mov cx,superinfo_size
773 .loop:
774                 lodsw
775                 dec si
776                 stosd                           ; Store expanded word
777                 xor ah,ah
778                 stosd                           ; Store expanded byte
779                 loop .loop
780
781 ;
782 ; Compute some information about this filesystem.
783 ;
784
785 ; First, generate the map of regions
786 genfatinfo:
787                 mov edx,[bxSectors]
788                 and dx,dx
789                 jnz .have_secs
790                 mov edx,[bsHugeSectors]
791 .have_secs:
792                 mov [TotalSectors],edx
793
794                 add edx,eax
795                 mov [EndSector],edx
796
797                 mov eax,[bxResSectors]
798                 mov [FAT],eax                   ; Beginning of FAT
799                 mov edx,[bxFATsecs]
800                 and dx,dx
801                 jnz .have_fatsecs
802                 mov edx,[bootsec+36]            ; FAT32 BPB_FATsz32
803 .have_fatsecs:
804                 imul edx,[bxFATs]
805                 add eax,edx
806                 mov [RootDirArea],eax           ; Beginning of root directory
807                 mov [RootDir],eax               ; For FAT12/16 == root dir location
808
809                 mov edx,[bxRootDirEnts]
810                 add dx,SECTOR_SIZE/32-1
811                 shr dx,SECTOR_SHIFT-5
812                 mov [RootDirSize],edx
813                 add eax,edx
814                 mov [DataArea],eax              ; Beginning of data area
815
816 ; Next, generate a cluster size shift count and mask
817                 mov eax,[bxSecPerClust]
818                 bsr cx,ax
819                 mov [ClustShift],cl
820                 push cx
821                 add cl,9
822                 mov [ClustByteShift],cl
823                 pop cx
824                 dec ax
825                 mov [ClustMask],eax
826                 inc ax
827                 shl eax,9
828                 mov [ClustSize],eax
829
830 ;
831 ; FAT12, FAT16 or FAT28^H^H32?  This computation is fscking ridiculous.
832 ;
833 getfattype:
834                 mov eax,[EndSector]
835                 sub eax,[DataArea]
836                 shr eax,cl                      ; cl == ClustShift
837                 mov cl,nextcluster_fat12-(nextcluster+2)
838                 cmp eax,4085                    ; FAT12 limit
839                 jb .setsize
840                 mov cl,nextcluster_fat16-(nextcluster+2)
841                 cmp eax,65525                   ; FAT16 limit
842                 jb .setsize
843                 ;
844                 ; FAT32, root directory is a cluster chain
845                 ;
846                 mov cl,[ClustShift]
847                 mov eax,[bootsec+44]            ; Root directory cluster
848                 sub eax,2
849                 shl eax,cl
850                 add eax,[DataArea]
851                 mov [RootDir],eax
852                 mov cl,nextcluster_fat28-(nextcluster+2)
853 .setsize:
854                 mov byte [nextcluster+1],cl
855
856 ;
857 ; Common initialization code
858 ;
859 %include "cpuinit.inc"
860 %include "init.inc"
861
862 ;
863 ; Clear Files structures
864 ;
865                 mov di,Files
866                 mov cx,(MAX_OPEN*open_file_t_size)/4
867                 xor eax,eax
868                 rep stosd
869
870 ;
871 ; Initialize the metadata cache
872 ;
873                 call initcache
874
875 ;
876 ; Now, everything is "up and running"... patch kaboom for more
877 ; verbosity and using the full screen system
878 ;
879                 ; E9 = JMP NEAR
880                 mov dword [kaboom.patch],0e9h+((kaboom2-(kaboom.patch+3)) << 8)
881
882 ;
883 ; Now we're all set to start with our *real* business.  First load the
884 ; configuration file (if any) and parse it.
885 ;
886 ; In previous versions I avoided using 32-bit registers because of a
887 ; rumour some BIOSes clobbered the upper half of 32-bit registers at
888 ; random.  I figure, though, that if there are any of those still left
889 ; they probably won't be trying to install Linux on them...
890 ;
891 ; The code is still ripe with 16-bitisms, though.  Not worth the hassle
892 ; to take'm out.  In fact, we may want to put them back if we're going
893 ; to boot ELKS at some point.
894 ;
895
896 ;
897 ; Load configuration file
898 ;
899                 mov di,syslinux_cfg
900                 call open
901                 jz no_config_file
902
903 ;
904 ; Now we have the config file open.  Parse the config file and
905 ; run the user interface.
906 ;
907 %include "ui.inc"
908
909 ;
910 ; Linux kernel loading code is common.
911 ;
912 %include "runkernel.inc"
913
914 ;
915 ; COMBOOT-loading code
916 ;
917 %include "comboot.inc"
918 %include "com32.inc"
919 %include "cmdline.inc"
920
921 ;
922 ; Boot sector loading code
923 ;
924 %include "bootsect.inc"
925
926 ;
927 ; abort_check: let the user abort with <ESC> or <Ctrl-C>
928 ;
929 abort_check:
930                 call pollchar
931                 jz ac_ret1
932                 pusha
933                 call getchar
934                 cmp al,27                       ; <ESC>
935                 je ac_kill
936                 cmp al,3                        ; <Ctrl-C>
937                 jne ac_ret2
938 ac_kill:        mov si,aborted_msg
939
940 ;
941 ; abort_load: Called by various routines which wants to print a fatal
942 ;             error message and return to the command prompt.  Since this
943 ;             may happen at just about any stage of the boot process, assume
944 ;             our state is messed up, and just reset the segment registers
945 ;             and the stack forcibly.
946 ;
947 ;             SI    = offset (in _text) of error message to print
948 ;
949 abort_load:
950                 mov ax,cs                       ; Restore CS = DS = ES
951                 mov ds,ax
952                 mov es,ax
953                 cli
954                 mov sp,StackBuf-2*3             ; Reset stack
955                 mov ss,ax                       ; Just in case...
956                 sti
957                 call cwritestr                  ; Expects SI -> error msg
958 al_ok:          jmp enter_command               ; Return to command prompt
959 ;
960 ; End of abort_check
961 ;
962 ac_ret2:        popa
963 ac_ret1:        ret
964
965 ;
966 ; allocate_file: Allocate a file structure
967 ;
968 ;               If successful:
969 ;                 ZF set
970 ;                 BX = file pointer
971 ;               In unsuccessful:
972 ;                 ZF clear
973 ;
974 allocate_file:
975                 TRACER 'a'
976                 push cx
977                 mov bx,Files
978                 mov cx,MAX_OPEN
979 .check:         cmp dword [bx], byte 0
980                 je .found
981                 add bx,open_file_t_size         ; ZF = 0
982                 loop .check
983                 ; ZF = 0 if we fell out of the loop
984 .found:         pop cx
985                 ret
986
987 ;
988 ; searchdir:
989 ;            Search the root directory for a pre-mangled filename in DS:DI.
990 ;
991 ;            NOTE: This file considers finding a zero-length file an
992 ;            error.  This is so we don't have to deal with that special
993 ;            case elsewhere in the program (most loops have the test
994 ;            at the end).
995 ;
996 ;            If successful:
997 ;               ZF clear
998 ;               SI      = file pointer
999 ;               DX:AX   = file length in bytes
1000 ;            If unsuccessful
1001 ;               ZF set
1002 ;
1003
1004 searchdir:
1005                 call allocate_file
1006                 jnz .alloc_failure
1007
1008                 push gs
1009                 push es
1010                 push ds
1011                 pop es                          ; ES = DS
1012
1013                 mov eax,[RootDir]               ; First root directory sector
1014
1015 .scansector:
1016                 call getcachesector
1017                 ; GS:SI now points to this sector
1018
1019                 mov cx,SECTOR_SIZE/32           ; 32 == directory entry size
1020 .scanentry:
1021                 cmp byte [gs:si],0
1022                 jz .failure                     ; Hit directory high water mark
1023                 push cx
1024                 push si
1025                 push di
1026                 mov cx,11
1027                 gs repe cmpsb
1028                 pop di
1029                 pop si
1030                 pop cx
1031                 jz .found
1032                 add si,32
1033                 loop .scanentry
1034
1035                 call nextsector
1036                 jnc .scansector                 ; CF is set if we're at end
1037
1038                 ; If we get here, we failed
1039 .failure:
1040                 pop es
1041                 pop gs
1042 .alloc_failure:
1043                 xor ax,ax                       ; ZF <- 1
1044                 ret
1045 .found:
1046                 mov eax,[gs:si+28]              ; File size
1047                 add eax,SECTOR_SIZE-1
1048                 shr eax,SECTOR_SHIFT
1049                 jz .failure                     ; Zero-length file
1050                 mov [bx+4],eax
1051
1052                 mov cl,[ClustShift]
1053                 mov dx,[gs:si+20]               ; High cluster word
1054                 shl edx,16
1055                 mov dx,[gs:si+26]               ; Low cluster word
1056                 sub edx,2
1057                 shl edx,cl
1058                 add edx,[DataArea]
1059                 mov [bx],edx                    ; Starting sector
1060
1061                 mov eax,[gs:si+28]              ; File length again
1062                 mov dx,[gs:si+30]               ; 16-bitism, sigh
1063                 mov si,bx
1064                 and eax,eax                     ; ZF <- 0
1065
1066                 pop es
1067                 pop gs
1068                 ret
1069
1070 ;
1071 ; writechr:     Write a single character in AL to the console without
1072 ;               mangling any registers; handle video pages correctly.
1073 ;
1074 writechr:
1075                 call write_serial       ; write to serial port if needed
1076                 pushfd
1077                 test byte [cs:DisplayCon], 01h
1078                 jz .nothing
1079                 pushad
1080                 mov ah,0Eh
1081                 mov bl,07h              ; attribute
1082                 mov bh,[cs:BIOS_page]   ; current page
1083                 int 10h
1084                 popad
1085 .nothing:
1086                 popfd
1087                 ret
1088
1089 ;
1090 ;
1091 ; kaboom2: once everything is loaded, replace the part of kaboom
1092 ;          starting with "kaboom.patch" with this part
1093
1094 kaboom2:
1095                 mov si,err_bootfailed
1096                 call cwritestr
1097                 call getchar
1098                 call vgaclearmode
1099                 int 19h                 ; And try once more to boot...
1100 .norge:         jmp short .norge        ; If int 19h returned; this is the end
1101
1102 ;
1103 ; mangle_name: Mangle a DOS filename pointed to by DS:SI into a buffer pointed
1104 ;              to by ES:DI; ends on encountering any whitespace
1105 ;
1106
1107 mangle_name:
1108                 mov cx,11                       ; # of bytes to write
1109 mn_loop:
1110                 lodsb
1111                 cmp al,' '                      ; If control or space, end
1112                 jna mn_end
1113                 cmp al,'.'                      ; Period -> space-fill
1114                 je mn_is_period
1115                 cmp al,'a'
1116                 jb mn_not_lower
1117                 cmp al,'z'
1118                 ja mn_not_uslower
1119                 sub al,020h
1120                 jmp short mn_not_lower
1121 mn_is_period:   mov al,' '                      ; We need to space-fill
1122 mn_period_loop: cmp cx,3                        ; If <= 3 characters left
1123                 jbe mn_loop                     ; Just ignore it
1124                 stosb                           ; Otherwise, write a period
1125                 loop mn_period_loop             ; Dec CX and (always) jump
1126 mn_not_uslower: cmp al,ucase_low
1127                 jb mn_not_lower
1128                 cmp al,ucase_high
1129                 ja mn_not_lower
1130                 mov bx,ucase_tab-ucase_low
1131                 cs xlatb
1132 mn_not_lower:   stosb
1133                 loop mn_loop                    ; Don't continue if too long
1134 mn_end:
1135                 mov al,' '                      ; Space-fill name
1136                 rep stosb                       ; Doesn't do anything if CX=0
1137                 ret                             ; Done
1138
1139 ;
1140 ; Upper-case table for extended characters; this is technically code page 865,
1141 ; but code page 437 users will probably not miss not being able to use the
1142 ; cent sign in kernel images too much :-)
1143 ;
1144 ; The table only covers the range 129 to 164; the rest we can deal with.
1145 ;
1146 ucase_low       equ 129
1147 ucase_high      equ 164
1148 ucase_tab       db 154, 144, 'A', 142, 'A', 143, 128, 'EEEIII'
1149                 db 142, 143, 144, 146, 146, 'O', 153, 'OUUY', 153, 154
1150                 db 157, 156, 157, 158, 159, 'AIOU', 165
1151
1152 ;
1153 ; unmangle_name: Does the opposite of mangle_name; converts a DOS-mangled
1154 ;                filename to the conventional representation.  This is needed
1155 ;                for the BOOT_IMAGE= parameter for the kernel.
1156 ;                NOTE: A 13-byte buffer is mandatory, even if the string is
1157 ;                known to be shorter.
1158 ;
1159 ;                DS:SI -> input mangled file name
1160 ;                ES:DI -> output buffer
1161 ;
1162 ;                On return, DI points to the first byte after the output name,
1163 ;                which is set to a null byte.
1164 ;
1165 unmangle_name:
1166                 push si                 ; Save pointer to original name
1167                 mov cx,8
1168                 mov bp,di
1169 un_copy_body:   lodsb
1170                 call lower_case
1171                 stosb
1172                 cmp al,' '
1173                 jbe un_cb_space
1174                 mov bp,di               ; Position of last nonblank+1
1175 un_cb_space:    loop un_copy_body
1176                 mov di,bp
1177                 mov al,'.'              ; Don't save
1178                 stosb
1179                 mov cx,3
1180 un_copy_ext:    lodsb
1181                 call lower_case
1182                 stosb
1183                 cmp al,' '
1184                 jbe un_ce_space
1185                 mov bp,di
1186 un_ce_space:    loop un_copy_ext
1187                 mov di,bp
1188                 mov byte [es:di], 0
1189                 pop si
1190                 ret
1191
1192 ;
1193 ; lower_case: Lower case a character in AL
1194 ;
1195 lower_case:
1196                 cmp al,'A'
1197                 jb lc_ret
1198                 cmp al,'Z'
1199                 ja lc_1
1200                 or al,20h
1201                 ret
1202 lc_1:           cmp al,lcase_low
1203                 jb lc_ret
1204                 cmp al,lcase_high
1205                 ja lc_ret
1206                 push bx
1207                 mov bx,lcase_tab-lcase_low
1208                 cs xlatb
1209                 pop bx
1210 lc_ret:         ret
1211
1212 ;
1213 ; getfssec_edx: Get multiple sectors from a file
1214 ;
1215 ;       This routine makes sure the subtransfers do not cross a 64K boundary,
1216 ;       and will correct the situation if it does, UNLESS *sectors* cross
1217 ;       64K boundaries.
1218 ;
1219 ;       ES:BX   -> Buffer
1220 ;       EDX     -> Current sector number
1221 ;       CX      -> Sector count (0FFFFh = until end of file)
1222 ;                  Must not exceed the ES segment
1223 ;       Returns EDX=0, CF=1 on EOF (not necessarily error)
1224 ;       All arguments are advanced to reflect data read.
1225 ;
1226 getfssec_edx:
1227                 push ebp
1228                 push eax
1229 .getfragment:
1230                 xor ebp,ebp                     ; Fragment sector count
1231                 push edx                        ; Starting sector pointer
1232 .getseccnt:
1233                 inc bp
1234                 dec cx
1235                 jz .do_read
1236                 xor eax,eax
1237                 mov ax,es
1238                 shl ax,4
1239                 add ax,bx                       ; Now AX = how far into 64K block we are
1240                 not ax                          ; Bytes left in 64K block
1241                 inc eax
1242                 shr eax,SECTOR_SHIFT            ; Sectors left in 64K block
1243                 cmp bp,ax
1244                 jnb .do_read                    ; Unless there is at least 1 more sector room...
1245                 mov eax,edx                     ; Current sector
1246                 inc edx                         ; Predict it's the linearly next sector
1247                 call nextsector
1248                 jc .do_read
1249                 cmp edx,eax                     ; Did it match?
1250                 jz .getseccnt
1251 .do_read:
1252                 pop eax                         ; Starting sector pointer
1253                 call getlinsecsr
1254                 lea eax,[eax+ebp-1]             ; This is the last sector actually read
1255                 shl bp,9
1256                 add bx,bp                       ; Adjust buffer pointer
1257                 call nextsector
1258                 jc .eof
1259                 mov edx,eax
1260                 and cx,cx
1261                 jnz .getfragment
1262 .done:
1263                 pop eax
1264                 pop ebp
1265                 ret
1266 .eof:
1267                 xor edx,edx
1268                 stc
1269                 jmp .done
1270
1271 ;
1272 ; getfssec: Get multiple sectors from a file
1273 ;
1274 ;       Same as above, except SI is a pointer to a open_file_t
1275 ;
1276 ;       ES:BX   -> Buffer
1277 ;       DS:SI   -> Pointer to open_file_t
1278 ;       CX      -> Sector count (0FFFFh = until end of file)
1279 ;                  Must not exceed the ES segment
1280 ;       Returns CF=1 on EOF (not necessarily error)
1281 ;       All arguments are advanced to reflect data read.
1282 ;
1283 getfssec:
1284                 push edx
1285                 movzx edx,cx
1286                 cmp edx,[si+4]
1287                 jbe .sizeok
1288                 mov edx,[si+4]
1289                 mov cx,dx
1290 .sizeok:
1291                 sub [si+4],edx
1292                 mov edx,[si]
1293                 call getfssec_edx
1294                 mov [si],edx
1295                 pop edx
1296                 ret
1297
1298 ;
1299 ; nextcluster: Advance a cluster pointer in EDI to the next cluster
1300 ;              pointed at in the FAT tables.  CF=0 on return if end of file.
1301 ;
1302 nextcluster:
1303                 jmp strict short nextcluster_fat28      ; This gets patched
1304
1305 nextcluster_fat12:
1306                 push eax
1307                 push edx
1308                 push bx
1309                 push cx
1310                 push si
1311                 mov edx,edi
1312                 shr edi,1
1313                 pushf                   ; Save the shifted-out LSB (=CF)
1314                 add edx,edi
1315                 mov eax,edx
1316                 shr eax,9
1317                 call getfatsector
1318                 mov bx,dx
1319                 and bx,1FFh
1320                 mov cl,[gs:si+bx]
1321                 inc edx
1322                 mov eax,edx
1323                 shr eax,9
1324                 call getfatsector
1325                 mov bx,dx
1326                 and bx,1FFh
1327                 mov ch,[gs:si+bx]
1328                 popf
1329                 jnc .even
1330                 shr cx,4
1331 .even:          and cx,0FFFh
1332                 movzx edi,cx
1333                 cmp di,0FF0h
1334                 pop si
1335                 pop cx
1336                 pop bx
1337                 pop edx
1338                 pop eax
1339                 ret
1340
1341 ;
1342 ; FAT16 decoding routine.
1343 ;
1344 nextcluster_fat16:
1345                 push eax
1346                 push si
1347                 push bx
1348                 mov eax,edi
1349                 shr eax,SECTOR_SHIFT-1
1350                 call getfatsector
1351                 mov bx,di
1352                 add bx,bx
1353                 and bx,1FEh
1354                 movzx edi,word [gs:si+bx]
1355                 cmp di,0FFF0h
1356                 pop bx
1357                 pop si
1358                 pop eax
1359                 ret
1360 ;
1361 ; FAT28 ("FAT32") decoding routine.
1362 ;
1363 nextcluster_fat28:
1364                 push eax
1365                 push si
1366                 push bx
1367                 mov eax,edi
1368                 shr eax,SECTOR_SHIFT-2
1369                 call getfatsector
1370                 mov bx,di
1371                 add bx,bx
1372                 add bx,bx
1373                 and bx,1FCh
1374                 mov edi,dword [gs:si+bx]
1375                 and edi,0FFFFFFFh       ; 28 bits only
1376                 cmp edi,0FFFFFF0h
1377                 pop bx
1378                 pop si
1379                 pop eax
1380                 ret
1381
1382 ;
1383 ; nextsector:   Given a sector in EAX on input, return the next sector
1384 ;               of the same filesystem object, which may be the root
1385 ;               directory or a cluster chain.  Returns  EOF.
1386 ;
1387 ;               Assumes CS == DS.
1388 ;
1389 nextsector:
1390                 push edi
1391                 push edx
1392                 mov edx,[DataArea]
1393                 mov edi,eax
1394                 sub edi,edx
1395                 jae .isdata
1396
1397                 ; Root directory
1398                 inc eax
1399                 cmp eax,edx
1400                 cmc
1401                 jmp .done
1402
1403 .isdata:
1404                 not edi
1405                 test edi,[ClustMask]
1406                 jz .endcluster
1407
1408                 ; It's not the final sector in a cluster
1409                 inc eax
1410                 jmp .done
1411
1412 .endcluster:
1413                 push gs                 ; nextcluster trashes gs
1414                 push cx
1415                 not edi
1416                 mov cl,[ClustShift]
1417                 shr edi,cl
1418                 add edi,2
1419
1420                 ; Now EDI contains the cluster number
1421                 call nextcluster
1422                 cmc
1423                 jc .exit                ; There isn't anything else...
1424
1425                 ; New cluster number now in EDI
1426                 sub edi,2
1427                 shl edi,cl              ; CF <- 0, unless something is very wrong
1428                 lea eax,[edi+edx]
1429 .exit:
1430                 pop cx
1431                 pop gs
1432 .done:
1433                 pop edx
1434                 pop edi
1435                 ret
1436
1437 ;
1438 ; getfatsector: Check for a particular sector (in EAX) in the FAT cache,
1439 ;               and return a pointer in GS:SI, loading it if needed.
1440 ;
1441 ;               Assumes CS == DS.
1442 ;
1443 getfatsector:
1444                 add eax,[FAT]           ; FAT starting address
1445                 jmp getcachesector
1446
1447 ; -----------------------------------------------------------------------------
1448 ;  Common modules
1449 ; -----------------------------------------------------------------------------
1450
1451 %include "getc.inc"             ; getc et al
1452 %include "conio.inc"            ; Console I/O
1453 %include "writestr.inc"         ; String output
1454 %include "parseconfig.inc"      ; High-level config file handling
1455 %include "parsecmd.inc"         ; Low-level config file handling
1456 %include "bcopy32.inc"          ; 32-bit bcopy
1457 %include "loadhigh.inc"         ; Load a file into high memory
1458 %include "font.inc"             ; VGA font stuff
1459 %include "graphics.inc"         ; VGA graphics
1460 %include "highmem.inc"          ; High memory sizing
1461 %include "strcpy.inc"           ; strcpy()
1462 %include "cache.inc"            ; Metadata disk cache
1463
1464 ; -----------------------------------------------------------------------------
1465 ;  Begin data section
1466 ; -----------------------------------------------------------------------------
1467
1468                 section .data
1469 ;
1470 ; Lower-case table for codepage 865
1471 ;
1472 lcase_low       equ 128
1473 lcase_high      equ 165
1474 lcase_tab       db 135, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138
1475                 db 139, 140, 141, 132, 134, 130, 145, 145, 147, 148, 149
1476                 db 150, 151, 152, 148, 129, 155, 156, 155, 158, 159, 160
1477                 db 161, 162, 163, 164, 164
1478
1479 copyright_str   db ' Copyright (C) 1994-', year, ' H. Peter Anvin'
1480                 db CR, LF, 0
1481 boot_prompt     db 'boot: ', 0
1482 wipe_char       db BS, ' ', BS, 0
1483 err_notfound    db 'Could not find kernel image: ',0
1484 err_notkernel   db CR, LF, 'Invalid or corrupt kernel image.', CR, LF, 0
1485 err_noram       db 'It appears your computer has less than '
1486                 asciidec dosram_k
1487                 db 'K of low ("DOS")'
1488                 db CR, LF
1489                 db 'RAM.  Linux needs at least this amount to boot.  If you get'
1490                 db CR, LF
1491                 db 'this message in error, hold down the Ctrl key while'
1492                 db CR, LF
1493                 db 'booting, and I will take your word for it.', CR, LF, 0
1494 err_badcfg      db 'Unknown keyword in syslinux.cfg.', CR, LF, 0
1495 err_noparm      db 'Missing parameter in syslinux.cfg.', CR, LF, 0
1496 err_noinitrd    db CR, LF, 'Could not find ramdisk image: ', 0
1497 err_nohighmem   db 'Not enough memory to load specified kernel.', CR, LF, 0
1498 err_highload    db CR, LF, 'Kernel transfer failure.', CR, LF, 0
1499 err_oldkernel   db 'Cannot load a ramdisk with an old kernel image.'
1500                 db CR, LF, 0
1501 err_notdos      db ': attempted DOS system call', CR, LF, 0
1502 err_comlarge    db 'COMBOOT image too large.', CR, LF, 0
1503 err_a20         db CR, LF, 'A20 gate not responding!', CR, LF, 0
1504 err_bootfailed  db CR, LF, 'Boot failed: please change disks and press '
1505                 db 'a key to continue.', CR, LF, 0
1506 ready_msg       db 'Ready.', CR, LF, 0
1507 crlfloading_msg db CR, LF
1508 loading_msg     db 'Loading ', 0
1509 dotdot_msg      db '.'
1510 dot_msg         db '.', 0
1511 aborted_msg     db ' aborted.'                  ; Fall through to crlf_msg!
1512 crlf_msg        db CR, LF
1513 null_msg        db 0
1514 crff_msg        db CR, FF, 0
1515 syslinux_cfg    db 'SYSLINUXCFG'                ; Mangled form
1516 ConfigName      db 'syslinux.cfg',0             ; Unmangled form
1517 %if IS_MDSLINUX
1518 manifest        db 'MANIFEST   '
1519 %endif
1520 ;
1521 ; Command line options we'd like to take a look at
1522 ;
1523 ; mem= and vga= are handled as normal 32-bit integer values
1524 initrd_cmd      db 'initrd='
1525 initrd_cmd_len  equ 7
1526
1527 ;
1528 ; Config file keyword table
1529 ;
1530 %include "keywords.inc"
1531
1532 ;
1533 ; Extensions to search for (in *forward* order).
1534 ;
1535 exten_table:    db 'CBT',0              ; COMBOOT (specific)
1536                 db 'BSS',0              ; Boot Sector (add superblock)
1537                 db 'BS ',0              ; Boot Sector 
1538                 db 'COM',0              ; COMBOOT (same as DOS)
1539                 db 'C32',0              ; COM32
1540 exten_table_end:
1541                 dd 0, 0                 ; Need 8 null bytes here
1542
1543 ;
1544 ; Misc initialized (data) variables
1545 ;
1546 %ifdef debug                            ; This code for debugging only
1547 debug_magic     dw 0D00Dh               ; Debug code sentinel
1548 %endif
1549
1550                 alignb 4, db 0
1551 BufSafe         dw trackbufsize/SECTOR_SIZE     ; Clusters we can load into trackbuf
1552 BufSafeSec      dw trackbufsize/SECTOR_SIZE     ; = how many sectors?
1553 BufSafeBytes    dw trackbufsize         ; = how many bytes?
1554 EndOfGetCBuf    dw getcbuf+trackbufsize ; = getcbuf+BufSafeBytes
1555 %ifndef DEPEND
1556 %if ( trackbufsize % SECTOR_SIZE ) != 0
1557 %error trackbufsize must be a multiple of SECTOR_SIZE
1558 %endif
1559 %endif