=== modified file 'ChangeLog' --- ChangeLog 2013-01-22 14:28:32 +0000 +++ ChangeLog 2013-01-22 17:35:51 +0000 @@ -1,3 +1,15 @@ +2013-01-22 Paulo Flabiano Smorigo + + Support Openfirmware disks with non-512B sectors. + + * grub-core/disk/ieee1275/ofdisk.c (grub_ofdisk_open): Get the block + size of the disk. + * (grub_ofdisk_get_block_size): New function. + * (grub_ofdisk_prepare): Use the correct block size. + * (grub_ofdisk_read): Likewise. + * (grub_ofdisk_write): Likewise. + * include/grub/ieee1275/ofdisk.h (grub_ofdisk_get_block_size): New proto. + 2013-01-22 Colin Watson * util/grub-reboot.in (usage): Document the need for === modified file 'grub-core/disk/ieee1275/ofdisk.c' --- grub-core/disk/ieee1275/ofdisk.c 2013-01-20 15:52:15 +0000 +++ grub-core/disk/ieee1275/ofdisk.c 2013-01-22 16:45:28 +0000 @@ -354,6 +354,13 @@ is possible to use seek for this. */ disk->total_sectors = GRUB_DISK_SIZE_UNKNOWN; + grub_uint32_t block_size = 0; + block_size = grub_ofdisk_get_block_size (devpath); + + for (disk->log_sector_size = 0; + (1U << disk->log_sector_size) < block_size; + disk->log_sector_size++); + { struct ofdisk_hash_ent *op; op = ofdisk_hash_find (devpath); @@ -415,7 +422,7 @@ last_devpath = disk->data; } - pos = sector << GRUB_DISK_SECTOR_BITS; + pos = sector << disk->log_sector_size; grub_ieee1275_seek (last_ihandle, pos, &status); if (status < 0) @@ -434,9 +441,9 @@ err = grub_ofdisk_prepare (disk, sector); if (err) return err; - grub_ieee1275_read (last_ihandle, buf, size << GRUB_DISK_SECTOR_BITS, + grub_ieee1275_read (last_ihandle, buf, size << disk->log_sector_size, &actual); - if (actual != (grub_ssize_t) (size << GRUB_DISK_SECTOR_BITS)) + if (actual != (grub_ssize_t) (size << disk->log_sector_size)) return grub_error (GRUB_ERR_READ_ERROR, N_("failure reading sector 0x%llx " "from `%s'"), (unsigned long long) sector, @@ -454,9 +461,9 @@ err = grub_ofdisk_prepare (disk, sector); if (err) return err; - grub_ieee1275_write (last_ihandle, buf, size << GRUB_DISK_SECTOR_BITS, + grub_ieee1275_write (last_ihandle, buf, size << disk->log_sector_size, &actual); - if (actual != (grub_ssize_t) (size << GRUB_DISK_SECTOR_BITS)) + if (actual != (grub_ssize_t) (size << disk->log_sector_size)) return grub_error (GRUB_ERR_WRITE_ERROR, N_("failure writing sector 0x%llx " "to `%s'"), (unsigned long long) sector, @@ -493,3 +500,46 @@ grub_disk_dev_unregister (&grub_ofdisk_dev); } + + +grub_uint32_t grub_ofdisk_get_block_size (const char *device) +{ + grub_uint32_t block_size = 0; + grub_ieee1275_ihandle_t dev_ihandle = 0; + + struct size_args_ieee1275 + { + struct grub_ieee1275_common_hdr common; + grub_ieee1275_cell_t method; + grub_ieee1275_cell_t ihandle; + grub_ieee1275_cell_t result; + grub_ieee1275_cell_t size1; + grub_ieee1275_cell_t size2; + } args_ieee1275; + + grub_ieee1275_open (device, &dev_ihandle); + if (! dev_ihandle) + { + grub_error (GRUB_ERR_UNKNOWN_DEVICE, "can't open device"); + return 0; + } + + INIT_IEEE1275_COMMON (&args_ieee1275.common, "call-method", 2, 2); + args_ieee1275.method = (grub_ieee1275_cell_t) "block-size"; + args_ieee1275.ihandle = dev_ihandle; + args_ieee1275.result = 1; + + if ((IEEE1275_CALL_ENTRY_FN (&args_ieee1275) == -1) || (args_ieee1275.result)) + { + /* If the method isn't available use the common size */ + grub_dprintf ("disk", "can't get block size\n"); + grub_ieee1275_close (dev_ihandle); + return GRUB_DISK_SECTOR_SIZE; + } + + grub_ieee1275_close (dev_ihandle); + block_size = args_ieee1275.size1; + + return block_size; +} + === modified file 'include/grub/ieee1275/ofdisk.h' --- include/grub/ieee1275/ofdisk.h 2007-07-21 23:32:33 +0000 +++ include/grub/ieee1275/ofdisk.h 2013-01-22 16:45:28 +0000 @@ -21,5 +21,6 @@ extern void grub_ofdisk_init (void); extern void grub_ofdisk_fini (void); +extern grub_uint32_t grub_ofdisk_get_block_size (const char *device); #endif /* ! GRUB_INIT_HEADER */