Re: libblkid: Is GPT GUID byte order wrong?

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On Mon, Feb 28, 2011 at 11:27:34PM -0500, Andrew Lutomirski wrote:
> I'm playing around with rewriting efibootmgr, and I want it to use
> libblkid to figure out how to label disks.  Unfortunately, there's a
> bit of byte order confusion.  libblkid treats gpt guids like they're
> big-endian, which seems to contradict the spec and all other software.

 .. because UUID is according to all standards 16 byte array, except
 Intel EFI standard...

> This means that the the first three fields should be byte-swapped.
> Wikipedia's page on GPT agrees.

 Yes, you're right. Good catch.

> Should I submit a patch to fix up the byte order?  I don't think that
> fixing this will break anyone's boot since findfs and friends seem to
> use UUID not PART_ENTRY_UUID.

 Fixed in master branch, see the patch below (it's based on GNU parted). 
 
 Thanks!

    Karel


>From c2ec2ff9a2e85c6146ab9253a61a158d8aee8edc Mon Sep 17 00:00:00 2001
From: Karel Zak <kzak@xxxxxxxxxx>
Date: Tue, 1 Mar 2011 10:01:21 +0100
Subject: [PATCH] libblkid: fix EFI GPT uuid byte order

Intel uses little-endians for UUID, the rest of the sane world uses 16
byte big-endian array...

Reported-by: Andrew Lutomirski <luto@xxxxxxx>
Signed-off-by: Karel Zak <kzak@xxxxxxxxxx>
---
 shlibs/blkid/src/partitions/gpt.c |   34 +++++++++++++++++++++++-----------
 1 files changed, 23 insertions(+), 11 deletions(-)

diff --git a/shlibs/blkid/src/partitions/gpt.c b/shlibs/blkid/src/partitions/gpt.c
index 8259c2f..7df17bb 100644
--- a/shlibs/blkid/src/partitions/gpt.c
+++ b/shlibs/blkid/src/partitions/gpt.c
@@ -32,20 +32,18 @@ typedef uint16_t efi_char16_t;
 
 /* UUID */
 typedef struct {
-	uint8_t  b[16];
+	uint32_t time_low;
+	uint16_t time_mid;
+	uint16_t time_hi_and_version;
+	uint8_t clock_seq_hi;
+	uint8_t clock_seq_low;
+	uint8_t node[6];
 } efi_guid_t;
 
-#define EFI_GUID(a,b,c,d0,d1,d2,d3,d4,d5,d6,d7)  ((efi_guid_t) \
-		{{ \
-	(a) & 0xff, ((a) >> 8) & 0xff, ((a) >> 16) & 0xff, ((a) >> 24) & 0xff, \
-	(b) & 0xff, ((b) >> 8) & 0xff, \
-	(c) & 0xff, ((c) >> 8) & 0xff, \
-	(d0), (d1), (d2), (d3), (d4), (d5), (d6), (d7) \
-}})
-
-#define GPT_UNUSED_ENTRY_GUID	EFI_GUID(0x00000000, 0x0000, 0x0000, 0x00, 0x00, \
-					0x00, 0x00, 0x00, 0x00, 0x00, 0x00)
 
+#define GPT_UNUSED_ENTRY_GUID \
+	    ((efi_guid_t) { 0x00000000, 0x0000, 0x0000, 0x00, 0x00, \
+	                    { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }})
 struct gpt_header {
 	uint64_t	signature;		/* "EFI PART" */
 	uint32_t	revision;
@@ -120,6 +118,17 @@ static inline int guidcmp(efi_guid_t left, efi_guid_t right)
 	return memcmp(&left, &right, sizeof (efi_guid_t));
 }
 
+/*
+ * UUID is traditionaly 16 byte big-endian array, except Intel EFI
+ * specification where the UUID is a structure of little-endian fields.
+ */
+static void swap_efi_guid(efi_guid_t *uid)
+{
+	uid->time_low = swab32(uid->time_low);
+	uid->time_mid = swab16(uid->time_mid);
+	uid->time_hi_and_version = swab16(uid->time_hi_and_version);
+}
+
 static int last_lba(blkid_probe pr, uint64_t *lba)
 {
 	blkid_loff_t sz = blkid_probe_get_size(pr);
@@ -352,6 +361,9 @@ static int probe_gpt_pt(blkid_probe pr, const struct blkid_idmag *mag)
 			(unsigned char *) e->partition_name,
 			sizeof(e->partition_name), BLKID_ENC_UTF16LE);
 
+		swap_efi_guid(&e->unique_partition_guid);
+		swap_efi_guid(&e->partition_type_guid);
+
 		blkid_partition_set_uuid(par,
 			(const unsigned char *) &e->unique_partition_guid);
 
-- 
1.7.3.4

--
To unsubscribe from this list: send the line "unsubscribe util-linux" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[Index of Archives]     [Netdev]     [Ethernet Bridging]     [Linux Wireless]     [Kernel Newbies]     [Security]     [Linux for Hams]     [Netfilter]     [Bugtraq]     [Yosemite News]     [MIPS Linux]     [ARM Linux]     [Linux RAID]     [Linux Admin]     [Samba]

  Powered by Linux