]> err.no Git - util-linux/commitdiff
libblkid: use BLKSSZGET for GPT sectors
authorKarel Zak <kzak@redhat.com>
Thu, 22 Oct 2009 12:52:39 +0000 (14:52 +0200)
committerKarel Zak <kzak@redhat.com>
Thu, 22 Oct 2009 12:52:39 +0000 (14:52 +0200)
The current implementation uses fixed sector size (512 bytes), that's
wrong. UEFI standard requires real logical sector size -- it means
BLKSSZGET for Linux.

The size of GPT header is not static, but whole sector is allocated
for the header. In theory the HeaderSize field could be greater than
sizeof(struct gpt_header). It means we have to read whole sector with
the header, because the header crc32 checksum is counted according to
HeaderSize.

Signed-off-by: Karel Zak <kzak@redhat.com>
lib/blkdev.c
shlibs/blkid/src/partitions/gpt.c
shlibs/blkid/src/probe.c

index 7c6c7bab4b7083be0eea0e345a9282f40981ee61..1ca4548bb8488cc2353d5bf07ed9cbd974de8577 100644 (file)
@@ -85,7 +85,11 @@ blkdev_get_sectors(int fd, unsigned long long *sectors)
        return -1;
 }
 
-/* get hardware sector size */
+/* get logical sector size (default is 512)
+ *
+ * This is the smallest unit the storage device can
+ * address. It is typically 512 bytes.
+ */
 int
 blkdev_get_sector_size(int fd, int *sector_size)
 {
index f2d54d741ceafaab08eee34d6d4c72ed6cc50885..dcadf754ee02eac5456126777dba3d296dc0729d 100644 (file)
@@ -23,7 +23,6 @@
 #include "dos.h"
 
 #define GPT_PRIMARY_LBA        1
-#define GPT_BLOCK_SIZE 512
 
 /* Signature - “EFI PART” */
 #define GPT_HEADER_SIGNATURE 0x5452415020494645ULL
@@ -67,7 +66,16 @@ struct gpt_header {
        uint32_t        sizeof_partition_entry;
        uint32_t        partition_entry_array_crc32;
 
-       uint8_t         reserved2[GPT_BLOCK_SIZE - 92];
+       /*
+        * The rest of the block is reserved by UEFI and must be zero. EFI
+        * standard handles this by:
+        *
+        * uint8_t              reserved2[ BLKSSZGET - 92 ];
+        *
+        * This definition is useless in practice. It is necessary to read
+        * whole block from the device rather than sizeof(struct gpt_header)
+        * only.
+        */
 } __attribute__ ((packed));
 
 /*** not used
@@ -104,7 +112,7 @@ static inline unsigned char *get_lba_buffer(blkid_probe pr,
                                        uint64_t lba, size_t bytes)
 {
        return blkid_probe_get_buffer(pr,
-                       GPT_BLOCK_SIZE * lba, bytes);
+                       blkid_probe_get_sectorsize(pr) * lba, bytes);
 }
 
 static inline int guidcmp(efi_guid_t left, efi_guid_t right)
@@ -115,7 +123,7 @@ static inline int guidcmp(efi_guid_t left, efi_guid_t right)
 static int last_lba(blkid_probe pr, uint64_t *lba)
 {
        blkid_loff_t sz = blkid_probe_get_size(pr);
-       if (sz < GPT_BLOCK_SIZE)
+       if (sz < blkid_probe_get_sectorsize(pr))
                return -1;
 
        *lba = (sz >> 9) - 1;
@@ -185,19 +193,31 @@ static struct gpt_header *get_gpt_header(
        uint32_t crc, orgcrc;
        uint64_t lu, fu;
        size_t esz;
+       uint32_t hsz, ssz;
+
+       ssz = blkid_probe_get_sectorsize(pr);
 
-       h = (struct gpt_header *) get_lba_buffer(pr, lba, sizeof(*h));
+       /* whole sector is allocated for GPT header */
+       h = (struct gpt_header *) get_lba_buffer(pr, lba, ssz);
        if (!h)
                return NULL;
 
        if (le64_to_cpu(h->signature) != GPT_HEADER_SIGNATURE)
                return NULL;
 
+       hsz = le32_to_cpu(h->header_size);
+
+       /* EFI: The HeaderSize must be greater than 92 and must be less
+        *      than or equal to the logical block size.
+        */
+       if (hsz > ssz || hsz < sizeof(*h))
+               return NULL;
+
        /* Header has to be verified when header_crc32 is zero */
        orgcrc = le32_to_cpu(h->header_crc32);
        h->header_crc32 = 0;
 
-       crc = count_crc32((unsigned char *) h, le32_to_cpu(h->header_size));
+       crc = count_crc32((unsigned char *) h, hsz);
        if (crc != orgcrc) {
                DBG(DEBUG_LOWPROBE, printf("GPT header corrupted\n"));
                return NULL;
@@ -235,7 +255,8 @@ static struct gpt_header *get_gpt_header(
                return NULL;
        }
 
-       /* The header seems valid, save it */
+       /* The header seems valid, save it
+        * (we don't care about zeros in hdr->reserved2 area) */
        memcpy(hdr, h, sizeof(*h));
        h = hdr;
 
@@ -349,9 +370,6 @@ const struct blkid_idinfo gpt_pt_idinfo =
         * skip the legacy MBR. We follows this behavior and MBR is optional.
         * See is_valid_pmbr().
         *
-        * It would be possible to check for "EFI PART" at begin of the disk,
-        * but the primary GPT is not required (in force mode).
-        *
         * It means we have to always call probe_gpt_pt().
         */
        .magics         = BLKID_NONE_MAGIC
index 078669f48ebf5042b5c94546ebdf769c4c4065cd..27bcf3d83a6eccb5f0636ed23809eff46128a7d4 100644 (file)
@@ -931,7 +931,7 @@ blkid_loff_t blkid_probe_get_size(blkid_probe pr)
  * blkid_probe_get_sectorsize:
  * @pr: probe
  *
- * Returns: block device hardware sector size (BLKSSZGET ioctl, default 512).
+ * Returns: block device logical sector size (BLKSSZGET ioctl, default 512).
  */
 unsigned int blkid_probe_get_sectorsize(blkid_probe pr)
 {