Support DOSEMU-style hard disk images
authorhpa <hpa>
Tue, 29 Oct 2002 06:12:58 +0000 (06:12 +0000)
committerhpa <hpa>
Tue, 29 Oct 2002 06:12:58 +0000 (06:12 +0000)
NEWS
memdisk/setup.c
mkdiskimage.in

diff --git a/NEWS b/NEWS
index 6dc6c9e..acaa087 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -3,8 +3,10 @@ apply to that specific program only; other changes apply to all of
 them.
 
 Changes in 2.01:
+       * MEMDISK: Support disk images with DOSEMU headers.
        * Update the mkdiskimage script to handle newer mtools
-         versions.
+         versions, and be able to generate disk images with DOSEMU
+         headers (controlled by the -d option).
 
 Changes in 2.00:
        * ALL: Add support for "COM32" (32-bit COMBOOT) images.
index 98a3c96..b96b431 100644 (file)
@@ -296,17 +296,18 @@ const char *getcmditem(const char *what)
 struct geometry {
   uint32_t sectors;            /* 512-byte sector count */
   uint32_t c, h, s;            /* C/H/S geometry */
+  uint32_t offset;             /* Byte offset for disk */
   uint8_t type;                        /* Type byte for INT 13h AH=08h */
   uint8_t driveno;             /* Drive no */
 };
 
 static const struct geometry geometries[] =
 { 
-  {  720, 40,  2,  9, 0x01, 0 }, /*  360 K */
-  { 1440, 80,  2,  9, 0x03, 0 }, /*  720 K*/
-  { 2400, 80,  2, 15, 0x02, 0 }, /* 1200 K */
-  { 2880, 80,  2, 18, 0x04, 0 }, /* 1440 K */
-  { 5760, 80,  2, 36, 0x06, 0 }, /* 2880 K */
+  {  720, 40,  2,  9, 0, 0x01, 0 }, /*  360 K */
+  { 1440, 80,  2,  9, 0, 0x03, 0 }, /*  720 K*/
+  { 2400, 80,  2, 15, 0, 0x02, 0 }, /* 1200 K */
+  { 2880, 80,  2, 18, 0, 0x04, 0 }, /* 1440 K */
+  { 5760, 80,  2, 36, 0, 0x06, 0 }, /* 2880 K */
 };
 #define known_geometries (sizeof(geometries)/sizeof(struct geometry))
 
@@ -320,24 +321,35 @@ struct ptab_entry {
   uint32_t size;
 };
 
+/* Format of a DOSEMU header */
+struct dosemu_header {
+  uint8_t magic[7];            /* DOSEMU\0 */
+  uint32_t h;
+  uint32_t s;
+  uint32_t c;
+  uint32_t offset;
+  uint8_t pad[105];
+} __attribute__((packed));
+
 const struct geometry *get_disk_image_geometry(uint32_t where, uint32_t size)
 {
-  static struct geometry hd_geometry = { 0, 0, 0, 0, 0, 0x80 };
+  static struct geometry hd_geometry = { 0, 0, 0, 0, 0, 0, 0x80 };
   struct ptab_entry ptab[4];   /* Partition table buffer */
+  struct dosemu_header dosemu;
   unsigned int sectors, v;
   unsigned int max_c, max_h, max_s;
-  unsigned int c, h, s;
+  unsigned int c, h, s, offset;
   int i;
+  int drive_specified;
   const char *p;
 
   printf("command line: %s\n", shdr->cmdline);
 
-  if ( size & 0x1ff ) {
-    puts("MEMDISK: Image has fractional end sector\n");
-    size &= ~0x1ff;
-  }
+  offset = 0;
+  if ( CMD_HASDATA(p = getcmditem("offset")) && (v = atou(p)) )
+    offset = v;
 
-  sectors = size >> 9;
+  sectors = (size-offset) >> 9;
   for ( i = 0 ; i < known_geometries ; i++ ) {
     if ( sectors == geometries[i].sectors ) {
       hd_geometry = geometries[i];
@@ -346,6 +358,20 @@ const struct geometry *get_disk_image_geometry(uint32_t where, uint32_t size)
   }
 
   hd_geometry.sectors = sectors;
+  hd_geometry.offset  = offset;
+
+  /* Do we have a DOSEMU header? */
+  copy_from_high(&dosemu, where+hd_geometry.offset, sizeof dosemu);
+  if ( !memcmp("DOSEMU", dosemu.magic, 7) ) {
+    /* Always a hard disk unless overruled by command-line options */
+    hd_geometry.driveno = 0x80;
+    hd_geometry.type = 0;
+    hd_geometry.c = dosemu.c;
+    hd_geometry.h = dosemu.h;
+    hd_geometry.s = dosemu.s;
+    hd_geometry.offset += dosemu.offset;
+    sectors = (size-hd_geometry.offset) >> 9;
+  }
 
   if ( CMD_HASDATA(p = getcmditem("c")) && (v = atou(p)) )
     hd_geometry.c = v;
@@ -358,16 +384,17 @@ const struct geometry *get_disk_image_geometry(uint32_t where, uint32_t size)
     hd_geometry.driveno = 0;
     if ( hd_geometry.type == 0 )
       hd_geometry.type = 0x10; /* ATAPI floppy, e.g. LS-120 */
-  }
-  if ( getcmditem("harddisk") != CMD_NOTFOUND ) {
+    drive_specified = 1;
+  } else if ( getcmditem("harddisk") != CMD_NOTFOUND ) {
     hd_geometry.driveno = 0x80;
     hd_geometry.type = 0;
+    drive_specified = 1;
   }
 
   if ( (hd_geometry.c == 0) || (hd_geometry.h == 0) ||
        (hd_geometry.s == 0) ) {
     /* Hard disk image, need to examine the partition table for geometry */
-    copy_from_high(&ptab, where+(512-2-4*16), sizeof ptab);
+    copy_from_high(&ptab, where+hd_geometry.offset+(512-2-4*16), sizeof ptab);
     
     max_c = max_h = 0;  max_s = 1;
     for ( i = 0 ; i < 4 ; i++ ) {
@@ -400,6 +427,9 @@ const struct geometry *get_disk_image_geometry(uint32_t where, uint32_t size)
       hd_geometry.c = sectors/(hd_geometry.h*hd_geometry.s);
   }
 
+  if ( (size-hd_geometry.offset) & 0x1ff ) {
+    puts("MEMDISK: Image has fractional end sector\n");
+  }
   if ( sectors % (hd_geometry.h*hd_geometry.s) ) {
     puts("MEMDISK: Image seems to have fractional end cylinder\n");
   }
@@ -491,7 +521,7 @@ uint32_t setup(void)
   pptr->heads     = geometry->h;
   pptr->sectors   = geometry->s;
   pptr->disksize  = geometry->sectors;
-  pptr->diskbuf   = shdr->ramdisk_image;
+  pptr->diskbuf   = shdr->ramdisk_image + geometry->offset;
   pptr->statusptr = (geometry->driveno & 0x80) ? 0x474 : 0x441;
 
   /* Set up a drive parameter table */
index a250af2..f75d0ac 100755 (executable)
@@ -22,7 +22,9 @@ sub absolute_path($) {
 
 for $a ( @ARGV ) {
     if ( $a =~ /^\-/ ) {
-       $opt{$'} = 1;
+       foreach $o ( split(//, substr($a,1)) ) {
+           $opt{$o} = 1;
+       }
     } else {
        push(@args, $a);
     }
@@ -33,7 +35,8 @@ $c += 0;  $h += 0;  $s += 0;
 
 if ( !$file || $c < 1 || $c > 1024 ||
      $h < 1 || $h > 256 || $s < 1 || $s > 63 ) {
-    print STDERR "Usage: $0 [-o] file c h s (max: 1024 256 63)\n";
+    print STDERR "Usage: $0 [-do] file c h s (max: 1024 256 63)\n";
+    print STDERR "    -d    add DOSEMU header\n";
     print STDERR "    -o    print filesystem offset to stdout\n";
     exit 1;
 }
@@ -43,6 +46,13 @@ $cylsize = $h*$s*512;
 sysopen(OUTPUT, $file, O_CREAT|O_RDWR|O_TRUNC, 0666)
     or die "$0: Cannot open: $file\n";
 
+# Print out DOSEMU header, if requested
+if ( $opt{'d'} ) {
+    $emuhdr = "DOSEMU\0" . pack("VVVV", $h, $s, $c, 128);
+    $emuhdr .= "\0" x (128 - length($emuhdr));
+    print OUTPUT $emuhdr;
+}
+
 # Print the MBR and partition table
 $mbr = '';
 while ( $line = <DATA> ) {
@@ -106,7 +116,7 @@ $imglink = $tmpdir.'/disk.img';
 die "$0: Failed to create symlink $imglink\n"
     if ( !symlink(absolute_path($file), $imglink) );
 
-$offset = $s*512;
+$offset = $s*512 + ($opt{'d'} ? 128 : 0);
 open(MCONFIG, "> ${cfgfile}") or die "$0: Cannot make mtools config\n";
 print MCONFIG "drive z:\n";
 print MCONFIG "file=\"${imglink}\"\n";