aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorH. Peter Anvin <hpa@zytor.com>2008-06-07 14:39:01 -0700
committerH. Peter Anvin <hpa@zytor.com>2008-06-07 14:39:01 -0700
commit8a6f179a7d7d1016988497e2a25b9706ad4ebcd7 (patch)
tree878a4ebfbfc28a93a78745275175d555059d19d4
parent6389a53252be6f3eaf8248ee6d58dff88697aad0 (diff)
downloadsyslinux-elf-8a6f179a7d7d1016988497e2a25b9706ad4ebcd7.tar.gz
syslinux-elf-8a6f179a7d7d1016988497e2a25b9706ad4ebcd7.tar.xz
syslinux-elf-8a6f179a7d7d1016988497e2a25b9706ad4ebcd7.zip
MEMDISK: algorithmic determination of floppy formats
Consider all disks < 4 MB to be floppies, and guess their geometry algorithmically.
-rw-r--r--NEWS3
-rw-r--r--doc/memdisk.txt57
-rwxr-xr-xmemdisk/fdgeo.pl54
-rw-r--r--memdisk/setup.c67
4 files changed, 143 insertions, 38 deletions
diff --git a/NEWS b/NEWS
index 085b5b82..5b841e24 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 759a7b27..808a9476 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 00000000..47d19afa
--- /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 298720a5..4d38598a 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");