I created several test cases to figure out how some of the FreeDOS loaders can exhibit memory overlap in some conditions. I uploaded all the files involved (except for the repos, qemu, and NASM) to https://pushbx.org/ecm/test/20240204/
qemu-system-i386
) and NASMkernel.sys
from https://pushbx.org/ecm/download/fdkernel.zip (also shown below)command.com
from https://pushbx.org/ecm/download/freecom.zip (also shown below)himemx.exe
from https://github.com/Baron-von-Riedesel/HimemX/releases/tag/v3.38ldebug.com
, lddebug.com
, extlib.eld
, quit.com
, instsect.com
from lDebugint3.com
(hexadecimal dump: CC B8 00 4C CD 21
)fdconfig.sys
, makk128.bat
, callmakk.bat
(contents shown below)disktest$ unzip -jq ~/wwwecm/download/fdkernel.zip bin/kernel.sys disktest$ unzip -jq ~/wwwecm/download/freecom.zip command.com disktest$ dd if=/dev/zero bs=1024 count=128 | tr '\0' '\377' > k128kib1.sys 128+0 records in 128+0 records out 131072 bytes (131 kB, 128 KiB) copied, 0.000498291 s, 263 MB/s disktest$ dd if=/dev/zero bs=1024 count=128 > k128kib0.sys 128+0 records in 128+0 records out 131072 bytes (131 kB, 128 KiB) copied, 0.000682236 s, 192 MB/s disktest$ dd if=../ldebug/bin/lddebug.com of=k128kib0.sys conv=notrunc 169+0 records in 169+0 records out 86528 bytes (87 kB, 84 KiB) copied, 0.00103689 s, 83.4 MB/s disktest$ dd if=../ldebug/bin/lddebug.com of=k128kib1.sys conv=notrunc 169+0 records in 169+0 records out 86528 bytes (87 kB, 84 KiB) copied, 0.00120152 s, 72.0 MB/s disktest$ cat fdconfig.sys switches=/f files=128 device=a:\himemx.exe /verbose /method:bios shell=a:\command.com /e:2048 /p:fdautoex.bat disktest$ file fdconfig.sys fdconfig.sys: ASCII text, with CRLF line terminators disktest$ cat makk128.bat c:instsect c: /f=k128kib0.sys /b=c:\k128kib0.bin /s12=c:\boot12.bin /s16=c:\boot16.bin /s32=c:\boot32.bin c:instsect c: /f=k128kib1.sys /b=c:\k128kib1.bin /s12=c:\boot12.bin /s16=c:\boot16.bin /s32=c:\boot32.bin disktest$ file makk128.bat makk128.bat: ASCII text, with CRLF line terminators disktest$ cat callmakk.bat call c:makk128.bat quit disktest$ file callmakk.bat callmakk.bat: ASCII text, with CRLF line terminators disktest$
Assemble the boot sector loaders in the kernel repo, using the revision created by https://github.com/FDOS/kernel/pull/120
kernel/boot$ nasm boot.asm -DISFAT12 -o boot12.bin -l boot12.lst kernel/boot$ nasm boot.asm -DISFAT16 -o boot16.bin -l boot16.lst kernel/boot$ nasm boot32.asm -o boot32.bin -l boot32.lst kernel/boot$ nasm boot32lb.asm -o boot32lb.bin -l boot32lb.lst
Preparing a FAT12 image looks like this:
disktest$ nasm -I ../kernel/boot/ -I ../lmacros/ -I ../ldebug/bin/ ../bootimg/bootimg.asm -D_MBR -D_MEDIAID=0F8h -D_UNIT=80h -D_SPC=256 -D_SPI=10240 -D_SPF=1 -D_ERROR_SMALL32=0 -D_BPE=12 -o k128f12.img -D_PAYLOADFILE=k128kib0.sys,k128kib1.sys,extlib.eld,boot12.bin,boot16.bin,::rename,boot32lb.bin,boot32.bin,instsect.com,makk128.bat
Preparing a FAT32 image with the 386+ LBA loader looks like this (note the changed BPE and output filename):
disktest$ nasm -I ../kernel/boot/ -I ../lmacros/ -I ../ldebug/bin/ ../bootimg/bootimg.asm -D_MBR -D_MEDIAID=0F8h -D_UNIT=80h -D_SPC=256 -D_SPI=10240 -D_SPF=1 -D_ERROR_SMALL32=0 -D_BPE=32 -o k128f321.img -D_PAYLOADFILE=k128kib0.sys,k128kib1.sys,extlib.eld,boot12.bin,boot16.bin,::rename,boot32lb.bin,boot32.bin,instsect.com,makk128.bat
Preparing a FAT32 image with the 386+ LBA loader and the padded directory looks like this (note the ::directorypad keyword and output filename):
disktest$ nasm -I ../kernel/boot/ -I ../lmacros/ -I ../ldebug/bin/ ../bootimg/bootimg.asm -D_MBR -D_MEDIAID=0F8h -D_UNIT=80h -D_SPC=256 -D_SPI=10240 -D_SPF=1 -D_ERROR_SMALL32=0 -D_BPE=32 -o k128f322.img -D_PAYLOADFILE=::directorypad,$((256 * 512 / 32)),k128kib0.sys,k128kib1.sys,extlib.eld,boot12.bin,boot16.bin,::rename,boot32lb.bin,boot32.bin,instsect.com,makk128.bat
The same commands are used to create k128f323.img and k128f324.img, except that ::rename,boot32lb.bin,
is dropped.
All the preparation for creating the boot images:
disktest$ nasm -I ../kernel/boot/ -I ../lmacros/ -I ../ldebug/bin/ ../bootimg/bootimg.asm -D_MBR -D_MEDIAID=0F8h -D_UNIT=80h -D_SPC=256 -D_SPI=10240 -D_SPF=1 -D_ERROR_SMALL32=0 -D_BPE=12 -o k128f12.img -D_PAYLOADFILE=k128kib0.sys,k128kib1.sys,extlib.eld,boot12.bin,boot16.bin,::rename,boot32lb.bin,boot32.bin,instsect.com,makk128.bat disktest$ nasm -I ../kernel/boot/ -I ../lmacros/ -I ../ldebug/bin/ ../bootimg/bootimg.asm -D_MBR -D_MEDIAID=0F8h -D_UNIT=80h -D_SPC=256 -D_SPI=10240 -D_SPF=1 -D_ERROR_SMALL32=0 -D_BPE=32 -o k128f321.img -D_PAYLOADFILE=k128kib0.sys,k128kib1.sys,extlib.eld,boot12.bin,boot16.bin,::rename,boot32lb.bin,boot32.bin,instsect.com,makk128.bat ../bootimg/bootimg.asm:522: warning: FAT would be detected as FAT12 (39 = 27h clusters) [-w+user] disktest$ nasm -I ../kernel/boot/ -I ../lmacros/ -I ../ldebug/bin/ ../bootimg/bootimg.asm -D_MBR -D_MEDIAID=0F8h -D_UNIT=80h -D_SPC=256 -D_SPI=10240 -D_SPF=1 -D_ERROR_SMALL32=0 -D_BPE=32 -o k128f322.img -D_PAYLOADFILE=::directorypad,$((256 * 512 / 32)),k128kib0.sys,k128kib1.sys,extlib.eld,boot12.bin,boot16.bin,::rename,boot32lb.bin,boot32.bin,instsect.com,makk128.bat ../bootimg/bootimg.asm:522: warning: FAT would be detected as FAT12 (39 = 27h clusters) [-w+user] disktest$ nasm -I ../kernel/boot/ -I ../lmacros/ -I ../ldebug/bin/ ../bootimg/bootimg.asm -D_MBR -D_MEDIAID=0F8h -D_UNIT=80h -D_SPC=256 -D_SPI=10240 -D_SPF=1 -D_ERROR_SMALL32=0 -D_BPE=32 -o k128f323.img -D_PAYLOADFILE=k128kib0.sys,k128kib1.sys,extlib.eld,boot12.bin,boot16.bin,boot32.bin,instsect.com,makk128.bat ../bootimg/bootimg.asm:522: warning: FAT would be detected as FAT12 (39 = 27h clusters) [-w+user] disktest$ nasm -I ../kernel/boot/ -I ../lmacros/ -I ../ldebug/bin/ ../bootimg/bootimg.asm -D_MBR -D_MEDIAID=0F8h -D_UNIT=80h -D_SPC=256 -D_SPI=10240 -D_SPF=1 -D_ERROR_SMALL32=0 -D_BPE=32 -o k128f324.img -D_PAYLOADFILE=::directorypad,$((256 * 512 / 32)),k128kib0.sys,k128kib1.sys,extlib.eld,boot12.bin,boot16.bin,boot32.bin,instsect.com,makk128.bat ../bootimg/bootimg.asm:522: warning: FAT would be detected as FAT12 (39 = 27h clusters) [-w+user] disktest$
To create the boot sector loader chain files for k128f12.img (the FAT12 image):
disktest$ nasm -l oldmbr.lst ../ldosmbr/oldmbr.asm -I ../lmacros/ -o oldmbr.bin; nasm -l boot12fd.lst ../ldosboot/boot.asm -I ../lmacros/ -D_COMPAT_FREEDOS -D_LBA=0 -D_USE_PART_INFO=0 -o boot12fd.bin; nasm ../bootimg/bootimg.asm -I ../lmacros/ -I ../ldebug/bin/ -o diskette.img -D_ALIGNDATA=0 -D_BOOTPATCHFILE=boot12fd.bin -D_MBRPATCHFILE=oldmbr.bin -D_PAYLOADFILE=ldebug.com,quit.com,kernel.sys,command.com,::rename,callmakk.bat,fdautoex.bat,fdconfig.sys,int3.com,himemx.exe,extlib.eld -D_ERROR_SMALL32=0 -D_BOOTINFOFILE=::bootpatchfile && qemu-system-i386 -fda diskette.img -boot order=a -display curses -hda k128f12.img
The parameter after -hda
is swapped to create the chain files for the FAT32 images.
To use the serial I/O of lDebug on a Linux host, you can run socat as in:
$ socat -r /tmp/trace.log pty,link=/tmp/vptty-dos,rawer pty,link=/tmp/vptty-linux,rawer & disown
Then picocom like: picocom /tmp/vptty-linux
Finally, run qemu like so:
disktest$ nasm -l oldmbr.lst ../ldosmbr/oldmbr.asm -I ../lmacros/ -o oldmbr.bin; nasm -l boot12ld.lst ../ldosboot/boot.asm -I ../lmacros/ -D_LOAD_NAME="'LDEBUG'" -o boot12ld.bin; nasm ../bootimg/bootimg.asm -I ../lmacros/ -I ../ldebug/bin/ -o diskette.img -D_ALIGNDATA=0 -D_BOOTPATCHFILE=boot12ld.bin -D_MBRPATCHFILE=oldmbr.bin -D_PAYLOADFILE=ldebug.com,quit.com,kernel.sys,command.com,::fill,1,32,fdautoex.bat,fdconfig.sys,int3.com,himemx.exe,extlib.eld -D_ERROR_SMALL32=0 -D_BOOTINFOFILE=::bootpatchfile && qemu-system-i386 -fda diskette.img -boot order=a -display curses -chardev serial,id=serial2,path=/tmp/vptty-dos -serial null -serial chardev:serial2 -hda k128f12.img
(Replace the parameter after -hda
with the other filenames to run the FAT32 loaders.)
Once the lDebug command line prompts for input (with a -
dash prompt), enter a BOOT command like boot protocol chain hda1/k128kib0.bin
or boot protocol chain hda1/k128kib1.bin
. If it is expected to work, run a g
command and the lDDebug prompt (tilde dash, ~-
) should show up. Entering q
to lDDebug will return control to the lDebug instance.
At the lDebug prompt, enter install timer, serial
to connect to the serial terminal. This will prompt the serial terminal for a "KEEP" keyword confirmation.
The FAT12 loader (in k128f12.img) will run as expected by default. However, if the load segment (FreeDOS SYS /L switch) is set to a larger value than the usual 60h or 70h, such as 200h, then the loader will corrupt its cluster list once it has read the full first cluster of the kernel file. If the kernel file is padded with zeros then the cluster list will be corrupted with zeroes, which happen to be the End Of Chain marker. However, if the file contains other data such as all-1s in the trail then the cluster list will be corrupted differently, leading to errors.
-boot protocol chain hda1/k128kib0.bin -e cs:7C5C 0000:7C5C 60.00 00.02
Patch the /L parameter address to 200h:0 rather than 60h:0.
-p 10 silent 1 AX=1FE0 BX=0080 CX=0000 DX=0080 SP=7BA0 BP=7C00 SI=7E00 DI=7E00 DS=1FE0 ES=1FE0 SS=1FE0 CS=1FE0 IP=7C66 NV UP EI PL ZR NA PE NC 1FE0:7C66 885624 mov [bp+24], dl SS:7C24=80
Skip the initial relocation of the loader, to allow to use breakpoints next.
-g 7CE3 AX=0002 BX=0000 CX=0000 DX=0080 SP=7BA0 BP=7C00 SI=7DFC DI=0000 DS=1FE0 ES=0200 SS=1FE0 CS=1FE0 IP=7CE3 NV UP EI PL ZR NA PE NC 1FE0:7CE3 50 push ax
Skip to where the directory scan has found the file.
-p AX=0002 BX=0000 CX=0000 DX=0080 SP=7B9E BP=7C00 SI=7DFC DI=0000 DS=1FE0 ES=0200 SS=1FE0 CS=1FE0 IP=7CE4 NV UP EI PL ZR NA PE NC 1FE0:7CE4 C45E5A les bx, [bp+5A] SS:7C5A=0200:0000 - AX=0002 BX=0000 CX=0000 DX=0080 SP=7B9E BP=7C00 SI=7DFC DI=0000 DS=1FE0 ES=0200 SS=1FE0 CS=1FE0 IP=7CE7 NV UP EI PL ZR NA PE NC 1FE0:7CE7 8B7E16 mov di, [bp+16] SS:7C16=0001 - AX=0002 BX=0000 CX=0000 DX=0080 SP=7B9E BP=7C00 SI=7DFC DI=0001 DS=1FE0 ES=0200 SS=1FE0 CS=1FE0 IP=7CEA NV UP EI PL ZR NA PE NC 1FE0:7CEA 8B46D2 mov ax, [bp-2E] SS:7BD2=0025 - AX=0025 BX=0000 CX=0000 DX=0080 SP=7B9E BP=7C00 SI=7DFC DI=0001 DS=1FE0 ES=0200 SS=1FE0 CS=1FE0 IP=7CED NV UP EI PL ZR NA PE NC 1FE0:7CED 8B56D4 mov dx, [bp-2C] SS:7BD4=0000 - AX=0025 BX=0000 CX=0000 DX=0000 SP=7B9E BP=7C00 SI=7DFC DI=0001 DS=1FE0 ES=0200 SS=1FE0 CS=1FE0 IP=7CF0 NV UP EI PL ZR NA PE NC 1FE0:7CF0 E86C00 call 7D5F - AX=0020 BX=0000 CX=0004 DX=0080 SP=7B9E BP=7C00 SI=7DFC DI=0000 DS=1FE0 ES=0220 SS=1FE0 CS=1FE0 IP=7CF3 NV UP EI PL ZR NA PE NC 1FE0:7CF3 58 pop ax - AX=0002 BX=0000 CX=0004 DX=0080 SP=7BA0 BP=7C00 SI=7DFC DI=0000 DS=1FE0 ES=0220 SS=1FE0 CS=1FE0 IP=7CF4 NV UP EI PL ZR NA PE NC 1FE0:7CF4 1E push ds - AX=0002 BX=0000 CX=0004 DX=0080 SP=7B9E BP=7C00 SI=7DFC DI=0000 DS=1FE0 ES=0220 SS=1FE0 CS=1FE0 IP=7CF5 NV UP EI PL ZR NA PE NC 1FE0:7CF5 07 pop es - AX=0002 BX=0000 CX=0004 DX=0080 SP=7BA0 BP=7C00 SI=7DFC DI=0000 DS=1FE0 ES=1FE0 SS=1FE0 CS=1FE0 IP=7CF6 NV UP EI PL ZR NA PE NC 1FE0:7CF6 8E5E5C mov ds, [bp+5C] SS:7C5C=0200 - AX=0002 BX=0000 CX=0004 DX=0080 SP=7BA0 BP=7C00 SI=7DFC DI=0000 DS=0200 ES=1FE0 SS=1FE0 CS=1FE0 IP=7CF9 NV UP EI PL ZR NA PE NC 1FE0:7CF9 BF0020 mov di, 2000 - AX=0002 BX=0000 CX=0004 DX=0080 SP=7BA0 BP=7C00 SI=7DFC DI=2000 DS=0200 ES=1FE0 SS=1FE0 CS=1FE0 IP=7CFC NV UP EI PL ZR NA PE NC 1FE0:7CFC AB stosw - AX=0002 BX=0000 CX=0004 DX=0080 SP=7BA0 BP=7C00 SI=7DFC DI=2002 DS=0200 ES=1FE0 SS=1FE0 CS=1FE0 IP=7CFD NV UP EI PL ZR NA PE NC 1FE0:7CFD 89C6 mov si, ax - AX=0002 BX=0000 CX=0004 DX=0080 SP=7BA0 BP=7C00 SI=0002 DI=2002 DS=0200 ES=1FE0 SS=1FE0 CS=1FE0 IP=7CFF NV UP EI PL ZR NA PE NC 1FE0:7CFF 01F6 add si, si - AX=0002 BX=0000 CX=0004 DX=0080 SP=7BA0 BP=7C00 SI=0004 DI=2002 DS=0200 ES=1FE0 SS=1FE0 CS=1FE0 IP=7D01 NV UP EI PL NZ NA PO NC 1FE0:7D01 01C6 add si, ax - AX=0002 BX=0000 CX=0004 DX=0080 SP=7BA0 BP=7C00 SI=0006 DI=2002 DS=0200 ES=1FE0 SS=1FE0 CS=1FE0 IP=7D03 NV UP EI PL NZ NA PE NC 1FE0:7D03 D1EE shr si, 1 - AX=0002 BX=0000 CX=0004 DX=0080 SP=7BA0 BP=7C00 SI=0003 DI=2002 DS=0200 ES=1FE0 SS=1FE0 CS=1FE0 IP=7D05 NV UP EI PL NZ NA PE NC 1FE0:7D05 AD lodsw - AX=FFFF BX=0000 CX=0004 DX=0080 SP=7BA0 BP=7C00 SI=0005 DI=2002 DS=0200 ES=1FE0 SS=1FE0 CS=1FE0 IP=7D06 NV UP EI PL NZ NA PE NC 1FE0:7D06 7304 jae 7D0C jumping - AX=FFFF BX=0000 CX=0004 DX=0080 SP=7BA0 BP=7C00 SI=0005 DI=2002 DS=0200 ES=1FE0 SS=1FE0 CS=1FE0 IP=7D0C NV UP EI PL NZ NA PE NC 1FE0:7D0C 80E40F and ah, 0F - AX=0FFF BX=0000 CX=0004 DX=0080 SP=7BA0 BP=7C00 SI=0005 DI=2002 DS=0200 ES=1FE0 SS=1FE0 CS=1FE0 IP=7D0F NV UP EI PL NZ NA PE NC 1FE0:7D0F 3DF80F cmp ax, 0FF8 - AX=0FFF BX=0000 CX=0004 DX=0080 SP=7BA0 BP=7C00 SI=0005 DI=2002 DS=0200 ES=1FE0 SS=1FE0 CS=1FE0 IP=7D12 NV UP EI PL NZ NA PO NC 1FE0:7D12 72E8 jb 7CFC not jumping - AX=0FFF BX=0000 CX=0004 DX=0080 SP=7BA0 BP=7C00 SI=0005 DI=2002 DS=0200 ES=1FE0 SS=1FE0 CS=1FE0 IP=7D14 NV UP EI PL NZ NA PO NC 1FE0:7D14 31C0 xor ax, ax - AX=0000 BX=0000 CX=0004 DX=0080 SP=7BA0 BP=7C00 SI=0005 DI=2002 DS=0200 ES=1FE0 SS=1FE0 CS=1FE0 IP=7D16 NV UP EI PL ZR NA PE NC 1FE0:7D16 AB stosw - AX=0000 BX=0000 CX=0004 DX=0080 SP=7BA0 BP=7C00 SI=0005 DI=2004 DS=0200 ES=1FE0 SS=1FE0 CS=1FE0 IP=7D17 NV UP EI PL ZR NA PE NC 1FE0:7D17 0E push cs - AX=0000 BX=0000 CX=0004 DX=0080 SP=7B9E BP=7C00 SI=0005 DI=2004 DS=0200 ES=1FE0 SS=1FE0 CS=1FE0 IP=7D18 NV UP EI PL ZR NA PE NC 1FE0:7D18 1F pop ds - AX=0000 BX=0000 CX=0004 DX=0080 SP=7BA0 BP=7C00 SI=0005 DI=2004 DS=1FE0 ES=1FE0 SS=1FE0 CS=1FE0 IP=7D19 NV UP EI PL ZR NA PE NC 1FE0:7D19 C45E5A les bx, [bp+5A] SS:7C5A=0200:0000 - AX=0000 BX=0000 CX=0004 DX=0080 SP=7BA0 BP=7C00 SI=0005 DI=2004 DS=1FE0 ES=0200 SS=1FE0 CS=1FE0 IP=7D1C NV UP EI PL ZR NA PE NC 1FE0:7D1C BE0020 mov si, 2000 - AX=0000 BX=0000 CX=0004 DX=0080 SP=7BA0 BP=7C00 SI=2000 DI=2004 DS=1FE0 ES=0200 SS=1FE0 CS=1FE0 IP=7D1F NV UP EI PL ZR NA PE NC 1FE0:7D1F AD lodsw - AX=0002 BX=0000 CX=0004 DX=0080 SP=7BA0 BP=7C00 SI=2002 DI=2004 DS=1FE0 ES=0200 SS=1FE0 CS=1FE0 IP=7D20 NV UP EI PL ZR NA PE NC 1FE0:7D20 09C0 or ax, ax - AX=0002 BX=0000 CX=0004 DX=0080 SP=7BA0 BP=7C00 SI=2002 DI=2004 DS=1FE0 ES=0200 SS=1FE0 CS=1FE0 IP=7D22 NV UP EI PL NZ NA PO NC 1FE0:7D22 7505 jnz 7D29 jumping - AX=0002 BX=0000 CX=0004 DX=0080 SP=7BA0 BP=7C00 SI=2002 DI=2004 DS=1FE0 ES=0200 SS=1FE0 CS=1FE0 IP=7D29 NV UP EI PL NZ NA PO NC 1FE0:7D29 48 dec ax - AX=0001 BX=0000 CX=0004 DX=0080 SP=7BA0 BP=7C00 SI=2002 DI=2004 DS=1FE0 ES=0200 SS=1FE0 CS=1FE0 IP=7D2A NV UP EI PL NZ NA PO NC 1FE0:7D2A 48 dec ax - AX=0000 BX=0000 CX=0004 DX=0080 SP=7BA0 BP=7C00 SI=2002 DI=2004 DS=1FE0 ES=0200 SS=1FE0 CS=1FE0 IP=7D2B NV UP EI PL ZR NA PE NC 1FE0:7D2B 8B7E0D mov di, [bp+0D] SS:7C0D=0100 - AX=0000 BX=0000 CX=0004 DX=0080 SP=7BA0 BP=7C00 SI=2002 DI=0100 DS=1FE0 ES=0200 SS=1FE0 CS=1FE0 IP=7D2E NV UP EI PL ZR NA PE NC 1FE0:7D2E 4F dec di - AX=0000 BX=0000 CX=0004 DX=0080 SP=7BA0 BP=7C00 SI=2002 DI=00FF DS=1FE0 ES=0200 SS=1FE0 CS=1FE0 IP=7D2F NV UP EI PL NZ AC PE NC 1FE0:7D2F 81E7FF00 and di, 00FF - AX=0000 BX=0000 CX=0004 DX=0080 SP=7BA0 BP=7C00 SI=2002 DI=00FF DS=1FE0 ES=0200 SS=1FE0 CS=1FE0 IP=7D33 NV UP EI PL NZ NA PE NC 1FE0:7D33 47 inc di - AX=0000 BX=0000 CX=0004 DX=0080 SP=7BA0 BP=7C00 SI=2002 DI=0100 DS=1FE0 ES=0200 SS=1FE0 CS=1FE0 IP=7D34 NV UP EI PL NZ AC PE NC 1FE0:7D34 F7E7 mul di - AX=0000 BX=0000 CX=0004 DX=0000 SP=7BA0 BP=7C00 SI=2002 DI=0100 DS=1FE0 ES=0200 SS=1FE0 CS=1FE0 IP=7D36 NV UP EI PL ZR NA PE NC 1FE0:7D36 0346DA add ax, [bp-26] SS:7BDA=0035 - AX=0035 BX=0000 CX=0004 DX=0000 SP=7BA0 BP=7C00 SI=2002 DI=0100 DS=1FE0 ES=0200 SS=1FE0 CS=1FE0 IP=7D39 NV UP EI PL NZ NA PE NC 1FE0:7D39 1356DC adc dx, [bp-24] SS:7BDC=0000 - AX=0035 BX=0000 CX=0004 DX=0000 SP=7BA0 BP=7C00 SI=2002 DI=0100 DS=1FE0 ES=0200 SS=1FE0 CS=1FE0 IP=7D3C NV UP EI PL ZR NA PE NC 1FE0:7D3C E82000 call 7D5F -p AX=0020 BX=0000 CX=0004 DX=0080 SP=7BA0 BP=7C00 SI=2002 DI=0000 DS=1FE0 ES=2200 SS=1FE0 CS=1FE0 IP=7D3F NV UP EI PL ZR NA PE NC 1FE0:7D3F EBDE jmp 7D1F - AX=0020 BX=0000 CX=0004 DX=0080 SP=7BA0 BP=7C00 SI=2002 DI=0000 DS=1FE0 ES=2200 SS=1FE0 CS=1FE0 IP=7D1F NV UP EI PL ZR NA PE NC 1FE0:7D1F AD lodsw -h linear es:0 00022000 decimal: 139264 -h linear ds:si 00021E02 decimal: 138754 -t AX=0000 BX=0000 CX=0004 DX=0080 SP=7BA0 BP=7C00 SI=2004 DI=0000 DS=1FE0 ES=2200 SS=1FE0 CS=1FE0 IP=7D20 NV UP EI PL ZR NA PE NC 1FE0:7D20 09C0 or ax, ax
The linear of es:0
points past the last data read from the kernel file by the prior readDisk call. The linear of ds:si
indicates where the next entry of the cluster list is read from. As is visible, the cluster list entry is located in memory below the end of the read file data.
-boot protocol chain hda1/k128kib1.bin -e cs:7C5C 0000:7C5C 60.00 00.02 -p 10 silent 1 AX=1FE0 BX=0080 CX=0000 DX=0080 SP=7BA0 BP=7C00 SI=7E00 DI=7E00 DS=1FE0 ES=1FE0 SS=1FE0 CS=1FE0 IP=7C66 NV UP EI PL ZR NA PE NC 1FE0:7C66 885624 mov [bp+24], dl SS:7C24=80 -g 7D1F AX=0000 BX=0000 CX=0004 DX=0080 SP=7BA0 BP=7C00 SI=2000 DI=2004 DS=1FE0 ES=0200 SS=1FE0 CS=1FE0 IP=7D1F NV UP EI PL ZR NA PE NC 1FE0:7D1F AD lodsw - AX=0020 BX=0000 CX=0004 DX=0080 SP=7BA0 BP=7C00 SI=2002 DI=0000 DS=1FE0 ES=2200 SS=1FE0 CS=1FE0 IP=7D1F NV UP EI PL ZR NA PE NC 1FE0:7D1F AD lodsw -h linear es:0 00022000 decimal: 139264 -h linear ds:si 00021E02 decimal: 138754 -t AX=FFFF BX=0000 CX=0004 DX=0080 SP=7BA0 BP=7C00 SI=2004 DI=0000 DS=1FE0 ES=2200 SS=1FE0 CS=1FE0 IP=7D20 NV UP EI PL ZR NA PE NC 1FE0:7D20 09C0 or ax, ax -
Same test case, except this time with the file ending in all-1s. It is plainly visible that the corrupted cluster list entry reads as 0FFFFh, which is invalid. Continuing the run with a G command to lDebug at this point results in the "Error!" display from the loader. A keypress then will return to the debugger, with the "Boot load called" interrupt message.
The cutoff value of the /L load segment is that it works if the segment is 1E0h or lower, and fails if it is 1E1h or higher. This is also visible above in that the second cluster list entry is loaded from linear 21E02h which is just above the file data if an 128 KiB file is loaded to 1E00h (segmented 1E0h:0).
lDebug connected to serial port. Enter KEEP to confirm. = keep -boot protocol chain hda1/k128kib1.bin -d cs:ip 0000:7C00 EB 3C 90 00 00 00 00 00-00 00 00 00 02 00 01 00 .<.............. 0000:7C10 02 E0 00 00 28 F8 01 00-12 00 02 00 24 00 00 00 ....(.......$... 0000:7C20 00 00 00 00 80 00 29 00-00 00 00 4E 4F 20 4E 41 ......)....NO NA 0000:7C30 4D 45 20 20 20 20 46 41-54 31 32 20 20 20 FA FC ME FAT12 .. 0000:7C40 31 C0 8E D8 BD 00 7C B8-E0 1F 8E C0 89 EE 89 EF 1.....|......... 0000:7C50 B9 00 01 F3 A5 EA 5E 7C-E0 1F 00 00 60 00 8E D8 ......^|....`... 0000:7C60 8E D0 8D 66 A0 FB 88 56-24 C7 46 C0 10 00 C7 46 ...f...V$.F....F 0000:7C70 C2 01 00 8C 5E C6 C7 46-C4 A0 63 8B 76 1C 8B 7E ....^..F..c.v..~ -e 0:7C5C as words 1E0 -g Boot load called
This works, the qemu terminal displays the lDDebug prompt.
-boot protocol chain hda1/k128kib1.bin -e 0:7C5C as words 1E1 -g Boot load called -
This does not work, the qemu terminal displays the "Error!" message from the loader.
This requires using k128f321.img or k128f323.img, the images that are formatted without the directory padding. Using k128f321.img (the LBA 386 loader):
-boot protocol chain hda1/k128kib0.bin -p 10 silent 1 AX=1FE0 BX=0080 CX=0000 DX=0080 SP=7BE0 BP=7C00 SI=7E00 DI=7E00 DS=1FE0 ES=1FE0 SS=1FE0 CS=1FE0 IP=7C82 NV UP EI PL ZR NA PE NC 1FE0:7C82 885640 mov [bp+40], dl SS:7C40=80
Skip the initial relocation.
- AX=1FE0 BX=0080 CX=0000 DX=0080 SP=7BE0 BP=7C00 SI=7E00 DI=7E00 DS=1FE0 ES=1FE0 SS=1FE0 CS=1FE0 IP=7C85 NV UP EI PL ZR NA PE NC 1FE0:7C85 BEC67D mov si, 7DC6 - AX=1FE0 BX=0080 CX=0000 DX=0080 SP=7BE0 BP=7C00 SI=7DC6 DI=7E00 DS=1FE0 ES=1FE0 SS=1FE0 CS=1FE0 IP=7C88 NV UP EI PL ZR NA PE NC 1FE0:7C88 E8F900 call 7D84 - AX=0E00 BX=0000 CX=0000 DX=0080 SP=7BE0 BP=7C00 SI=7DD7 DI=7E00 DS=1FE0 ES=1FE0 SS=1FE0 CS=1FE0 IP=7C8B NV UP EI PL ZR NA PE NC 1FE0:7C8B 6631C0 xor eax, eax - AX=0000 BX=0000 CX=0000 DX=0080 SP=7BE0 BP=7C00 SI=7DD7 DI=7E00 DS=1FE0 ES=1FE0 SS=1FE0 CS=1FE0 IP=7C8E NV UP EI PL ZR NA PE NC 1FE0:7C8E 66894644 mov [bp+44], eax SS:7C44=4E000000 - AX=0000 BX=0000 CX=0000 DX=0080 SP=7BE0 BP=7C00 SI=7DD7 DI=7E00 DS=1FE0 ES=1FE0 SS=1FE0 CS=1FE0 IP=7C92 NV UP EI PL ZR NA PE NC 1FE0:7C92 8B460E mov ax, [bp+0E] SS:7C0E=0010 - AX=0010 BX=0000 CX=0000 DX=0080 SP=7BE0 BP=7C00 SI=7DD7 DI=7E00 DS=1FE0 ES=1FE0 SS=1FE0 CS=1FE0 IP=7C95 NV UP EI PL ZR NA PE NC 1FE0:7C95 6603461C add eax, [bp+1C] SS:7C1C=00000024 - AX=0034 BX=0000 CX=0000 DX=0080 SP=7BE0 BP=7C00 SI=7DD7 DI=7E00 DS=1FE0 ES=1FE0 SS=1FE0 CS=1FE0 IP=7C99 NV UP EI PL NZ NA PO NC 1FE0:7C99 66894648 mov [bp+48], eax SS:7C48=414E204F - AX=0034 BX=0000 CX=0000 DX=0080 SP=7BE0 BP=7C00 SI=7DD7 DI=7E00 DS=1FE0 ES=1FE0 SS=1FE0 CS=1FE0 IP=7C9D NV UP EI PL NZ NA PO NC 1FE0:7C9D 6689464C mov [bp+4C], eax SS:7C4C=2020454D - AX=0034 BX=0000 CX=0000 DX=0080 SP=7BE0 BP=7C00 SI=7DD7 DI=7E00 DS=1FE0 ES=1FE0 SS=1FE0 CS=1FE0 IP=7CA1 NV UP EI PL NZ NA PO NC 1FE0:7CA1 668B4610 mov eax, [bp+10] SS:7C10=00000002 - AX=0002 BX=0000 CX=0000 DX=0080 SP=7BE0 BP=7C00 SI=7DD7 DI=7E00 DS=1FE0 ES=1FE0 SS=1FE0 CS=1FE0 IP=7CA5 NV UP EI PL NZ NA PO NC 1FE0:7CA5 66F76E24 imul dword [bp+24] SS:7C24=00000001 - AX=0002 BX=0000 CX=0000 DX=0000 SP=7BE0 BP=7C00 SI=7DD7 DI=7E00 DS=1FE0 ES=1FE0 SS=1FE0 CS=1FE0 IP=7CA9 NV UP EI PL NZ NA PO NC 1FE0:7CA9 6601464C add [bp+4C], eax SS:7C4C=00000034 - AX=0002 BX=0000 CX=0000 DX=0000 SP=7BE0 BP=7C00 SI=7DD7 DI=7E00 DS=1FE0 ES=1FE0 SS=1FE0 CS=1FE0 IP=7CAD NV UP EI PL NZ NA PE NC 1FE0:7CAD B80002 mov ax, 0200 - AX=0200 BX=0000 CX=0000 DX=0000 SP=7BE0 BP=7C00 SI=7DD7 DI=7E00 DS=1FE0 ES=1FE0 SS=1FE0 CS=1FE0 IP=7CB0 NV UP EI PL NZ NA PE NC 1FE0:7CB0 3B460B cmp ax, [bp+0B] SS:7C0B=0200 - AX=0200 BX=0000 CX=0000 DX=0000 SP=7BE0 BP=7C00 SI=7DD7 DI=7E00 DS=1FE0 ES=1FE0 SS=1FE0 CS=1FE0 IP=7CB3 NV UP EI PL ZR NA PE NC 1FE0:7CB3 7408 jz 7CBD jumping - AX=0200 BX=0000 CX=0000 DX=0000 SP=7BE0 BP=7C00 SI=7DD7 DI=7E00 DS=1FE0 ES=1FE0 SS=1FE0 CS=1FE0 IP=7CBD NV UP EI PL ZR NA PE NC 1FE0:7CBD 668B462C mov eax, [bp+2C] SS:7C2C=00000002 - AX=0002 BX=0000 CX=0000 DX=0000 SP=7BE0 BP=7C00 SI=7DD7 DI=7E00 DS=1FE0 ES=1FE0 SS=1FE0 CS=1FE0 IP=7CC1 NV UP EI PL ZR NA PE NC 1FE0:7CC1 6650 push eax - AX=0002 BX=0000 CX=0000 DX=0000 SP=7BDC BP=7C00 SI=7DD7 DI=7E00 DS=1FE0 ES=1FE0 SS=1FE0 CS=1FE0 IP=7CC3 NV UP EI PL ZR NA PE NC 1FE0:7CC3 E89600 call 7D5C - AX=0036 BX=0000 CX=0000 DX=0100 SP=7BDC BP=7C00 SI=7DD7 DI=7E00 DS=1FE0 ES=1FE0 SS=1FE0 CS=1FE0 IP=7CC6 NV UP EI PL NZ NA PE NC 1FE0:7CC6 724F jb 7D17 not jumping - AX=0036 BX=0000 CX=0000 DX=0100 SP=7BDC BP=7C00 SI=7DD7 DI=7E00 DS=1FE0 ES=1FE0 SS=1FE0 CS=1FE0 IP=7CC8 NV UP EI PL NZ NA PE NC 1FE0:7CC8 C45E76 les bx, [bp+76] SS:7C76=0060:0000 - AX=0036 BX=0000 CX=0000 DX=0100 SP=7BDC BP=7C00 SI=7DD7 DI=7E00 DS=1FE0 ES=0060 SS=1FE0 CS=1FE0 IP=7CCB NV UP EI PL NZ NA PE NC 1FE0:7CCB E8BC00 call 7D8A - AX=0037 BX=0200 CX=0000 DX=0100 SP=7BDC BP=7C00 SI=7DD7 DI=7E00 DS=1FE0 ES=0060 SS=1FE0 CS=1FE0 IP=7CCE NV UP EI PL NZ NA PE NC 1FE0:7CCE 31FF xor di, di - AX=0037 BX=0200 CX=0000 DX=0100 SP=7BDC BP=7C00 SI=7DD7 DI=0000 DS=1FE0 ES=0060 SS=1FE0 CS=1FE0 IP=7CD0 NV UP EI PL ZR NA PE NC 1FE0:7CD0 B90B00 mov cx, 000B - AX=0037 BX=0200 CX=000B DX=0100 SP=7BDC BP=7C00 SI=7DD7 DI=0000 DS=1FE0 ES=0060 SS=1FE0 CS=1FE0 IP=7CD3 NV UP EI PL ZR NA PE NC 1FE0:7CD3 BEF17D mov si, 7DF1 - AX=0037 BX=0200 CX=000B DX=0100 SP=7BDC BP=7C00 SI=7DF1 DI=0000 DS=1FE0 ES=0060 SS=1FE0 CS=1FE0 IP=7CD6 NV UP EI PL ZR NA PE NC 1FE0:7CD6 F3A6 repe cmpsb - AX=0037 BX=0200 CX=0000 DX=0100 SP=7BDC BP=7C00 SI=7DFC DI=000B DS=1FE0 ES=0060 SS=1FE0 CS=1FE0 IP=7CD8 NV UP EI PL ZR NA PE NC 1FE0:7CD8 7415 jz 7CEF jumping -gt AX=0037 BX=0200 CX=0000 DX=0100 SP=7BDC BP=7C00 SI=7DFC DI=000B DS=1FE0 ES=0060 SS=1FE0 CS=1FE0 IP=7CEF NV UP EI PL ZR NA PE NC 1FE0:7CEF 26FF7509 push word [es:di+09] ES:0014=0000
Skip until the directory scan has found its match.
-p AX=0037 BX=0200 CX=0000 DX=0100 SP=7BDA BP=7C00 SI=7DFC DI=000B DS=1FE0 ES=0060 SS=1FE0 CS=1FE0 IP=7CF3 NV UP EI PL ZR NA PE NC 1FE0:7CF3 26FF750F push word [es:di+0F] ES:001A=0003 - AX=0037 BX=0200 CX=0000 DX=0100 SP=7BD8 BP=7C00 SI=7DFC DI=000B DS=1FE0 ES=0060 SS=1FE0 CS=1FE0 IP=7CF7 NV UP EI PL ZR NA PE NC 1FE0:7CF7 6658 pop eax - AX=0003 BX=0200 CX=0000 DX=0100 SP=7BDC BP=7C00 SI=7DFC DI=000B DS=1FE0 ES=0060 SS=1FE0 CS=1FE0 IP=7CF9 NV UP EI PL ZR NA PE NC 1FE0:7CF9 29DB sub bx, bx - AX=0003 BX=0000 CX=0000 DX=0100 SP=7BDC BP=7C00 SI=7DFC DI=000B DS=1FE0 ES=0060 SS=1FE0 CS=1FE0 IP=7CFB NV UP EI PL ZR NA PE NC 1FE0:7CFB 6650 push eax - AX=0003 BX=0000 CX=0000 DX=0100 SP=7BD8 BP=7C00 SI=7DFC DI=000B DS=1FE0 ES=0060 SS=1FE0 CS=1FE0 IP=7CFD NV UP EI PL ZR NA PE NC 1FE0:7CFD E85C00 call 7D5C - AX=0136 BX=0000 CX=0000 DX=0100 SP=7BD8 BP=7C00 SI=7DFC DI=000B DS=1FE0 ES=0060 SS=1FE0 CS=1FE0 IP=7D00 NV UP EI PL NZ NA PE NC 1FE0:7D00 720D jb 7D0F not jumping - AX=0136 BX=0000 CX=0000 DX=0100 SP=7BD8 BP=7C00 SI=7DFC DI=000B DS=1FE0 ES=0060 SS=1FE0 CS=1FE0 IP=7D02 NV UP EI PL NZ NA PE NC 1FE0:7D02 E88500 call 7D8A - AX=0137 BX=0200 CX=0000 DX=0100 SP=7BD8 BP=7C00 SI=7DFC DI=000B DS=1FE0 ES=0060 SS=1FE0 CS=1FE0 IP=7D05 NV UP EI PL NZ NA PE NC 1FE0:7D05 4A dec dx - AX=0137 BX=0200 CX=0000 DX=00FF SP=7BD8 BP=7C00 SI=7DFC DI=000B DS=1FE0 ES=0060 SS=1FE0 CS=1FE0 IP=7D06 NV UP EI PL NZ AC PE NC 1FE0:7D06 75FA jnz 7D02 jumping -gnt AX=0236 BX=0000 CX=0000 DX=0000 SP=7BD8 BP=7C00 SI=7DFC DI=000B DS=1FE0 ES=2060 SS=1FE0 CS=1FE0 IP=7D08 NV UP EI PL ZR NA PE NC 1FE0:7D08 6658 pop eax -t AX=0003 BX=0000 CX=0000 DX=0000 SP=7BDC BP=7C00 SI=7DFC DI=000B DS=1FE0 ES=2060 SS=1FE0 CS=1FE0 IP=7D0A NV UP EI PL ZR NA PE NC 1FE0:7D0A E81600 call 7D23 - AX=0003 BX=0000 CX=0000 DX=0000 SP=7BDA BP=7C00 SI=7DFC DI=000B DS=1FE0 ES=2060 SS=1FE0 CS=1FE0 IP=7D23 NV UP EI PL ZR NA PE NC 1FE0:7D23 06 push es - AX=0003 BX=0000 CX=0000 DX=0000 SP=7BD8 BP=7C00 SI=7DFC DI=000B DS=1FE0 ES=2060 SS=1FE0 CS=1FE0 IP=7D24 NV UP EI PL ZR NA PE NC 1FE0:7D24 57 push di - AX=0003 BX=0000 CX=0000 DX=0000 SP=7BD6 BP=7C00 SI=7DFC DI=000B DS=1FE0 ES=2060 SS=1FE0 CS=1FE0 IP=7D25 NV UP EI PL ZR NA PE NC 1FE0:7D25 53 push bx - AX=0003 BX=0000 CX=0000 DX=0000 SP=7BD4 BP=7C00 SI=7DFC DI=000B DS=1FE0 ES=2060 SS=1FE0 CS=1FE0 IP=7D26 NV UP EI PL ZR NA PE NC 1FE0:7D26 89C7 mov di, ax - AX=0003 BX=0000 CX=0000 DX=0000 SP=7BD4 BP=7C00 SI=7DFC DI=0003 DS=1FE0 ES=2060 SS=1FE0 CS=1FE0 IP=7D28 NV UP EI PL ZR NA PE NC 1FE0:7D28 C1E702 shl di, 02 - AX=0003 BX=0000 CX=0000 DX=0000 SP=7BD4 BP=7C00 SI=7DFC DI=000C DS=1FE0 ES=2060 SS=1FE0 CS=1FE0 IP=7D2B NV UP EI PL NZ NA PE NC 1FE0:7D2B 50 push ax - AX=0003 BX=0000 CX=0000 DX=0000 SP=7BD2 BP=7C00 SI=7DFC DI=000C DS=1FE0 ES=2060 SS=1FE0 CS=1FE0 IP=7D2C NV UP EI PL NZ NA PE NC 1FE0:7D2C 8B460B mov ax, [bp+0B] SS:7C0B=0200 - AX=0200 BX=0000 CX=0000 DX=0000 SP=7BD2 BP=7C00 SI=7DFC DI=000C DS=1FE0 ES=2060 SS=1FE0 CS=1FE0 IP=7D2F NV UP EI PL NZ NA PE NC 1FE0:7D2F 48 dec ax - AX=01FF BX=0000 CX=0000 DX=0000 SP=7BD2 BP=7C00 SI=7DFC DI=000C DS=1FE0 ES=2060 SS=1FE0 CS=1FE0 IP=7D30 NV UP EI PL NZ AC PE NC 1FE0:7D30 21C7 and di, ax - AX=01FF BX=0000 CX=0000 DX=0000 SP=7BD2 BP=7C00 SI=7DFC DI=000C DS=1FE0 ES=2060 SS=1FE0 CS=1FE0 IP=7D32 NV UP EI PL NZ NA PE NC 1FE0:7D32 58 pop ax - AX=0003 BX=0000 CX=0000 DX=0000 SP=7BD4 BP=7C00 SI=7DFC DI=000C DS=1FE0 ES=2060 SS=1FE0 CS=1FE0 IP=7D33 NV UP EI PL NZ NA PE NC 1FE0:7D33 66C1E807 shr eax, 07 - AX=0000 BX=0000 CX=0000 DX=0000 SP=7BD4 BP=7C00 SI=7DFC DI=000C DS=1FE0 ES=2060 SS=1FE0 CS=1FE0 IP=7D37 NV UP EI PL ZR NA PE NC 1FE0:7D37 66034648 add eax, [bp+48] SS:7C48=00000034 - AX=0034 BX=0000 CX=0000 DX=0000 SP=7BD4 BP=7C00 SI=7DFC DI=000C DS=1FE0 ES=2060 SS=1FE0 CS=1FE0 IP=7D3B NV UP EI PL NZ NA PO NC 1FE0:7D3B BB0020 mov bx, 2000 - AX=0034 BX=2000 CX=0000 DX=0000 SP=7BD4 BP=7C00 SI=7DFC DI=000C DS=1FE0 ES=2060 SS=1FE0 CS=1FE0 IP=7D3E NV UP EI PL NZ NA PO NC 1FE0:7D3E 8EC3 mov es, bx - AX=0034 BX=2000 CX=0000 DX=0000 SP=7BD4 BP=7C00 SI=7DFC DI=000C DS=1FE0 ES=2000 SS=1FE0 CS=1FE0 IP=7D40 NV UP EI PL NZ NA PO NC 1FE0:7D40 29DB sub bx, bx -p AX=0034 BX=0000 CX=0000 DX=0000 SP=7BD4 BP=7C00 SI=7DFC DI=000C DS=1FE0 ES=2000 SS=1FE0 CS=1FE0 IP=7D42 NV UP EI PL ZR NA PE NC 1FE0:7D42 663B4644 cmp eax, [bp+44] SS:7C44=00000000 - AX=0034 BX=0000 CX=0000 DX=0000 SP=7BD4 BP=7C00 SI=7DFC DI=000C DS=1FE0 ES=2000 SS=1FE0 CS=1FE0 IP=7D46 NV UP EI PL NZ NA PO NC 1FE0:7D46 7407 jz 7D4F not jumping
This comparison checks whether the requested FAT sector has been read yet. In this case, it has not (no FAT sector at all is loaded yet) so the branch is not taken, so as to read in the FAT sector next.
- AX=0034 BX=0000 CX=0000 DX=0000 SP=7BD4 BP=7C00 SI=7DFC DI=000C DS=1FE0 ES=2000 SS=1FE0 CS=1FE0 IP=7D48 NV UP EI PL NZ NA PO NC 1FE0:7D48 66894644 mov [bp+44], eax SS:7C44=00000000 - AX=0034 BX=0000 CX=0000 DX=0000 SP=7BD4 BP=7C00 SI=7DFC DI=000C DS=1FE0 ES=2000 SS=1FE0 CS=1FE0 IP=7D4C NV UP EI PL NZ NA PO NC 1FE0:7D4C E83B00 call 7D8A -p AX=0035 BX=0200 CX=0000 DX=0000 SP=7BD4 BP=7C00 SI=7DFC DI=000C DS=1FE0 ES=2000 SS=1FE0 CS=1FE0 IP=7D4F NV UP EI PL NZ NA PE NC 1FE0:7D4F 268065030F and byte [es:di+03], 0F ES:000F=0F - AX=0035 BX=0200 CX=0000 DX=0000 SP=7BD4 BP=7C00 SI=7DFC DI=000C DS=1FE0 ES=2000 SS=1FE0 CS=1FE0 IP=7D54 NV UP EI PL NZ NA PE NC 1FE0:7D54 26668B05 mov eax, [es:di] ES:000C=0FFFFFFF
The sector having been read, this loads the correct FAT entry from the sector.
- AX=FFFF BX=0200 CX=0000 DX=0000 SP=7BD4 BP=7C00 SI=7DFC DI=000C DS=1FE0 ES=2000 SS=1FE0 CS=1FE0 IP=7D58 NV UP EI PL NZ NA PE NC 1FE0:7D58 5B pop bx - AX=FFFF BX=0000 CX=0000 DX=0000 SP=7BD6 BP=7C00 SI=7DFC DI=000C DS=1FE0 ES=2000 SS=1FE0 CS=1FE0 IP=7D59 NV UP EI PL NZ NA PE NC 1FE0:7D59 5F pop di - AX=FFFF BX=0000 CX=0000 DX=0000 SP=7BD8 BP=7C00 SI=7DFC DI=000B DS=1FE0 ES=2000 SS=1FE0 CS=1FE0 IP=7D5A NV UP EI PL NZ NA PE NC 1FE0:7D5A 07 pop es - AX=FFFF BX=0000 CX=0000 DX=0000 SP=7BDA BP=7C00 SI=7DFC DI=000B DS=1FE0 ES=2060 SS=1FE0 CS=1FE0 IP=7D5B NV UP EI PL NZ NA PE NC 1FE0:7D5B C3 retn - AX=FFFF BX=0000 CX=0000 DX=0000 SP=7BDC BP=7C00 SI=7DFC DI=000B DS=1FE0 ES=2060 SS=1FE0 CS=1FE0 IP=7D0D NV UP EI PL NZ NA PE NC 1FE0:7D0D EBEC jmp 7CFB - AX=FFFF BX=0000 CX=0000 DX=0000 SP=7BDC BP=7C00 SI=7DFC DI=000B DS=1FE0 ES=2060 SS=1FE0 CS=1FE0 IP=7CFB NV UP EI PL NZ NA PE NC 1FE0:7CFB 6650 push eax - AX=FFFF BX=0000 CX=0000 DX=0000 SP=7BD8 BP=7C00 SI=7DFC DI=000B DS=1FE0 ES=2060 SS=1FE0 CS=1FE0 IP=7CFD NV UP EI PL NZ NA PE NC 1FE0:7CFD E85C00 call 7D5C - AX=FFFF BX=0000 CX=0000 DX=0000 SP=7BD8 BP=7C00 SI=7DFC DI=000B DS=1FE0 ES=2060 SS=1FE0 CS=1FE0 IP=7D00 NV UP EI PL NZ NA PO CY 1FE0:7D00 720D jb 7D0F jumping - AX=FFFF BX=0000 CX=0000 DX=0000 SP=7BD8 BP=7C00 SI=7DFC DI=000B DS=1FE0 ES=2060 SS=1FE0 CS=1FE0 IP=7D0F NV UP EI PL NZ NA PO CY 1FE0:7D0F 8A5640 mov dl, [bp+40] SS:7C40=80 - AX=FFFF BX=0000 CX=0000 DX=0080 SP=7BD8 BP=7C00 SI=7DFC DI=000B DS=1FE0 ES=2060 SS=1FE0 CS=1FE0 IP=7D12 NV UP EI PL NZ NA PO CY 1FE0:7D12 88D3 mov bl, dl - AX=FFFF BX=0080 CX=0000 DX=0080 SP=7BD8 BP=7C00 SI=7DFC DI=000B DS=1FE0 ES=2060 SS=1FE0 CS=1FE0 IP=7D14 NV UP EI PL NZ NA PO CY 1FE0:7D14 FF6E76 jmp far [bp+76] SS:7C76=0060:0000 - AX=FFFF BX=0080 CX=0000 DX=0080 SP=7BD8 BP=7C00 SI=7DFC DI=000B DS=1FE0 ES=2060 SS=1FE0 CS=0060 IP=0000 NV UP EI PL NZ NA PO CY 0060:0000 4D dec bp -d 2000:0 l 100 2000:0000 F8 FF FF 0F FF FF FF 0F-FF FF FF 0F FF FF FF 0F ................ 2000:0010 FF FF FF 0F 06 00 00 00-FF FF FF 0F FF FF FF 0F ................ 2000:0020 FF FF FF 0F FF FF FF 0F-FF FF FF 0F FF FF FF 0F ................ 2000:0030 FF FF FF 0F FF FF FF 0F-00 00 00 00 00 00 00 00 ................ 2000:0040 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................ 2000:0050 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................ 2000:0060 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................ 2000:0070 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................ 2000:0080 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................ 2000:0090 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................ 2000:00A0 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................ 2000:00B0 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................ 2000:00C0 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................ 2000:00D0 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................ 2000:00E0 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................ 2000:00F0 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................ -
The file data in the area 600h to below 20600h is corrupted with the FAT sector data at 20000h to 201FFh.
The same test with the trailing all-1s file makes it clearer that the file data is corrupted:
-boot protocol chain hda1/k128kib1.bin -p 10 silent 1 AX=1FE0 BX=0080 CX=0000 DX=0080 SP=7BE0 BP=7C00 SI=7E00 DI=7E00 DS=1FE0 ES=1FE0 SS=1FE0 CS=1FE0 IP=7C82 NV UP EI PL ZR NA PE NC 1FE0:7C82 885640 mov [bp+40], dl SS:7C40=80 -g 7D14 AX=FFFF BX=0080 CX=0000 DX=0080 SP=7BD8 BP=7C00 SI=7DFC DI=002B DS=1FE0 ES=2060 SS=1FE0 CS=1FE0 IP=7D14 NV UP EI PL NZ NA PO CY 1FE0:7D14 FF6E76 jmp far [bp+76] SS:7C76=0060:0000 -d 2000:0 l 210 2000:0000 F8 FF FF 0F FF FF FF 0F-FF FF FF 0F FF FF FF 0F ................ 2000:0010 FF FF FF 0F 06 00 00 00-FF FF FF 0F FF FF FF 0F ................ 2000:0020 FF FF FF 0F FF FF FF 0F-FF FF FF 0F FF FF FF 0F ................ 2000:0030 FF FF FF 0F FF FF FF 0F-00 00 00 00 00 00 00 00 ................ 2000:0040 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................ 2000:0050 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................ 2000:0060 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................ 2000:0070 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................ 2000:0080 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................ 2000:0090 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................ 2000:00A0 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................ 2000:00B0 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................ 2000:00C0 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................ 2000:00D0 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................ 2000:00E0 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................ 2000:00F0 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................ 2000:0100 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................ 2000:0110 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................ 2000:0120 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................ 2000:0130 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................ 2000:0140 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................ 2000:0150 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................ 2000:0160 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................ 2000:0170 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................ 2000:0180 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................ 2000:0190 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................ 2000:01A0 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................ 2000:01B0 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................ 2000:01C0 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................ 2000:01D0 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................ 2000:01E0 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................ 2000:01F0 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................ 2000:0200 FF FF FF FF FF FF FF FF-FF FF FF FF FF FF FF FF ................ -
The entire area of 20000h to below 20600h should be filled with 0FFh bytes. However, the FAT sector corrupts this area.
Using k128f323.img (the CHS 8086 FAT32 loader, without directory padding) the same error can be discovered:
-boot protocol chain hda1/k128kib1.bin -p 10 silent 1 AX=1FE0 BX=0080 CX=0000 DX=0F80 SP=7BE0 BP=7C00 SI=7E00 DI=7E00 DS=1FE0 ES=1FE0 SS=1FE0 CS=1FE0 IP=7C82 NV UP EI PL ZR NA PE NC 1FE0:7C82 885640 mov [bp+40], dl SS:7C40=80 -g 7D77 AX=FFFF BX=0000 CX=0111 DX=0FFF SP=7BD0 BP=7C00 SI=7DFC DI=0010 DS=1FE0 ES=2060 SS=1FE0 CS=1FE0 IP=7D77 NV UP EI PL NZ NA PO CY 1FE0:7D77 8A5640 mov dl, [bp+40] SS:7C40=80 -d 2000:0 l 210 2000:0000 F8 FF FF 0F FF FF FF 0F-FF FF FF 0F FF FF FF 0F ................ 2000:0010 FF FF FF 0F 06 00 00 00-FF FF FF 0F FF FF FF 0F ................ 2000:0020 FF FF FF 0F FF FF FF 0F-FF FF FF 0F FF FF FF 0F ................ 2000:0030 FF FF FF 0F FF FF FF 0F-00 00 00 00 00 00 00 00 ................ 2000:0040 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................ 2000:0050 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................ 2000:0060 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................ 2000:0070 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................ 2000:0080 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................ 2000:0090 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................ 2000:00A0 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................ 2000:00B0 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................ 2000:00C0 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................ 2000:00D0 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................ 2000:00E0 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................ 2000:00F0 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................ 2000:0100 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................ 2000:0110 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................ 2000:0120 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................ 2000:0130 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................ 2000:0140 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................ 2000:0150 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................ 2000:0160 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................ 2000:0170 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................ 2000:0180 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................ 2000:0190 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................ 2000:01A0 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................ 2000:01B0 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................ 2000:01C0 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................ 2000:01D0 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................ 2000:01E0 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................ 2000:01F0 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................ 2000:0200 FF FF FF FF FF FF FF FF-FF FF FF FF FF FF FF FF ................ -
This test, in turn, requires using the images that are formatted with the directory padding, that is k128f322.img or k128f324.img. The former ends up like so:
lDebug connected to serial port. Enter KEEP to confirm. = keep -boot protocol chain hda1/k128kib0.bin -p 10 silent 1 AX=1FE0 BX=0080 CX=0000 DX=0080 SP=7BE0 BP=7C00 SI=7E00 DI=7E00 DS=1FE0 ES=1FE0 SS=1FE0 CS=1FE0 IP=7C82 NV UP EI PL ZR NA PE NC 1FE0:7C82 885640 mov [bp+40], dl SS:7C40=80
As before, skip the relocation.
-g 7D42 AX=0034 BX=0000 CX=000A DX=0000 SP=7BD8 BP=7C00 SI=7DF2 DI=0008 DS=1FE0 ES=2000 SS=1FE0 CS=1FE0 IP=7D42 NV UP EI PL ZR NA PE NC 1FE0:7D42 663B4644 cmp eax, [bp+44] SS:7C44=00000000
This is the first time that next_cluster is called. It is caused by the root directory scanning continuing past the first root cluster, which we filled with empty deleted directory entries. No FAT sector is buffered yet, so past this comparison the function will load the first FAT sector.
-g 7D42 AX=0034 BX=0000 CX=0000 DX=0000 SP=7BD4 BP=7C00 SI=7DFC DI=0010 DS=1FE0 ES=2000 SS=1FE0 CS=1FE0 IP=7D42 NV UP EI PL ZR NA PE NC 1FE0:7D42 663B4644 cmp eax, [bp+44] SS:7C44=00000034
This is the second time that next_cluster is called. In this case, it wants to read the FAT entry that corresponds to the first data cluster of the kernel file. As the FAT sector was already read prior, the variable matches the FAT sector to load. Therefore, the sector is not loaded again as it is expected that it was preserved.
-t AX=0034 BX=0000 CX=0000 DX=0000 SP=7BD4 BP=7C00 SI=7DFC DI=0010 DS=1FE0 ES=2000 SS=1FE0 CS=1FE0 IP=7D46 NV UP EI PL ZR NA PE NC 1FE0:7D46 7407 jz 7D4F jumping - AX=0034 BX=0000 CX=0000 DX=0000 SP=7BD4 BP=7C00 SI=7DFC DI=0010 DS=1FE0 ES=2000 SS=1FE0 CS=1FE0 IP=7D4F NV UP EI PL ZR NA PE NC 1FE0:7D4F 268065030F and byte [es:di+03], 0F ES:0013=00 - AX=0034 BX=0000 CX=0000 DX=0000 SP=7BD4 BP=7C00 SI=7DFC DI=0010 DS=1FE0 ES=2000 SS=1FE0 CS=1FE0 IP=7D54 NV UP EI PL ZR NA PE NC 1FE0:7D54 26668B05 mov eax, [es:di] ES:0010=00000000 - AX=0000 BX=0000 CX=0000 DX=0000 SP=7BD4 BP=7C00 SI=7DFC DI=0010 DS=1FE0 ES=2000 SS=1FE0 CS=1FE0 IP=7D58 NV UP EI PL ZR NA PE NC 1FE0:7D58 5B pop bx -
Turns out the FAT sector was actually overwritten by the file data, so when using the file with the trailing all-0s the code will read a zero as the content of the FAT entry. This is wrong, and results in a hang.
The same error can be observed with k128f324.img (the 8086 CHS loader):
lDebug connected to serial port. Enter KEEP to confirm. = keep -boot protocol chain hda1/k128kib0.bin -p 10 silent 1 AX=1FE0 BX=0080 CX=0000 DX=0080 SP=7BE0 BP=7C00 SI=7E00 DI=7E00 DS=1FE0 ES=1FE0 SS=1FE0 CS=1FE0 IP=7C82 NV UP EI PL ZR NA PE NC 1FE0:7C82 885640 mov [bp+40], dl SS:7C40=80
As before, skip the relocation.
-g 7D5A AX=0034 BX=0000 CX=0000 DX=0000 SP=7BDA BP=7C00 SI=7DF2 DI=0008 DS=1FE0 ES=2000 SS=1FE0 CS=1FE0 IP=7D5A NV UP EI PL ZR NA PE NC 1FE0:7D5A 3B4648 cmp ax, [bp+48] SS:7C48=0000 -t AX=0034 BX=0000 CX=0000 DX=0000 SP=7BDA BP=7C00 SI=7DF2 DI=0008 DS=1FE0 ES=2000 SS=1FE0 CS=1FE0 IP=7D5D NV UP EI PL NZ NA PO NC 1FE0:7D5D 7505 jnz 7D64 jumping - AX=0034 BX=0000 CX=0000 DX=0000 SP=7BDA BP=7C00 SI=7DF2 DI=0008 DS=1FE0 ES=2000 SS=1FE0 CS=1FE0 IP=7D64 NV UP EI PL NZ NA PO NC 1FE0:7D64 894648 mov [bp+48], ax SS:7C48=0000 - AX=0034 BX=0000 CX=0000 DX=0000 SP=7BDA BP=7C00 SI=7DF2 DI=0008 DS=1FE0 ES=2000 SS=1FE0 CS=1FE0 IP=7D67 NV UP EI PL NZ NA PO NC 1FE0:7D67 89564A mov [bp+4A], dx SS:7C4A=0000 - AX=0034 BX=0000 CX=0000 DX=0000 SP=7BDA BP=7C00 SI=7DF2 DI=0008 DS=1FE0 ES=2000 SS=1FE0 CS=1FE0 IP=7D6A NV UP EI PL NZ NA PO NC 1FE0:7D6A E83D00 call 7DAA
No FAT sector is loaded yet during root directory traversal. As the directory entry is not found in the first cluster, the next root cluster is loaded.
-g 7D5A AX=0034 BX=0000 CX=0000 DX=0000 SP=7BD0 BP=7C00 SI=7DFC DI=0010 DS=1FE0 ES=2000 SS=1FE0 CS=1FE0 IP=7D5A NV UP EI PL ZR NA PE NC 1FE0:7D5A 3B4648 cmp ax, [bp+48] SS:7C48=0034 -t AX=0034 BX=0000 CX=0000 DX=0000 SP=7BD0 BP=7C00 SI=7DFC DI=0010 DS=1FE0 ES=2000 SS=1FE0 CS=1FE0 IP=7D5D NV UP EI PL ZR NA PE NC 1FE0:7D5D 7505 jnz 7D64 not jumping - AX=0034 BX=0000 CX=0000 DX=0000 SP=7BD0 BP=7C00 SI=7DFC DI=0010 DS=1FE0 ES=2000 SS=1FE0 CS=1FE0 IP=7D5F NV UP EI PL ZR NA PE NC 1FE0:7D5F 3B564A cmp dx, [bp+4A] SS:7C4A=0000 - AX=0034 BX=0000 CX=0000 DX=0000 SP=7BD0 BP=7C00 SI=7DFC DI=0010 DS=1FE0 ES=2000 SS=1FE0 CS=1FE0 IP=7D62 NV UP EI PL ZR NA PE NC 1FE0:7D62 7409 jz 7D6D jumping - AX=0034 BX=0000 CX=0000 DX=0000 SP=7BD0 BP=7C00 SI=7DFC DI=0010 DS=1FE0 ES=2000 SS=1FE0 CS=1FE0 IP=7D6D NV UP EI PL ZR NA PE NC 1FE0:7D6D 5B pop bx - AX=0034 BX=0000 CX=0000 DX=0000 SP=7BD2 BP=7C00 SI=7DFC DI=0010 DS=1FE0 ES=2000 SS=1FE0 CS=1FE0 IP=7D6E NV UP EI PL ZR NA PE NC 1FE0:7D6E 268B05 mov ax, [es:di] ES:0010=0000 - AX=0000 BX=0000 CX=0000 DX=0000 SP=7BD2 BP=7C00 SI=7DFC DI=0010 DS=1FE0 ES=2000 SS=1FE0 CS=1FE0 IP=7D71 NV UP EI PL ZR NA PE NC 1FE0:7D71 268B5502 mov dx, [es:di+02] ES:0012=0000 - AX=0000 BX=0000 CX=0000 DX=0000 SP=7BD2 BP=7C00 SI=7DFC DI=0010 DS=1FE0 ES=2000 SS=1FE0 CS=1FE0 IP=7D75 NV UP EI PL ZR NA PE NC 1FE0:7D75 07 pop es -
The FAT sector is expected to be already loaded, but it was corrupted by the file data. Continuing after this will result in a division error interrupt from a div cx
that expects to divide the sector number in order to calculate the CHS tuple. As the quotient overflows 16 bits, an interrupt 0 is fired.
The large file overlap only occurs if the file, rounded up to a cluster boundary, reaches close to 128 KiB. To be precise, a rounded up file size up to 129_536 Bytes (126.5 KiB) will not run into problems with the default /L load segment of 60h. If the cluster size is 128 KiB, the file will always run into problems. If it is 64 KiB, then a file larger than 64 KiB will run into problems. If it is 32 KiB, then a file larger than 96 KiB will run into problems. And so on.
The nature of the overlap is determined by which FAT sectors are read, and when. To simplify the example, assume a 128 KiB cluster size and that the file has only one cluster (as in our test cases). If the first cluster of the file has its FAT entry in another sector than the last root directory FAT entry read, then the loader will read the new FAT sector and find the appropriate entry in it. This is also true if the root directory scan only accessed the first cluster of the root directory, as in that case no FAT sector is read by the scan at all.
In this case, the trailing file data will be corrupted by the FAT sector, but the FAT sector is not corrupted. For a cluster size of 128 KiB, this case is very likely because 4_096 directory entries will fit in the first root cluster. (In the example tests, I had to pad the root directory with as many entries to force the directory scan to load a FAT sector.) If the actual file size is not larger than 126.5 KiB and the 128 KiB read occurs only because of rounding up to the cluster size, then the corruption is benign as it does not affect the actual file data read by the loader. Otherwise, the trail of the file data is corrupted.
If the root directory scan did load a FAT sector and the same FAT sector is needed throughout until after more than 126.5 KiB of file data have been read, then the FAT sector is corrupted and the exact behaviour that results depends on the loader, what exact FAT entry it tries to read, and what trailing data from the file read has overwritten the FAT sector.
Using a higher /L load segment than 60h will shrink the allowed rounded up size of the file before it runs into problems. For example, with /L 200
, the rounded up file size must not exceed 120 KiB.
File sizes beyond 128 KiB will generally always be a problem and might overwrite any of the data structures, including the stack of the loader. The code is located in the 512 Bytes starting at 1FE0h:7C00h or linear 27A00h, while the stack lives below this address. So a read that corrupts the code would also corrupt the stack first, at which point a crash is almost entirely inevitable.
Discussion
Bug report about the FAT32 overlap: https://github.com/FDOS/kernel/issues/127
Pull Request for the "ecm boot overlap" branch, fixing these overlaps and doing some more maintenance on the loaders: https://github.com/FDOS/kernel/pull/135