From d35b67005f7281668221cd335f0b19b3d68a225d Mon Sep 17 00:00:00 2001 From: matt Date: Wed, 5 Apr 2017 04:16:07 -0400 Subject: [PATCH 2/7] Added search_pt_uuid module --- grub-core/Makefile.core.def | 5 ++++ grub-core/commands/search.c | 56 ++++++++++++++++++++++++++++++++++ grub-core/commands/search_ptuuid.c | 5 ++++ grub-core/commands/search_wrap.c | 12 ++++++-- grub-core/disk/efi/efidisk.c | 61 +++++++++++++++++++++++++++++++++++++- grub-core/disk/i386/pc/biosdisk.c | 27 ++++++++++++++++- grub-core/partmap/gpt.c | 4 +++ grub-core/partmap/msdos.c | 12 +++++--- include/grub/disk.h | 5 ++++ include/grub/misc.h | 22 ++++++++++++++ include/grub/partition.h | 3 ++ include/grub/search.h | 2 ++ 12 files changed, 205 insertions(+), 9 deletions(-) create mode 100644 grub-core/commands/search_ptuuid.c diff --git a/grub-core/Makefile.core.def b/grub-core/Makefile.core.def index 2dfa22a..91d5a82 100644 --- a/grub-core/Makefile.core.def +++ b/grub-core/Makefile.core.def @@ -994,6 +994,11 @@ module = { }; module = { + name = search_pt_uuid; + common = commands/search_ptuuid.c; +}; + +module = { name = search_label; common = commands/search_label.c; }; diff --git a/grub-core/commands/search.c b/grub-core/commands/search.c index 2fea001..d0c26c9 100644 --- a/grub-core/commands/search.c +++ b/grub-core/commands/search.c @@ -73,6 +73,8 @@ if(grub_strcmp (ctx->print_once, name) != 0) #ifdef DO_SEARCH_FS_UUID #define compare_fn grub_strcasecmp +#elif defined (DO_SEARCH_PT_UUID) +#define compare_fn grub_strcasecmp #else #define compare_fn grub_strcmp #endif @@ -95,6 +97,56 @@ if(grub_strcmp (ctx->print_once, name) != 0) } grub_free (buf); } +#elif defined (DO_SEARCH_PT_UUID) + { + + /* Obtain the partition table from the root device. */ + grub_device_t dev; + char *partuuid = 0; + dev = grub_device_open (name); + if (dev && dev->disk) + { + grub_disk_t disk = dev->disk; + grub_partition_t p = disk->partition; + /*Read the disk UUID/GUID*/ + if (grub_strlen(name) == 3 && name[0] == 'h' && name[1] == 'd' && name[2] >= '0' && name[2] <= '9') + { + if (disk->dev->partuuid) + { + disk->dev->partuuid (dev, &partuuid); + if (grub_errno == GRUB_ERR_NONE && partuuid) + { + if (compare_fn (partuuid, ctx->key) == 0) + { + found = 1; + } + grub_free (partuuid); + } + } + } + /*Read the partition UUID/GUID*/ + else if (disk) + { + if (p && (grub_strcmp (p->partmap->name, "msdos") == 0 || grub_strcmp (p->partmap->name, "gpt") == 0 )) + { + if (disk->partition->number + 1) + { + partuuid = grub_strdup (p->partuuid); + if (grub_errno == GRUB_ERR_NONE && partuuid) + { + if (compare_fn (partuuid, ctx->key) == 0) + { + found = 1; + } + grub_free (partuuid); + } + } + } + } + } + if (dev) + grub_device_close (dev); + } #else { /* SEARCH_FS_UUID or SEARCH_LABEL */ @@ -326,6 +378,8 @@ static grub_command_t cmd; GRUB_MOD_INIT(search_fs_file) #elif defined (DO_SEARCH_FS_UUID) GRUB_MOD_INIT(search_fs_uuid) +#elif defined (DO_SEARCH_PT_UUID) +GRUB_MOD_INIT(search_pt_uuid) #else GRUB_MOD_INIT(search_label) #endif @@ -340,6 +394,8 @@ GRUB_MOD_INIT(search_label) GRUB_MOD_FINI(search_fs_file) #elif defined (DO_SEARCH_FS_UUID) GRUB_MOD_FINI(search_fs_uuid) +#elif defined (DO_SEARCH_PT_UUID) +GRUB_MOD_FINI(search_pt_uuid) #else GRUB_MOD_FINI(search_label) #endif diff --git a/grub-core/commands/search_ptuuid.c b/grub-core/commands/search_ptuuid.c new file mode 100644 index 0000000..06f8391 --- /dev/null +++ b/grub-core/commands/search_ptuuid.c @@ -0,0 +1,5 @@ +#define DO_SEARCH_PT_UUID 1 +#define FUNC_NAME grub_search_pt_uuid +#define COMMAND_NAME "search.pt_uuid" +#define HELP_MESSAGE N_("Search devices by disk/partition UUID/GUID. If VARIABLE is specified, the first device found is set to a variable.") +#include "search.c" diff --git a/grub-core/commands/search_wrap.c b/grub-core/commands/search_wrap.c index d7fd26b..85f35d2 100644 --- a/grub-core/commands/search_wrap.c +++ b/grub-core/commands/search_wrap.c @@ -36,6 +36,8 @@ static const struct grub_arg_option options[] = 0, 0}, {"fs-uuid", 'u', 0, N_("Search devices by a filesystem UUID."), 0, 0}, + {"pt-uuid", 'p', 0, N_("Search devices by a disk/partition UUID/GUID."), + 0, 0}, {"set", 's', GRUB_ARG_OPTION_OPTIONAL, N_("Set a variable to the first device found."), N_("VARNAME"), ARG_TYPE_STRING}, @@ -71,6 +73,7 @@ enum options SEARCH_FILE, SEARCH_LABEL, SEARCH_FS_UUID, + SEARCH_PT_UUID, SEARCH_SET, SEARCH_NO_FLOPPY, SEARCH_HINT, @@ -186,6 +189,9 @@ grub_cmd_search (grub_extcmd_context_t ctxt, int argc, char **args) else if (state[SEARCH_FS_UUID].set) grub_search_fs_uuid (id, var, state[SEARCH_NO_FLOPPY].set, hints, nhints); + else if (state[SEARCH_PT_UUID].set) + grub_search_pt_uuid (id, var, state[SEARCH_NO_FLOPPY].set, + hints, nhints); else if (state[SEARCH_FILE].set) grub_search_fs_file (id, var, state[SEARCH_NO_FLOPPY].set, hints, nhints); @@ -204,10 +210,10 @@ GRUB_MOD_INIT(search) cmd = grub_register_extcmd ("search", grub_cmd_search, GRUB_COMMAND_FLAG_EXTRACTOR | GRUB_COMMAND_ACCEPT_DASH, - N_("[-f|-l|-u|-s|-n] [--hint HINT [--hint HINT] ...]" + N_("[-f|-l|-u|-p|-s|-n] [--hint HINT [--hint HINT] ...]" " NAME"), - N_("Search devices by file, filesystem label" - " or filesystem UUID." + N_("Search devices by file, filesystem label," + " filesystem UUID or disk/partition UUID/GUID." " If --set is specified, the first device found is" " set to a variable. If no variable name is" " specified, `root' is used."), diff --git a/grub-core/disk/efi/efidisk.c b/grub-core/disk/efi/efidisk.c index e66b35d..dfeb685 100644 --- a/grub-core/disk/efi/efidisk.c +++ b/grub-core/disk/efi/efidisk.c @@ -18,6 +18,8 @@ #include #include +#include +#include #include #include #include @@ -622,6 +624,62 @@ grub_efidisk_write (struct grub_disk *disk, grub_disk_addr_t sector, return GRUB_ERR_NONE; } +static grub_uint8_t grub_gpt_magic[8] = + { + 0x45, 0x46, 0x49, 0x20, 0x50, 0x41, 0x52, 0x54 + }; + +/* 512 << 7 = 65536 byte sectors. */ +#define MAX_SECTOR_LOG 7 + +static grub_err_t +grub_efidisk_uuid (grub_device_t device, char **partuuid) +{ + grub_disk_t disk = device->disk; + unsigned int mbr_sig = 0xaa55; + struct grub_gpt_header gpt; + struct grub_msdos_partition_mbr mbr; + unsigned int i; + int sector_log = 0; + if (grub_strlen(disk->name) == 3 && disk->name[0] == 'h' && disk->name[1] == 'd' && disk->name[2] >= '0' && disk->name[2] <= '9') + { + /* Read the protective MBR. */ + if (grub_disk_read (disk, 0, 0, sizeof (mbr), &mbr) == GRUB_ERR_NONE) + if (mbr.signature == mbr_sig) + { + for (i = 0; i < 4; i++) + if (mbr.entries[i].type == GRUB_PC_PARTITION_TYPE_GPT_DISK) + break; + /* Read the GPT header. */ + if (mbr.entries[i].type == GRUB_PC_PARTITION_TYPE_GPT_DISK) + { + if (i < 4) + { + for (sector_log = 0; sector_log < MAX_SECTOR_LOG; sector_log++) + { + if (grub_disk_read (disk, 1 << sector_log, 0, sizeof (gpt), &gpt) == GRUB_ERR_NONE) + { + if (grub_memcmp (gpt.magic, grub_gpt_magic, sizeof (grub_gpt_magic)) == 0) + { + if (disk->dev && gpt.guid) + { + *partuuid = grub_xasprintf ("%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x", + gpt.guid[3],gpt.guid[2],gpt.guid[1],gpt.guid[0],gpt.guid[5],gpt.guid[4],gpt.guid[7],gpt.guid[6], + gpt.guid[8],gpt.guid[9],gpt.guid[10],gpt.guid[11],gpt.guid[12],gpt.guid[13],gpt.guid[14], + gpt.guid[15]); + } + else + *partuuid = NULL; + } + } + break; + } + } + } + } + } +return grub_errno; +} static struct grub_disk_dev grub_efidisk_dev = { @@ -632,7 +690,8 @@ static struct grub_disk_dev grub_efidisk_dev = .close = grub_efidisk_close, .read = grub_efidisk_read, .write = grub_efidisk_write, - .next = 0 + .next = 0, + .partuuid = grub_efidisk_uuid }; void diff --git a/grub-core/disk/i386/pc/biosdisk.c b/grub-core/disk/i386/pc/biosdisk.c index f0aadd1..53a24a9 100644 --- a/grub-core/disk/i386/pc/biosdisk.c +++ b/grub-core/disk/i386/pc/biosdisk.c @@ -633,6 +633,30 @@ grub_biosdisk_write (grub_disk_t disk, grub_disk_addr_t sector, return grub_errno; } +static grub_err_t +grub_biosdisk_uuid (grub_device_t device, char **partuuid) +{ + grub_disk_t disk = device->disk; + grub_uint8_t mbr_buf[512]; + unsigned int mbr_id = 0; + unsigned int mbr_sig = 0xaa55; + if (grub_strlen(disk->name) == 3 && disk->name[0] == 'h' && disk->name[1] == 'd' && disk->name[2] >= '0' && disk->name[2] <= '9') + { + if (grub_disk_read (disk, 0, 0, sizeof (mbr_buf), &mbr_buf) == GRUB_ERR_NONE) + if (mbr_get_sig (mbr_buf) == mbr_sig) + { + mbr_id = mbr_get_id (mbr_buf); + if (disk->dev) + { + *partuuid = grub_xasprintf ("%08x", mbr_id); + } + else + *partuuid = NULL; + } + } +return grub_errno; +} + static struct grub_disk_dev grub_biosdisk_dev = { .name = "biosdisk", @@ -642,7 +666,8 @@ static struct grub_disk_dev grub_biosdisk_dev = .close = grub_biosdisk_close, .read = grub_biosdisk_read, .write = grub_biosdisk_write, - .next = 0 + .next = 0, + .partuuid = grub_biosdisk_uuid }; static void diff --git a/grub-core/partmap/gpt.c b/grub-core/partmap/gpt.c index 83bcba7..0012204 100644 --- a/grub-core/partmap/gpt.c +++ b/grub-core/partmap/gpt.c @@ -108,6 +108,10 @@ grub_gpt_partition_map_iterate (grub_disk_t disk, part.index = last_offset; part.partmap = &grub_gpt_partition_map; part.parent = disk->partition; + part.partuuid = grub_xasprintf ("%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x", + entry.guid[3],entry.guid[2],entry.guid[1],entry.guid[0],entry.guid[5],entry.guid[4],entry.guid[7], + entry.guid[6],entry.guid[8],entry.guid[9],entry.guid[10],entry.guid[11],entry.guid[12], + entry.guid[13],entry.guid[14],entry.guid[15]); grub_dprintf ("gpt", "GPT entry %d: start=%lld, length=%lld\n", i, (unsigned long long) part.start, diff --git a/grub-core/partmap/msdos.c b/grub-core/partmap/msdos.c index 6d4b455..acde247 100644 --- a/grub-core/partmap/msdos.c +++ b/grub-core/partmap/msdos.c @@ -113,6 +113,7 @@ grub_partition_msdos_iterate (grub_disk_t disk, struct grub_partition p; struct grub_msdos_partition_mbr mbr; int labeln = 0; + unsigned int mbr_id = 0; grub_disk_addr_t lastaddr; grub_disk_addr_t ext_offset; grub_disk_addr_t delta = 0; @@ -180,12 +181,15 @@ grub_partition_msdos_iterate (grub_disk_t disk, p.len = grub_le_to_cpu32 (e->length) << (disk->log_sector_size - GRUB_DISK_SECTOR_BITS); p.msdostype = e->type; - - grub_dprintf ("partition", - "partition %d: flag 0x%x, type 0x%x, start 0x%llx, len 0x%llx\n", + if (p.offset == 0) /*allows for the correct mbr to be read when extended/logical partitions are read.*/ + mbr_id = mbr_get_id(mbr.code); + p.partuuid = grub_xasprintf ("%08x-%02x", mbr_id, p.number + 2);/*2 since it starts off number = -1*/ + grub_dprintf ("partition", + "partition %d: flag 0x%x, type 0x%x, start 0x%llx, len 0x%llx, PARTUUID 0x%s\n", p.index, e->flag, e->type, (unsigned long long) p.start, - (unsigned long long) p.len); + (unsigned long long) p.len, + p.partuuid); /* If this partition is a normal one, call the hook. */ if (! grub_msdos_partition_is_empty (e->type) diff --git a/include/grub/disk.h b/include/grub/disk.h index b385af8..dd9dd67 100644 --- a/include/grub/disk.h +++ b/include/grub/disk.h @@ -100,6 +100,11 @@ struct grub_disk_dev /* The next disk device. */ struct grub_disk_dev *next; + + /* Return the partuuid (disk/partition UUID/GUID) of the device DEVICE in PARTUUID. The partuuid is + returned in a grub_malloc'ed buffer and should be freed by the + caller. */ + grub_err_t (*partuuid) (grub_device_t device, char **partuuid); }; typedef struct grub_disk_dev *grub_disk_dev_t; diff --git a/include/grub/misc.h b/include/grub/misc.h index 2a9f87c..a559654 100644 --- a/include/grub/misc.h +++ b/include/grub/misc.h @@ -51,6 +51,28 @@ grub_strncpy (char *dest, const char *src, int c) return dest; } +static inline unsigned int grub_assemble_32le(const unsigned char *p) +{ + return p[0] | (p[1] << 8) | (p[2] << 16) | (p[3] << 24); +} + +static inline unsigned int mbr_get_id(const unsigned char *mbr) +{ + return grub_assemble_32le(&mbr[440]); +} + +static inline unsigned int grub_assemble_16le(const unsigned char *p) +{ + return p[0] | (p[1] << 8); +} + +static inline unsigned int mbr_get_sig(const unsigned char *mbr) +{ + return grub_assemble_16le(&mbr[510]); +} + + + static inline char * grub_stpcpy (char *dest, const char *src) { diff --git a/include/grub/partition.h b/include/grub/partition.h index 7adb7ec..68c4128 100644 --- a/include/grub/partition.h +++ b/include/grub/partition.h @@ -87,6 +87,9 @@ struct grub_partition /* The type of partition whne it's on MSDOS. Used for embedding detection. */ grub_uint8_t msdostype; + + /*Partition UUID/GUID*/ + const char *partuuid; }; grub_partition_t EXPORT_FUNC(grub_partition_probe) (struct grub_disk *disk, diff --git a/include/grub/search.h b/include/grub/search.h index d80347d..69cbad0 100644 --- a/include/grub/search.h +++ b/include/grub/search.h @@ -23,6 +23,8 @@ void grub_search_fs_file (const char *key, const char *var, int no_floppy, char **hints, unsigned nhints); void grub_search_fs_uuid (const char *key, const char *var, int no_floppy, char **hints, unsigned nhints); +void grub_search_pt_uuid (const char *key, const char *var, int no_floppy, + char **hints, unsigned nhints); void grub_search_label (const char *key, const char *var, int no_floppy, char **hints, unsigned nhints); -- 2.7.4