--- grub-0.93/stage2/disk_io.c.alt-partition-map 2003-08-22 19:48:46 +0400 +++ grub-0.93/stage2/disk_io.c 2003-08-22 19:48:46 +0400 @@ -344,7 +344,8 @@ embed a Stage 1.5 into a partition instead of a MBR, use system calls directly instead of biosdisk, because of the bug in Linux. *sigh* */ - return write_to_partition (device_map, current_drive, current_partition, + return write_to_partition (device_map, partition_map, + current_drive, current_partition, sector, sector_count, buf); } else --- grub-0.93/stage2/shared.h.alt-partition-map 2003-08-22 19:48:46 +0400 +++ grub-0.93/stage2/shared.h 2003-08-22 19:48:46 +0400 @@ -588,6 +588,8 @@ extern char **device_map; /* The filename which stores the information about a device map. */ extern char *device_map_file; +/* The map between drive/partition numbers and UNIX device file names. */ +extern struct partition_map_entry *partition_map; /* The array of geometries. */ extern struct geometry *disks; /* Assign DRIVE to a device name DEVICE. */ --- grub-0.93/lib/device.c.alt-partition-map 2003-08-22 19:48:46 +0400 +++ grub-0.93/lib/device.c 2003-08-22 20:10:33 +0400 @@ -369,9 +369,27 @@ return 1; } +#ifdef __linux__ +/* Find device name for PARTITION on DRIVE in MAP. */ +static const char * +find_device_for_partition (struct partition_map_entry *map, + int drive, int partition) +{ + while (map) + { + if ((map->drive == drive) && (map->partition == partition)) + return map->device_name; + map = map->next; + } + + return NULL; +} +#endif /* __linux__ */ + /* Read mapping information from FP, and write it to MAP. */ static int -read_device_map (FILE *fp, char **map, const char *map_file) +read_device_map (FILE *fp, char **map, const char *map_file, + struct partition_map_entry **partition_map) { static void show_error (int no, const char *msg) { @@ -388,6 +406,9 @@ char *ptr, *eptr; int drive; int is_floppy = 0; +#ifdef __linux__ + int partition = -1; +#endif /* __linux__ */ /* Increase the number of lines. */ line_number++; @@ -431,6 +452,27 @@ if (! is_floppy) drive += 0x80; + +#ifdef __linux__ + /* Check for a possible partition map entry. */ + if (*ptr == ',') + { + if (is_floppy) + { + show_error (line_number, + "Partitions on floppy drives are not allowed"); + return 0; + } + + ptr++; + partition = strtoul (ptr, &ptr, 10); + if (partition < 0 || partition > 255) /* XXX: max value? */ + { + show_error (line_number, "Bad partition number"); + return 0; + } + } +#endif /* __linux__ */ if (*ptr != ')') { @@ -455,6 +497,35 @@ eptr++; *eptr = 0; +#ifdef __linux__ + if (partition != -1) + { + struct partition_map_entry *new_entry; + /* Multiple entries for a given partition is not allowed. */ + if (find_device_for_partition (*partition_map, drive, partition)) + { + show_error (line_number, "Duplicated entry found"); + return 0; + } + + /* Allocate a new partition map entry. */ + new_entry = malloc (sizeof (struct partition_map_entry)); + assert (new_entry); + + /* Fill the entry. */ + new_entry->next = *partition_map; + new_entry->drive = drive; + new_entry->partition = partition; + new_entry->device_name = strdup (ptr); + assert (new_entry->device_name); + + /* Place the new entry at the beginning of the list. */ + *partition_map = new_entry; + + continue; + } +#endif + /* Multiple entries for a given drive is not allowed. */ if (map[drive]) { @@ -476,7 +547,8 @@ If it is zero, don't probe any floppy at all. If it is one, probe one floppy. If it is two, probe two floppies. And so on. */ int -init_device_map (char ***map, const char *map_file, int floppy_disks) +init_device_map (char ***map, struct partition_map_entry **partition_map, + const char *map_file, int floppy_disks) { int i; int num_hd = 0; @@ -501,7 +573,7 @@ { int ret; - ret = read_device_map (fp, *map, map_file); + ret = read_device_map (fp, *map, map_file, partition_map); fclose (fp); return ret; } @@ -651,7 +723,7 @@ /* Restore the memory consumed for MAP. */ void -restore_device_map (char **map) +restore_device_map (char **map, struct partition_map_entry *partition_map) { int i; @@ -660,6 +732,17 @@ free (map[i]); free (map); + +#ifdef __linux__ + while (partition_map) + { + struct partition_map_entry *next = partition_map->next; + if (partition_map->device_name) + free (partition_map->device_name); + free (partition_map); + partition_map = next; + } +#endif /* __linux__ */ } #ifdef __linux__ @@ -667,10 +750,12 @@ a whole disk is not consistent with the one for a partition of the disk. */ int -write_to_partition (char **map, int drive, int partition, +write_to_partition (char **map, struct partition_map_entry *partition_map, + int drive, int partition, int sector, int size, const char *buf) { char dev[PATH_MAX]; /* XXX */ + const char *partition_dev; int fd; if ((partition & 0x00FF00) != 0x00FF00) @@ -681,21 +766,31 @@ return 1; } - assert (map[drive] != 0); - - strcpy (dev, map[drive]); - if (have_devfs ()) + /* First try to find the entry in PARTITION_MAP. */ + partition_dev = find_device_for_partition (partition_map, drive, + (partition >> 16) & 0xFF); + if (partition_dev) { - if (strcmp (dev + strlen(dev) - 5, "/disc") == 0) - strcpy (dev + strlen(dev) - 5, "/part"); + strcpy (dev, partition_dev); /* XXX */ } + else + { + assert (map[drive] != 0); + + strcpy (dev, map[drive]); + if (have_devfs ()) + { + if (strcmp (dev + strlen(dev) - 5, "/disc") == 0) + strcpy (dev + strlen(dev) - 5, "/part"); + } - sprintf (dev + strlen(dev), "%s%d", - /* Compaq smart and others */ - (strncmp(dev, "/dev/ida/", 9) == 0 || - strncmp(dev, "/dev/cciss/", 11) == 0 || - strncmp(dev, "/dev/rd/", 8) == 0) ? "p" : "", - ((partition >> 16) & 0xFF) + 1); + sprintf (dev + strlen(dev), "%s%d", + /* Compaq smart and others */ + (strncmp(dev, "/dev/ida/", 9) == 0 || + strncmp(dev, "/dev/cciss/", 11) == 0 || + strncmp(dev, "/dev/rd/", 8) == 0) ? "p" : "", + ((partition >> 16) & 0xFF) + 1); + } /* Open the partition. */ fd = open (dev, O_RDWR); --- grub-0.93/lib/device.h.alt-partition-map 2000-08-08 20:41:55 +0400 +++ grub-0.93/lib/device.h 2003-08-22 19:48:46 +0400 @@ -32,15 +32,28 @@ #define DEFAULT_HD_HEADS 128 #define DEFAULT_HD_SECTORS 63 +struct partition_map_entry +{ + struct partition_map_entry *next; + int drive; + int partition; + char *device_name; +}; + /* Function prototypes. */ extern void get_drive_geometry (struct geometry *geom, char **map, int drive); extern int check_device (const char *device); -extern int init_device_map (char ***map, const char *map_file, +extern int init_device_map (char ***map, + struct partition_map_entry **partition_map, + const char *map_file, int no_floppies); -extern void restore_device_map (char **map); +extern void restore_device_map (char **map, + struct partition_map_entry *partition_map); #ifdef __linux__ -extern int write_to_partition (char **map, int drive, int partition, +extern int write_to_partition (char **map, + struct partition_map_entry *partition_map, + int drive, int partition, int offset, int size, const char *buf); #endif /* __linux__ */ --- grub-0.93/grub/asmstub.c.alt-partition-map 2003-08-22 19:48:46 +0400 +++ grub-0.93/grub/asmstub.c 2003-08-22 19:48:46 +0400 @@ -86,6 +86,9 @@ /* The map between BIOS drives and UNIX device file names. */ char **device_map = 0; +/* The map between drive/partition numbers and UNIX device file names. */ +struct partition_map_entry *partition_map = 0; + /* The jump buffer for exiting correctly. */ static jmp_buf env_for_exit; @@ -153,7 +156,8 @@ for (i = 0; i < NUM_DISKS; i++) disks[i].flags = -1; - if (! init_device_map (&device_map, device_map_file, floppy_disks)) + if (! init_device_map (&device_map, &partition_map, device_map_file, + floppy_disks)) return 1; /* Check some invariants. */ @@ -211,8 +215,9 @@ close (serial_fd); /* Release memory. */ - restore_device_map (device_map); + restore_device_map (device_map, partition_map); device_map = 0; + partition_map = 0; free (disks); disks = 0; free (scratch);