Return-Path: pjones@redhat.com Received: from zmta02.collab.prod.int.phx2.redhat.com (LHLO zmta02.collab.prod.int.phx2.redhat.com) (10.5.5.32) by mail04.corp.redhat.com with LMTP; Wed, 14 Jul 2010 14:25:52 -0400 (EDT) Received: from localhost (localhost.localdomain [127.0.0.1]) by zmta02.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id B69C19F152 for ; Wed, 14 Jul 2010 14:25:52 -0400 (EDT) Received: from zmta02.collab.prod.int.phx2.redhat.com ([127.0.0.1]) by localhost (zmta02.collab.prod.int.phx2.redhat.com [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id jCHcGZehMQ5J for ; Wed, 14 Jul 2010 14:25:52 -0400 (EDT) Received: from int-mx08.intmail.prod.int.phx2.redhat.com (int-mx08.intmail.prod.int.phx2.redhat.com [10.5.11.21]) by zmta02.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id A601C9F14C for ; Wed, 14 Jul 2010 14:25:52 -0400 (EDT) Received: from pjones4.install.bos.redhat.com (pjones4.install.bos.redhat.com [10.16.52.154]) by int-mx08.intmail.prod.int.phx2.redhat.com (8.13.8/8.13.8) with ESMTP id o6EIPpGh017771; Wed, 14 Jul 2010 14:25:52 -0400 From: Peter Jones To: Matt Domsch Cc: Peter Jones , Stuart Hayes Subject: [efibootmgr patch] Handle sector_size != 512. Date: Wed, 14 Jul 2010 14:26:49 -0400 Message-Id: <1279132009-26635-1-git-send-email-pjones@redhat.com> In-Reply-To: <1279121617-17961-1-git-send-email-pjones@redhat.com> References: <1279121617-17961-1-git-send-email-pjones@redhat.com> X-Scanned-By: MIMEDefang 2.67 on 10.5.11.21 Disks can have 4kB sectors now, so don't just bail out when that's the case. --- src/include/disk.h | 3 +++ src/lib/disk.c | 43 +++++++++++++++++++++++++++++++++---------- src/lib/gpt.c | 30 ++++++++++++++---------------- 3 files changed, 50 insertions(+), 26 deletions(-) diff --git a/src/include/disk.h b/src/include/disk.h index eb93d10..8aa37d7 100644 --- a/src/include/disk.h +++ b/src/include/disk.h @@ -65,6 +65,9 @@ enum _interface_type {interface_type_unknown, ata, atapi, scsi, usb, i1394, fibre, i2o, md}; + +unsigned int lcm(unsigned int x, unsigned int y); + int disk_get_pci(int fd, unsigned char *bus, unsigned char *device, diff --git a/src/lib/disk.c b/src/lib/disk.c index 883864f..9c3a878 100644 --- a/src/lib/disk.c +++ b/src/lib/disk.c @@ -420,6 +420,27 @@ get_sector_size(int filedes) return sector_size; } +/************************************************************ + * lcm + * Requires: + * - numbers of which to find the lowest common multiple + * Modifies: nothing + * Returns: + * lowest common multiple of x and y + ************************************************************/ +unsigned int +lcm(unsigned int x, unsigned int y) +{ + unsigned int m = x, n = y, o; + + while ((o = m % n)) { + m = n; + n = o; + } + + return (x / n) * y; +} + /** * disk_get_partition_info() * @fd - open file descriptor to disk @@ -442,26 +463,27 @@ disk_get_partition_info (int fd, uint8_t *mbr_type, uint8_t *signature_type) { legacy_mbr *mbr; - void *mbr_unaligned; + void *mbr_sector; + size_t mbr_size; off_t offset; int this_bytes_read = 0; int gpt_invalid=0, mbr_invalid=0; int rc=0; int sector_size = get_sector_size(fd); - if (sizeof(*mbr) != sector_size) - return 1; - mbr_unaligned = malloc(sizeof(*mbr)+sector_size-1); - mbr = (legacy_mbr *) - (((unsigned long)mbr_unaligned + sector_size - 1) & - ~(unsigned long)(sector_size-1)); - memset(mbr, 0, sizeof(*mbr)); + + mbr_size = lcm(sizeof(*mbr), sector_size); + if ((rc = posix_memalign(&mbr_sector, sector_size, mbr_size)) != 0) + goto error; + memset(mbr_sector, '\0', mbr_size); + offset = lseek(fd, 0, SEEK_SET); - this_bytes_read = read(fd, mbr, sizeof(*mbr)); + this_bytes_read = read(fd, mbr_sector, mbr_size); if (this_bytes_read < sizeof(*mbr)) { rc=1; goto error_free_mbr; } + mbr = (legacy_mbr *)mbr_sector; gpt_invalid = gpt_disk_get_partition_info(fd, num, start, size, signature, @@ -479,7 +501,8 @@ disk_get_partition_info (int fd, } } error_free_mbr: - free(mbr_unaligned); + free(mbr_sector); + error: return rc; } diff --git a/src/lib/gpt.c b/src/lib/gpt.c index d90ddaf..83e7a94 100644 --- a/src/lib/gpt.c +++ b/src/lib/gpt.c @@ -215,26 +215,24 @@ read_lastoddsector(int fd, uint64_t lba, void *buffer, size_t count) static ssize_t read_lba(int fd, uint64_t lba, void *buffer, size_t bytes) { - int sector_size = get_sector_size(fd); - off_t offset = lba * sector_size; + int sector_size = get_sector_size(fd); + off_t offset = lba * sector_size; ssize_t bytesread; - void *aligned; - void *unaligned; - - if (bytes % sector_size) - return EINVAL; + void *iobuf; + size_t iobuf_size; + int rc; - unaligned = malloc(bytes+sector_size-1); - aligned = (void *) - (((unsigned long)unaligned + sector_size - 1) & - ~(unsigned long)(sector_size-1)); - memset(aligned, 0, bytes); + iobuf_size = lcm(bytes, sector_size); + rc = posix_memalign(&iobuf, sector_size, iobuf_size); + if (rc) + return rc; + memset(iobuf, 0, bytes); - lseek(fd, offset, SEEK_SET); - bytesread = read(fd, aligned, bytes); - memcpy(buffer, aligned, bytesread); - free(unaligned); + lseek(fd, offset, SEEK_SET); + bytesread = read(fd, iobuf, iobuf_size); + memcpy(buffer, iobuf, bytes); + free(iobuf); /* Kludge. This is necessary to read/write the last block of an odd-sized disk, until Linux 2.5.x kernel fixes. -- 1.7.1.1