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 +++++++++++++++++++++++++++++++++++ grub-core/osdep/devmapper/hostdisk.c | 230 +++++++++++++++++++++++ 2 files changed, 577 insertions(+) create mode 100644 grub-core/osdep/devmapper/getroot.c create mode 100644 grub-core/osdep/devmapper/hostdisk.c (limited to 'grub-core/osdep/devmapper') 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 diff --git a/grub-core/osdep/devmapper/hostdisk.c b/grub-core/osdep/devmapper/hostdisk.c new file mode 100644 index 0000000..a8afc0c --- /dev/null +++ b/grub-core/osdep/devmapper/hostdisk.c @@ -0,0 +1,230 @@ +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#if defined(MAJOR_IN_MKDEV) +#include +#elif defined(MAJOR_IN_SYSMACROS) +#include +#endif + +#ifdef HAVE_DEVICE_MAPPER +# include + +static void device_mapper_null_log (int level __attribute__ ((unused)), + const char *file __attribute__ ((unused)), + int line __attribute__ ((unused)), + int dm_errno __attribute__ ((unused)), + const char *f __attribute__ ((unused)), + ...) +{ +} + +int +grub_device_mapper_supported (void) +{ + static int supported = -1; + + if (supported == -1) + { + struct dm_task *dmt; + + /* Suppress annoying log messages. */ + dm_log_with_errno_init (&device_mapper_null_log); + + dmt = dm_task_create (DM_DEVICE_VERSION); + supported = (dmt != NULL); + if (dmt) + dm_task_destroy (dmt); + + /* Restore the original logger. */ + dm_log_with_errno_init (NULL); + } + + return supported; +} + +int +grub_util_device_is_mapped (const char *dev) +{ + struct stat st; + + if (!grub_device_mapper_supported ()) + return 0; + + if (stat (dev, &st) < 0) + return 0; + +#if GRUB_DISK_DEVS_ARE_CHAR + if (! S_ISCHR (st.st_mode)) +#else + if (! S_ISBLK (st.st_mode)) +#endif + return 0; + + return dm_is_dm_major (major (st.st_rdev)); +} + +int +grub_util_device_is_mapped_stat (struct stat *st) +{ +#if GRUB_DISK_DEVS_ARE_CHAR + if (! S_ISCHR (st->st_mode)) +#else + if (! S_ISBLK (st->st_mode)) +#endif + return 0; + + if (!grub_device_mapper_supported ()) + return 0; + + return dm_is_dm_major (major (st->st_rdev)); +} + + +int +grub_util_get_dm_node_linear_info (dev_t dev, + int *maj, int *min, + grub_disk_addr_t *st) +{ + struct dm_task *dmt; + void *next = NULL; + uint64_t length, start; + char *target, *params; + const char *ptr; + int major = 0, minor = 0; + int first = 1; + grub_disk_addr_t partstart = 0; + const char *node_uuid; + + major = major (dev); + minor = minor (dev); + + while (1) + { + dmt = dm_task_create(DM_DEVICE_TABLE); + if (!dmt) + break; + + if (! (dm_task_set_major_minor (dmt, major, minor, 0))) + { + dm_task_destroy (dmt); + break; + } + dm_task_no_open_count(dmt); + if (!dm_task_run(dmt)) + { + dm_task_destroy (dmt); + break; + } + node_uuid = dm_task_get_uuid (dmt); + if (node_uuid && (strncmp (node_uuid, "LVM-", 4) == 0 + || strncmp (node_uuid, "mpath-", 6) == 0)) + { + dm_task_destroy (dmt); + break; + } + + next = dm_get_next_target(dmt, next, &start, &length, + &target, ¶ms); + if (grub_strcmp (target, "linear") != 0) + { + dm_task_destroy (dmt); + break; + } + major = grub_strtoul (params, &ptr, 10); + if (grub_errno) + { + dm_task_destroy (dmt); + grub_errno = GRUB_ERR_NONE; + return 0; + } + if (*ptr != ':') + { + dm_task_destroy (dmt); + return 0; + } + ptr++; + minor = grub_strtoul (ptr, &ptr, 10); + if (grub_errno) + { + grub_errno = GRUB_ERR_NONE; + dm_task_destroy (dmt); + return 0; + } + + if (*ptr != ' ') + { + dm_task_destroy (dmt); + return 0; + } + ptr++; + partstart += grub_strtoull (ptr, &ptr, 10); + if (grub_errno) + { + grub_errno = GRUB_ERR_NONE; + dm_task_destroy (dmt); + return 0; + } + + dm_task_destroy (dmt); + first = 0; + if (!dm_is_dm_major (major)) + break; + } + if (first) + return 0; + if (maj) + *maj = major; + if (min) + *min = minor; + if (st) + *st = partstart; + return 1; +} +#else + +int +grub_util_device_is_mapped (const char *dev __attribute__ ((unused))) +{ + return 0; +} + +int +grub_util_get_dm_node_linear_info (dev_t dev __attribute__ ((unused)), + int *maj __attribute__ ((unused)), + int *min __attribute__ ((unused)), + grub_disk_addr_t *st __attribute__ ((unused))) +{ + return 0; +} + +int +grub_util_device_is_mapped_stat (struct stat *st __attribute__ ((unused))) +{ + return 0; +} + +#endif -- cgit v1.2.3