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