grub-devel
[Top][All Lists]
Advanced

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

[GRUB PARTUUID PATCH 1/2] Add PARTUUID detection support to grub-probe


From: Nicholas Vinson
Subject: [GRUB PARTUUID PATCH 1/2] Add PARTUUID detection support to grub-probe
Date: Sun, 19 Jun 2016 18:37:47 -0700

Add PARTUUID detection to grub-probe.  The grub-probe utility is used by
grub-mkconfig to determine the filesystem [GU]UID, so updating it to be
able to return partition [GU]UIDs seemed like the natural choice.  The
other obvious choice was to rely on Linux userland tools and /dev file
structure which would added to the runtime dependencies of grub-probe.

Signed-off-by: Nicholas Vinson <address@hidden>
---
 grub-core/partmap/gpt.c   |  2 ++
 grub-core/partmap/msdos.c | 12 ++++++++--
 include/grub/partition.h  |  9 +++++++-
 util/grub-probe.c         | 58 +++++++++++++++++++++++++++++++++++++++++++++++
 4 files changed, 78 insertions(+), 3 deletions(-)

diff --git a/grub-core/partmap/gpt.c b/grub-core/partmap/gpt.c
index 83bcba7..fd0bbef 100644
--- a/grub-core/partmap/gpt.c
+++ b/grub-core/partmap/gpt.c
@@ -99,6 +99,8 @@ grub_gpt_partition_map_iterate (grub_disk_t disk,
       if (grub_memcmp (&grub_gpt_partition_type_empty, &entry.type,
                       sizeof (grub_gpt_partition_type_empty)))
        {
+          grub_memcpy(part.guid.gpt, entry.guid, sizeof(part.guid.gpt));
+
          /* Calculate the first block and the size of the partition.  */
          part.start = grub_le_to_cpu64 (entry.start) << sector_log;
          part.len = (grub_le_to_cpu64 (entry.end)
diff --git a/grub-core/partmap/msdos.c b/grub-core/partmap/msdos.c
index 6d4b455..79bb5b2 100644
--- a/grub-core/partmap/msdos.c
+++ b/grub-core/partmap/msdos.c
@@ -169,6 +169,13 @@ grub_partition_msdos_iterate (grub_disk_t disk,
        if (mbr.entries[i].flag & 0x7f)
          return grub_error (GRUB_ERR_BAD_PART_TABLE, "bad boot flag");
 
+      /*
+       * Copy off the NT Disk signature.  Linux uses this to compute the
+       * PARTUUID.  The disk signature is 440 bytes in and 4 bytes long.
+       */
+      if (p.offset == 0)
+        grub_memcpy(p.guid.mbr, mbr.code + 440, sizeof(p.guid.mbr));
+
       /* Analyze DOS partitions.  */
       for (p.index = 0; p.index < 4; p.index++)
        {
@@ -191,7 +198,7 @@ grub_partition_msdos_iterate (grub_disk_t disk,
          if (! grub_msdos_partition_is_empty (e->type)
              && ! grub_msdos_partition_is_extended (e->type))
            {
-             p.number++;
+             p.guid.mbr[4] = ++p.number;
 
              if (hook (disk, &p, hook_data))
                return grub_errno;
@@ -199,7 +206,7 @@ grub_partition_msdos_iterate (grub_disk_t disk,
          else if (p.number < 3)
            /* If this partition is a logical one, shouldn't increase the
               partition number.  */
-           p.number++;
+           p.guid.mbr[4] = ++p.number;
        }
 
       /* Find an extended partition.  */
@@ -209,6 +216,7 @@ grub_partition_msdos_iterate (grub_disk_t disk,
 
          if (grub_msdos_partition_is_extended (e->type))
            {
+              p.guid.mbr[4] = 4 + i; // logical partitions start with 4.
              p.offset = ext_offset
                + (grub_le_to_cpu32 (e->start)
                   << (disk->log_sector_size - GRUB_DISK_SECTOR_BITS));
diff --git a/include/grub/partition.h b/include/grub/partition.h
index 7adb7ec..4a80bf7 100644
--- a/include/grub/partition.h
+++ b/include/grub/partition.h
@@ -66,6 +66,13 @@ struct grub_partition
   /* The partition number.  */
   int number;
 
+  /* Unique partition GUID. */
+  union
+  {
+      grub_uint8_t gpt[16];
+      grub_uint8_t mbr[5];
+  } guid;
+
   /* The start sector (relative to parent).  */
   grub_disk_addr_t start;
 
@@ -84,7 +91,7 @@ struct grub_partition
   /* The type partition map.  */
   grub_partition_map_t partmap;
 
-  /* The type of partition whne it's on MSDOS.
+  /* The type of partition when it's on MSDOS.
      Used for embedding detection.  */
   grub_uint8_t msdostype;
 };
diff --git a/util/grub-probe.c b/util/grub-probe.c
index 8ac527d..5ea9c4c 100644
--- a/util/grub-probe.c
+++ b/util/grub-probe.c
@@ -62,6 +62,7 @@ enum {
   PRINT_DRIVE,
   PRINT_DEVICE,
   PRINT_PARTMAP,
+  PRINT_PARTUUID,
   PRINT_ABSTRACTION,
   PRINT_CRYPTODISK_UUID,
   PRINT_HINT_STR,
@@ -85,6 +86,7 @@ static const char *targets[] =
     [PRINT_DRIVE]              = "drive",
     [PRINT_DEVICE]             = "device",
     [PRINT_PARTMAP]            = "partmap",
+    [PRINT_PARTUUID]           = "partuuid",
     [PRINT_ABSTRACTION]        = "abstraction",
     [PRINT_CRYPTODISK_UUID]    = "cryptodisk_uuid",
     [PRINT_HINT_STR]           = "hints_string",
@@ -617,6 +619,62 @@ probe (const char *path, char **device_names, char delim)
       else if (print == PRINT_CRYPTODISK_UUID)
        probe_cryptodisk_uuid (dev->disk, delim);
 
+      else if (print == PRINT_PARTUUID && dev->disk->partition)
+        {
+          grub_uint8_t be_guid[16];
+          int i;
+          int guid_len;
+          if (strcmp(dev->disk->partition->partmap->name, "gpt") == 0)
+            {
+              guid_len = sizeof(dev->disk->partition->guid.gpt);
+              /**
+               * The GUID disk format is LE(4) LE(2) LE(2) BE(8).
+               * where LE(n) means n-bytes little-endian formatted and
+               * BE(n) means n-bytes big-endian formatted.
+               */
+              for(i = 3; i >= 0; i--)
+                {
+                  be_guid[3 - i] = dev->disk->partition->guid.gpt[i];
+                }
+              for (i = 1; i >= 0; i--)
+                {
+                  be_guid[5 - i] = dev->disk->partition->guid.gpt[i + 4];
+                  be_guid[7 - i] = dev->disk->partition->guid.gpt[i + 6];
+                }
+              for (i = 7; i >= 0; i--)
+                {
+                  be_guid[i + 8] = dev->disk->partition->guid.gpt[i + 8];
+                }
+            }
+          else if (strcmp(dev->disk->partition->partmap->name, "msdos") == 0)
+            {
+              guid_len = sizeof(dev->disk->partition->guid.mbr);
+              /*
+               * First 4 bytes are in LE order and need to be swapped them to 
BE
+               * order.
+               */
+              for(i = 3; i >= 0; i--)
+                {
+                  be_guid[3 - i] = dev->disk->partition->guid.mbr[i];
+                }
+                /* Adjust the last number so that it is 1-indexed. */
+                be_guid[4] = dev->disk->partition->guid.mbr[4] + 1;
+            }
+            for (i = 0; i < guid_len; i++)
+              {
+                switch(i)
+                  {
+                  case 4:
+                  case 6:
+                  case 8:
+                  case 10:
+                    printf("-");
+                  default:
+                    printf("%02x", be_guid[i]);
+                  }
+              }
+          putchar(delim);
+        }
       else if (print == PRINT_PARTMAP)
        /* Check if dev->disk itself is contained in a partmap.  */
        probe_partmap (dev->disk, delim);
-- 
2.9.0




reply via email to

[Prev in Thread] Current Thread [Next in Thread]