From: Vladimir 'phcoder' Serbinenko Date: Mon, 25 Jul 2011 06:14:34 +0000 (+0200) Subject: Support ATA disks with 4K sectors. X-Git-Tag: 2.00~1148 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=6795300e7f230ac552c984ef051f0ae79f318bcf;p=thirdparty%2Fgrub.git Support ATA disks with 4K sectors. * include/grub/ata.h (grub_ata): New member log_sector_size. * grub-core/disk/ata.c (grub_ata_dumpinfo): Show sector size. (grub_ata_identify): Read sector size. (grub_ata_readwrite): Use log_sector_size rather than hardcoded value. --- diff --git a/ChangeLog b/ChangeLog index 32dfada58..5c4e20c28 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,12 @@ +2011-07-25 Vladimir Serbinenko + + Support ATA disks with non-4K sectors. + + * include/grub/ata.h (grub_ata): New member log_sector_size. + * grub-core/disk/ata.c (grub_ata_dumpinfo): Show sector size. + (grub_ata_identify): Read sector size. + (grub_ata_readwrite): Use log_sector_size rather than hardcoded value. + 2011-07-25 Vladimir Serbinenko * util/grub-install.in: Don't use uhci outside of x86. diff --git a/grub-core/disk/ata.c b/grub-core/disk/ata.c index 8add7f4de..330635f57 100644 --- a/grub-core/disk/ata.c +++ b/grub-core/disk/ata.c @@ -57,6 +57,7 @@ grub_ata_dumpinfo (struct grub_ata *dev, char *info) { grub_dprintf ("ata", "Addressing: %d\n", dev->addr); grub_dprintf ("ata", "Sectors: %lld\n", (unsigned long long) dev->size); + grub_dprintf ("ata", "Sector size: %u\n", 1U << dev->log_sector_size); } } @@ -170,6 +171,21 @@ grub_ata_identify (struct grub_ata *dev) else dev->size = grub_le_to_cpu64(*((grub_uint64_t *) &info16[100])); + if (info16[106] & (1 << 12)) + { + grub_uint32_t secsize; + secsize = grub_le_to_cpu32 (*((grub_uint32_t *) &info16[117])); + if (secsize & (secsize - 1) || !secsize + || secsize > 1048576) + secsize = 256; + for (dev->log_sector_size = 0; + (1U << dev->log_sector_size) < secsize; + dev->log_sector_size++); + dev->log_sector_size++; + } + else + dev->log_sector_size = 9; + /* Read CHS information. */ dev->cylinders = info16[1]; dev->heads = info16[3]; @@ -314,7 +330,7 @@ grub_ata_readwrite (grub_disk_t disk, grub_disk_addr_t sector, grub_ata_setaddress (ata, &parms, sector, batch, addressing); parms.taskfile.cmd = (! rw ? cmd : cmd_write); parms.buffer = buf; - parms.size = batch * GRUB_DISK_SECTOR_SIZE; + parms.size = batch << ata->log_sector_size; parms.write = rw; if (ata->dma) parms.dma = 1; @@ -322,9 +338,9 @@ grub_ata_readwrite (grub_disk_t disk, grub_disk_addr_t sector, err = ata->dev->readwrite (ata, &parms, 0); if (err) return err; - if (parms.size != batch * GRUB_DISK_SECTOR_SIZE) + if (parms.size != batch << ata->log_sector_size) return grub_error (GRUB_ERR_READ_ERROR, "incomplete read"); - buf += GRUB_DISK_SECTOR_SIZE * batch; + buf += batch << ata->log_sector_size; sector += batch; nsectors += batch; } @@ -433,6 +449,7 @@ grub_ata_open (const char *name, grub_disk_t disk) return grub_error (GRUB_ERR_UNKNOWN_DEVICE, "not an ATA harddisk"); disk->total_sectors = ata->size; + disk->log_sector_size = ata->log_sector_size; disk->id = grub_make_scsi_id (id, bus, 0); diff --git a/include/grub/ata.h b/include/grub/ata.h index 6938b6a42..1a19f27aa 100644 --- a/include/grub/ata.h +++ b/include/grub/ata.h @@ -170,6 +170,7 @@ struct grub_ata /* Sector count. */ grub_uint64_t size; + grub_uint32_t log_sector_size; /* CHS maximums. */ grub_uint16_t cylinders;