chenall/grub4dos

GRLDR cannot be loaded when stored on a high cluster number

1ras opened this issue · 5 comments

1ras commented

It seems that a boot record written with bootlace.com 0.4.6a cannot load GRLDR when stored above a certain cluster number somewhere above 32768. File system is FAT16 on a hard drive.

Here is what happens:

Screenshot_20230810_215642

Here is a disk editor screenshot, the last column is the start cluster:

Screenshot_20230810_211830

The file system is defragmented and all GRLDR.* files are identical (identical MD5 checksum). I rename one GRLDR.* file at a time to GRLDR (without extension) and see if it can be loaded.

From the screenshot, GRLDR.3 till GRLDR.6 are able to load and GRLDR.7 till GRLDR.19 are unable to load.

The issue depends on the bootlace.com version that was used to write the boot sector.

Every 0.4.6a bootlace.com version is affected:

0.4.6a-2012-01-01 FAILS
0.4.6a-2012-12-31 FAILS
0.4.6a-2013-11-30 FAILS
latest FAILS

Where 0.4.5c bootlace.com works perfectly fine:

0.4.5c-2015-05-18 WORKS
0.4.5c-2016-01-18 WORKS

After many tests I belief that the behavior is related to the cluster number and the limit is somewhere around 32768.

How many sectors per cluster?

1ras commented

4096 bytes per cluster, which means 8 sectors of 512 bytes

1ras commented

The issue is independent of the cluster size and only depends on the cluster number. Here are the steps to replicate the issue on Linux with a 32K cluster size:

# This is the device of the USB flash drive we use (2 GB minimum size for 32K cluster size)
# ALL DATA ON THIS DEVICE WILL BE LOST !
DEV=/dev/sdX

# Write new partition table - ALL DATA ON DEVICE WILL BE LOST !
echo ",+1900M,6,*" | sfdisk -w always -W always $DEV

# Format partition with FAT16 - ALL DATA ON DEVICE WILL BE LOST !
mkdosfs -v -F 16 ${DEV}1

# Make device bootable
bootlace64.com $DEV

# Mount partition and cd to it
mount $[DEV}1 /mnt
cd /mnt

# Copy grldr
cp /location/of/grldr grldr

# Consume approx. 32.400 clusters (this takes a while)...
mkdir dir; for N in $(seq 1 32400); do echo > dir/$N; done

# Duplicate grldr 50 times...
for N in $(seq 1 50); do cp grldr grldr.$N; done

# Check the start clusters of the grldr files (c=cluster#)
sync; fatcat ${DEV}1 -l /

# Choose one which does not fit entirely below 32768 clusters
# and replace it with the working grldr file by renaming
mv grldr grldr.0
mv grldr.XX grldr

# Unmount
cd
umount /mnt

# Try booting

Results in my case (replicated with Linux KVM/qemu):

$ sync; fatcat ${DEV}1 -l /
(...)
f 15/8/2023 11:51:44  grldr.31                       c=32745 s=323037 (315.466K)
f 15/8/2023 11:51:44  grldr.32                       c=32755 s=323037 (315.466K)
f 15/8/2023 11:51:44  grldr.33                       c=32765 s=323037 (315.466K)
f 15/8/2023 11:51:44  grldr.34                       c=32775 s=323037 (315.466K)
f 15/8/2023 11:51:44  grldr.35                       c=32785 s=323037 (315.466K)
(...)

grldr.32 (starts at cluster 32755):

Screenshot_20230815_135937

grldr.33 (starts at cluster 32765 but does not entirely fit below cluster 32768) and grldr.34 (starts at cluster 32775):

Screenshot_20230815_135544

I also added a menu.lst to cluster 32945 to see if grldr itself is affected, but fortunately grldr is able to load the menu.lst.

1ras commented

I also tested with 120 MB (2K cluster size) and partition type "e" (FAT16X LBA). The partition command in this case is:

# Write new partition table - ALL DATA ON DEVICE WILL BE LOST !
echo ",+120M,e,*" | sfdisk -w always -W always $DEV

The cluster consumption is different, so we need to reserve fewer clusters ourselves:

# Consume approx. 28.000 clusters (this takes a while)...
mkdir dir; for N in $(seq 1 28000); do echo > dir/$N; done

Everything else is the same and the results are the same.

1ras commented

I can confirm that issue is resolved.
Thanks for providing grub4dos!