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
68 vk_append: resb max_cmd_len
+1 ; Command line
70 vk_end: equ $
; Should be <= vk_size
74 ; Segment assignments in the bottom 640K
75 ; Stick to the low 512K in case we're using something like M-systems flash
76 ; which load a driver into low RAM (evil!!)
78 ; 0000h - main code/data segment (and BIOS segment)
80 real_mode_seg
equ 4000h
81 cache_seg
equ 3000h ; 64K area for metadata cache
82 vk_seg
equ 2000h ; Virtual kernels
83 xfer_buf_seg
equ 1000h ; Bounce buffer for I/O to high mem
84 comboot_seg
equ real_mode_seg
; COMBOOT image loading zone
87 ; File structure. This holds the information for each currently open file.
90 file_sector resd
1 ; Sector pointer (0 = structure free)
91 file_left resd
1 ; Number of sectors left
95 %if
(open_file_t_size
& (open_file_t_size
-1))
96 %error
"open_file_t is not a power of 2"
100 ; ---------------------------------------------------------------------------
102 ; ---------------------------------------------------------------------------
105 ; Memory below this point is reserved for the BIOS and the MBR
108 trackbufsize
equ 8192
109 trackbuf resb trackbufsize
; Track buffer goes here
110 getcbuf resb trackbufsize
116 ; Expanded superblock
118 resq
16 ; The first 16 bytes expanded 8 times
119 FAT resd
1 ; Location of (first) FAT
120 RootDirArea resd
1 ; Location of root directory area
121 RootDir resd
1 ; Location of root directory proper
122 DataArea resd
1 ; Location of data area
123 RootDirSize resd
1 ; Root dir size in sectors
124 TotalSectors resd
1 ; Total number of sectors
125 EndSector resd
1 ; Location of filesystem end
126 ClustSize resd
1 ; Bytes/cluster
127 ClustMask resd
1 ; Sectors/cluster - 1
128 CopySuper resb
1 ; Distinguish .bs versus .bss
129 DriveNumber resb
1 ; BIOS drive number
130 ClustShift resb
1 ; Shift count for sectors/cluster
131 ClustByteShift resb
1 ; Shift count for bytes/cluster
133 alignb open_file_t_size
134 Files resb MAX_OPEN
*open_file_t_size
137 ; Constants for the xfer_buf_seg
139 ; The xfer_buf_seg is also used to store message file buffers. We
140 ; need two trackbuffers (text and graphics), plus a work buffer
141 ; for the graphics decompressor.
143 xbs_textbuf
equ 0 ; Also hard-coded, do not change
144 xbs_vgabuf
equ trackbufsize
145 xbs_vgatmpbuf
equ 2*trackbufsize
150 ; Some of the things that have to be saved very early are saved
151 ; "close" to the initial stack pointer offset, in order to
152 ; reduce the code size...
154 StackBuf
equ $
-44-32 ; Start the stack here (grow down - 4K)
155 PartInfo
equ StackBuf
; Saved partition table entry
156 FloppyTable
equ PartInfo
+16 ; Floppy info table (must follow PartInfo)
157 OrigFDCTabPtr
equ StackBuf
-4 ; The high dword on the stack
160 ; Primary entry point. Tempting as though it may be, we can't put the
161 ; initial "cli" here; the jmp opcode in the first byte is part of the
162 ; "magic number" (using the term very loosely) for the DOS superblock.
165 jmp short start
; 2 bytes
168 ; "Superblock" follows -- it's in the boot sector, so it's already
169 ; loaded and ready for us
171 bsOemName
db 'SYSLINUX' ; The SYS command sets this, so...
173 ; These are the fields we actually care about. We end up expanding them
174 ; all to dword size early in the code, so generate labels for both
175 ; the expanded and unexpanded versions.
178 bx %+ %1 equ SuperInfo
+($
-superblock
)*8+4
183 bx %+ %1 equ SuperInfo
+($
-superblock
)*8
188 bx %+ %1 equ $
; no expansion for dwords
203 superinfo_size
equ ($
-superblock
)-1 ; How much to expand
207 ; This is as far as FAT12/16 and FAT32 are consistent
209 zb
54 ; FAT12/16 need 26 more bytes,
210 ; FAT32 need 54 more bytes
211 superblock_len
equ $
-superblock
213 SecPerClust
equ bxSecPerClust
215 ; Note we don't check the constraints above now; we did that at install
219 cli ; No interrupts yet, please
226 mov sp,StackBuf
; Just below BSS
229 ; DS:SI may contain a partition table entry. Preserve it for us.
231 mov cx,8 ; Save partition info
235 mov ds,ax ; Now we can initialize DS...
238 ; Now sautee the BIOS floppy info block to that it will support decent-
239 ; size transfers; the floppy block is 11 bytes and is stored in the
240 ; INT 1Eh vector (brilliant waste of resources, eh?)
242 ; Of course, if BIOSes had been properly programmed, we wouldn't have
243 ; had to waste precious space with this code.
246 lfs si,[bx] ; FS:SI -> original fdctab
247 push fs ; Save on stack in case we need to bail
250 ; Save the old fdctab even if hard disk so the stack layout
251 ; is the same. The instructions above do not change the flags
252 mov [DriveNumber
],dl ; Save drive number in DL
253 and dl,dl ; If floppy disk (00-7F), assume no
258 mov cl,6 ; 12 bytes (CX == 0)
259 ; es:di -> FloppyTable already
260 ; This should be safe to do now, interrupts are off...
261 mov [bx],di ; FloppyTable
262 mov [bx+2],ax ; Segment 0
263 fs rep movsw ; Faster to move words
264 mov cl,[bsSecPerTrack
] ; Patch the sector count
267 int 13h ; Some BIOSes need this
269 jmp short not_harddisk
271 ; The drive number and possibly partition information was passed to us
272 ; by the BIOS or previous boot loader (MBR). Current "best practice" is to
273 ; trust that rather than what the superblock contains.
275 ; Would it be better to zero out bsHidden if we don't have a partition table?
277 ; Note: di points to beyond the end of PartInfo
280 test byte [di-16],7Fh
; Sanity check: "active flag" should
281 jnz no_partition
; be 00 or 80
282 mov eax,[di-8] ; Partition offset (dword)
286 ; Get disk drive parameters (don't trust the superblock.) Don't do this for
287 ; floppy drives -- INT 13:08 on floppy drives will (may?) return info about
288 ; what the *drive* supports, not about the *media*. Fortunately floppy disks
289 ; tend to have a fixed, well-defined geometry which is stored in the superblock.
291 ; DL == drive # still
298 inc dx ; Contains # of heads - 1
301 mov [bsSecPerTrack
],cx
305 ; Ready to enable interrupts, captain
310 ; Do we have EBIOS (EDD)?
314 mov ah,41h ; EDD existence query
320 test cl,1 ; Extended disk access functionality set
323 ; We have EDD support...
325 mov byte [getlinsec.
jmp+1],(getlinsec_ebios
-(getlinsec.
jmp+2))
329 ; Load the first sector of LDLINUX.SYS; this used to be all proper
330 ; with parsing the superblock and root directory; it doesn't fit
331 ; together with EBIOS support, unfortunately.
333 mov eax,[FirstSector
] ; Sector start
334 mov bx,ldlinux_sys
; Where to load it
337 ; Some modicum of integrity checking
338 cmp dword [ldlinux_magic
+4],LDLINUX_MAGIC^HEXDATE
345 ; getonesec: get one disk sector
348 mov bp,1 ; One sector
352 ; getlinsec: load a sequence of BP floppy sector given by the linear sector
353 ; number in EAX into the buffer at ES:BX. We try to optimize
354 ; by loading up to a whole track at a time, but the user
355 ; is responsible for not crossing a 64K boundary.
356 ; (Yes, BP is weird for a count, but it was available...)
358 ; On return, BX points to the first byte after the transferred
361 ; This routine assumes CS == DS, and trashes most registers.
363 ; Stylistic note: use "xchg" instead of "mov" when the source is a register
364 ; that is dead from that point; this saves space. However, please keep
365 ; the order to dst,src to keep things sane.
368 add eax,[bsHidden
] ; Add partition offset
369 xor edx,edx ; Zero-extend LBA (eventually allow 64 bits)
371 .
jmp: jmp strict
short getlinsec_cbios
376 ; getlinsec implementation for EBIOS (EDD)
380 push bp ; Sectors left
382 call maxtrans
; Enforce maximum transfer size
383 movzx edi,bp ; Sectors we are about to read
400 mov ah,42h ; Extended Read
404 lea sp,[si+16] ; Remove DAPA
407 add eax,edi ; Advance sector pointer
408 sub bp,di ; Sectors left
409 shl di,SECTOR_SHIFT
; 512-byte sectors
410 add bx,di ; Advance buffer pointer
417 ; Some systems seem to get "stuck" in an error state when
418 ; using EBIOS. Doesn't happen when using CBIOS, which is
419 ; good, since some other systems get timeout failures
420 ; waiting for the floppy disk to spin up.
422 pushad ; Try resetting the device
427 loop .retry
; CX-- and jump if not zero
429 ;shr word [MaxTransfer],1 ; Reduce the transfer size
432 ; Total failure. Try falling back to CBIOS.
433 mov byte [getlinsec.
jmp+1],(getlinsec_cbios
-(getlinsec.
jmp+2))
434 ;mov byte [MaxTransfer],63 ; Max possibe CBIOS transfer
437 ; ... fall through ...
442 ; getlinsec implementation for legacy CBIOS
451 movzx esi,word [bsSecPerTrack
]
452 movzx edi,word [bsHeads
]
454 ; Dividing by sectors to get (track,sector): we may have
455 ; up to 2^18 tracks, so we need to use 32-bit arithmetric.
459 xchg cx,dx ; CX <- sector index (0-based)
462 div edi ; Convert track to head/cyl
464 ; We should test this, but it doesn't fit...
469 ; Now we have AX = cyl, DX = head, CX = sector (0-based),
470 ; BP = sectors to transfer, SI = bsSecPerTrack,
471 ; ES:BX = data target
474 call maxtrans
; Enforce maximum transfer size
476 ; Must not cross track boundaries, so BP <= SI-CX
483 shl ah,6 ; Because IBM was STOOPID
484 ; and thought 8 bits were enough
485 ; then thought 10 bits were enough...
486 inc cx ; Sector numbers are 1-based, sigh
491 xchg ax,bp ; Sector to transfer count
492 mov ah,02h ; Read sectors
500 movzx ecx,al ; ECX <- sectors transferred
501 shl ax,SECTOR_SHIFT
; Convert sectors in AL to bytes in AX
516 xchg ax,bp ; Sectors transferred <- 0
517 shr word [MaxTransfer
],1
519 ; Fall through to disk_error
522 ; kaboom: write a message and bail out.
528 mov sp,StackBuf
-4 ; Reset stack
529 mov ds,si ; Reset data segment
530 pop dword [fdctab
] ; Restore FDC table
531 .
patch: ; When we have full code, intercept here
534 ; Write error message, this assumes screen page 0
538 mov ah,0Eh
; Write to screen as TTY
539 mov bx,0007h ; Attribute
544 int 16h ; Wait for keypress
545 int 19h ; And try once more to boot...
546 .
norge: jmp short .norge
; If int 19h returned; this is the end
549 ; Truncate BP to MaxTransfer
558 ; Error message on failure
560 bailmsg: db 'Boot error', 0Dh, 0Ah, 0
562 ; This fails if the boot sector overflows
565 FirstSector
dd 0xDEADBEEF ; Location of sector 1
566 MaxTransfer
dw 0x007F ; Max transfer size
567 bootsignature
dw 0AA55h
570 ; ===========================================================================
572 ; ===========================================================================
573 ; Start of LDLINUX.SYS
574 ; ===========================================================================
578 syslinux_banner
db 0Dh, 0Ah
584 db version_str
, ' ', date
, ' ', 0
585 db 0Dh, 0Ah, 1Ah ; EOF if we "type" this in DOS
588 ldlinux_magic
dd LDLINUX_MAGIC
589 dd LDLINUX_MAGIC^HEXDATE
592 ; This area is patched by the installer. It is found by looking for
593 ; LDLINUX_MAGIC, plus 8 bytes.
596 LDLDwords
dw 0 ; Total dwords starting at ldlinux_sys
597 LDLSectors
dw 0 ; Number of sectors - (bootsec+this sec)
598 CheckSum
dd 0 ; Checksum starting at ldlinux_sys
599 ; value = LDLINUX_MAGIC - [sum of dwords]
601 ; Space for up to 64 sectors, the theoretical maximum
602 SectorPtrs times
64 dd 0
606 ; Note that some BIOSes are buggy and run the boot sector at 07C0:0000
607 ; instead of 0000:7C00 and the like. We don't want to add anything
608 ; more to the boot sector, so it is written to not assume a fixed
609 ; value in CS, but we don't want to deal with that anymore from now
616 ; Tell the user we got this far
618 mov si,syslinux_banner
622 ; Tell the user if we're using EBIOS or CBIOS
626 cmp byte [getlinsec.
jmp+1],(getlinsec_ebios
-(getlinsec.
jmp+2))
634 %define HAVE_BIOSNAME
1
639 ; Now we read the rest of LDLINUX.SYS. Don't bother loading the first
640 ; sector again, though.
644 mov bx,7C00h
+2*SECTOR_SIZE
; Where we start loading
650 lodsd ; First sector of this chunk
658 inc edx ; Next linear sector
659 cmp [si],edx ; Does it match
660 jnz .chunk_ready
; If not, this is it
661 add si,4 ; If so, add sector to chunk
662 jmp short .make_chunk
673 ; All loaded up, verify that we got what we needed.
674 ; Note: the checksum field is embedded in the checksum region, so
675 ; by the time we get to the end it should all cancel out.
680 mov edx,-LDLINUX_MAGIC
686 and edx,edx ; Should be zero
687 jz all_read
; We're cool, go for it!
690 ; Uh-oh, something went bad...
692 mov si,checksumerr_msg
697 ; -----------------------------------------------------------------------------
698 ; Subroutines that have to be in the first sector
699 ; -----------------------------------------------------------------------------
703 ; writestr: write a null-terminated string to the console
704 ; This assumes we're on page 0. This is only used for early
705 ; messages, so it should be OK.
711 mov ah,0Eh
; Write to screen as TTY
712 mov bx,0007h ; Attribute
718 ; getlinsecsr: save registers, call getlinsec, restore registers
726 ; Checksum error message
728 checksumerr_msg
db ' Load error - ', 0 ; Boot failed appended
733 cbios_name
db 'CBIOS', 0
734 ebios_name
db 'EBIOS', 0
741 cmp word [Debug_Magic
],0D00Dh
746 rl_checkpt
equ $
; Must be <= 8000h
748 rl_checkpt_off
equ ($
-$$
)
750 %if rl_checkpt_off
> 400h
751 %error
"Sector 1 overflow"
755 ; ----------------------------------------------------------------------------
756 ; End of code and data that have to be in the first sector
757 ; ----------------------------------------------------------------------------
761 ; Let the user (and programmer!) know we got this far. This used to be
762 ; in Sector 1, but makes a lot more sense here.
769 ; Insane hack to expand the superblock to dwords
775 mov cx,superinfo_size
779 stosd ; Store expanded word
781 stosd ; Store expanded byte
785 ; Compute some information about this filesystem.
788 ; First, generate the map of regions
793 mov edx,[bsHugeSectors
]
795 mov [TotalSectors
],edx
800 mov eax,[bxResSectors
]
801 mov [FAT
],eax ; Beginning of FAT
805 mov edx,[bootsec
+36] ; FAT32 BPB_FATsz32
809 mov [RootDirArea
],eax ; Beginning of root directory
810 mov [RootDir
],eax ; For FAT12/16 == root dir location
812 mov edx,[bxRootDirEnts
]
813 add dx,SECTOR_SIZE
/32-1
814 shr dx,SECTOR_SHIFT
-5
815 mov [RootDirSize
],edx
817 mov [DataArea
],eax ; Beginning of data area
819 ; Next, generate a cluster size shift count and mask
820 mov eax,[bxSecPerClust
]
825 mov [ClustByteShift
],cl
834 ; FAT12, FAT16 or FAT28^H^H32? This computation is fscking ridiculous.
839 shr eax,cl ; cl == ClustShift
840 mov cl,nextcluster_fat12
-(nextcluster
+2)
841 cmp eax,4085 ; FAT12 limit
843 mov cl,nextcluster_fat16
-(nextcluster
+2)
844 cmp eax,65525 ; FAT16 limit
847 ; FAT32, root directory is a cluster chain
850 mov eax,[bootsec
+44] ; Root directory cluster
855 mov cl,nextcluster_fat28
-(nextcluster
+2)
857 mov byte [nextcluster
+1],cl
860 ; Common initialization code
862 %include "cpuinit.inc"
866 ; Clear Files structures
869 mov cx,(MAX_OPEN
*open_file_t_size
)/4
874 ; Initialize the metadata cache
879 ; Now, everything is "up and running"... patch kaboom for more
880 ; verbosity and using the full screen system
883 mov dword [kaboom.patch
],0e9h
+((kaboom2
-(kaboom.patch
+3)) << 8)
886 ; Now we're all set to start with our *real* business. First load the
887 ; configuration file (if any) and parse it.
889 ; In previous versions I avoided using 32-bit registers because of a
890 ; rumour some BIOSes clobbered the upper half of 32-bit registers at
891 ; random. I figure, though, that if there are any of those still left
892 ; they probably won't be trying to install Linux on them...
894 ; The code is still ripe with 16-bitisms, though. Not worth the hassle
895 ; to take'm out. In fact, we may want to put them back if we're going
896 ; to boot ELKS at some point.
900 ; Load configuration file
907 ; Now we have the config file open. Parse the config file and
908 ; run the user interface.
913 ; Linux kernel loading code is common.
915 %include "runkernel.inc"
918 ; COMBOOT-loading code
920 %include "comboot.inc"
922 %include "cmdline.inc"
925 ; Boot sector loading code
927 %include "bootsect.inc"
935 ; allocate_file: Allocate a file structure
948 .
check: cmp dword [bx], byte 0
950 add bx,open_file_t_size
; ZF = 0
952 ; ZF = 0 if we fell out of the loop
958 ; Search the root directory for a pre-mangled filename in DS:DI.
960 ; NOTE: This file considers finding a zero-length file an
961 ; error. This is so we don't have to deal with that special
962 ; case elsewhere in the program (most loops have the test
968 ; DX:AX = file length in bytes
984 mov eax,[RootDir
] ; First root directory sector
988 ; GS:SI now points to this sector
990 mov cx,SECTOR_SIZE
/32 ; 32 == directory entry size
993 jz .failure
; Hit directory high water mark
1007 jnc .scansector
; CF is set if we're at end
1009 ; If we get here, we failed
1016 xor eax,eax ; ZF <- 1
1019 mov eax,[gs:si+28] ; File size
1020 add eax,SECTOR_SIZE
-1
1021 shr eax,SECTOR_SHIFT
1022 jz .failure
; Zero-length file
1026 mov dx,[gs:si+20] ; High cluster word
1028 mov dx,[gs:si+26] ; Low cluster word
1032 mov [bx],edx ; Starting sector
1034 mov eax,[gs:si+28] ; File length again
1035 mov dx,[gs:si+30] ; 16-bitism, sigh
1037 and eax,eax ; ZF <- 0
1046 ; writechr: Write a single character in AL to the console without
1047 ; mangling any registers; handle video pages correctly.
1050 call write_serial
; write to serial port if needed
1052 test byte [cs:DisplayCon
], 01h
1056 mov bl,07h ; attribute
1057 mov bh,[cs:BIOS_page
] ; current page
1066 ; kaboom2: once everything is loaded, replace the part of kaboom
1067 ; starting with "kaboom.patch" with this part
1070 mov si,err_bootfailed
1074 int 19h ; And try once more to boot...
1075 .
norge: jmp short .norge
; If int 19h returned; this is the end
1078 ; mangle_name: Mangle a DOS filename pointed to by DS:SI into a buffer pointed
1079 ; to by ES:DI; ends on encountering any whitespace
1083 mov cx,11 ; # of bytes to write
1086 cmp al,' ' ; If control or space, end
1088 cmp al,'.' ; Period -> space-fill
1095 jmp short mn_not_lower
1096 mn_is_period: mov al,' ' ; We need to space-fill
1097 mn_period_loop: cmp cx,3 ; If <= 3 characters left
1098 jbe mn_loop
; Just ignore it
1099 stosb ; Otherwise, write a period
1100 loop mn_period_loop
; Dec CX and (always) jump
1101 mn_not_uslower: cmp al,ucase_low
1105 mov bx,ucase_tab
-ucase_low
1108 loop mn_loop
; Don't continue if too long
1110 mov al,' ' ; Space-fill name
1111 rep stosb ; Doesn't do anything if CX=0
1115 ; Upper-case table for extended characters; this is technically code page 865,
1116 ; but code page 437 users will probably not miss not being able to use the
1117 ; cent sign in kernel images too much :-)
1119 ; The table only covers the range 129 to 164; the rest we can deal with.
1123 ucase_tab
db 154, 144, 'A', 142, 'A', 143, 128, 'EEEIII'
1124 db 142, 143, 144, 146, 146, 'O', 153, 'OUUY', 153, 154
1125 db 157, 156, 157, 158, 159, 'AIOU', 165
1128 ; unmangle_name: Does the opposite of mangle_name; converts a DOS-mangled
1129 ; filename to the conventional representation. This is needed
1130 ; for the BOOT_IMAGE= parameter for the kernel.
1131 ; NOTE: A 13-byte buffer is mandatory, even if the string is
1132 ; known to be shorter.
1134 ; DS:SI -> input mangled file name
1135 ; ES:DI -> output buffer
1137 ; On return, DI points to the first byte after the output name,
1138 ; which is set to a null byte.
1141 push si ; Save pointer to original name
1149 mov bp,di ; Position of last nonblank+1
1150 un_cb_space: loop un_copy_body
1152 mov al,'.' ; Don't save
1161 un_ce_space: loop un_copy_ext
1168 ; lower_case: Lower case a character in AL
1177 lc_1: cmp al,lcase_low
1182 mov bx,lcase_tab
-lcase_low
1188 ; getfssec_edx: Get multiple sectors from a file
1190 ; This routine makes sure the subtransfers do not cross a 64K boundary,
1191 ; and will correct the situation if it does, UNLESS *sectors* cross
1195 ; EDX -> Current sector number
1196 ; CX -> Sector count (0FFFFh = until end of file)
1197 ; Must not exceed the ES segment
1198 ; Returns EDX=0, CF=1 on EOF (not necessarily error)
1199 ; All arguments are advanced to reflect data read.
1205 xor ebp,ebp ; Fragment sector count
1206 push edx ; Starting sector pointer
1214 add ax,bx ; Now AX = how far into 64K block we are
1215 not ax ; Bytes left in 64K block
1217 shr eax,SECTOR_SHIFT
; Sectors left in 64K block
1219 jnb .do_read
; Unless there is at least 1 more sector room...
1220 mov eax,edx ; Current sector
1221 inc edx ; Predict it's the linearly next sector
1224 cmp edx,eax ; Did it match?
1227 pop eax ; Starting sector pointer
1229 lea eax,[eax+ebp-1] ; This is the last sector actually read
1231 add bx,bp ; Adjust buffer pointer
1247 ; getfssec: Get multiple sectors from a file
1249 ; Same as above, except SI is a pointer to a open_file_t
1252 ; DS:SI -> Pointer to open_file_t
1253 ; CX -> Sector count (0FFFFh = until end of file)
1254 ; Must not exceed the ES segment
1255 ; Returns CF=1 on EOF (not necessarily error)
1256 ; All arguments are advanced to reflect data read.
1274 ; nextcluster: Advance a cluster pointer in EDI to the next cluster
1275 ; pointed at in the FAT tables. CF=0 on return if end of file.
1278 jmp strict
short nextcluster_fat28
; This gets patched
1288 pushf ; Save the shifted-out LSB (=CF)
1317 ; FAT16 decoding routine.
1324 shr eax,SECTOR_SHIFT
-1
1329 movzx edi,word [gs:si+bx]
1336 ; FAT28 ("FAT32") decoding routine.
1343 shr eax,SECTOR_SHIFT
-2
1349 mov edi,dword [gs:si+bx]
1350 and edi,0FFFFFFFh
; 28 bits only
1358 ; nextsector: Given a sector in EAX on input, return the next sector
1359 ; of the same filesystem object, which may be the root
1360 ; directory or a cluster chain. Returns EOF.
1380 test edi,[ClustMask
]
1383 ; It's not the final sector in a cluster
1388 push gs ; nextcluster trashes gs
1395 ; Now EDI contains the cluster number
1398 jc .exit
; There isn't anything else...
1400 ; New cluster number now in EDI
1402 shl edi,cl ; CF <- 0, unless something is very wrong
1413 ; getfatsector: Check for a particular sector (in EAX) in the FAT cache,
1414 ; and return a pointer in GS:SI, loading it if needed.
1419 add eax,[FAT
] ; FAT starting address
1422 ; -----------------------------------------------------------------------------
1424 ; -----------------------------------------------------------------------------
1426 %include "getc.inc" ; getc et al
1427 %include "conio.inc" ; Console I/O
1428 %include "writestr.inc" ; String output
1429 %include "parseconfig.inc" ; High-level config file handling
1430 %include "parsecmd.inc" ; Low-level config file handling
1431 %include "bcopy32.inc" ; 32-bit bcopy
1432 %include "loadhigh.inc" ; Load a file into high memory
1433 %include "font.inc" ; VGA font stuff
1434 %include "graphics.inc" ; VGA graphics
1435 %include "highmem.inc" ; High memory sizing
1436 %include "strcpy.inc" ; strcpy()
1437 %include "cache.inc" ; Metadata disk cache
1439 ; -----------------------------------------------------------------------------
1440 ; Begin data section
1441 ; -----------------------------------------------------------------------------
1445 ; Lower-case table for codepage 865
1449 lcase_tab
db 135, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138
1450 db 139, 140, 141, 132, 134, 130, 145, 145, 147, 148, 149
1451 db 150, 151, 152, 148, 129, 155, 156, 155, 158, 159, 160
1452 db 161, 162, 163, 164, 164
1454 copyright_str
db ' Copyright (C) 1994-', year
, ' H. Peter Anvin'
1456 boot_prompt
db 'boot: ', 0
1457 wipe_char
db BS
, ' ', BS
, 0
1458 err_notfound
db 'Could not find kernel image: ',0
1459 err_notkernel
db CR
, LF
, 'Invalid or corrupt kernel image.', CR
, LF
, 0
1460 err_noram
db 'It appears your computer has less than '
1462 db 'K of low ("DOS")'
1464 db 'RAM. Linux needs at least this amount to boot. If you get'
1466 db 'this message in error, hold down the Ctrl key while'
1468 db 'booting, and I will take your word for it.', CR
, LF
, 0
1469 err_badcfg
db 'Unknown keyword in syslinux.cfg.', CR
, LF
, 0
1470 err_noparm
db 'Missing parameter in syslinux.cfg.', CR
, LF
, 0
1471 err_noinitrd
db CR
, LF
, 'Could not find ramdisk image: ', 0
1472 err_nohighmem
db 'Not enough memory to load specified kernel.', CR
, LF
, 0
1473 err_highload
db CR
, LF
, 'Kernel transfer failure.', CR
, LF
, 0
1474 err_oldkernel
db 'Cannot load a ramdisk with an old kernel image.'
1476 err_notdos
db ': attempted DOS system call', CR
, LF
, 0
1477 err_comlarge
db 'COMBOOT image too large.', CR
, LF
, 0
1478 err_a20
db CR
, LF
, 'A20 gate not responding!', CR
, LF
, 0
1479 err_bootfailed
db CR
, LF
, 'Boot failed: please change disks and press '
1480 db 'a key to continue.', CR
, LF
, 0
1481 ready_msg
db 'Ready.', CR
, LF
, 0
1482 crlfloading_msg
db CR
, LF
1483 loading_msg
db 'Loading ', 0
1486 aborted_msg
db ' aborted.' ; Fall through to crlf_msg!
1489 crff_msg
db CR
, FF
, 0
1490 syslinux_cfg
db 'SYSLINUXCFG' ; Mangled form
1491 ConfigName
db 'syslinux.cfg',0 ; Unmangled form
1493 manifest
db 'MANIFEST '
1496 ; Command line options we'd like to take a look at
1498 ; mem= and vga= are handled as normal 32-bit integer values
1499 initrd_cmd
db 'initrd='
1500 initrd_cmd_len
equ 7
1503 ; Config file keyword table
1505 %include "keywords.inc"
1508 ; Extensions to search for (in *forward* order).
1510 exten_table: db 'CBT',0 ; COMBOOT (specific)
1511 db 'BSS',0 ; Boot Sector (add superblock)
1512 db 'BS ',0 ; Boot Sector
1513 db 'COM',0 ; COMBOOT (same as DOS)
1516 dd 0, 0 ; Need 8 null bytes here
1519 ; Misc initialized (data) variables
1521 %ifdef debug
; This code for debugging only
1522 debug_magic
dw 0D00Dh
; Debug code sentinel
1526 BufSafe
dw trackbufsize
/SECTOR_SIZE
; Clusters we can load into trackbuf
1527 BufSafeSec
dw trackbufsize
/SECTOR_SIZE
; = how many sectors?
1528 BufSafeBytes
dw trackbufsize
; = how many bytes?
1529 EndOfGetCBuf
dw getcbuf
+trackbufsize
; = getcbuf+BufSafeBytes
1531 %if
( trackbufsize
% SECTOR_SIZE
) != 0
1532 %error trackbufsize must be a multiple of SECTOR_SIZE