This adds a new grub module called hurdhelper. This module simplifies the loading of hurd multiboot modules by allowing them to be loaded in one line (in order of loading).
A typical use case would be: grub> insmod hurdhelper grub> multiboot /boot/gnumach-1.8-486-dbg.gz root=part:2:device:wd0 noide grub> hurdmodules pci-arbiter acpi rumpdisk ext2fs exec grub> boot This could, for example, allow hurd to be booted from the grub shell manually without remembering and typing dozens of commands. Signed-off-by: Damien Zammit <dam...@zamaudio.com> --- grub-core/Makefile.core.def | 8 ++ grub-core/loader/hurdhelper.c | 201 ++++++++++++++++++++++++++++++++++ grub-core/loader/multiboot.c | 6 + include/grub/multiboot.h | 1 + include/grub/multiboot2.h | 1 + 5 files changed, 217 insertions(+) create mode 100644 grub-core/loader/hurdhelper.c diff --git a/grub-core/Makefile.core.def b/grub-core/Makefile.core.def index 8022e1c0a..f2cdc3008 100644 --- a/grub-core/Makefile.core.def +++ b/grub-core/Makefile.core.def @@ -1788,6 +1788,14 @@ module = { enable = i386_xen_pvh; }; +module = { + name = hurdhelper; + common = loader/hurdhelper.c; + enable = x86; + enable = i386_pc; + enable = i386_multiboot; +}; + module = { name = xen_boot; arm64 = loader/arm64/xen_boot.c; diff --git a/grub-core/loader/hurdhelper.c b/grub-core/loader/hurdhelper.c new file mode 100644 index 000000000..bc25a6b7a --- /dev/null +++ b/grub-core/loader/hurdhelper.c @@ -0,0 +1,201 @@ +/* hurdhelper.c - helper for loading GNU/Hurd multiboot modules. */ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2022 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 <grub/loader.h> +#include <grub/command.h> +#ifdef GRUB_USE_MULTIBOOT2 +#include <grub/multiboot2.h> +#define GRUB_MULTIBOOT(x) grub_multiboot2_ ## x +#else +#include <grub/multiboot.h> +#define GRUB_MULTIBOOT(x) grub_multiboot_ ## x +#endif +#include <grub/cpu/multiboot.h> +#include <grub/memory.h> +#include <grub/dl.h> +#include <grub/err.h> + +#define MBI_STRLEN 512 + +#define HURD_FS_PARAMS1 "--multiboot-command-line=${kernel-command-line}" +#define HURD_FS_PARAMS2 "--store-type=typed" +#define HURD_FS_PARAMS3 "${root}" +#define HURD_HOST_PRIV "--host-priv-port=${host-port}" +#define HURD_DEV_MASTER "--device-master-port=${device-port}" +#define HURD_PREFIX "/hurd/" +#define LIB_PREFIX "/lib/" +#define FS_TASK "ext2fs" +#define EXEC_TASK "exec" +#define LD_SO_1 "ld.so.1" +#define STATIC_SUFFIX ".static" + +GRUB_MOD_LICENSE ("GPLv3+"); + +static grub_dl_t my_mod; + +static int +is_fs_task (char *arg) +{ + if (!grub_strncmp(arg, FS_TASK, 6)) + return 1; + else + return 0; +} + +static int +is_exec_task (char *arg) +{ + if (!grub_strncmp(arg, EXEC_TASK, 4)) + return 1; + else + return 0; +} + +static const char * +lookup_suffix (char *arg) +{ + if (is_exec_task(arg)) + return ""; + else + return STATIC_SUFFIX; +} + +static int +zalloc_array(char *base[], int members, int size) +{ + int i; + + for (i = 0; i < members; i++) + { + base[i] = grub_zalloc(size); + if (!base[i]) + goto free_and_fail; + } + return 0; + +free_and_fail: + for (i--; i > 0; i--) + grub_free(base[i]); + return 1; +} + +static grub_err_t +grub_cmd_hurdmodules (grub_command_t cmd __attribute__ ((unused)), + int argc, char *argv[]) +{ + int err; + + if (argc < 2) + return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("minimum two filenames expected")); + + /* first module has different args */ + { + char *new_argv[10]; + err = zalloc_array(new_argv, 10, MBI_STRLEN); + if (err) + return grub_error (GRUB_ERR_OUT_OF_MEMORY, "can't create array for hurdhelper"); + grub_snprintf(new_argv[0], MBI_STRLEN, "%s%s%s", HURD_PREFIX, argv[0], lookup_suffix(argv[0])); + grub_snprintf(new_argv[1], MBI_STRLEN, "%s", argv[0]); + grub_snprintf(new_argv[2], MBI_STRLEN, "%s", HURD_HOST_PRIV); + grub_snprintf(new_argv[3], MBI_STRLEN, "%s", HURD_DEV_MASTER); + grub_snprintf(new_argv[4], MBI_STRLEN, "%s", is_fs_task(argv[0]) ? HURD_FS_PARAMS1 : ""); + grub_snprintf(new_argv[5], MBI_STRLEN, "--next-task=${%s-task}", argv[1]); + grub_snprintf(new_argv[6], MBI_STRLEN, "%s", is_fs_task(argv[0]) ? HURD_FS_PARAMS2 : ""); + grub_snprintf(new_argv[7], MBI_STRLEN, "%s", is_fs_task(argv[0]) ? HURD_FS_PARAMS3 : ""); + grub_snprintf(new_argv[8], MBI_STRLEN, "$(task-create)"); + grub_snprintf(new_argv[9], MBI_STRLEN, "$(task-resume)"); + err = GRUB_MULTIBOOT (cmd_module) (10, new_argv); + grub_free(new_argv[0]); + grub_free(new_argv[1]); + grub_free(new_argv[2]); + grub_free(new_argv[3]); + grub_free(new_argv[4]); + grub_free(new_argv[5]); + grub_free(new_argv[6]); + grub_free(new_argv[7]); + grub_free(new_argv[8]); + grub_free(new_argv[9]); + if (err) + return err; + } + + argc--; + argv++; + for (; argc > 1 && !is_exec_task(argv[0]); argc--, argv++) + { + char *new_argv[7]; + err = zalloc_array(new_argv, 7, MBI_STRLEN); + if (err) + return grub_error (GRUB_ERR_OUT_OF_MEMORY, "can't create array for hurdhelper"); + grub_snprintf(new_argv[0], MBI_STRLEN, "%s%s%s", HURD_PREFIX, argv[0], lookup_suffix(argv[0])); + grub_snprintf(new_argv[1], MBI_STRLEN, "%s", argv[0]); + grub_snprintf(new_argv[2], MBI_STRLEN, "%s", is_fs_task(argv[0]) ? HURD_FS_PARAMS1 : ""); + grub_snprintf(new_argv[3], MBI_STRLEN, "--next-task=${%s-task}", argv[1]); + grub_snprintf(new_argv[4], MBI_STRLEN, "%s", is_fs_task(argv[0]) ? HURD_FS_PARAMS2 : ""); + grub_snprintf(new_argv[5], MBI_STRLEN, "%s", is_fs_task(argv[0]) ? HURD_FS_PARAMS3 : ""); + grub_snprintf(new_argv[6], MBI_STRLEN, "$(%s-task=task-create)", argv[0]); + err = GRUB_MULTIBOOT (cmd_module) (7, new_argv); + grub_free(new_argv[0]); + grub_free(new_argv[1]); + grub_free(new_argv[2]); + grub_free(new_argv[3]); + grub_free(new_argv[4]); + grub_free(new_argv[5]); + grub_free(new_argv[6]); + if (err) + return err; + } + + /* exec module has different args */ + { + char *new_argv[4]; + err = zalloc_array(new_argv, 4, MBI_STRLEN); + if (err) + return grub_error (GRUB_ERR_OUT_OF_MEMORY, "can't create array for hurdhelper"); + grub_snprintf(new_argv[0], MBI_STRLEN, "%s%s", LIB_PREFIX, LD_SO_1); + grub_snprintf(new_argv[1], MBI_STRLEN, "%s", EXEC_TASK); + grub_snprintf(new_argv[2], MBI_STRLEN, "%s%s", HURD_PREFIX, EXEC_TASK); + grub_snprintf(new_argv[3], MBI_STRLEN, "$(%s-task=task-create)", EXEC_TASK); + err = GRUB_MULTIBOOT (cmd_module) (4, new_argv); + grub_free(new_argv[0]); + grub_free(new_argv[1]); + grub_free(new_argv[2]); + grub_free(new_argv[3]); + if (err) + return err; + } + + return GRUB_ERR_NONE; +} + +static grub_command_t cmd_hurdmodules; + +GRUB_MOD_INIT(hurdhelper) +{ + cmd_hurdmodules = + grub_register_command ("hurdmodules", grub_cmd_hurdmodules, + 0, N_("Load a HURD of multiboot modules.")); + + my_mod = mod; +} + +GRUB_MOD_FINI(hurdhelper) +{ + grub_unregister_command (cmd_hurdmodules); +} diff --git a/grub-core/loader/multiboot.c b/grub-core/loader/multiboot.c index facb13f3d..1edb9048d 100644 --- a/grub-core/loader/multiboot.c +++ b/grub-core/loader/multiboot.c @@ -440,6 +440,12 @@ grub_cmd_module (grub_command_t cmd __attribute__ ((unused)), return GRUB_ERR_NONE; } +grub_err_t +GRUB_MULTIBOOT (cmd_module) (int argc, char *argv[]) +{ + return grub_cmd_module (NULL, argc, argv); +} + static grub_command_t cmd_multiboot, cmd_module; GRUB_MOD_INIT(multiboot) diff --git a/include/grub/multiboot.h b/include/grub/multiboot.h index bd0a9873e..d801c5ecd 100644 --- a/include/grub/multiboot.h +++ b/include/grub/multiboot.h @@ -46,6 +46,7 @@ void grub_multiboot_free_mbi (void); grub_err_t grub_multiboot_init_mbi (int argc, char *argv[]); grub_err_t grub_multiboot_add_module (grub_addr_t start, grub_size_t size, int argc, char *argv[]); +grub_err_t grub_multiboot_cmd_module (int argc, char *argv[]); void grub_multiboot_set_bootdev (void); void grub_multiboot_add_elfsyms (grub_size_t num, grub_size_t entsize, diff --git a/include/grub/multiboot2.h b/include/grub/multiboot2.h index 502d34ef1..6f790863c 100644 --- a/include/grub/multiboot2.h +++ b/include/grub/multiboot2.h @@ -38,6 +38,7 @@ void grub_multiboot2_free_mbi (void); grub_err_t grub_multiboot2_init_mbi (int argc, char *argv[]); grub_err_t grub_multiboot2_add_module (grub_addr_t start, grub_size_t size, int argc, char *argv[]); +grub_err_t grub_multiboot2_cmd_module (int argc, char *argv[]); void grub_multiboot2_set_bootdev (void); void grub_multiboot2_add_elfsyms (grub_size_t num, grub_size_t entsize, -- 2.40.1