diff --git a/grub-core/Makefile.core.def b/grub-core/Makefile.core.def index 5e12f1ace..a084b4110 100644 --- a/grub-core/Makefile.core.def +++ b/grub-core/Makefile.core.def @@ -821,6 +821,13 @@ module = { enable = x86_64_efi; }; +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 000000000..5a829f5e4 --- /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 . + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +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