Because of cache coherency problem grub accesses partitions on linux by
hdaX device and not by hda with correct offset. The problem is that
because of 4K cache blocks disk.c may read sectors before the partition
and hence making hostdisk.c try to read from negative offset. I'm sad
that we need such workarounds for free systems.

-- 
Regards
Vladimir 'φ-coder/phcoder' Serbinenko

=== modified file 'util/hostdisk.c'
--- util/hostdisk.c	2010-01-25 17:04:22 +0000
+++ util/hostdisk.c	2010-01-31 11:52:27 +0000
@@ -336,7 +336,8 @@
     char dev[PATH_MAX];
 
     strcpy (dev, map[disk->id].device);
-    if (disk->partition && strncmp (map[disk->id].device, "/dev/", 5) == 0)
+    if (disk->partition && sector >= disk->partition->start
+	&& strncmp (map[disk->id].device, "/dev/", 5) == 0)
       is_partition = linux_find_partition (dev, disk->partition->start);
 
     /* Open the partition.  */
@@ -490,6 +491,23 @@
 {
   int fd;
 
+  /* Split pre-partition and partition reads.  */
+  if (disk->partition && sector < disk->partition->start
+      && sector + size > disk->partition->start)
+    {
+      grub_err_t err;
+      err = grub_util_biosdisk_read (disk, sector,
+				     disk->partition->start - sector,
+				     buf);
+      if (err)
+	return err;
+
+      return grub_util_biosdisk_read (disk, disk->partition->start,
+				      size - (disk->partition->start - sector),
+				      buf + ((disk->partition->start - sector)
+					     << GRUB_DISK_SECTOR_BITS));
+    }
+
   fd = open_device (disk, sector, O_RDONLY);
   if (fd < 0)
     return grub_errno;
@@ -527,6 +545,23 @@
 {
   int fd;
 
+  /* Split pre-partition and partition writes.  */
+  if (disk->partition && sector < disk->partition->start
+      && sector + size > disk->partition->start)
+    {
+      grub_err_t err;
+      err = grub_util_biosdisk_write (disk, sector,
+				      disk->partition->start - sector,
+				      buf);
+      if (err)
+	return err;
+
+      return grub_util_biosdisk_write (disk, disk->partition->start,
+				       size - (disk->partition->start - sector),
+				       buf + ((disk->partition->start - sector)
+					      << GRUB_DISK_SECTOR_BITS));
+    }
+
   fd = open_device (disk, sector, O_WRONLY);
   if (fd < 0)
     return grub_errno;

Attachment: signature.asc
Description: OpenPGP digital signature

_______________________________________________
Grub-devel mailing list
Grub-devel@gnu.org
http://lists.gnu.org/mailman/listinfo/grub-devel

Reply via email to