While playing with some less than usual configurations, I've got bitten
few times by geometry settings in case of, usually, microsoft[ish]
systems. First two examples, then the improvement idea.
Example #1
My usb stick has zip-compatible geometry, which should work fine both in
hdd and zip modes. It usually does, at least as far as syslinux and
normal software is considered - excluding some of a bit older award
bioses that regardless of everything, seem to forcibly treat the usb
stick as a floppy (or some unspecified alien), unless the actual
filesystem is FAT16 (and I mean /actual/ filesystem, not partition type
flag in mbr - this is the same issue as once described in this thread -
http://syslinux.zytor.com/archives/2006-September/007286.html ).
Putting aside wicked bioses, I also have freedos on the same partition
for different/weird/legacy purposes. Here the fun begins - BPB of
syslinux partition has obviously zip geometry (32/64). When the stick is
treated as USB HDD, some of the bioses use other geometries than the zip
one. In such case regardless of the method (chain.c32 from sector or
kernel file, bss) - booting of course didn't work. Freedos (or at least
some of its kernels) require not only hidden sectors, but also heads and
sectors matching the bios geometry.
My stick also happened to have drive == 0 set in its BPB, so in such
case, FDOS never managed to boot. Depending on creation method, one
might end with such value.
Example #2
Bioses try to be clever, when they see partitions not on a typical
cylinder (63*255 sectors) boundary. For example, with 1MB aligned
partitions, I sometimes ended with 240 or 224 heads. To my small
surprise, ntldr and/or ntfs bootsector (as formatted from windows up to
and including xp) actually DO require proper CHS geometry in its BPB,
matching bios imaginations - just hidden sectors is not enough. When I
cloned windows partitions from one pc to another, I sometimes ended with
unbootable windows (and simple hexedit /dev/whateverN to adjust values
of heads and sectors-per-track fixed the issue).
Anyway, I was thinking about extending chain.c32 code a bit to do
following when "sethidden" option is specified (or better add extra
options - such as "setgeometry", "setdrive" and
"setbpb" (equivalent of
all options specified) - to keep it more flexible):
- update hidden sectors field (as it does currently) - at 0x1C
- update sectors-per-track and heads fields (if cbios data is valid) -
at 0x18 and 0x1A respectively
- update drive number (also respecting opt.swap value) - at 0x24
Additionally - "savebpb" could allow permanent update of the sector
(would be executed only if some of the values changed).
Patch should be straightforward. A side "bonus" to that would be a
capability to chainload DOSes from drive > 0x80 without a stub. I have
one question though:
if (!opt.loadfile || data[0].base >= 0x7c00 + SECTOR) {
/* Actually read the boot sector */
if (!cur_part) {
data[ndata].data = mbr;
Both freedos/msdos/pcdos option implicitly assume sethidden, but
considering their data[0].base - the condition will always be false (and
rightly so as the kernel overlaps with bootsector), so sethidden will
not work here.
Also, looking at freedos bootsectors, I think they require relocated
bootsector to work (at 0x1fe0:0x7c00) - so there is potentially a room
for improvement here.
Would patches adding such functionality be considered ?