1 ; -*- fundamental -*- (asm-mode sucks)
2 ; ****************************************************************************
6 ; A program to boot Linux kernels off an MS-DOS formatted floppy disk. This
7 ; functionality is good to have for installation floppies, where it may
8 ; be hard to find a functional Linux system to run LILO off.
10 ; This program allows manipulation of the disk to take place entirely
11 ; from MS-LOSS, and can be especially useful in conjunction with the
14 ; Copyright (C) 1994-2005 H. Peter Anvin
16 ; This program is free software; you can redistribute it and/or modify
17 ; it under the terms of the GNU General Public License as published by
18 ; the Free Software Foundation, Inc., 53 Temple Place Ste 330,
19 ; Boston MA 02111-1307, USA; either version 2 of the License, or
20 ; (at your option) any later version; incorporated herein by reference.
22 ; ****************************************************************************
30 ; Some semi-configurable constants... change on your own risk.
33 FILENAME_MAX_LG2 equ 4 ; log2(Max filename size Including final null)
34 FILENAME_MAX equ 11 ; Max mangled filename size
35 NULLFILE equ ' ' ; First char space == null filename
36 NULLOFFSET equ 0 ; Position in which to look
37 retry_count equ 16 ; How patient are we with the disk?
38 %assign HIGHMEM_SLOP 0 ; Avoid this much memory near the top
39 LDLINUX_MAGIC equ 0x3eb202fe ; A random number to identify ourselves with
41 MAX_OPEN_LG2 equ 6 ; log2(Max number of open files)
42 MAX_OPEN equ (1 << MAX_OPEN_LG2)
45 SECTOR_SIZE equ (1 << SECTOR_SHIFT)
48 ; This is what we need to do when idle
58 ; The following structure is used for "virtual kernels"; i.e. LILO-style
59 ; option labels. The options we permit here are `kernel' and `append
60 ; Since there is no room in the bottom 64K for all of these, we
61 ; stick them at vk_seg:0000 and copy them down before we need them.
64 vk_vname: resb FILENAME_MAX ; Virtual name **MUST BE FIRST!**
65 vk_rname: resb FILENAME_MAX ; Real name
67 vk_type: resb 1 ; Type of file
69 vk_append: resb max_cmd_len+1 ; Command line
71 vk_end: equ $ ; Should be <= vk_size
75 ; Segment assignments in the bottom 640K
76 ; Stick to the low 512K in case we're using something like M-systems flash
77 ; which load a driver into low RAM (evil!!)
79 ; 0000h - main code/data segment (and BIOS segment)
81 real_mode_seg equ 4000h
82 cache_seg equ 3000h ; 64K area for metadata cache
83 vk_seg equ 2000h ; Virtual kernels
84 xfer_buf_seg equ 1000h ; Bounce buffer for I/O to high mem
85 comboot_seg equ real_mode_seg ; COMBOOT image loading zone
88 ; File structure. This holds the information for each currently open file.
91 file_sector resd 1 ; Sector pointer (0 = structure free)
92 file_left resd 1 ; Number of sectors left
96 %if (open_file_t_size & (open_file_t_size-1))
97 %error "open_file_t is not a power of 2"
101 ; ---------------------------------------------------------------------------
103 ; ---------------------------------------------------------------------------
106 ; Memory below this point is reserved for the BIOS and the MBR
109 trackbufsize equ 8192
110 trackbuf resb trackbufsize ; Track buffer goes here
111 getcbuf resb trackbufsize
117 ; Expanded superblock
119 resq 16 ; The first 16 bytes expanded 8 times
120 FAT resd 1 ; Location of (first) FAT
121 RootDirArea resd 1 ; Location of root directory area
122 RootDir resd 1 ; Location of root directory proper
123 DataArea resd 1 ; Location of data area
124 RootDirSize resd 1 ; Root dir size in sectors
125 TotalSectors resd 1 ; Total number of sectors
126 EndSector resd 1 ; Location of filesystem end
127 ClustSize resd 1 ; Bytes/cluster
128 ClustMask resd 1 ; Sectors/cluster - 1
129 CopySuper resb 1 ; Distinguish .bs versus .bss
130 DriveNumber resb 1 ; BIOS drive number
131 ClustShift resb 1 ; Shift count for sectors/cluster
132 ClustByteShift resb 1 ; Shift count for bytes/cluster
134 alignb open_file_t_size
135 Files resb MAX_OPEN*open_file_t_size
138 ; Constants for the xfer_buf_seg
140 ; The xfer_buf_seg is also used to store message file buffers. We
141 ; need two trackbuffers (text and graphics), plus a work buffer
142 ; for the graphics decompressor.
144 xbs_textbuf equ 0 ; Also hard-coded, do not change
145 xbs_vgabuf equ trackbufsize
146 xbs_vgatmpbuf equ 2*trackbufsize
151 ; Some of the things that have to be saved very early are saved
152 ; "close" to the initial stack pointer offset, in order to
153 ; reduce the code size...
155 StackBuf equ $-44-32 ; Start the stack here (grow down - 4K)
156 PartInfo equ StackBuf ; Saved partition table entry
157 FloppyTable equ PartInfo+16 ; Floppy info table (must follow PartInfo)
158 OrigFDCTabPtr equ StackBuf-4 ; The high dword on the stack
161 ; Primary entry point. Tempting as though it may be, we can't put the
162 ; initial "cli" here; the jmp opcode in the first byte is part of the
163 ; "magic number" (using the term very loosely) for the DOS superblock.
166 jmp short start ; 2 bytes
169 ; "Superblock" follows -- it's in the boot sector, so it's already
170 ; loaded and ready for us
172 bsOemName db 'SYSLINUX' ; The SYS command sets this, so...
174 ; These are the fields we actually care about. We end up expanding them
175 ; all to dword size early in the code, so generate labels for both
176 ; the expanded and unexpanded versions.
179 bx %+ %1 equ SuperInfo+($-superblock)*8+4
184 bx %+ %1 equ SuperInfo+($-superblock)*8
189 bx %+ %1 equ $ ; no expansion for dwords
204 superinfo_size equ ($-superblock)-1 ; How much to expand
208 ; This is as far as FAT12/16 and FAT32 are consistent
210 zb 54 ; FAT12/16 need 26 more bytes,
211 ; FAT32 need 54 more bytes
212 superblock_len equ $-superblock
214 SecPerClust equ bxSecPerClust
216 ; Note we don't check the constraints above now; we did that at install
220 cli ; No interrupts yet, please
227 mov sp,StackBuf ; Just below BSS
230 ; DS:SI may contain a partition table entry. Preserve it for us.
232 mov cx,8 ; Save partition info
236 mov ds,ax ; Now we can initialize DS...
239 ; Now sautee the BIOS floppy info block to that it will support decent-
240 ; size transfers; the floppy block is 11 bytes and is stored in the
241 ; INT 1Eh vector (brilliant waste of resources, eh?)
243 ; Of course, if BIOSes had been properly programmed, we wouldn't have
244 ; had to waste precious space with this code.
247 lfs si,[bx] ; FS:SI -> original fdctab
248 push fs ; Save on stack in case we need to bail
251 ; Save the old fdctab even if hard disk so the stack layout
252 ; is the same. The instructions above do not change the flags
253 mov [DriveNumber],dl ; Save drive number in DL
254 and dl,dl ; If floppy disk (00-7F), assume no
259 mov cl,6 ; 12 bytes (CX == 0)
260 ; es:di -> FloppyTable already
261 ; This should be safe to do now, interrupts are off...
262 mov [bx],di ; FloppyTable
263 mov [bx+2],ax ; Segment 0
264 fs rep movsw ; Faster to move words
265 mov cl,[bsSecPerTrack] ; Patch the sector count
268 int 13h ; Some BIOSes need this
270 jmp short not_harddisk
272 ; The drive number and possibly partition information was passed to us
273 ; by the BIOS or previous boot loader (MBR). Current "best practice" is to
274 ; trust that rather than what the superblock contains.
276 ; Would it be better to zero out bsHidden if we don't have a partition table?
278 ; Note: di points to beyond the end of PartInfo
281 test byte [di-16],7Fh ; Sanity check: "active flag" should
282 jnz no_partition ; be 00 or 80
283 mov eax,[di-8] ; Partition offset (dword)
287 ; Get disk drive parameters (don't trust the superblock.) Don't do this for
288 ; floppy drives -- INT 13:08 on floppy drives will (may?) return info about
289 ; what the *drive* supports, not about the *media*. Fortunately floppy disks
290 ; tend to have a fixed, well-defined geometry which is stored in the superblock.
292 ; DL == drive # still
299 inc dx ; Contains # of heads - 1
302 mov [bsSecPerTrack],cx
306 ; Ready to enable interrupts, captain
311 ; Do we have EBIOS (EDD)?
315 mov ah,41h ; EDD existence query
321 test cl,1 ; Extended disk access functionality set
324 ; We have EDD support...
326 mov byte [getlinsec.jmp+1],(getlinsec_ebios-(getlinsec.jmp+2))
330 ; Load the first sector of LDLINUX.SYS; this used to be all proper
331 ; with parsing the superblock and root directory; it doesn't fit
332 ; together with EBIOS support, unfortunately.
334 mov eax,[FirstSector] ; Sector start
335 mov bx,ldlinux_sys ; Where to load it
338 ; Some modicum of integrity checking
339 cmp dword [ldlinux_magic+4],LDLINUX_MAGIC^HEXDATE
346 ; getonesec: get one disk sector
349 mov bp,1 ; One sector
353 ; getlinsec: load a sequence of BP floppy sector given by the linear sector
354 ; number in EAX into the buffer at ES:BX. We try to optimize
355 ; by loading up to a whole track at a time, but the user
356 ; is responsible for not crossing a 64K boundary.
357 ; (Yes, BP is weird for a count, but it was available...)
359 ; On return, BX points to the first byte after the transferred
362 ; This routine assumes CS == DS, and trashes most registers.
364 ; Stylistic note: use "xchg" instead of "mov" when the source is a register
365 ; that is dead from that point; this saves space. However, please keep
366 ; the order to dst,src to keep things sane.
369 add eax,[bsHidden] ; Add partition offset
370 xor edx,edx ; Zero-extend LBA (eventually allow 64 bits)
372 .jmp: jmp strict short getlinsec_cbios
377 ; getlinsec implementation for EBIOS (EDD)
381 push bp ; Sectors left
383 call maxtrans ; Enforce maximum transfer size
384 movzx edi,bp ; Sectors we are about to read
401 mov ah,42h ; Extended Read
405 lea sp,[si+16] ; Remove DAPA
408 add eax,edi ; Advance sector pointer
409 sub bp,di ; Sectors left
410 shl di,SECTOR_SHIFT ; 512-byte sectors
411 add bx,di ; Advance buffer pointer
418 ; Some systems seem to get "stuck" in an error state when
419 ; using EBIOS. Doesn't happen when using CBIOS, which is
420 ; good, since some other systems get timeout failures
421 ; waiting for the floppy disk to spin up.
423 pushad ; Try resetting the device
428 loop .retry ; CX-- and jump if not zero
430 ;shr word [MaxTransfer],1 ; Reduce the transfer size
433 ; Total failure. Try falling back to CBIOS.
434 mov byte [getlinsec.jmp+1],(getlinsec_cbios-(getlinsec.jmp+2))
435 ;mov byte [MaxTransfer],63 ; Max possibe CBIOS transfer
438 ; ... fall through ...
443 ; getlinsec implementation for legacy CBIOS
452 movzx esi,word [bsSecPerTrack]
453 movzx edi,word [bsHeads]
455 ; Dividing by sectors to get (track,sector): we may have
456 ; up to 2^18 tracks, so we need to use 32-bit arithmetric.
460 xchg cx,dx ; CX <- sector index (0-based)
463 div edi ; Convert track to head/cyl
465 ; We should test this, but it doesn't fit...
470 ; Now we have AX = cyl, DX = head, CX = sector (0-based),
471 ; BP = sectors to transfer, SI = bsSecPerTrack,
472 ; ES:BX = data target
475 call maxtrans ; Enforce maximum transfer size
477 ; Must not cross track boundaries, so BP <= SI-CX
484 shl ah,6 ; Because IBM was STOOPID
485 ; and thought 8 bits were enough
486 ; then thought 10 bits were enough...
487 inc cx ; Sector numbers are 1-based, sigh
492 xchg ax,bp ; Sector to transfer count
493 mov ah,02h ; Read sectors
501 movzx ecx,al ; ECX <- sectors transferred
502 shl ax,SECTOR_SHIFT ; Convert sectors in AL to bytes in AX
517 xchg ax,bp ; Sectors transferred <- 0
518 shr word [MaxTransfer],1
520 ; Fall through to disk_error
523 ; kaboom: write a message and bail out.
529 mov sp,StackBuf-4 ; Reset stack
530 mov ds,si ; Reset data segment
531 pop dword [fdctab] ; Restore FDC table
532 .patch: ; When we have full code, intercept here
535 ; Write error message, this assumes screen page 0
539 mov ah,0Eh ; Write to screen as TTY
540 mov bx,0007h ; Attribute
545 int 16h ; Wait for keypress
546 int 19h ; And try once more to boot...
547 .norge: jmp short .norge ; If int 19h returned; this is the end
550 ; Truncate BP to MaxTransfer
559 ; Error message on failure
561 bailmsg: db 'Boot error', 0Dh, 0Ah, 0
563 ; This fails if the boot sector overflows
566 FirstSector dd 0xDEADBEEF ; Location of sector 1
567 MaxTransfer dw 0x007F ; Max transfer size
568 bootsignature dw 0AA55h
571 ; ===========================================================================
573 ; ===========================================================================
574 ; Start of LDLINUX.SYS
575 ; ===========================================================================
579 syslinux_banner db 0Dh, 0Ah
585 db version_str, ' ', date, ' ', 0
586 db 0Dh, 0Ah, 1Ah ; EOF if we "type" this in DOS
589 ldlinux_magic dd LDLINUX_MAGIC
590 dd LDLINUX_MAGIC^HEXDATE
593 ; This area is patched by the installer. It is found by looking for
594 ; LDLINUX_MAGIC, plus 8 bytes.
597 LDLDwords dw 0 ; Total dwords starting at ldlinux_sys
598 LDLSectors dw 0 ; Number of sectors - (bootsec+this sec)
599 CheckSum dd 0 ; Checksum starting at ldlinux_sys
600 ; value = LDLINUX_MAGIC - [sum of dwords]
602 ; Space for up to 64 sectors, the theoretical maximum
603 SectorPtrs times 64 dd 0
607 ; Note that some BIOSes are buggy and run the boot sector at 07C0:0000
608 ; instead of 0000:7C00 and the like. We don't want to add anything
609 ; more to the boot sector, so it is written to not assume a fixed
610 ; value in CS, but we don't want to deal with that anymore from now
617 ; Tell the user we got this far
619 mov si,syslinux_banner
623 ; Tell the user if we're using EBIOS or CBIOS
627 cmp byte [getlinsec.jmp+1],(getlinsec_ebios-(getlinsec.jmp+2))
635 %define HAVE_BIOSNAME 1
640 ; Now we read the rest of LDLINUX.SYS. Don't bother loading the first
641 ; sector again, though.
645 mov bx,7C00h+2*SECTOR_SIZE ; Where we start loading
651 lodsd ; First sector of this chunk
659 inc edx ; Next linear sector
660 cmp [si],edx ; Does it match
661 jnz .chunk_ready ; If not, this is it
662 add si,4 ; If so, add sector to chunk
663 jmp short .make_chunk
674 ; All loaded up, verify that we got what we needed.
675 ; Note: the checksum field is embedded in the checksum region, so
676 ; by the time we get to the end it should all cancel out.
681 mov edx,-LDLINUX_MAGIC
687 and edx,edx ; Should be zero
688 jz all_read ; We're cool, go for it!
691 ; Uh-oh, something went bad...
693 mov si,checksumerr_msg
698 ; -----------------------------------------------------------------------------
699 ; Subroutines that have to be in the first sector
700 ; -----------------------------------------------------------------------------
704 ; writestr: write a null-terminated string to the console
705 ; This assumes we're on page 0. This is only used for early
706 ; messages, so it should be OK.
712 mov ah,0Eh ; Write to screen as TTY
713 mov bx,0007h ; Attribute
719 ; getlinsecsr: save registers, call getlinsec, restore registers
727 ; Checksum error message
729 checksumerr_msg db ' Load error - ', 0 ; Boot failed appended
734 cbios_name db 'CBIOS', 0
735 ebios_name db 'EBIOS', 0
742 cmp word [Debug_Magic],0D00Dh
747 rl_checkpt equ $ ; Must be <= 8000h
749 rl_checkpt_off equ ($-$$)
751 %if rl_checkpt_off > 400h
752 %error "Sector 1 overflow"
756 ; ----------------------------------------------------------------------------
757 ; End of code and data that have to be in the first sector
758 ; ----------------------------------------------------------------------------
762 ; Let the user (and programmer!) know we got this far. This used to be
763 ; in Sector 1, but makes a lot more sense here.
770 ; Insane hack to expand the superblock to dwords
776 mov cx,superinfo_size
780 stosd ; Store expanded word
782 stosd ; Store expanded byte
786 ; Compute some information about this filesystem.
789 ; First, generate the map of regions
794 mov edx,[bsHugeSectors]
796 mov [TotalSectors],edx
801 mov eax,[bxResSectors]
802 mov [FAT],eax ; Beginning of FAT
806 mov edx,[bootsec+36] ; FAT32 BPB_FATsz32
810 mov [RootDirArea],eax ; Beginning of root directory
811 mov [RootDir],eax ; For FAT12/16 == root dir location
813 mov edx,[bxRootDirEnts]
814 add dx,SECTOR_SIZE/32-1
815 shr dx,SECTOR_SHIFT-5
816 mov [RootDirSize],edx
818 mov [DataArea],eax ; Beginning of data area
820 ; Next, generate a cluster size shift count and mask
821 mov eax,[bxSecPerClust]
826 mov [ClustByteShift],cl
835 ; FAT12, FAT16 or FAT28^H^H32? This computation is fscking ridiculous.
840 shr eax,cl ; cl == ClustShift
841 mov cl,nextcluster_fat12-(nextcluster+2)
842 cmp eax,4085 ; FAT12 limit
844 mov cl,nextcluster_fat16-(nextcluster+2)
845 cmp eax,65525 ; FAT16 limit
848 ; FAT32, root directory is a cluster chain
851 mov eax,[bootsec+44] ; Root directory cluster
856 mov cl,nextcluster_fat28-(nextcluster+2)
858 mov byte [nextcluster+1],cl
861 ; Common initialization code
863 %include "cpuinit.inc"
867 ; Clear Files structures
870 mov cx,(MAX_OPEN*open_file_t_size)/4
875 ; Initialize the metadata cache
880 ; Now, everything is "up and running"... patch kaboom for more
881 ; verbosity and using the full screen system
884 mov dword [kaboom.patch],0e9h+((kaboom2-(kaboom.patch+3)) << 8)
887 ; Now we're all set to start with our *real* business. First load the
888 ; configuration file (if any) and parse it.
890 ; In previous versions I avoided using 32-bit registers because of a
891 ; rumour some BIOSes clobbered the upper half of 32-bit registers at
892 ; random. I figure, though, that if there are any of those still left
893 ; they probably won't be trying to install Linux on them...
895 ; The code is still ripe with 16-bitisms, though. Not worth the hassle
896 ; to take'm out. In fact, we may want to put them back if we're going
897 ; to boot ELKS at some point.
901 ; Load configuration file
908 ; Now we have the config file open. Parse the config file and
909 ; run the user interface.
914 ; Linux kernel loading code is common.
916 %include "runkernel.inc"
919 ; COMBOOT-loading code
921 %include "comboot.inc"
923 %include "cmdline.inc"
926 ; Boot sector loading code
928 %include "bootsect.inc"
936 ; allocate_file: Allocate a file structure
949 .check: cmp dword [bx], byte 0
951 add bx,open_file_t_size ; ZF = 0
953 ; ZF = 0 if we fell out of the loop
959 ; Search the root directory for a pre-mangled filename in DS:DI.
961 ; NOTE: This file considers finding a zero-length file an
962 ; error. This is so we don't have to deal with that special
963 ; case elsewhere in the program (most loops have the test
969 ; DX:AX = file length in bytes
985 mov eax,[RootDir] ; First root directory sector
989 ; GS:SI now points to this sector
991 mov cx,SECTOR_SIZE/32 ; 32 == directory entry size
994 jz .failure ; Hit directory high water mark
1008 jnc .scansector ; CF is set if we're at end
1010 ; If we get here, we failed
1017 xor eax,eax ; ZF <- 1
1020 mov eax,[gs:si+28] ; File size
1021 add eax,SECTOR_SIZE-1
1022 shr eax,SECTOR_SHIFT
1023 jz .failure ; Zero-length file
1027 mov dx,[gs:si+20] ; High cluster word
1029 mov dx,[gs:si+26] ; Low cluster word
1033 mov [bx],edx ; Starting sector
1035 mov eax,[gs:si+28] ; File length again
1036 mov dx,[gs:si+30] ; 16-bitism, sigh
1038 and eax,eax ; ZF <- 0
1048 ; kaboom2: once everything is loaded, replace the part of kaboom
1049 ; starting with "kaboom.patch" with this part
1052 mov si,err_bootfailed
1056 int 19h ; And try once more to boot...
1057 .norge: jmp short .norge ; If int 19h returned; this is the end
1060 ; mangle_name: Mangle a DOS filename pointed to by DS:SI into a buffer pointed
1061 ; to by ES:DI; ends on encountering any whitespace
1065 mov cx,11 ; # of bytes to write
1068 cmp al,' ' ; If control or space, end
1070 cmp al,'.' ; Period -> space-fill
1077 jmp short mn_not_lower
1078 mn_is_period: mov al,' ' ; We need to space-fill
1079 mn_period_loop: cmp cx,3 ; If <= 3 characters left
1080 jbe mn_loop ; Just ignore it
1081 stosb ; Otherwise, write a period
1082 loop mn_period_loop ; Dec CX and (always) jump
1083 mn_not_uslower: cmp al,ucase_low
1087 mov bx,ucase_tab-ucase_low
1090 loop mn_loop ; Don't continue if too long
1092 mov al,' ' ; Space-fill name
1093 rep stosb ; Doesn't do anything if CX=0
1097 ; Upper-case table for extended characters; this is technically code page 865,
1098 ; but code page 437 users will probably not miss not being able to use the
1099 ; cent sign in kernel images too much :-)
1101 ; The table only covers the range 129 to 164; the rest we can deal with.
1105 ucase_tab db 154, 144, 'A', 142, 'A', 143, 128, 'EEEIII'
1106 db 142, 143, 144, 146, 146, 'O', 153, 'OUUY', 153, 154
1107 db 157, 156, 157, 158, 159, 'AIOU', 165
1110 ; unmangle_name: Does the opposite of mangle_name; converts a DOS-mangled
1111 ; filename to the conventional representation. This is needed
1112 ; for the BOOT_IMAGE= parameter for the kernel.
1113 ; NOTE: A 13-byte buffer is mandatory, even if the string is
1114 ; known to be shorter.
1116 ; DS:SI -> input mangled file name
1117 ; ES:DI -> output buffer
1119 ; On return, DI points to the first byte after the output name,
1120 ; which is set to a null byte.
1123 push si ; Save pointer to original name
1131 mov bp,di ; Position of last nonblank+1
1132 un_cb_space: loop un_copy_body
1134 mov al,'.' ; Don't save
1143 un_ce_space: loop un_copy_ext
1150 ; lower_case: Lower case a character in AL
1159 lc_1: cmp al,lcase_low
1164 mov bx,lcase_tab-lcase_low
1170 ; getfssec_edx: Get multiple sectors from a file
1172 ; This routine makes sure the subtransfers do not cross a 64K boundary,
1173 ; and will correct the situation if it does, UNLESS *sectors* cross
1177 ; EDX -> Current sector number
1178 ; CX -> Sector count (0FFFFh = until end of file)
1179 ; Must not exceed the ES segment
1180 ; Returns EDX=0, CF=1 on EOF (not necessarily error)
1181 ; All arguments are advanced to reflect data read.
1187 xor ebp,ebp ; Fragment sector count
1188 push edx ; Starting sector pointer
1196 add ax,bx ; Now AX = how far into 64K block we are
1197 not ax ; Bytes left in 64K block
1199 shr eax,SECTOR_SHIFT ; Sectors left in 64K block
1201 jnb .do_read ; Unless there is at least 1 more sector room...
1202 mov eax,edx ; Current sector
1203 inc edx ; Predict it's the linearly next sector
1206 cmp edx,eax ; Did it match?
1209 pop eax ; Starting sector pointer
1211 lea eax,[eax+ebp-1] ; This is the last sector actually read
1213 add bx,bp ; Adjust buffer pointer
1229 ; getfssec: Get multiple sectors from a file
1231 ; Same as above, except SI is a pointer to a open_file_t
1234 ; DS:SI -> Pointer to open_file_t
1235 ; CX -> Sector count (0FFFFh = until end of file)
1236 ; Must not exceed the ES segment
1237 ; Returns CF=1 on EOF (not necessarily error)
1238 ; All arguments are advanced to reflect data read.
1256 ; nextcluster: Advance a cluster pointer in EDI to the next cluster
1257 ; pointed at in the FAT tables. CF=0 on return if end of file.
1260 jmp strict short nextcluster_fat28 ; This gets patched
1270 pushf ; Save the shifted-out LSB (=CF)
1299 ; FAT16 decoding routine.
1306 shr eax,SECTOR_SHIFT-1
1311 movzx edi,word [gs:si+bx]
1318 ; FAT28 ("FAT32") decoding routine.
1325 shr eax,SECTOR_SHIFT-2
1331 mov edi,dword [gs:si+bx]
1332 and edi,0FFFFFFFh ; 28 bits only
1340 ; nextsector: Given a sector in EAX on input, return the next sector
1341 ; of the same filesystem object, which may be the root
1342 ; directory or a cluster chain. Returns EOF.
1362 test edi,[ClustMask]
1365 ; It's not the final sector in a cluster
1370 push gs ; nextcluster trashes gs
1377 ; Now EDI contains the cluster number
1380 jc .exit ; There isn't anything else...
1382 ; New cluster number now in EDI
1384 shl edi,cl ; CF <- 0, unless something is very wrong
1395 ; getfatsector: Check for a particular sector (in EAX) in the FAT cache,
1396 ; and return a pointer in GS:SI, loading it if needed.
1401 add eax,[FAT] ; FAT starting address
1404 ; -----------------------------------------------------------------------------
1406 ; -----------------------------------------------------------------------------
1408 %include "getc.inc" ; getc et al
1409 %include "conio.inc" ; Console I/O
1410 %include "plaincon.inc" ; writechr
1411 %include "writestr.inc" ; String output
1412 %include "configinit.inc" ; Initialize configuration
1413 %include "parseconfig.inc" ; High-level config file handling
1414 %include "parsecmd.inc" ; Low-level config file handling
1415 %include "bcopy32.inc" ; 32-bit bcopy
1416 %include "loadhigh.inc" ; Load a file into high memory
1417 %include "font.inc" ; VGA font stuff
1418 %include "graphics.inc" ; VGA graphics
1419 %include "highmem.inc" ; High memory sizing
1420 %include "strcpy.inc" ; strcpy()
1421 %include "cache.inc" ; Metadata disk cache
1423 ; -----------------------------------------------------------------------------
1424 ; Begin data section
1425 ; -----------------------------------------------------------------------------
1429 ; Lower-case table for codepage 865
1433 lcase_tab db 135, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138
1434 db 139, 140, 141, 132, 134, 130, 145, 145, 147, 148, 149
1435 db 150, 151, 152, 148, 129, 155, 156, 155, 158, 159, 160
1436 db 161, 162, 163, 164, 164
1438 copyright_str db ' Copyright (C) 1994-', year, ' H. Peter Anvin'
1440 boot_prompt db 'boot: ', 0
1441 wipe_char db BS, ' ', BS, 0
1442 err_notfound db 'Could not find kernel image: ',0
1443 err_notkernel db CR, LF, 'Invalid or corrupt kernel image.', CR, LF, 0
1444 err_noram db 'It appears your computer has less than '
1446 db 'K of low ("DOS")'
1448 db 'RAM. Linux needs at least this amount to boot. If you get'
1450 db 'this message in error, hold down the Ctrl key while'
1452 db 'booting, and I will take your word for it.', CR, LF, 0
1453 err_badcfg db 'Unknown keyword in syslinux.cfg.', CR, LF, 0
1454 err_noparm db 'Missing parameter in syslinux.cfg.', CR, LF, 0
1455 err_noinitrd db CR, LF, 'Could not find ramdisk image: ', 0
1456 err_nohighmem db 'Not enough memory to load specified kernel.', CR, LF, 0
1457 err_highload db CR, LF, 'Kernel transfer failure.', CR, LF, 0
1458 err_oldkernel db 'Cannot load a ramdisk with an old kernel image.'
1460 err_notdos db ': attempted DOS system call', CR, LF, 0
1461 err_comlarge db 'COMBOOT image too large.', CR, LF, 0
1462 err_a20 db CR, LF, 'A20 gate not responding!', CR, LF, 0
1463 err_bootfailed db CR, LF, 'Boot failed: please change disks and press '
1464 db 'a key to continue.', CR, LF, 0
1465 ready_msg db 'Ready.', CR, LF, 0
1466 crlfloading_msg db CR, LF
1467 loading_msg db 'Loading ', 0
1470 aborted_msg db ' aborted.' ; Fall through to crlf_msg!
1473 crff_msg db CR, FF, 0
1474 syslinux_cfg db 'SYSLINUXCFG' ; Mangled form
1475 ConfigName db 'syslinux.cfg',0 ; Unmangled form
1477 manifest db 'MANIFEST '
1480 ; Command line options we'd like to take a look at
1482 ; mem= and vga= are handled as normal 32-bit integer values
1483 initrd_cmd db 'initrd='
1484 initrd_cmd_len equ 7
1487 ; Config file keyword table
1489 %include "keywords.inc"
1492 ; Extensions to search for (in *forward* order).
1494 exten_table: db 'CBT',0 ; COMBOOT (specific)
1495 db 'BSS',0 ; Boot Sector (add superblock)
1496 db 'BS ',0 ; Boot Sector
1497 db 'COM',0 ; COMBOOT (same as DOS)
1500 dd 0, 0 ; Need 8 null bytes here
1503 ; Misc initialized (data) variables
1505 %ifdef debug ; This code for debugging only
1506 debug_magic dw 0D00Dh ; Debug code sentinel
1510 BufSafe dw trackbufsize/SECTOR_SIZE ; Clusters we can load into trackbuf
1511 BufSafeSec dw trackbufsize/SECTOR_SIZE ; = how many sectors?
1512 BufSafeBytes dw trackbufsize ; = how many bytes?
1513 EndOfGetCBuf dw getcbuf+trackbufsize ; = getcbuf+BufSafeBytes
1515 %if ( trackbufsize % SECTOR_SIZE ) != 0
1516 %error trackbufsize must be a multiple of SECTOR_SIZE