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" <medhe...@web.de>
> An: systemd-devel@lists.freedesktop.org
> Cc: "Jan Janssen" <medhe...@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
> 
>
_______________________________________________
systemd-devel mailing list
systemd-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/systemd-devel

Reply via email to