From 6e7a315eb67cb6c113cf37e1d66c4f11a51a2b3e Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Sun, 7 Apr 2024 18:29:51 +0200 Subject: Adding upstream version 2.06. Signed-off-by: Daniel Baumann --- grub-core/osdep/devmapper/getroot.c | 347 ++++++++++++++++++++++++++++++++++++ 1 file changed, 347 insertions(+) create mode 100644 grub-core/osdep/devmapper/getroot.c (limited to 'grub-core/osdep/devmapper/getroot.c') diff --git a/grub-core/osdep/devmapper/getroot.c b/grub-core/osdep/devmapper/getroot.c new file mode 100644 index 0000000..a13a39c --- /dev/null +++ b/grub-core/osdep/devmapper/getroot.c @@ -0,0 +1,347 @@ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 1999,2000,2001,2002,2003,2006,2007,2008,2009,2010,2011,2012,2013 Free Software Foundation, Inc. + * + * GRUB is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * GRUB is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GRUB. If not, see . + */ + +#include +#include + +#include +#include + +#ifdef HAVE_DEVICE_MAPPER + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#ifdef HAVE_LIMITS_H +#include +#endif + +#if defined(MAJOR_IN_MKDEV) +#include +#elif defined(MAJOR_IN_SYSMACROS) +#include +#endif + +#include + +#include +#include + +#include +#include +#include +#include + +static int +grub_util_open_dm (const char *os_dev, struct dm_tree **tree, + struct dm_tree_node **node) +{ + uint32_t maj, min; + struct stat st; + + *node = NULL; + *tree = NULL; + + if (stat (os_dev, &st) < 0) + return 0; + + maj = major (st.st_rdev); + min = minor (st.st_rdev); + + if (!dm_is_dm_major (maj)) + return 0; + + *tree = dm_tree_create (); + if (! *tree) + { + grub_puts_ (N_("Failed to create `device-mapper' tree")); + grub_dprintf ("hostdisk", "dm_tree_create failed\n"); + return 0; + } + + if (! dm_tree_add_dev (*tree, maj, min)) + { + grub_dprintf ("hostdisk", "dm_tree_add_dev failed\n"); + dm_tree_free (*tree); + *tree = NULL; + return 0; + } + + *node = dm_tree_find_node (*tree, maj, min); + if (! *node) + { + grub_dprintf ("hostdisk", "dm_tree_find_node failed\n"); + dm_tree_free (*tree); + *tree = NULL; + return 0; + } + return 1; +} + +static char * +get_dm_uuid (const char *os_dev) +{ + struct dm_tree *tree; + struct dm_tree_node *node; + const char *node_uuid; + char *ret; + + if (!grub_util_open_dm (os_dev, &tree, &node)) + return NULL; + + node_uuid = dm_tree_node_get_uuid (node); + if (! node_uuid) + { + grub_dprintf ("hostdisk", "%s has no DM uuid\n", os_dev); + dm_tree_free (tree); + return NULL; + } + + ret = grub_strdup (node_uuid); + + dm_tree_free (tree); + + return ret; +} + +enum grub_dev_abstraction_types +grub_util_get_dm_abstraction (const char *os_dev) +{ + char *uuid; + + uuid = get_dm_uuid (os_dev); + + if (uuid == NULL) + return GRUB_DEV_ABSTRACTION_NONE; + + if (strncmp (uuid, "LVM-", 4) == 0) + { + grub_free (uuid); + return GRUB_DEV_ABSTRACTION_LVM; + } + if (strncmp (uuid, "CRYPT-LUKS1-", 12) == 0) + { + grub_free (uuid); + return GRUB_DEV_ABSTRACTION_LUKS; + } + + grub_free (uuid); + return GRUB_DEV_ABSTRACTION_NONE; +} + +void +grub_util_pull_devmapper (const char *os_dev) +{ + struct dm_tree *tree; + struct dm_tree_node *node; + struct dm_tree_node *child; + void *handle = NULL; + char *lastsubdev = NULL; + char *uuid; + + uuid = get_dm_uuid (os_dev); + + if (!grub_util_open_dm (os_dev, &tree, &node)) + { + grub_free (uuid); + return; + } + + while ((child = dm_tree_next_child (&handle, node, 0))) + { + const struct dm_info *dm = dm_tree_node_get_info (child); + char *subdev; + if (!dm) + continue; + subdev = grub_find_device ("/dev", makedev (dm->major, dm->minor)); + if (subdev) + { + lastsubdev = subdev; + grub_util_pull_device (subdev); + } + } + if (uuid && strncmp (uuid, "CRYPT-LUKS1-", sizeof ("CRYPT-LUKS1-") - 1) == 0 + && lastsubdev) + { + char *grdev = grub_util_get_grub_dev (lastsubdev); + dm_tree_free (tree); + if (grdev) + { + grub_err_t err; + err = grub_cryptodisk_cheat_mount (grdev, os_dev); + if (err) + grub_util_error (_("can't mount encrypted volume `%s': %s"), + lastsubdev, grub_errmsg); + } + grub_free (grdev); + } + else + dm_tree_free (tree); + grub_free (uuid); +} + +char * +grub_util_devmapper_part_to_disk (struct stat *st, + int *is_part, const char *path) +{ + int major, minor; + + if (grub_util_get_dm_node_linear_info (st->st_rdev, + &major, &minor, 0)) + { + *is_part = 1; + return grub_find_device ("/dev", makedev (major, minor)); + } + *is_part = 0; + return xstrdup (path); +} + +char * +grub_util_get_devmapper_grub_dev (const char *os_dev) +{ + char *uuid, *optr; + char *grub_dev; + + uuid = get_dm_uuid (os_dev); + if (!uuid) + return NULL; + + switch (grub_util_get_dev_abstraction (os_dev)) + { + case GRUB_DEV_ABSTRACTION_LVM: + { + unsigned i; + int dashes[] = { 0, 6, 10, 14, 18, 22, 26, 32, 38, 42, 46, 50, 54, 58}; + + grub_dev = xmalloc (grub_strlen (uuid) + 40); + optr = grub_stpcpy (grub_dev, "lvmid/"); + for (i = 0; i < ARRAY_SIZE (dashes) - 1; i++) + { + memcpy (optr, uuid + sizeof ("LVM-") - 1 + dashes[i], + dashes[i+1] - dashes[i]); + optr += dashes[i+1] - dashes[i]; + *optr++ = '-'; + } + optr = stpcpy (optr, uuid + sizeof ("LVM-") - 1 + dashes[i]); + *optr = '\0'; + grub_dev[sizeof("lvmid/xxxxxx-xxxx-xxxx-xxxx-xxxx-xxxx-xxxxxx") - 1] + = '/'; + free (uuid); + return grub_dev; + } + + case GRUB_DEV_ABSTRACTION_LUKS: + { + char *dash; + + dash = grub_strchr (uuid + sizeof ("CRYPT-LUKS1-") - 1, '-'); + if (dash) + *dash = 0; + grub_dev = grub_xasprintf ("cryptouuid/%s", + uuid + sizeof ("CRYPT-LUKS1-") - 1); + grub_free (uuid); + return grub_dev; + } + + default: + grub_free (uuid); + return NULL; + } +} + +char * +grub_util_get_vg_uuid (const char *os_dev) +{ + char *uuid, *vgid; + int dashes[] = { 0, 6, 10, 14, 18, 22, 26, 32}; + unsigned i; + char *optr; + + uuid = get_dm_uuid (os_dev); + if (!uuid) + return NULL; + + vgid = xmalloc (grub_strlen (uuid)); + optr = vgid; + for (i = 0; i < ARRAY_SIZE (dashes) - 1; i++) + { + memcpy (optr, uuid + sizeof ("LVM-") - 1 + dashes[i], + dashes[i+1] - dashes[i]); + optr += dashes[i+1] - dashes[i]; + *optr++ = '-'; + } + optr--; + *optr = '\0'; + grub_free (uuid); + return vgid; +} + +void +grub_util_devmapper_cleanup (void) +{ + dm_lib_release (); +} + +#else +void +grub_util_pull_devmapper (const char *os_dev __attribute__ ((unused))) +{ + return; +} + +void +grub_util_devmapper_cleanup (void) +{ +} + +enum grub_dev_abstraction_types +grub_util_get_dm_abstraction (const char *os_dev __attribute__ ((unused))) +{ + return GRUB_DEV_ABSTRACTION_NONE; +} + +char * +grub_util_get_vg_uuid (const char *os_dev __attribute__ ((unused))) +{ + return NULL; +} + +char * +grub_util_devmapper_part_to_disk (struct stat *st __attribute__ ((unused)), + int *is_part __attribute__ ((unused)), + const char *os_dev __attribute__ ((unused))) +{ + return NULL; +} + +char * +grub_util_get_devmapper_grub_dev (const char *os_dev __attribute__ ((unused))) +{ + return NULL; +} + +#endif -- cgit v1.2.3