Support parsing the command line, and setting the geometry that way.
authorhpa <hpa>
Wed, 12 Dec 2001 21:52:44 +0000 (21:52 +0000)
committerhpa <hpa>
Wed, 12 Dec 2001 21:52:44 +0000 (21:52 +0000)
memdisk/conio.c
memdisk/conio.h
memdisk/init.S16
memdisk/memdisk.doc
memdisk/setup.c

index 8599ddd..f1ca699 100644 (file)
@@ -78,6 +78,14 @@ static int skip_atoi(const char **s)
   return i;
 }
 
+unsigned int atou(const char *s)
+{
+  unsigned int i = 0;
+  while (isdigit(*s))
+    i = i*10 + (*s++ - '0');
+  return i;
+}
+
 static int strnlen(const char *s, int maxlen)
 {
   const char *es = s;
@@ -256,9 +264,6 @@ int vsprintf(char *buf, const char *fmt, va_list args)
       
     case 's':
       s = va_arg(args, char *);
-      if (!s)
-       s = "(null)";
-      
       len = strnlen(s, precision);
       
       if (!(flags & LEFT))
index 7f823ae..93ad000 100644 (file)
@@ -26,5 +26,6 @@
 int putchar(int);
 int puts(const char *);
 int printf(const char *, ...);
+unsigned int atou(const char *);
 
 #endif
index 2e87d1d..b07dc5b 100644 (file)
@@ -139,7 +139,28 @@ start:
 
 startc:
 /*
- * Set up the operating environment expected by the C code.
+ * Copy the command line, if there is one
+ */
+               xorw %di,%di            # Bottom of our own segment
+               movl cmd_line_ptr, %eax
+               andl %eax,%eax
+               jz endcmd               # No command line?
+               movw %ax,%si
+               shrl $4,%eax            # Convert to a segment address
+               andw $0x000F,%si        # Starting offset
+               movw %ax,%gs
+               movw $496,%cx           # Maximum number of bytes
+copycmd:
+               lodsb %gs:(%si),%al
+               andb %al,%al            # Make sure we're null-terminated
+               jz endcmd
+               stosb %al,%es:(%di)
+               loopw copycmd
+endcmd:
+               xorb %al,%al
+               stosb %al,%es:(%di)
+/*
+ * Jump to C code
  */
                sti                     # Maybe not?
                calll setup             # Call the C code
index 59a2308..64d19df 100644 (file)
@@ -43,6 +43,15 @@ should typically have an MBR and a partition table.  The disk C/H/S
 geometry is determined by examining the partition table, so the entire
 image should be partitioned for proper operation.
 
+You can also specify the geometry manually with the following command
+line options (currently untested):
+
+   c=<number>  Specify number of cylinders
+   h=<number>  Specify number of heads
+   s=<number>  Specify number of sectors
+   floppy      The image is a floppy image
+   harddisk    The image is a hard disk image
+
 If you want to recompile it from sources, you will need to make sure that
 you have a fairly recent binutils installed.  I have been using the
 binutils-2.11.90.0.8-9 RPM from RedHat.
index 7428479..0fa9dbf 100644 (file)
@@ -49,7 +49,7 @@ struct patch_area {
 
 /* This is the header in the boot sector/setup area */
 struct setup_header {
-  uint8_t dummy[0x1f1];                /* Boot sector */
+  char cmdline[0x1f1];
   uint8_t setup_secs;
   uint16_t syssize;
   uint16_t swap_dev;
@@ -115,7 +115,7 @@ static void high_bcopy(uint32_t dst, uint32_t src, uint16_t len)
   high_mover.dst2  = dst >> 16;
   high_mover.dst3  = dst >> 24;
 
-  asm volatile("pushf ; movb $0x87,%%ah ; int $0x15 ; popf"
+  asm volatile("pushfl ; movb $0x87,%%ah ; int $0x15 ; popfl"
               :: "S" (&high_mover), "c" (len >> 1)
               : "eax", "ebx", "ecx", "edx",
               "ebp", "esi", "edi", "memory");
@@ -185,6 +185,62 @@ rdz_32(uint32_t addr)
 #define BIOS_BASEMEM   0x413    /* Amount of DOS memory */
 
 /*
+ * Routine to seek for a command-line item and return a pointer
+ * to the data portion, if present
+ */
+static inline int
+isspace(int ch)
+{
+  return (ch == ' ') || ((ch >= '\b') && (ch <= '\r'));
+}
+
+/* Magic return values */
+#define CMD_NOTFOUND   ((char *)-1) /* Not found */
+#define CMD_BOOL       ((char *)-2) /* Found boolean option */
+#define CMD_HASDATA(X) ((int)(X) >= 0)
+const char *getcmditem(const char *what)
+{
+  const char *p, *wp;
+  int match = 0;
+
+  for ( p = shdr->cmdline ; *p ; p++ ) {
+    switch ( match ) {
+    case 0:                    /* Ground state */
+      if ( isspace(*p) )
+       break;
+
+      wp = what;
+      /* Fall through */
+
+    case 1:                    /* Matching */
+      if ( *wp == '\0' ) {
+       if ( *p == '=' )
+         return p+1;
+       else if ( isspace(*p) )
+         return CMD_BOOL;
+       else {
+         match = 2;
+         break;
+       }
+      }
+      if ( *p != *wp++ )
+       match = 2;              /* Skipping bogus */
+      break;
+
+    case 2:
+      if ( isspace(*p) )
+       match = 0;              /* Next option */
+    }
+  }
+    
+  /* Check for matching string at end of line */
+  if ( match == 1 && *wp == '\0' )
+    return CMD_BOOL;
+  
+  return CMD_NOTFOUND;
+}
+
+/*
  * Figure out the "geometry" of the disk in question
  */
 struct geometry {
@@ -216,63 +272,88 @@ struct ptab_entry {
 
 const struct geometry *get_disk_image_geometry(uint32_t where, uint32_t size)
 {
-  static struct geometry hd_geometry;
+  static struct geometry hd_geometry = { 0, 0, 0, 0, 0, 0x80 };
   struct ptab_entry ptab[4];   /* Partition table buffer */
-  uint32_t sectors;
+  unsigned int sectors, v;
+  unsigned int max_c, max_h, max_s;
+  unsigned int c, h, s;
   int i;
-  int c, h, s;
-  int max_c, max_h, max_s;
+  const char *p;
+
+  printf("command line: %s\n", shdr->cmdline);
 
   if ( size & 0x1ff ) {
     puts("MEMDISK: Image has fractional end sector\n");
     size &= ~0x1ff;
   }
+
   sectors = size >> 9;
+  hd_geometry.sectors = sectors;
 
   for ( i = 0 ; i < known_geometries ; i++ ) {
     if ( sectors == geometries[i].sectors ) {
-      return &geometries[i];
+      hd_geometry = geometries[i];
+      break;
     }
   }
 
-  /* No match, must be a hard disk image */
-  /* Need to examine the partition table for geometry */
-  copy_from_high(&ptab, where+(512-2-4*16), sizeof ptab);
+  if ( CMD_HASDATA(p = getcmditem("c")) && (v = atou(p)) )
+    hd_geometry.c = v;
+  if ( CMD_HASDATA(p = getcmditem("h")) && (v = atou(p)) )
+    hd_geometry.h = v;
+  if ( CMD_HASDATA(p = getcmditem("s")) && (v = atou(p)) )
+    hd_geometry.s = v;
   
-  max_c = max_h = 0;  max_s = 1;
-  for ( i = 0 ; i < 4 ; i++ ) {
-    if ( ptab[i].type ) {
-      c = ptab[i].start_c + (ptab[i].start_s >> 6);
-      s = (ptab[i].start_s & 0x3f);
-      h = ptab[i].start_h;
-      
-      if ( max_c < c ) max_c = c;
-      if ( max_h < h ) max_h = h;
-      if ( max_s < s ) max_s = s;
-      
-      c = ptab[i].end_c + (ptab[i].end_s >> 6);
-      s = (ptab[i].end_s & 0x3f);
-      h = ptab[i].end_h;
-      
-      if ( max_c < c ) max_c = c;
-      if ( max_h < h ) max_h = h;
-      if ( max_s < s ) max_s = s;
-    }
+  if ( getcmditem("floppy") != CMD_NOTFOUND ) {
+    hd_geometry.driveno = 0;
+    if ( hd_geometry.type == 0 )
+      hd_geometry.type = 0x10; /* ATAPI floppy, e.g. LS-120 */
+  }
+  if ( getcmditem("harddisk") != CMD_NOTFOUND ) {
+    hd_geometry.driveno = 0x80;
+    hd_geometry.type = 0;
   }
 
-  max_c++; max_h++;            /* Convert to count (1-based) */
-
-  hd_geometry.sectors = sectors;
-  hd_geometry.c       = sectors/(max_h*max_s);
-  hd_geometry.h       = max_h;
-  hd_geometry.s       = max_s;
-  hd_geometry.type    = 0;
-  hd_geometry.driveno = 0x80;  /* Hard drive */
+  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);
+    
+    max_c = max_h = 0;  max_s = 1;
+    for ( i = 0 ; i < 4 ; i++ ) {
+      if ( ptab[i].type ) {
+       c = ptab[i].start_c + (ptab[i].start_s >> 6);
+       s = (ptab[i].start_s & 0x3f);
+       h = ptab[i].start_h;
+       
+       if ( max_c < c ) max_c = c;
+       if ( max_h < h ) max_h = h;
+       if ( max_s < s ) max_s = s;
+       
+       c = ptab[i].end_c + (ptab[i].end_s >> 6);
+       s = (ptab[i].end_s & 0x3f);
+       h = ptab[i].end_h;
+       
+       if ( max_c < c ) max_c = c;
+       if ( max_h < h ) max_h = h;
+       if ( max_s < s ) max_s = s;
+      }
+    }
+    
+    max_c++; max_h++;          /* Convert to count (1-based) */
+    
+    if ( !hd_geometry.h )
+      hd_geometry.h = max_h;
+    if ( !hd_geometry.s )
+      hd_geometry.s = max_s;
+    if ( !hd_geometry.c )
+      hd_geometry.c = sectors/(hd_geometry.h*hd_geometry.s);
+  }
 
-  if ( sectors % (max_s*max_h) ) {
+  if ( sectors % (hd_geometry.h*hd_geometry.s) ) {
     puts("MEMDISK: Image seems to have fractional end cylinder\n");
   }
-  if ( max_c > hd_geometry.c ) {
+  if ( (hd_geometry.c*hd_geometry.h*hd_geometry.s) > sectors ) {
     puts("MEMDISK: Image appears to be truncated\n");
   }