diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-07 16:29:51 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-07 16:29:51 +0000 |
commit | 6e7a315eb67cb6c113cf37e1d66c4f11a51a2b3e (patch) | |
tree | 32451fa3cdd9321fb2591fada9891b2cb70a9cd1 /grub-core/osdep/hurd | |
parent | Initial commit. (diff) | |
download | grub2-6e7a315eb67cb6c113cf37e1d66c4f11a51a2b3e.tar.xz grub2-6e7a315eb67cb6c113cf37e1d66c4f11a51a2b3e.zip |
Adding upstream version 2.06.upstream/2.06upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'grub-core/osdep/hurd')
-rw-r--r-- | grub-core/osdep/hurd/getroot.c | 247 | ||||
-rw-r--r-- | grub-core/osdep/hurd/hostdisk.c | 146 |
2 files changed, 393 insertions, 0 deletions
diff --git a/grub-core/osdep/hurd/getroot.c b/grub-core/osdep/hurd/getroot.c new file mode 100644 index 0000000..c66b206 --- /dev/null +++ b/grub-core/osdep/hurd/getroot.c @@ -0,0 +1,247 @@ +/* + * 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 <http://www.gnu.org/licenses/>. + */ + +#include <config-util.h> +#include <config.h> + +#include <sys/stat.h> +#include <sys/types.h> +#include <assert.h> +#include <fcntl.h> +#include <unistd.h> +#include <string.h> +#include <dirent.h> +#include <errno.h> +#include <error.h> +#include <stdio.h> +#include <stdlib.h> +#include <stdint.h> +#ifdef HAVE_LIMITS_H +#include <limits.h> +#endif + +#include <grub/types.h> + +#include <grub/util/misc.h> + +#include <grub/mm.h> +#include <grub/misc.h> +#include <grub/emu/misc.h> +#include <grub/emu/hostdisk.h> +#include <grub/emu/getroot.h> + +#include <sys/wait.h> + +#include <hurd.h> +#include <hurd/lookup.h> +#include <hurd/fs.h> +#include <sys/mman.h> + +static char * +grub_util_find_hurd_root_device (const char *path) +{ + file_t file; + error_t err; + char *argz = NULL, *name = NULL, *ret; + size_t argz_len = 0; + int i; + + file = file_name_lookup (path, 0, 0); + if (file == MACH_PORT_NULL) + /* TRANSLATORS: The first %s is the file being looked at, the second %s is + the error message. */ + grub_util_error (_("cannot open `%s': %s"), path, strerror (errno)); + + /* This returns catenated 0-terminated strings. */ + err = file_get_fs_options (file, &argz, &argz_len); + if (err) + /* TRANSLATORS: On GNU/Hurd, a "translator" is similar to a filesystem + mount, but handled by a userland daemon, whose invocation command line + is being fetched here. First %s is the file being looked at (for which + we are fetching the "translator" command line), second %s is the error + message. + */ + grub_util_error (_("cannot get translator command line " + "for path `%s': %s"), path, strerror(err)); + if (argz_len == 0) + grub_util_error (_("translator command line is empty for path `%s'"), path); + + /* Make sure the string is terminated. */ + argz[argz_len-1] = 0; + + /* Skip first word (translator path) and options. */ + for (i = strlen (argz) + 1; i < argz_len; i += strlen (argz + i) + 1) + { + if (argz[i] != '-') + { + /* Non-option. Only accept one, assumed to be the FS path. */ + /* XXX: this should be replaced by an RPC to the translator. */ + if (name) + /* TRANSLATORS: we expect to get something like + /hurd/foobar --option1 --option2=baz /dev/something + */ + grub_util_error (_("translator `%s' for path `%s' has several " + "non-option words, at least `%s' and `%s'"), + argz, path, name, argz + i); + name = argz + i; + } + } + + if (!name) + /* TRANSLATORS: we expect to get something like + /hurd/foobar --option1 --option2=baz /dev/something + */ + grub_util_error (_("translator `%s' for path `%s' is given only options, " + "cannot find device part"), argz, path); + + if (strncmp (name, "device:", sizeof ("device:") - 1) == 0) + { + char *dev_name = name + sizeof ("device:") - 1; + size_t size = sizeof ("/dev/") - 1 + strlen (dev_name) + 1; + char *next; + ret = malloc (size); + next = stpncpy (ret, "/dev/", size); + stpncpy (next, dev_name, size - (next - ret)); + } + else if (!strncmp (name, "file:", sizeof ("file:") - 1)) + ret = strdup (name + sizeof ("file:") - 1); + else + ret = strdup (name); + + munmap (argz, argz_len); + return ret; +} + +static int +is_fulldisk (const char *child, const char *parent) +{ + if (strcmp (parent, child) == 0) + return 1; + if (strncmp (parent, "/dev/", sizeof ("/dev/") - 1) == 0 + && child[0] !=0 && strcmp (parent + sizeof ("/dev/") - 1, child) == 0) + return 1; + if (strncmp (child, "/dev/", sizeof ("/dev/") - 1) == 0 + && parent[0] != 0 && strcmp (child + sizeof ("/dev/") - 1, parent) == 0) + return 1; + return 0; +} + +char * +grub_util_part_to_disk (const char *os_dev, + struct stat *st, + int *is_part) +{ + char *path; + grub_disk_addr_t offset; + char *p; + + if (! S_ISBLK (st->st_mode)) + { + *is_part = 0; + return xstrdup (os_dev); + } + + if (!grub_util_hurd_get_disk_info (os_dev, NULL, &offset, NULL, &path)) + return xstrdup (os_dev); + + /* Some versions of Hurd use badly glued Linux code to handle partitions + resulting in partitions being promoted to disks. */ + if (path && !(offset == 0 && is_fulldisk (path, os_dev) + && (strncmp ("/dev/sd", os_dev, 7) == 0 + || strncmp ("/dev/hd", os_dev, 7) == 0))) + { + *is_part = !is_fulldisk (path, os_dev); + if (path[0] != '/') + { + char *n = xasprintf ("/dev/%s", path); + free (path); + path = n; + } + return path; + } + free (path); + + path = xstrdup (os_dev); + + p = strchr (path + 7, 's'); + if (p) + { + *is_part = 1; + *p = '\0'; + } + return path; +} + +enum grub_dev_abstraction_types +grub_util_get_dev_abstraction_os (const char *os_dev __attribute__((unused))) +{ + return GRUB_DEV_ABSTRACTION_NONE; +} + +int +grub_util_pull_device_os (const char *os_dev __attribute__ ((unused)), + enum grub_dev_abstraction_types ab __attribute__ ((unused))) +{ + return 0; +} + +char * +grub_util_get_grub_dev_os (const char *os_dev __attribute__ ((unused))) +{ + return NULL; +} + +grub_disk_addr_t +grub_util_find_partition_start_os (const char *dev) +{ + grub_uint32_t secsize; + grub_disk_addr_t offset; + char *path; + if (!grub_util_hurd_get_disk_info (dev, &secsize, &offset, NULL, &path)) + return 0; + if (path && !(offset == 0 && is_fulldisk (path, dev) + && (strncmp ("/dev/sd", dev, 7) == 0 + || strncmp ("/dev/hd", dev, 7) == 0))) + { + free (path); + return (secsize / 512) * offset; + } + free (path); + return -1; +} + +char ** +grub_guess_root_devices (const char *dir) +{ + char **os_dev = NULL; + + os_dev = xmalloc (2 * sizeof (os_dev[0])); + + /* GNU/Hurd specific function. */ + os_dev[0] = grub_util_find_hurd_root_device (dir); + + if (!os_dev[0]) + { + free (os_dev); + return 0; + } + + os_dev[1] = 0; + + return os_dev; +} diff --git a/grub-core/osdep/hurd/hostdisk.c b/grub-core/osdep/hurd/hostdisk.c new file mode 100644 index 0000000..c47b5a5 --- /dev/null +++ b/grub-core/osdep/hurd/hostdisk.c @@ -0,0 +1,146 @@ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 1999,2000,2001,2002,2003,2004,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 <http://www.gnu.org/licenses/>. + */ + +#include <config-util.h> + +#include <grub/disk.h> +#include <grub/partition.h> +#include <grub/msdos_partition.h> +#include <grub/types.h> +#include <grub/err.h> +#include <grub/emu/misc.h> +#include <grub/emu/hostdisk.h> +#include <grub/emu/getroot.h> +#include <grub/misc.h> +#include <grub/i18n.h> +#include <grub/list.h> + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <ctype.h> +#include <assert.h> +#include <unistd.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <fcntl.h> +#include <errno.h> +#include <limits.h> + +#include <hurd.h> +#include <hurd/lookup.h> +#include <hurd/fs.h> +#include <sys/mman.h> + +int +grub_util_hurd_get_disk_info (const char *dev, grub_uint32_t *secsize, grub_disk_addr_t *offset, + grub_disk_addr_t *size, char **parent) +{ + file_t file; + mach_port_t *ports; + int *ints; + loff_t *offsets; + char *data; + error_t err; + mach_msg_type_number_t num_ports = 0, num_ints = 0, num_offsets = 0, data_len = 0; + + file = file_name_lookup (dev, 0, 0); + if (file == MACH_PORT_NULL) + return 0; + + err = file_get_storage_info (file, + &ports, &num_ports, + &ints, &num_ints, + &offsets, &num_offsets, + &data, &data_len); + + if (num_ints < 1) + grub_util_error (_("Storage information for `%s' does not include type"), dev); + if (ints[0] != STORAGE_DEVICE) + grub_util_error (_("`%s' is not a local disk"), dev); + + if (num_offsets != 2) + grub_util_error (_("Storage information for `%s' indicates neither a plain partition nor a plain disk"), dev); + if (parent) + { + *parent = NULL; + if (num_ints >= 5) + { + size_t len = ints[4]; + if (len > data_len) + len = data_len; + *parent = xmalloc (len+1); + memcpy (*parent, data, len); + (*parent)[len] = '\0'; + } + } + if (offset) + *offset = offsets[0]; + if (size) + *size = offsets[1]; + if (secsize) + *secsize = ints[2]; + if (ports && num_ports > 0) + { + mach_msg_type_number_t i; + for (i = 0; i < num_ports; i++) + { + mach_port_t port = ports[i]; + if (port != MACH_PORT_NULL) + mach_port_deallocate (mach_task_self(), port); + } + munmap ((caddr_t) ports, num_ports * sizeof (*ports)); + } + + if (ints && num_ints > 0) + munmap ((caddr_t) ints, num_ints * sizeof (*ints)); + if (offsets && num_offsets > 0) + munmap ((caddr_t) offsets, num_offsets * sizeof (*offsets)); + if (data && data_len > 0) + munmap (data, data_len); + mach_port_deallocate (mach_task_self (), file); + + return 1; +} + +grub_int64_t +grub_util_get_fd_size_os (grub_util_fd_t fd, const char *name, unsigned *log_secsize) +{ + grub_uint32_t sector_size; + grub_disk_addr_t size; + unsigned log_sector_size; + + if (!grub_util_hurd_get_disk_info (name, §or_size, NULL, &size, NULL)) + return -1; + + if (sector_size & (sector_size - 1) || !sector_size) + return -1; + for (log_sector_size = 0; + (1 << log_sector_size) < sector_size; + log_sector_size++); + + if (log_secsize) + *log_secsize = log_sector_size; + + return size << log_sector_size; +} + +void +grub_hostdisk_flush_initial_buffer (const char *os_dev __attribute__ ((unused))) +{ +} |