From 8a6f179a7d7d1016988497e2a25b9706ad4ebcd7 Mon Sep 17 00:00:00 2001 From: "H. Peter Anvin" Date: Sat, 7 Jun 2008 14:39:01 -0700 Subject: [PATCH] MEMDISK: algorithmic determination of floppy formats Consider all disks < 4 MB to be floppies, and guess their geometry algorithmically. --- NEWS | 3 +++ doc/memdisk.txt | 57 +++++++++++++++++++++++++++++++---------------- memdisk/fdgeo.pl | 54 +++++++++++++++++++++++++++++++++++++++++++++ memdisk/setup.c | 67 ++++++++++++++++++++++++++++++++++++++++---------------- 4 files changed, 143 insertions(+), 38 deletions(-) create mode 100755 memdisk/fdgeo.pl diff --git a/NEWS b/NEWS index 085b5b8..5b841e2 100644 --- a/NEWS +++ b/NEWS @@ -29,6 +29,9 @@ Changes in 3.70: * Change default dir for auxiliary files from /usr/lib/syslinux to /usr/share/syslinux. * SYSLINUX: VFAT long filename support. + * MEMDISK: Any image less than 4096K (4 MB) is treated as a + floppy disk. The geometry-guessing code will recognize all + common extended formats, but Changes in 3.64: * SYSLINUX/EXTLINUX: support "localboot" with the same feature diff --git a/doc/memdisk.txt b/doc/memdisk.txt index 759a7b2..808a947 100644 --- a/doc/memdisk.txt +++ b/doc/memdisk.txt @@ -28,25 +28,44 @@ Note the following: a) The disk image can be uncompressed or compressed with gzip or zip. -b) If the disk image is one of the following sizes, it's assumed to be a - floppy image: - - 368,640 bytes - 360K floppy - 737,280 bytes - 720K floppy - 1,222,800 bytes - 1200K floppy - 1,474,560 bytes - 1440K floppy - 1,720,320 bytes - 1680K floppy (common extended format) - 1,763,328 bytes - 1722K floppy (common extended format) - 2,949,120 bytes - 2880K floppy - 3,932,160 bytes - 3840K floppy (extended format) - - For any other size, the image is assumed to be a hard disk image, - and should typically have an MBR and a partition table. It may - optionally have a DOSEMU geometry header; in which case the header - is used to determine the C/H/S geometry of the disk. Otherwise, - the geometry is determined by examining the partition table, so the - entire image should be partitioned for proper operation (it may be - divided between multiple partitions, however.) +b) If the disk image is less than 4,194,304 bytes (4096K, 4 MB) it is + assumed to be a floppy image and MEMDISK will try to guess its + geometry based on the size of the file. MEMDISK recognizes all the + standard floppy sizes as well as common extended formats: + + 163,840 bytes (160K) c=40 h=1 s=8 5.25" SSSD + 184,320 bytes (180K) c=40 h=1 s=9 5.25" SSSD + 327,680 bytes (320K) c=40 h=2 s=8 5.25" DSDD + 368,640 bytes (360K) c=40 h=2 s=9 5.25" DSDD + 655,360 bytes (640K) c=80 h=2 s=8 3.5" DSDD + 737,280 bytes (720K) c=80 h=2 s=9 3.5" DSDD + 1,222,800 bytes (1200K) c=80 h=2 s=15 5.25" DSHD + 1,474,560 bytes (1440K) c=80 h=2 s=18 3.5" DSHD + 1,638,400 bytes (1600K) c=80 h=2 s=20 3.5" DSHD (extended) + 1,720,320 bytes (1680K) c=80 h=2 s=21 3.5" DSHD (extended) + 1,763,328 bytes (1722K) c=82 h=2 s=21 3.5" DSHD (extended) + 1,784,832 bytes (1743K) c=83 h=2 s=21 3.5" DSHD (extended) + 1,802,240 bytes (1760K) c=80 h=2 s=22 3.5" DSHD (extended) + 1,884,160 bytes (1840K) c=80 h=2 s=23 3.5" DSHD (extended) + 1,966,080 bytes (1920K) c=80 h=2 s=24 3.5" DSHD (extended) + 2,949,120 bytes (2880K) c=80 h=2 s=36 3.5" DSED + 3,194,880 bytes (3120K) c=80 h=2 s=39 3.5" DSED (extended) + 3,276,800 bytes (3200K) c=80 h=2 s=40 3.5" DSED (extended) + 3,604,480 bytes (3520K) c=80 h=2 s=44 3.5" DSED (extended) + 3,932,160 bytes (3840K) c=80 h=2 s=48 3.5" DSED (extended) + + A small perl script is included in the MEMDISK directory which can + determine the geometry that MEMDISK would select for other sizes; + in general MEMDISK will correctly detect most physical extended + formats used, with 80 cylinders or slightly more. + + If the image is 4 MB or larger, it is assumed to be a hard disk + image, and should typically have an MBR and a partition table. It + may optionally have a DOSEMU geometry header; in which case the + header is used to determine the C/H/S geometry of the disk. + Otherwise, the geometry is determined by examining the partition + table, so the entire image should be partitioned for proper + operation (it may be divided between multiple partitions, however.) You can also specify the geometry manually with the following command line options: diff --git a/memdisk/fdgeo.pl b/memdisk/fdgeo.pl new file mode 100755 index 0000000..47d19af --- /dev/null +++ b/memdisk/fdgeo.pl @@ -0,0 +1,54 @@ +#!/usr/bin/perl +# +# Try automatic generation of geometries +# + +($k) = @ARGV; +$sec = int($k*2+0.5); + +if ($sec < 320*2) { + $c = 40; + $h = 1; + $type = 1; +} elsif ($sec < 640*2) { + $c = 40; + $h = 2; + $type = 1; +} elsif ($sec < 1200*2) { + $c = 80; + $h = 2; + $type = 3; +} elsif ($sec < 1440*2) { + $c = 80; + $h = 2; + $type = 2; +} elsif ($sec < 2880*2) { + $c = 80; + $h = 2; + $type = 4; +} elsif ($sec < 4096*2) { + $c = 80; + $h = 2; + $type = 6; +} else { + printf "%.1fK, %d sectors: ", $sec/2, $sec; + print "Considered a hard disk\n"; +} + +$ok = 0; +while ($c < 256) { + $s = int($sec/($c*$h)+0.5); + if ($s <= 63 && $sec == $c*$h*$s) { + $ok = 1; + last; + } + $c++; +} + +printf "%.1fK, %d sectors: ", $sec/2, $sec; +if ($ok) { + print "c=$c, h=$h, s=$s, type=$type\n"; +} else { + print "No valid geometry found (MEMDISK will fake it)\n"; +} + diff --git a/memdisk/setup.c b/memdisk/setup.c index 298720a..4d38598 100644 --- a/memdisk/setup.c +++ b/memdisk/setup.c @@ -362,19 +362,6 @@ struct geometry { uint8_t driveno; /* Drive no */ }; -static const struct geometry geometries[] = -{ - { 360*2, 40, 2, 9, 0, 0x01, 0 }, /* 360 K */ - { 720*2, 80, 2, 9, 0, 0x03, 0 }, /* 720 K*/ - { 1200*2, 80, 2, 15, 0, 0x02, 0 }, /* 1200 K */ - { 1440*2, 80, 2, 18, 0, 0x04, 0 }, /* 1440 K */ - { 1680*2, 80, 2, 21, 0, 0x04, 0 }, /* 1680 K */ - { 1722*2, 82, 2, 21, 0, 0x04, 0 }, /* 1722 K */ - { 2880*2, 80, 2, 36, 0, 0x06, 0 }, /* 2880 K */ - { 3840*2, 80, 2, 48, 0, 0x06, 0 }, /* 3840 K */ -}; -#define known_geometries (sizeof(geometries)/sizeof(struct geometry)) - /* Format of a DOS partition table entry */ struct ptab_entry { uint8_t active; @@ -399,7 +386,7 @@ struct dosemu_header { const struct geometry *get_disk_image_geometry(uint32_t where, uint32_t size) { - static struct geometry hd_geometry = { 0, 0, 0, 0, 0, 0, 0x80 }; + static struct geometry hd_geometry; struct ptab_entry ptab[4]; /* Partition table buffer */ struct dosemu_header dosemu; unsigned int sectors, v; @@ -416,11 +403,52 @@ const struct geometry *get_disk_image_geometry(uint32_t where, uint32_t size) offset = v; sectors = (size-offset) >> 9; - for ( i = 0 ; i < known_geometries ; i++ ) { - if ( sectors == geometries[i].sectors ) { - hd_geometry = geometries[i]; - break; + + if (sectors < 4096*2) { + int ok = 0; + unsigned int xsectors = sectors; + + while (!ok) { + /* Assume it's a floppy drive, guess a geometry */ + unsigned int type, track; + + if (xsectors < 320*2) { + c = 40; h = 1; type = 1; + } else if (xsectors < 640*2) { + c = 40; h = 2; type = 1; + } else if (xsectors < 1200*2) { + c = 80; h = 2; type = 3; + } else if (xsectors < 1440*2) { + c = 80; h = 2; type = 2; + } else if (xsectors < 2880*2) { + c = 80; h = 2; type = 4; + } else { + c = 80; h = 2; type = 6; + } + track = c*h; + while (c < 256) { + s = xsectors/track; + if (s < 63 && (xsectors % track) == 0) { + ok = 1; + break; + } + c++; + track += h; + } + if (ok) { + hd_geometry.driveno = 0; + hd_geometry.c = c; + hd_geometry.h = h; + hd_geometry.s = s; + } else { + /* No valid floppy geometry, fake it by simulating broken + sectors at the end of the image... */ + xsectors++; + } } + } else { + /* Hard disk */ + hd_geometry.driveno = 0x80; } hd_geometry.sectors = sectors; @@ -606,10 +634,11 @@ __cdecl void setup(__cdecl syscall_t cs_syscall, void *cs_bounce) else do_edd = (geometry->driveno & 0x80) ? 1 : 0; - printf("Disk is %s %d, %u K, C/H/S = %u/%u/%u, EDD %s\n", + printf("Disk is %s %d, %u%s K, C/H/S = %u/%u/%u, EDD %s\n", (geometry->driveno & 0x80) ? "hard disk" : "floppy", geometry->driveno & 0x7f, geometry->sectors >> 1, + (geometry->sectors & 1) ? ".5" : "", geometry->c, geometry->h, geometry->s, do_edd ? "on" : "off"); -- 2.7.4