a5bd9f6
From 069348765049ede8357b604a232cc636e5f2dbbb Mon Sep 17 00:00:00 2001
a5bd9f6
From: Vladimir 'phcoder' Serbinenko <phcoder@gmail.com>
a5bd9f6
Date: Tue, 19 Feb 2013 09:10:26 +0100
a5bd9f6
Subject: [PATCH 153/364] 	Support Openfirmware disks with non-512B
a5bd9f6
 sectors.
a5bd9f6
a5bd9f6
	* grub-core/disk/ieee1275/ofdisk.c (grub_ofdisk_open): Get the block
a5bd9f6
	size of the disk.
a5bd9f6
	* (grub_ofdisk_get_block_size): New function.
a5bd9f6
	* (grub_ofdisk_prepare): Use the correct block size.
a5bd9f6
	* (grub_ofdisk_read): Likewise.
a5bd9f6
	* (grub_ofdisk_write): Likewise.
a5bd9f6
	* include/grub/ieee1275/ofdisk.h (grub_ofdisk_get_block_size):
a5bd9f6
	New proto.
a5bd9f6
---
a5bd9f6
 ChangeLog                        | 13 +++++++++
a5bd9f6
 grub-core/disk/ieee1275/ofdisk.c | 59 ++++++++++++++++++++++++++++++++++++----
a5bd9f6
 include/grub/ieee1275/ofdisk.h   |  3 ++
a5bd9f6
 3 files changed, 70 insertions(+), 5 deletions(-)
a5bd9f6
a5bd9f6
diff --git a/ChangeLog b/ChangeLog
a5bd9f6
index 3731229..654ebcb 100644
a5bd9f6
--- a/ChangeLog
a5bd9f6
+++ b/ChangeLog
a5bd9f6
@@ -1,3 +1,16 @@
a5bd9f6
+2013-02-19  Paulo Flabiano Smorigo <pfsmorigo@br.ibm.com>
a5bd9f6
+
a5bd9f6
+	Support Openfirmware disks with non-512B sectors.
a5bd9f6
+
a5bd9f6
+	* grub-core/disk/ieee1275/ofdisk.c (grub_ofdisk_open): Get the block
a5bd9f6
+	size of the disk.
a5bd9f6
+	* (grub_ofdisk_get_block_size): New function.
a5bd9f6
+	* (grub_ofdisk_prepare): Use the correct block size.
a5bd9f6
+	* (grub_ofdisk_read): Likewise.
a5bd9f6
+	* (grub_ofdisk_write): Likewise.
a5bd9f6
+	* include/grub/ieee1275/ofdisk.h (grub_ofdisk_get_block_size):
a5bd9f6
+	New proto.
a5bd9f6
+
a5bd9f6
 2013-02-06  Vladimir Serbinenko  <phcoder@gmail.com>
a5bd9f6
 
a5bd9f6
 	* grub-core/commands/lsacpi.c: Fix types on 64-bit platform.
a5bd9f6
diff --git a/grub-core/disk/ieee1275/ofdisk.c b/grub-core/disk/ieee1275/ofdisk.c
a5bd9f6
index 644bbd2..2130cb1 100644
a5bd9f6
--- a/grub-core/disk/ieee1275/ofdisk.c
a5bd9f6
+++ b/grub-core/disk/ieee1275/ofdisk.c
a5bd9f6
@@ -349,6 +349,14 @@ grub_ofdisk_open (const char *name, grub_disk_t disk)
a5bd9f6
       return grub_error (GRUB_ERR_UNKNOWN_DEVICE, "not a block device");
a5bd9f6
     }
a5bd9f6
 
a5bd9f6
+  grub_uint32_t block_size = 0;
a5bd9f6
+  if (grub_ofdisk_get_block_size (devpath, &block_size) == 0)
a5bd9f6
+    {
a5bd9f6
+      for (disk->log_sector_size = 0;
a5bd9f6
+           (1U << disk->log_sector_size) < block_size;
a5bd9f6
+           disk->log_sector_size++);
a5bd9f6
+    }
a5bd9f6
+
a5bd9f6
   /* XXX: There is no property to read the number of blocks.  There
a5bd9f6
      should be a property `#blocks', but it is not there.  Perhaps it
a5bd9f6
      is possible to use seek for this.  */
a5bd9f6
@@ -415,7 +423,7 @@ grub_ofdisk_prepare (grub_disk_t disk, grub_disk_addr_t sector)
a5bd9f6
       last_devpath = disk->data;      
a5bd9f6
     }
a5bd9f6
 
a5bd9f6
-  pos = sector << GRUB_DISK_SECTOR_BITS;
a5bd9f6
+  pos = sector << disk->log_sector_size;
a5bd9f6
 
a5bd9f6
   grub_ieee1275_seek (last_ihandle, pos, &status);
a5bd9f6
   if (status < 0)
a5bd9f6
@@ -434,9 +442,9 @@ grub_ofdisk_read (grub_disk_t disk, grub_disk_addr_t sector,
a5bd9f6
   err = grub_ofdisk_prepare (disk, sector);
a5bd9f6
   if (err)
a5bd9f6
     return err;
a5bd9f6
-  grub_ieee1275_read (last_ihandle, buf, size  << GRUB_DISK_SECTOR_BITS,
a5bd9f6
+  grub_ieee1275_read (last_ihandle, buf, size  << disk->log_sector_size,
a5bd9f6
 		      &actual);
a5bd9f6
-  if (actual != (grub_ssize_t) (size  << GRUB_DISK_SECTOR_BITS))
a5bd9f6
+  if (actual != (grub_ssize_t) (size  << disk->log_sector_size))
a5bd9f6
     return grub_error (GRUB_ERR_READ_ERROR, N_("failure reading sector 0x%llx "
a5bd9f6
 					       "from `%s'"),
a5bd9f6
 		       (unsigned long long) sector,
a5bd9f6
@@ -454,9 +462,9 @@ grub_ofdisk_write (grub_disk_t disk, grub_disk_addr_t sector,
a5bd9f6
   err = grub_ofdisk_prepare (disk, sector);
a5bd9f6
   if (err)
a5bd9f6
     return err;
a5bd9f6
-  grub_ieee1275_write (last_ihandle, buf, size  << GRUB_DISK_SECTOR_BITS,
a5bd9f6
+  grub_ieee1275_write (last_ihandle, buf, size  << disk->log_sector_size,
a5bd9f6
 		       &actual);
a5bd9f6
-  if (actual != (grub_ssize_t) (size << GRUB_DISK_SECTOR_BITS))
a5bd9f6
+  if (actual != (grub_ssize_t) (size << disk->log_sector_size))
a5bd9f6
     return grub_error (GRUB_ERR_WRITE_ERROR, N_("failure writing sector 0x%llx "
a5bd9f6
 						"to `%s'"),
a5bd9f6
 		       (unsigned long long) sector,
a5bd9f6
@@ -493,3 +501,44 @@ grub_ofdisk_fini (void)
a5bd9f6
 
a5bd9f6
   grub_disk_dev_unregister (&grub_ofdisk_dev);
a5bd9f6
 }
a5bd9f6
+
a5bd9f6
+grub_err_t
a5bd9f6
+grub_ofdisk_get_block_size (const char *device, grub_uint32_t *block_size)
a5bd9f6
+{
a5bd9f6
+  struct size_args_ieee1275
a5bd9f6
+    {
a5bd9f6
+      struct grub_ieee1275_common_hdr common;
a5bd9f6
+      grub_ieee1275_cell_t method;
a5bd9f6
+      grub_ieee1275_cell_t ihandle;
a5bd9f6
+      grub_ieee1275_cell_t result;
a5bd9f6
+      grub_ieee1275_cell_t size1;
a5bd9f6
+      grub_ieee1275_cell_t size2;
a5bd9f6
+    } args_ieee1275;
a5bd9f6
+
a5bd9f6
+  if (last_ihandle)
a5bd9f6
+    grub_ieee1275_close (last_ihandle);
a5bd9f6
+
a5bd9f6
+  last_ihandle = 0;
a5bd9f6
+  last_devpath = NULL;
a5bd9f6
+
a5bd9f6
+  grub_ieee1275_open (device, &last_ihandle);
a5bd9f6
+  if (! last_ihandle)
a5bd9f6
+    return grub_error (GRUB_ERR_UNKNOWN_DEVICE, "can't open device");
a5bd9f6
+
a5bd9f6
+  INIT_IEEE1275_COMMON (&args_ieee1275.common, "call-method", 2, 2);
a5bd9f6
+  args_ieee1275.method = (grub_ieee1275_cell_t) "block-size";
a5bd9f6
+  args_ieee1275.ihandle = last_ihandle;
a5bd9f6
+  args_ieee1275.result = 1;
a5bd9f6
+
a5bd9f6
+  *block_size = GRUB_DISK_SECTOR_SIZE;
a5bd9f6
+
a5bd9f6
+  if ((IEEE1275_CALL_ENTRY_FN (&args_ieee1275) == -1) || (args_ieee1275.result))
a5bd9f6
+    grub_dprintf ("disk", "can't get block size\n");
a5bd9f6
+  else
a5bd9f6
+    if (args_ieee1275.size1
a5bd9f6
+        && !(args_ieee1275.size1 & (args_ieee1275.size1 - 1))
a5bd9f6
+        && args_ieee1275.size1 >= 512 && args_ieee1275.size1 <= 16384)
a5bd9f6
+      *block_size = args_ieee1275.size1;
a5bd9f6
+
a5bd9f6
+  return 0;
a5bd9f6
+}
a5bd9f6
diff --git a/include/grub/ieee1275/ofdisk.h b/include/grub/ieee1275/ofdisk.h
a5bd9f6
index 2f69e3f..3f58317 100644
a5bd9f6
--- a/include/grub/ieee1275/ofdisk.h
a5bd9f6
+++ b/include/grub/ieee1275/ofdisk.h
a5bd9f6
@@ -22,4 +22,7 @@
a5bd9f6
 extern void grub_ofdisk_init (void);
a5bd9f6
 extern void grub_ofdisk_fini (void);
a5bd9f6
 
a5bd9f6
+extern grub_err_t grub_ofdisk_get_block_size (const char *device,
a5bd9f6
+                                              grub_uint32_t *block_size);
a5bd9f6
+
a5bd9f6
 #endif /* ! GRUB_INIT_HEADER */
a5bd9f6
-- 
a5bd9f6
1.8.1.4
a5bd9f6