Address feedback from Daniel's review (interdiff attached). Specifically, perform a style cleanup, add more documentation, and add three comments.
Be well, --Robbie Raymund Will (1): Add support for grub-emu to kexec Linux menu entries docs/grub.texi | 28 ++++-- grub-core/Makefile.am | 1 + grub-core/Makefile.core.def | 2 +- grub-core/kern/emu/main.c | 4 + grub-core/kern/emu/misc.c | 18 +++- grub-core/loader/emu/linux.c | 183 +++++++++++++++++++++++++++++++++++ include/grub/emu/exec.h | 4 +- include/grub/emu/hostfile.h | 3 +- include/grub/emu/misc.h | 3 + 9 files changed, 233 insertions(+), 13 deletions(-) create mode 100644 grub-core/loader/emu/linux.c Interdiff against v4: diff --git a/docs/grub.texi b/docs/grub.texi index af119dea3b..1463e62e6b 100644 --- a/docs/grub.texi +++ b/docs/grub.texi @@ -1,4 +1,4 @@ -\input texinfo +i\input texinfo @c -*-texinfo-*- @c %**start of header @setfilename grub.info @@ -923,17 +923,17 @@ magic. @node General boot methods @section How to boot operating systems -GRUB has two distinct boot methods. One of the two is to load an -operating system directly, and the other is to chain-load another boot -loader which then will load an operating system actually. Generally -speaking, the former is more desirable, because you don't need to -install or maintain other boot loaders and GRUB is flexible enough to -load an operating system from an arbitrary disk/partition. However, -the latter is sometimes required, since GRUB doesn't support all the -existing operating systems natively. +GRUB has three distinct boot methods: loading an operating system +directly, using kexec from userspace, and chainloading another +bootloader. Generally speaking, the first two are more desirable +because you don't need to install or maintain other boot loaders and +GRUB is flexible enough to load an operating system from an arbitrary +disk/partition. However, chainloading is sometimes required, as GRUB +doesn't support all existing operating systems natively. @menu * Loading an operating system directly:: +* Kexec:: * Chain-loading:: @end menu @@ -959,6 +959,16 @@ use more complicated instructions. @xref{DOS/Windows}, for more information. +@node Kexec +@subsection Kexec with grub2-emu + +grub2 can be run in userspace by invoking the grub2-emu tool. It will +read all configuration scripts as if booting directly (see @xref{Loading +an operating system directly}). With the @code{--kexec} flag, and +kexec(8) support from the operating system, the @command{linux} command +will directly boot the target image. + + @node Chain-loading @subsection Chain-loading an OS diff --git a/grub-core/loader/emu/linux.c b/grub-core/loader/emu/linux.c index bdcdbb0ff4..f232f195b3 100644 --- a/grub-core/loader/emu/linux.c +++ b/grub-core/loader/emu/linux.c @@ -1,6 +1,6 @@ /* * GRUB -- GRand Unified Bootloader - * Copyright (C) 2006,2007,2008,2009,2010 Free Software Foundation, Inc. + * 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 @@ -38,8 +38,9 @@ grub_linux_boot (void) { grub_err_t rc = GRUB_ERR_NONE; char *initrd_param; - const char *kexec[] = { "kexec", "-la", kernel_path, boot_cmdline, NULL, NULL }; - const char *systemctl[] = { "systemctl", "kexec", NULL }; + const char *kexec[] = {"kexec", "-la", kernel_path, boot_cmdline, NULL, + NULL}; + const char *systemctl[] = {"systemctl", "kexec", NULL}; int kexecute = grub_util_get_kexecute (); if (initrd_path) @@ -49,9 +50,7 @@ grub_linux_boot (void) kexec[4] = boot_cmdline; } else - { - initrd_param = grub_xasprintf ("%s", ""); - } + initrd_param = grub_xasprintf ("%s", ""); grub_dprintf ("linux", "%serforming 'kexec -la %s %s %s'\n", (kexecute) ? "P" : "Not p", @@ -64,30 +63,32 @@ grub_linux_boot (void) if (rc != GRUB_ERR_NONE) { - grub_error (rc, N_("Error trying to perform kexec load operation.")); + grub_error (rc, N_("error trying to perform kexec load operation")); grub_sleep (3); return rc; } if (kexecute < 1) - grub_fatal (N_("Use '"PACKAGE"-emu --kexec' to force a system restart.")); + grub_fatal (N_("use '"PACKAGE"-emu --kexec' to force a system restart")); grub_dprintf ("linux", "Performing 'systemctl kexec' (%s) ", (kexecute==1) ? "do-or-die" : "just-in-case"); rc = grub_util_exec (systemctl); if (kexecute == 1) - grub_fatal (N_("Error trying to perform 'systemctl kexec'")); + grub_fatal (N_("error trying to perform 'systemctl kexec': %d"), rc); - /* WARNING: forcible reset should only be used in read-only environments. - * grub-emu cannot check for these - users beware. */ + /* + * WARNING: forcible reset should only be used in read-only environments. + * grub-emu cannot check for these - users beware. + */ grub_dprintf ("linux", "Performing 'kexec -e -x'"); kexec[1] = "-e"; kexec[2] = "-x"; kexec[3] = NULL; rc = grub_util_exec (kexec); if ( rc != GRUB_ERR_NONE ) - grub_fatal (N_("Error trying to directly perform 'kexec -e'.")); + grub_fatal (N_("error trying to directly perform 'kexec -e': %d"), rc); return rc; } @@ -95,45 +96,43 @@ grub_linux_boot (void) static grub_err_t grub_linux_unload (void) { + /* Unloading: we're no longer in use. */ grub_dl_unref (my_mod); - if ( boot_cmdline != NULL ) - grub_free (boot_cmdline); + grub_free (boot_cmdline); boot_cmdline = NULL; return GRUB_ERR_NONE; } static grub_err_t -grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)), int argc, char *argv[]) +grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)), int argc, + char *argv[]) { int i; char *tempstr; + /* Mark ourselves as in-use. */ grub_dl_ref (my_mod); if (argc == 0) return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("filename expected")); - if ( !grub_util_is_regular (argv[0]) ) - return grub_error (GRUB_ERR_FILE_NOT_FOUND, N_("Cannot find kernel file %s"), argv[0]); - - if ( kernel_path != NULL ) - grub_free (kernel_path); + if (!grub_util_is_regular (argv[0])) + return grub_error (GRUB_ERR_FILE_NOT_FOUND, + N_("cannot find kernel file %s"), argv[0]); + grub_free (kernel_path); kernel_path = grub_xasprintf ("%s", argv[0]); - if ( boot_cmdline != NULL ) - { - grub_free(boot_cmdline); - boot_cmdline = NULL; - } + grub_free (boot_cmdline); + boot_cmdline = NULL; - if ( argc > 1 ) + if (argc > 1) { - boot_cmdline = grub_xasprintf("--command-line=%s", argv[1]); + boot_cmdline = grub_xasprintf ("--command-line=%s", argv[1]); for ( i = 2; i < argc; i++ ) { - tempstr = grub_xasprintf("%s %s", boot_cmdline, argv[i]); - grub_free(boot_cmdline); + tempstr = grub_xasprintf ("%s %s", boot_cmdline, argv[i]); + grub_free (boot_cmdline); boot_cmdline = tempstr; } } @@ -144,19 +143,20 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)), int argc, char *arg } static grub_err_t -grub_cmd_initrd (grub_command_t cmd __attribute__ ((unused)), int argc, char *argv[]) +grub_cmd_initrd (grub_command_t cmd __attribute__ ((unused)), int argc, + char *argv[]) { if (argc == 0) return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("filename expected")); - if ( !grub_util_is_regular (argv[0]) ) - return grub_error (GRUB_ERR_FILE_NOT_FOUND, N_("Cannot find initrd file %s"), argv[0]); - - if ( initrd_path != NULL ) - grub_free (initrd_path); + if (!grub_util_is_regular (argv[0])) + return grub_error (GRUB_ERR_FILE_NOT_FOUND, + N_("Cannot find initrd file %s"), argv[0]); + grub_free (initrd_path); initrd_path = grub_xasprintf("%s", argv[0]); + /* We are done - mark ourselves as on longer in use. */ grub_dl_unref (my_mod); return GRUB_ERR_NONE; @@ -166,8 +166,10 @@ static grub_command_t cmd_linux, cmd_initrd; GRUB_MOD_INIT (linux) { - cmd_linux = grub_register_command ("linux", grub_cmd_linux, 0, N_("Load Linux.")); - cmd_initrd = grub_register_command ("initrd", grub_cmd_initrd, 0, N_("Load initrd.")); + cmd_linux = grub_register_command ("linux", grub_cmd_linux, 0, + N_("Load Linux.")); + cmd_initrd = grub_register_command ("initrd", grub_cmd_initrd, 0, + N_("Load initrd.")); my_mod = mod; kernel_path = NULL; initrd_path = NULL; -- 2.35.1 _______________________________________________ Grub-devel mailing list Grub-devel@gnu.org https://lists.gnu.org/mailman/listinfo/grub-devel