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 <nvinson...@gmail.com> --- 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 _______________________________________________ Grub-devel mailing list Grub-devel@gnu.org https://lists.gnu.org/mailman/listinfo/grub-devel