[syslinux] Possible improvements for chain.c

Michal Soltys soltys at ziu.info
Tue Jul 20 16:19:43 PDT 2010


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 ?




More information about the Syslinux mailing list