--- grub-0.97/lib/device.c.alt-partition-map	2006-08-01 21:23:02 +0400
+++ grub-0.97/lib/device.c	2006-08-01 21:29:27 +0400
@@ -601,9 +601,27 @@ check_device (const char *device)
   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)
 {
   auto void show_error (int no, const char *msg);
   auto void show_warning (int no, const char *msg, ...);
@@ -634,6 +652,9 @@ read_device_map (FILE *fp, char **map, c
       char *ptr, *eptr;
       int drive;
       int is_floppy = 0;
+#ifdef __linux__
+      int partition = -1;
+#endif /* __linux__ */
       
       /* Increase the number of lines.  */
       line_number++;
@@ -684,6 +705,27 @@ read_device_map (FILE *fp, char **map, c
       
       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 != ')')
 	{
@@ -708,6 +750,35 @@ read_device_map (FILE *fp, char **map, c
 	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])
 	{
@@ -731,7 +802,8 @@ read_device_map (FILE *fp, char **map, c
    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;
@@ -756,7 +828,7 @@ init_device_map (char ***map, const char
 	{
 	  int ret;
 
-	  ret = read_device_map (fp, *map, map_file);
+	  ret = read_device_map (fp, *map, map_file, partition_map);
 	  fclose (fp);
 	  return ret;
 	}
@@ -927,7 +999,7 @@ init_device_map (char ***map, const char
 
 /* 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;
 
@@ -936,6 +1008,17 @@ restore_device_map (char **map)
       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__
@@ -956,10 +1039,12 @@ is_disk_device (char **map, int drive)
 }
 
 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, len, pnum;
   
   if ((partition & 0x00FF00) != 0x00FF00)
@@ -970,24 +1055,34 @@ write_to_partition (char **map, int driv
       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 */
     }
-
-  len = strlen(dev);
-  pnum = ((partition >> 16) & 0xFF);
-  if (isdigit(dev[len-1]))
+  else
     {
-      /* It is obviously some RAID disk: "/dev/<dsk>/c0d0" . "p1" */
-      sprintf (dev + len, "p%d",  pnum + 1);
+      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");
+	}
+
+      len = strlen(dev);
+      pnum = ((partition >> 16) & 0xFF);
+      if (isdigit(dev[len-1]))
+	{
+	  /* It is obviously some RAID disk: "/dev/<dsk>/c0d0" . "p1" */
+	  sprintf (dev + len, "p%d",  pnum + 1);
+	}
+      else
+	sprintf (dev + len, "%d",  pnum + 1);
     }
-  else
-    sprintf (dev + len, "%d",  pnum + 1);
   
   /* Open the partition.  */
   fd = open (dev, O_RDWR);
--- grub-0.97/lib/device.h.alt-partition-map	2004-05-23 20:35:00 +0400
+++ grub-0.97/lib/device.h	2006-08-01 21:26:01 +0400
@@ -32,16 +32,29 @@
 #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 is_disk_device (char **map, int drive);
-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.97/grub/asmstub.c.alt-partition-map	2006-08-01 21:23:02 +0400
+++ grub-0.97/grub/asmstub.c	2006-08-01 21:24:36 +0400
@@ -88,6 +88,9 @@ struct geometry *disks = 0;
 /* 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;
 
@@ -173,7 +176,8 @@ grub_stage2 (void)
   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. */
@@ -231,8 +235,9 @@ grub_stage2 (void)
     close (serial_fd);
   
   /* Release memory. */
-  restore_device_map (device_map);
+  restore_device_map (device_map, partition_map);
   device_map = 0;
+  partition_map = 0;
   munmap(disks, NUM_DISKS * sizeof (*disks));
   disks = 0;
   munmap(scratch, 0x100000 + EXTENDED_MEMSIZE + 15);
--- grub-0.97/stage2/disk_io.c.alt-partition-map	2006-08-01 21:23:02 +0400
+++ grub-0.97/stage2/disk_io.c	2006-08-01 21:23:22 +0400
@@ -376,7 +376,8 @@ devwrite (int sector, int sector_count, 
 	 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.97/stage2/shared.h.alt-partition-map	2006-08-01 21:23:02 +0400
+++ grub-0.97/stage2/shared.h	2006-08-01 21:23:22 +0400
@@ -605,6 +605,8 @@ extern int floppy_disks;
 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.  */
