From 9e9382ece3511ff530cfb3e1c1e7a7dbaa3416b6 Mon Sep 17 00:00:00 2001 From: Peter Jones Date: Sat, 8 Sep 2012 09:40:24 +0200 Subject: [PATCH 033/364] * grub-core/Makefile.core.def (efifwsetup): New module. * grub-core/commands/efi/efifwsetup.c: New file. * grub-core/kern/efi/efi.c (grub_efi_set_variable): New function * include/grub/efi/api.h (GRUB_EFI_OS_INDICATIONS_BOOT_TO_FW_UI): New define. * include/grub/efi/efi.h (grub_efi_set_variable): New proto. --- ChangeLog | 9 ++++ grub-core/Makefile.core.def | 6 +++ grub-core/commands/efi/efifwsetup.c | 90 +++++++++++++++++++++++++++++++++++++ grub-core/kern/efi/efi.c | 30 +++++++++++++ include/grub/efi/api.h | 2 + include/grub/efi/efi.h | 5 +++ 6 files changed, 142 insertions(+) create mode 100644 grub-core/commands/efi/efifwsetup.c diff --git a/ChangeLog b/ChangeLog index 10b1ab3..e8f0577 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,12 @@ +2012-09-08 Peter Jones + + * grub-core/Makefile.core.def (efifwsetup): New module. + * grub-core/commands/efi/efifwsetup.c: New file. + * grub-core/kern/efi/efi.c (grub_efi_set_variable): New function + * include/grub/efi/api.h (GRUB_EFI_OS_INDICATIONS_BOOT_TO_FW_UI): + New define. + * include/grub/efi/efi.h (grub_efi_set_variable): New proto. + 2012-09-05 Jiri Slaby * configure.ac: Add SuSe path. diff --git a/grub-core/Makefile.core.def b/grub-core/Makefile.core.def index de702d6..7a7b97a 100644 --- a/grub-core/Makefile.core.def +++ b/grub-core/Makefile.core.def @@ -575,6 +575,12 @@ module = { }; module = { + name = efifwsetup; + efi = commands/efi/efifwsetup.c; + enable = efi; +}; + +module = { name = blocklist; common = commands/blocklist.c; }; diff --git a/grub-core/commands/efi/efifwsetup.c b/grub-core/commands/efi/efifwsetup.c new file mode 100644 index 0000000..7a137a7 --- /dev/null +++ b/grub-core/commands/efi/efifwsetup.c @@ -0,0 +1,90 @@ +/* fwsetup.c - Reboot into firmware setup menu. */ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2012 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 . + */ + +#include +#include +#include +#include +#include +#include +#include + +GRUB_MOD_LICENSE ("GPLv3+"); + +static grub_err_t +grub_cmd_fwsetup (grub_command_t cmd __attribute__ ((unused)), + int argc __attribute__ ((unused)), + char **args __attribute__ ((unused))) +{ + grub_efi_uint64_t *old_os_indications; + grub_efi_uint64_t os_indications = GRUB_EFI_OS_INDICATIONS_BOOT_TO_FW_UI; + grub_err_t status; + grub_size_t oi_size; + grub_efi_guid_t global = GRUB_EFI_GLOBAL_VARIABLE_GUID; + + old_os_indications = grub_efi_get_variable ("OsIndications", &global, + &oi_size); + + if (old_os_indications != NULL && oi_size == sizeof (os_indications)) + os_indications |= *old_os_indications; + + status = grub_efi_set_variable ("OsIndications", &global, &os_indications, + sizeof (os_indications)); + if (status != GRUB_ERR_NONE) + return status; + + grub_reboot (); + + return GRUB_ERR_BUG; +} + +static grub_command_t cmd = NULL; + +static grub_efi_boolean_t +efifwsetup_is_supported (void) +{ + grub_efi_uint64_t *os_indications_supported = NULL; + grub_size_t oi_size = 0; + grub_efi_guid_t global = GRUB_EFI_GLOBAL_VARIABLE_GUID; + + os_indications_supported = grub_efi_get_variable ("OsIndicationsSupported", + &global, &oi_size); + + if (!os_indications_supported) + return 0; + + if (*os_indications_supported & GRUB_EFI_OS_INDICATIONS_BOOT_TO_FW_UI) + return 1; + + return 0; +} + +GRUB_MOD_INIT (efifwsetup) +{ + if (efifwsetup_is_supported ()) + cmd = grub_register_command ("fwsetup", grub_cmd_fwsetup, NULL, + N_("Reboot into firmware setup menu.")); + +} + +GRUB_MOD_FINI (efifwsetup) +{ + if (cmd) + grub_unregister_command (cmd); +} diff --git a/grub-core/kern/efi/efi.c b/grub-core/kern/efi/efi.c index 02d2f9a..e8a62ec 100644 --- a/grub-core/kern/efi/efi.c +++ b/grub-core/kern/efi/efi.c @@ -181,6 +181,36 @@ grub_efi_set_virtual_address_map (grub_efi_uintn_t memory_map_size, return grub_error (GRUB_ERR_IO, "set_virtual_address_map failed"); } +grub_err_t +grub_efi_set_variable(const char *var, const grub_efi_guid_t *guid, + void *data, grub_size_t datasize) +{ + grub_efi_status_t status; + grub_efi_runtime_services_t *r; + grub_efi_char16_t *var16; + grub_size_t len, len16; + + len = grub_strlen (var); + len16 = len * GRUB_MAX_UTF16_PER_UTF8; + var16 = grub_malloc ((len16 + 1) * sizeof (var16[0])); + if (!var16) + return grub_errno; + len16 = grub_utf8_to_utf16 (var16, len16, (grub_uint8_t *) var, len, NULL); + var16[len16] = 0; + + r = grub_efi_system_table->runtime_services; + + status = efi_call_5 (r->set_variable, var16, guid, + (GRUB_EFI_VARIABLE_NON_VOLATILE + | GRUB_EFI_VARIABLE_BOOTSERVICE_ACCESS + | GRUB_EFI_VARIABLE_RUNTIME_ACCESS), + datasize, data); + if (status == GRUB_EFI_SUCCESS) + return GRUB_ERR_NONE; + + return grub_error (GRUB_ERR_IO, "could not set EFI variable `%s'", var); +} + void * grub_efi_get_variable (const char *var, const grub_efi_guid_t *guid, grub_size_t *datasize_out) diff --git a/include/grub/efi/api.h b/include/grub/efi/api.h index 9e7a8d8..ae61730 100644 --- a/include/grub/efi/api.h +++ b/include/grub/efi/api.h @@ -58,6 +58,8 @@ #define GRUB_EFI_OPEN_PROTOCOL_BY_DRIVER 0x00000010 #define GRUB_EFI_OPEN_PROTOCOL_BY_EXCLUSIVE 0x00000020 +#define GRUB_EFI_OS_INDICATIONS_BOOT_TO_FW_UI 0x0000000000000001ULL + #define GRUB_EFI_VARIABLE_NON_VOLATILE 0x0000000000000001 #define GRUB_EFI_VARIABLE_BOOTSERVICE_ACCESS 0x0000000000000002 #define GRUB_EFI_VARIABLE_RUNTIME_ACCESS 0x0000000000000004 diff --git a/include/grub/efi/efi.h b/include/grub/efi/efi.h index e67d92b..489cf9e 100644 --- a/include/grub/efi/efi.h +++ b/include/grub/efi/efi.h @@ -64,6 +64,11 @@ grub_err_t EXPORT_FUNC (grub_efi_set_virtual_address_map) (grub_efi_uintn_t memo void *EXPORT_FUNC (grub_efi_get_variable) (const char *variable, const grub_efi_guid_t *guid, grub_size_t *datasize_out); +grub_err_t +EXPORT_FUNC (grub_efi_set_variable) (const char *var, + const grub_efi_guid_t *guid, + void *data, + grub_size_t datasize); int EXPORT_FUNC (grub_efi_compare_device_paths) (const grub_efi_device_path_t *dp1, const grub_efi_device_path_t *dp2); -- 1.8.1.4