From 8f832546796bd8ba3b2b073ead4f21c7244f2b25 Mon Sep 17 00:00:00 2001 From: okuji Date: Wed, 13 Oct 1999 23:02:06 +0000 Subject: [PATCH] device map file support. --- ChangeLog | 23 +++++ NEWS | 4 + docs/grub.8 | 5 +- docs/stamp-vti | 6 +- docs/version.texi | 6 +- grub/asmstub.c | 248 +++++++++++++++++++++++++++++++++++----------- grub/main.c | 14 ++- stage2/shared.h | 2 + 8 files changed, 242 insertions(+), 66 deletions(-) diff --git a/ChangeLog b/ChangeLog index fd18ed3b7..051356215 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,26 @@ +1999-10-13 OKUJI Yoshinori + + * grub/asmstub.c (assign_device_name): If DEVICE is NULL, set + DEVICE_MAP[DRIVE] to NULL. + (get_diskinfo): If open or read fails, call assign_device_name + to disable accessing the drive DRIVE. + (grub_stage2): The device mapping routine is moved to ... + (init_device_map): ... here. This new function also reads/writes + a device map file. If DEVICE_MAP_FILE already exists, then use + the data in it instead of probing devices. Otherwise, guess the + map between BIOS drives and OS devices, and write it to the file + DEVICE_MAP_FILE if it can be opened. + * grub/main.c (device_map_file): New variable. + (default_device_map_file): Likewise. + (OPT_DEVICE_MAP): New macro. + (longopts): Added an entry for "device-map". + (usage): Print the usage about --device-map as well. + (main): Set DEFAULT_DEVICE_MAP_FILE to DEVICE_MAP_FILE. If + OPT_DEVICE_MAP is found, set DEVICE_MAP_FILE to a duplicated + string of OPTARG. + * stage2/shared.h [GRUB_UTIL] (device_map_file): Declared. + * docs/grub.8: Regenerated. + 1999-10-13 OKUJI Yoshinori * stage2/builtins.c (color_func): Do not set NORMAL_COLOR or diff --git a/NEWS b/NEWS index e63f6aa4e..b238bfc35 100644 --- a/NEWS +++ b/NEWS @@ -7,6 +7,10 @@ New in 0.5.94: * The command "embed" embeds a Stage 1.5 in the sectors after a MBR or in the "bootloader" area in a FFS partition. * Support symbolic color name syntax in the command "color". +* The grub shell loads the BIOS drive mapping information from a device + map file (the default is "/boot/grub/device.map") if it already + exists. If not found, try to create it based on the guessed + information. New in 0.5.93: * ELF format of FreeBSD kernel is supported. diff --git a/docs/grub.8 b/docs/grub.8 index bd8388121..b76877513 100644 --- a/docs/grub.8 +++ b/docs/grub.8 @@ -1,5 +1,5 @@ .\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.013. -.TH GRUB "8" "September 1999" "GNU GRUB 0.5.93" FSF +.TH GRUB "8" "October 1999" "GNU GRUB 0.5.94" FSF .SH NAME GRUB \- the grub shell .SH SYNOPSIS @@ -18,6 +18,9 @@ specify stage2 boot_drive [default=0x0] \fB\-\-config\-file\fR=\fIFILE\fR specify stage2 config_file [default=/boot/grub/menu.lst] .TP +\fB\-\-device\-map\fR=\fIFILE\fR +specify the device map file [default=/boot/grub/device.map] +.TP \fB\-\-help\fR display this message and exit .TP diff --git a/docs/stamp-vti b/docs/stamp-vti index b7e8736a5..b75a93977 100644 --- a/docs/stamp-vti +++ b/docs/stamp-vti @@ -1,3 +1,3 @@ -@set UPDATED 10 September 1999 -@set EDITION 0.5.93 -@set VERSION 0.5.93 +@set UPDATED 13 October 1999 +@set EDITION 0.5.94 +@set VERSION 0.5.94 diff --git a/docs/version.texi b/docs/version.texi index b7e8736a5..b75a93977 100644 --- a/docs/version.texi +++ b/docs/version.texi @@ -1,3 +1,3 @@ -@set UPDATED 10 September 1999 -@set EDITION 0.5.93 -@set VERSION 0.5.93 +@set UPDATED 13 October 1999 +@set EDITION 0.5.94 +@set VERSION 0.5.94 diff --git a/grub/asmstub.c b/grub/asmstub.c index 45d5aa285..20ecc7852 100644 --- a/grub/asmstub.c +++ b/grub/asmstub.c @@ -33,6 +33,7 @@ int grub_stage2 (void); #include #include +#include #include #include #include @@ -94,6 +95,7 @@ static jmp_buf env_for_exit; static void get_floppy_disk_name (char *name, int unit); static void get_ide_disk_name (char *name, int unit); static void get_scsi_disk_name (char *name, int unit); +static void init_device_map (void); /* The main entry point into this mess. */ int @@ -102,8 +104,8 @@ grub_stage2 (void) /* These need to be static, because they survive our stack transitions. */ static int status = 0; static char *realstack; - int i, num_hd = 0; char *scratch, *simstack; + int i; /* We need a nested function so that we get a clean stack frame, regardless of how the code is optimized. */ @@ -145,59 +147,7 @@ grub_stage2 (void) for (i = 0; i < NUM_DISKS; i++) disks[i].flags = -1; - assert (device_map == 0); - device_map = malloc (NUM_DISKS * sizeof (char *)); - assert (device_map); - - /* Probe devices for creating the device map. */ - - /* Initialize DEVICE_MAP. */ - for (i = 0; i < NUM_DISKS; i++) - device_map[i] = 0; - - /* Print something as the user does not think GRUB has been crashed. */ - fprintf (stderr, - "Probe devices to guess BIOS drives. This may take a long time.\n"); - - /* Floppies. */ - if (! no_floppy) - for (i = 0; i < 2; i++) - { - char name[16]; - - if (i == 1 && ! probe_second_floppy) - break; - - get_floppy_disk_name (name, i); - if (check_device (name)) - assign_device_name (i, name); - } - - /* IDE disks. */ - for (i = 0; i < 4; i++) - { - char name[16]; - - get_ide_disk_name (name, i); - if (check_device (name)) - { - assign_device_name (num_hd + 0x80, name); - num_hd++; - } - } - - /* The rest is SCSI disks. */ - for (i = 0; i < 8; i++) - { - char name[16]; - - get_scsi_disk_name (name, i); - if (check_device (name)) - { - assign_device_name (num_hd + 0x80, name); - num_hd++; - } - } + init_device_map (); /* Check some invariants. */ assert ((SCRATCHSEG << 4) == SCRATCHADDR); @@ -263,6 +213,180 @@ grub_stage2 (void) return status; } +static void +init_device_map (void) +{ + int i; + int num_hd = 0; + FILE *fp; + + static void print_error (int no, const char *msg) + { + fprintf (stderr, "%s:%d: error: %s\n", device_map_file, no, msg); + } + + assert (device_map == 0); + device_map = malloc (NUM_DISKS * sizeof (char *)); + assert (device_map); + + /* Probe devices for creating the device map. */ + + /* Initialize DEVICE_MAP. */ + for (i = 0; i < NUM_DISKS; i++) + device_map[i] = 0; + + /* Open the device map file. */ + fp = fopen (device_map_file, "r"); + if (fp) + { + /* If there is the device map file, use the data in it instead of + probing devices. */ + char buf[1024]; /* XXX */ + int line_number = 0; + + while (fgets (buf, sizeof (buf), fp)) + { + char *ptr, *eptr; + int drive; + int is_floppy = 0; + + /* Increase the number of lines. */ + line_number++; + + /* If the first character is '#', skip it. */ + if (buf[0] == '#') + continue; + + ptr = buf; + /* Skip leading spaces. */ + while (*ptr && isspace (*ptr)) + ptr++; + + if (*ptr != '(') + { + print_error (line_number, "No open parenthesis found"); + stop (); + } + + ptr++; + if ((*ptr != 'f' && *ptr != 'h') || *(ptr + 1) != 'd') + { + print_error (line_number, "Bad drive name"); + stop (); + } + + if (*ptr == 'f') + is_floppy = 1; + + ptr += 2; + drive = strtoul (ptr, &ptr, 10); + if (drive < 0 || drive > 8) + { + print_error (line_number, "Bad device number"); + stop (); + } + + if (! is_floppy) + drive += 0x80; + + if (*ptr != ')') + { + print_error (line_number, "No close parenthesis found"); + stop (); + } + + ptr++; + /* Skip spaces. */ + while (*ptr && isspace (*ptr)) + ptr++; + + if (! *ptr) + { + print_error (line_number, "No filename found"); + stop (); + } + + /* Terminate the filename. */ + eptr = ptr; + while (*eptr && ! isspace (*eptr)) + eptr++; + *eptr = 0; + + assign_device_name (drive, ptr); + } + + fclose (fp); + return; + } + + /* Print something as the user does not think GRUB has been crashed. */ + fprintf (stderr, + "Probe devices to guess BIOS drives. This may take a long time.\n"); + + /* Try to open the device map file to write the probed data. */ + fp = fopen (device_map_file, "w"); + + /* Floppies. */ + if (! no_floppy) + for (i = 0; i < 2; i++) + { + char name[16]; + + if (i == 1 && ! probe_second_floppy) + break; + + get_floppy_disk_name (name, i); + if (check_device (name)) + { + assign_device_name (i, name); + + /* If the device map file is opened, write the map. */ + if (fp) + fprintf (fp, "(fd%d)\t%s\n", i, name); + } + } + + /* IDE disks. */ + for (i = 0; i < 4; i++) + { + char name[16]; + + get_ide_disk_name (name, i); + if (check_device (name)) + { + assign_device_name (num_hd + 0x80, name); + + /* If the device map file is opened, write the map. */ + if (fp) + fprintf (fp, "(hd%d)\t%s\n", num_hd, name); + + num_hd++; + } + } + + /* The rest is SCSI disks. */ + for (i = 0; i < 8; i++) + { + char name[16]; + + get_scsi_disk_name (name, i); + if (check_device (name)) + { + assign_device_name (num_hd + 0x80, name); + + /* If the device map file is opened, write the map. */ + if (fp) + fprintf (fp, "(hd%d)\t%s\n", num_hd, name); + + num_hd++; + } + } + + /* OK, close the device map file if opened. */ + if (fp) + fclose (fp); +} + /* These three functions are quite different among OSes. */ static void get_floppy_disk_name (char *name, int unit) @@ -378,7 +502,10 @@ assign_device_name (int drive, const char *device) } /* Assign DRIVE to DEVICE. */ - device_map[drive] = strdup (device); + if (! device) + device_map[drive] = 0; + else + device_map[drive] = strdup (device); } void @@ -714,10 +841,16 @@ get_diskinfo (int drive, struct geometry *geometry) { disks[drive].flags = open (devname, O_RDONLY); if (disks[drive].flags == -1) - return -1; + { + assign_device_name (drive, 0); + return -1; + } } else - return -1; + { + assign_device_name (drive, 0); + return -1; + } } /* Attempt to read the first sector. */ @@ -725,6 +858,7 @@ get_diskinfo (int drive, struct geometry *geometry) { close (disks[drive].flags); disks[drive].flags = -1; + assign_device_name (drive, 0); return -1; } diff --git a/grub/main.c b/grub/main.c index 29e84d060..a03313018 100644 --- a/grub/main.c +++ b/grub/main.c @@ -38,9 +38,11 @@ int verbose = 0; int read_only = 0; int no_floppy = 0; int probe_second_floppy = 0; +char *device_map_file = "/boot/grub/device.map"; static int default_boot_drive; static int default_install_partition; static char *default_config_file; +static char *default_device_map_file; #define OPT_HELP -2 #define OPT_VERSION -3 @@ -55,6 +57,7 @@ static char *default_config_file; #define OPT_READ_ONLY -12 #define OPT_PROBE_SECOND_FLOPPY -13 #define OPT_NO_FLOPPY -14 +#define OPT_DEVICE_MAP -15 #define OPTSTRING "" static struct option longopts[] = @@ -62,6 +65,7 @@ static struct option longopts[] = {"batch", no_argument, 0, OPT_BATCH}, {"boot-drive", required_argument, 0, OPT_BOOT_DRIVE}, {"config-file", required_argument, 0, OPT_CONFIG_FILE}, + {"device-map", required_argument, 0, OPT_DEVICE_MAP}, {"help", no_argument, 0, OPT_HELP}, {"hold", no_argument, 0, OPT_HOLD}, {"install-partition", required_argument, 0, OPT_INSTALL_PARTITION}, @@ -90,6 +94,7 @@ Enter the GRand Unified Bootloader command shell.\n\ --batch turn on batch mode for non-interactive use\n\ --boot-drive=DRIVE specify stage2 boot_drive [default=0x%x]\n\ --config-file=FILE specify stage2 config_file [default=%s]\n\ + --device-map=FILE specify the device map file [default=%s]\n\ --help display this message and exit\n\ --hold wait until a debugger will attach\n\ --install-partition=PAR specify stage2 install_partition [default=0x%x]\n\ @@ -104,7 +109,7 @@ Enter the GRand Unified Bootloader command shell.\n\ Report bugs to bug-grub@gnu.org\n\ ", default_boot_drive, default_config_file, - default_install_partition); + default_device_map_file, default_install_partition); exit (status); } @@ -128,7 +133,8 @@ main (int argc, char **argv) default_config_file = config_file; else default_config_file = "NONE"; - + default_device_map_file = device_map_file; + /* Parse command-line options. */ do { @@ -204,6 +210,10 @@ main (int argc, char **argv) case OPT_PROBE_SECOND_FLOPPY: probe_second_floppy = 1; break; + + case OPT_DEVICE_MAP: + device_map_file = strdup (optarg); + break; default: usage (1); diff --git a/stage2/shared.h b/stage2/shared.h index 097a1064c..f3652e320 100644 --- a/stage2/shared.h +++ b/stage2/shared.h @@ -391,6 +391,8 @@ extern int no_floppy; extern int probe_second_floppy; /* The map between BIOS drives and UNIX device file names. */ extern char **device_map; +/* The filename which stores the information about a device map. */ +extern char *device_map_file; /* The array of geometries. */ extern struct geometry *disks; /* Check if DEVICE can be read. If an error occurs, return zero,