Add a command to obtain the contents of EFI firmware variables. --- docs/grub.texi | 7 ++ grub-core/Makefile.core.def | 7 ++ grub-core/commands/efi/getenv.c | 153 ++++++++++++++++++++++++++++++++++++++++ 3 files changed, 167 insertions(+) create mode 100644 grub-core/commands/efi/getenv.c
diff --git a/docs/grub.texi b/docs/grub.texi index b9ddb9b..4469638 100644 --- a/docs/grub.texi +++ b/docs/grub.texi @@ -3818,6 +3818,7 @@ you forget a command, you can run the command @command{help} * eval:: Evaluate agruments as GRUB commands * export:: Export an environment variable * false:: Do nothing, unsuccessfully +* getenv:: Retrieve an EFI firmware variable * gettext:: Translate a string * gptsync:: Fill an MBR based on GPT entries * halt:: Shut down your computer @@ -4258,6 +4259,12 @@ Do nothing, unsuccessfully. This is mainly useful in control constructs such as @code{if} and @code{while} (@pxref{Shell-like scripting}). @end deffn +@node getenv +@subsection getenv + +@deffn Command getenv [@option{-e}] [@option{-g}] envvar +Retrieves an EFI variable with the name provided by @option{-e} and the GUID +provied by @option{-g} and stores it in environment variable @var{envvar} @node gettext @subsection gettext diff --git a/grub-core/Makefile.core.def b/grub-core/Makefile.core.def index 2dfa22a..db77a7f 100644 --- a/grub-core/Makefile.core.def +++ b/grub-core/Makefile.core.def @@ -817,6 +817,13 @@ module = { }; module = { + name = getenv; + common = commands/efi/getenv.c; + enable = i386_efi; + enable = x86_64_efi; +}; + +module = { name = gptsync; common = commands/gptsync.c; }; diff --git a/grub-core/commands/efi/getenv.c b/grub-core/commands/efi/getenv.c new file mode 100644 index 0000000..5a829f5 --- /dev/null +++ b/grub-core/commands/efi/getenv.c @@ -0,0 +1,153 @@ +/* getenv.c - retrieve EFI variables. */ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2009 Free Software Foundation, Inc. + * Copyright (C) 2014 CoreOS, 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/efi/efi.h> +#include <grub/dl.h> +#include <grub/env.h> +#include <grub/err.h> +#include <grub/extcmd.h> +#include <grub/i18n.h> +#include <grub/misc.h> +#include <grub/mm.h> + +GRUB_MOD_LICENSE ("GPLv3+"); + +static const struct grub_arg_option options_getenv[] = { + {"var-name", 'e', 0, + N_("Environment variable to query"), + N_("VARNAME"), ARG_TYPE_STRING}, + {"var-guid", 'g', 0, + N_("GUID of environment variable to query"), + N_("GUID"), ARG_TYPE_STRING}, + {"binary", 'b', 0, + N_("Read binary data and represent it as hex"), + 0, ARG_TYPE_NONE}, + {0, 0, 0, 0, 0, 0} +}; + +enum options_getenv +{ + GETENV_VAR_NAME, + GETENV_VAR_GUID, + GETENV_BINARY, +}; + +static grub_err_t +grub_cmd_getenv (grub_extcmd_context_t ctxt, int argc, char **args) +{ + struct grub_arg_list *state = ctxt->state; + char *envvar = NULL, *guid = NULL, *bindata = NULL, *data = NULL; + grub_size_t datasize; + grub_efi_guid_t efi_var_guid; + grub_efi_boolean_t binary = state[GETENV_BINARY].set; + unsigned int i; + + if (!state[GETENV_VAR_NAME].set || !state[GETENV_VAR_GUID].set) + { + grub_error (GRUB_ERR_INVALID_COMMAND, N_("-e and -g are required")); + goto done; + } + + if (argc != 1) + { + grub_error (GRUB_ERR_BAD_ARGUMENT, N_("unexpected arguments")); + goto done; + } + + envvar = state[GETENV_VAR_NAME].arg; + guid = state[GETENV_VAR_GUID].arg; + + if (grub_strlen(guid) != 36 || + guid[8] != '-' || + guid[13] != '-' || + guid[18] != '-' || + guid[23] != '-') + { + grub_error (GRUB_ERR_BAD_ARGUMENT, N_("invalid GUID")); + goto done; + } + + /* Forgive me father for I have sinned */ + guid[8] = 0; + efi_var_guid.data1 = grub_strtoul(guid, NULL, 16); + guid[13] = 0; + efi_var_guid.data2 = grub_strtoul(guid + 9, NULL, 16); + guid[18] = 0; + efi_var_guid.data3 = grub_strtoul(guid + 14, NULL, 16); + efi_var_guid.data4[7] = grub_strtoul(guid + 34, NULL, 16); + guid[34] = 0; + efi_var_guid.data4[6] = grub_strtoul(guid + 32, NULL, 16); + guid[32] = 0; + efi_var_guid.data4[5] = grub_strtoul(guid + 30, NULL, 16); + guid[30] = 0; + efi_var_guid.data4[4] = grub_strtoul(guid + 28, NULL, 16); + guid[28] = 0; + efi_var_guid.data4[3] = grub_strtoul(guid + 26, NULL, 16); + guid[26] = 0; + efi_var_guid.data4[2] = grub_strtoul(guid + 24, NULL, 16); + guid[23] = 0; + efi_var_guid.data4[1] = grub_strtoul(guid + 21, NULL, 16); + guid[21] = 0; + efi_var_guid.data4[0] = grub_strtoul(guid + 19, NULL, 16); + + data = grub_efi_get_variable(envvar, &efi_var_guid, &datasize); + + if (!data || !datasize) + { + grub_error (GRUB_ERR_FILE_NOT_FOUND, N_("No such variable")); + goto done; + } + + if (binary) + { + bindata = grub_zalloc(datasize * 2 + 1); + for (i=0; i<datasize; i++) + grub_snprintf(bindata + i*2, 3, "%02x", data[i]); + + if (grub_env_set (args[0], bindata)) + goto done; + } + else if (grub_env_set (args[0], data)) + { + goto done; + } + + grub_errno = GRUB_ERR_NONE; + +done: + grub_free(bindata); + grub_free(data); + return grub_errno; +} + +static grub_extcmd_t cmd_getenv; + +GRUB_MOD_INIT(getenv) +{ + cmd_getenv = grub_register_extcmd ("getenv", grub_cmd_getenv, 0, + N_("-e envvar -g guidenv setvar"), + N_("Read a firmware environment variable"), + options_getenv); +} + +GRUB_MOD_FINI(getenv) +{ + grub_unregister_extcmd (cmd_getenv); +} -- 2.9.3 _______________________________________________ Grub-devel mailing list Grub-devel@gnu.org https://lists.gnu.org/mailman/listinfo/grub-devel