[systemd-devel] [PATCH 1/2] systemctl: Add reboot to firmware support
Jan Janssen
medhefgo at web.de
Tue Mar 17 01:10:55 PDT 2015
I certainly see the point of not adding fsck mode indication, but I'd still like to see
this one go in. If your firmware and/or bootloader won't give you a chance to, the os is
your only chance should you still be able to boot to it. And it's quite hard to even find
out how to reboot to firmware unless you know that it's called os indication. There isn't
even any convenient tool out there that allows you to do so, the best thing is fiddling
with the variable yourself using the shell[1].
Jan
[1] http://unix.stackexchange.com/questions/152144/how-to-write-edit-update-the-osindications-efi-variable-from-command-line
> Gesendet: Sonntag, 15. März 2015 um 11:56 Uhr
> Von: "Jan Janssen" <medhefgo at web.de>
> An: systemd-devel at lists.freedesktop.org
> Cc: "Jan Janssen" <medhefgo at web.de>
> Betreff: [PATCH 1/2] systemctl: Add reboot to firmware support
>
> ---
> man/systemctl.xml | 10 ++++++++
> shell-completion/bash/systemctl.in | 2 +-
> shell-completion/zsh/_systemctl.in | 1 +
> src/shared/efivars.h | 7 +++---
> src/systemctl/systemctl.c | 48 ++++++++++++++++++++++++++++++++++----
> 5 files changed, 60 insertions(+), 8 deletions(-)
>
> diff --git a/man/systemctl.xml b/man/systemctl.xml
> index 50e6bc9..3e2bcde 100644
> --- a/man/systemctl.xml
> +++ b/man/systemctl.xml
> @@ -456,6 +456,16 @@
> </varlistentry>
>
> <varlistentry>
> + <term><option>--firmware</option></term>
> +
> + <listitem>
> + <para>Indicate to the firmware to boot into EFI setup on machines
> + that support it if <command>reboot</command> is used. Note that
> + this is only supported if the machine was booted in EFI mode.</para>
> + </listitem>
> + </varlistentry>
> +
> + <varlistentry>
> <term><option>--root=</option></term>
>
> <listitem>
> diff --git a/shell-completion/bash/systemctl.in b/shell-completion/bash/systemctl.in
> index 8063316..f14fe7a 100644
> --- a/shell-completion/bash/systemctl.in
> +++ b/shell-completion/bash/systemctl.in
> @@ -92,7 +92,7 @@ _systemctl () {
> local -A OPTS=(
> [STANDALONE]='--all -a --reverse --after --before --defaults --fail --ignore-dependencies --failed --force -f --full -l --global
> --help -h --no-ask-password --no-block --no-legend --no-pager --no-reload --no-wall
> - --quiet -q --privileged -P --system --user --version --runtime --recursive -r'
> + --quiet -q --privileged -P --system --user --version --runtime --recursive -r --firmware'
> [ARG]='--host -H --kill-who --property -p --signal -s --type -t --state --root'
> )
>
> diff --git a/shell-completion/zsh/_systemctl.in b/shell-completion/zsh/_systemctl.in
> index 7f2d5ac..1caf9a4 100644
> --- a/shell-completion/zsh/_systemctl.in
> +++ b/shell-completion/zsh/_systemctl.in
> @@ -375,6 +375,7 @@ _arguments -s \
> '--global[Enable/disable unit files globally]' \
> "--no-reload[When enabling/disabling unit files, don't reload daemon configuration]" \
> '--no-ask-password[Do not ask for system passwords]' \
> + '--firmware[Reboot to EFI setup on machines that support it]' \
> '--kill-who=[Who to send signal to]:killwho:(main control all)' \
> {-s+,--signal=}'[Which signal to send]:signal:_signals' \
> {-f,--force}'[When enabling unit files, override existing symlinks. When shutting down, execute action immediately]' \
> diff --git a/src/shared/efivars.h b/src/shared/efivars.h
> index 2492893..7bdfb74 100644
> --- a/src/shared/efivars.h
> +++ b/src/shared/efivars.h
> @@ -28,9 +28,10 @@
>
> #define EFI_VENDOR_LOADER SD_ID128_MAKE(4a,67,b0,82,0a,4c,41,cf,b6,c7,44,0b,29,bb,8c,4f)
> #define EFI_VENDOR_GLOBAL SD_ID128_MAKE(8b,e4,df,61,93,ca,11,d2,aa,0d,00,e0,98,03,2b,8c)
> -#define EFI_VARIABLE_NON_VOLATILE 0x0000000000000001
> -#define EFI_VARIABLE_BOOTSERVICE_ACCESS 0x0000000000000002
> -#define EFI_VARIABLE_RUNTIME_ACCESS 0x0000000000000004
> +#define EFI_VARIABLE_NON_VOLATILE 0x0000000000000001
> +#define EFI_VARIABLE_BOOTSERVICE_ACCESS 0x0000000000000002
> +#define EFI_VARIABLE_RUNTIME_ACCESS 0x0000000000000004
> +#define EFI_OS_INDICATIONS_BOOT_TO_FW_UI 0x0000000000000001
>
> bool is_efi_boot(void);
> int is_efi_secure_boot(void);
> diff --git a/src/systemctl/systemctl.c b/src/systemctl/systemctl.c
> index 3158a38..8aee3c4 100644
> --- a/src/systemctl/systemctl.c
> +++ b/src/systemctl/systemctl.c
> @@ -68,6 +68,8 @@
> #include "bus-common-errors.h"
> #include "mkdir.h"
> #include "dropin.h"
> +#include "virt.h"
> +#include "efivars.h"
>
> static char **arg_types = NULL;
> static char **arg_states = NULL;
> @@ -132,7 +134,7 @@ static char *arg_host = NULL;
> static unsigned arg_lines = 10;
> static OutputMode arg_output = OUTPUT_SHORT;
> static bool arg_plain = false;
> -
> +static bool arg_firmware = false;
> static bool original_stdout_is_tty;
>
> static int daemon_reload(sd_bus *bus, char **args);
> @@ -2923,9 +2925,40 @@ static int start_special(sd_bus *bus, char **args) {
> if (r < 0)
> return r;
>
> - if (arg_force >= 2 && geteuid() != 0) {
> - log_error("Must be root.");
> - return -EPERM;
> + if ((arg_firmware || arg_force >= 2) && geteuid() != 0)
> + return log_error_errno(EPERM, "Must be root.");
> +
> + if (arg_firmware) {
> + size_t s;
> + uint64_t b;
> + _cleanup_free_ void *v = NULL;
> +
> + if (a != ACTION_REBOOT)
> + return log_error_errno(EINVAL, "Must use reboot command to reboot to firmware.");
> + else if (detect_container(NULL) > 0)
> + return log_error_errno(ENOTSUP, "Cannot reboot to firmware from within a container.");
> + else if (!is_efi_boot())
> + return log_error_errno(ENOTSUP, "Reboot to firmware requires the system to be booted in EFI mode.");
> +
> + r = efi_get_variable(EFI_VENDOR_GLOBAL, "OsIndicationsSupported", NULL, &v, &s);
> + if (r < 0 || s != sizeof(uint64_t))
> + return log_error_errno(r, "Error reading OsIndicationsSupported EFI variable.");
> +
> + b = *(uint64_t *)v;
> + if (!(b & EFI_OS_INDICATIONS_BOOT_TO_FW_UI))
> + return log_error_errno(ENOTSUP, "Reboot to firmware not supported.");
> +
> + free(v);
> + v = NULL;
> + r = efi_get_variable(EFI_VENDOR_GLOBAL, "OsIndications", NULL, &v, &s);
> + if (r < 0 || s != sizeof(uint64_t))
> + return log_error_errno(r, "Error reading OsIndications EFI variable.");
> +
> + b = *(uint64_t *)v;
> + b |= EFI_OS_INDICATIONS_BOOT_TO_FW_UI;
> + r = efi_set_variable(EFI_VENDOR_GLOBAL, "OsIndications", &b, s);
> + if (r < 0)
> + return log_error_errno(r, "Error writing OsIndications EFI variable.");
> }
>
> if (a == ACTION_REBOOT && args[1]) {
> @@ -5965,6 +5998,7 @@ static void systemctl_help(void) {
> " --runtime Enable unit files only temporarily until next reboot\n"
> " -f --force When enabling unit files, override existing symlinks\n"
> " When shutting down, execute action immediately\n"
> + " --firmware Reboot to EFI setup on machines that support it\n"
> " --preset-mode= Apply only enable, only disable, or all presets\n"
> " --root=PATH Enable unit files in the specified root directory\n"
> " -n --lines=INTEGER Number of journal entries to show\n"
> @@ -6150,6 +6184,7 @@ static int systemctl_parse_argv(int argc, char *argv[]) {
> ARG_STATE,
> ARG_JOB_MODE,
> ARG_PRESET_MODE,
> + ARG_FIRMWARE,
> };
>
> static const struct option options[] = {
> @@ -6192,6 +6227,7 @@ static int systemctl_parse_argv(int argc, char *argv[]) {
> { "state", required_argument, NULL, ARG_STATE },
> { "recursive", no_argument, NULL, 'r' },
> { "preset-mode", required_argument, NULL, ARG_PRESET_MODE },
> + { "firmware", no_argument, NULL, ARG_FIRMWARE },
> {}
> };
>
> @@ -6468,6 +6504,10 @@ static int systemctl_parse_argv(int argc, char *argv[]) {
>
> break;
>
> + case ARG_FIRMWARE:
> + arg_firmware = true;
> + break;
> +
> case '?':
> return -EINVAL;
>
> --
> 2.3.2
>
>
More information about the systemd-devel
mailing list