[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