From 6b190cc5cf21708b6aacc50c9050e074f67bed90 Mon Sep 17 00:00:00 2001 From: hpa Date: Wed, 12 Dec 2001 21:52:44 +0000 Subject: [PATCH] Support parsing the command line, and setting the geometry that way. --- memdisk/conio.c | 11 +++- memdisk/conio.h | 1 + memdisk/init.S16 | 23 +++++++- memdisk/memdisk.doc | 9 +++ memdisk/setup.c | 159 +++++++++++++++++++++++++++++++++++++++------------- 5 files changed, 160 insertions(+), 43 deletions(-) diff --git a/memdisk/conio.c b/memdisk/conio.c index 8599ddd..f1ca699 100644 --- a/memdisk/conio.c +++ b/memdisk/conio.c @@ -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)) diff --git a/memdisk/conio.h b/memdisk/conio.h index 7f823ae..93ad000 100644 --- a/memdisk/conio.h +++ b/memdisk/conio.h @@ -26,5 +26,6 @@ int putchar(int); int puts(const char *); int printf(const char *, ...); +unsigned int atou(const char *); #endif diff --git a/memdisk/init.S16 b/memdisk/init.S16 index 2e87d1d..b07dc5b 100644 --- a/memdisk/init.S16 +++ b/memdisk/init.S16 @@ -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 diff --git a/memdisk/memdisk.doc b/memdisk/memdisk.doc index 59a2308..64d19df 100644 --- a/memdisk/memdisk.doc +++ b/memdisk/memdisk.doc @@ -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= Specify number of cylinders + h= Specify number of heads + s= 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. diff --git a/memdisk/setup.c b/memdisk/setup.c index 7428479..0fa9dbf 100644 --- a/memdisk/setup.c +++ b/memdisk/setup.c @@ -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"); } -- 2.7.4