Hi. Are we still considering this? On Mon, Dec 14, 2015 at 11:17 AM, Ignat Korchagin <ig...@cloudflare.com> wrote:
> Sorry, pasted wrong file. Here is the correct one: > > diff --git a/grub-core/Makefile.core.def b/grub-core/Makefile.core.def > index 0cc40bb..aa7b927 100644 > --- a/grub-core/Makefile.core.def > +++ b/grub-core/Makefile.core.def > @@ -735,6 +735,12 @@ module = { > }; > > module = { > + name = efivar; > + efi = commands/efi/efivar.c; > + enable = efi; > +}; > + > +module = { > name = blocklist; > common = commands/blocklist.c; > }; > diff --git a/grub-core/commands/efi/efivar.c > b/grub-core/commands/efi/efivar.c > new file mode 100644 > index 0000000..7fe7bda > --- /dev/null > +++ b/grub-core/commands/efi/efivar.c > @@ -0,0 +1,236 @@ > +/* efivar.c - Read EFI global variables. */ > +/* > + * GRUB -- GRand Unified Bootloader > + * Copyright (C) 2015 Free Software Foundation, Inc. > + * Copyright (C) 2015 CloudFlare, 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/types.h> > +#include <grub/mm.h> > +#include <grub/misc.h> > +#include <grub/efi/api.h> > +#include <grub/efi/efi.h> > +#include <grub/extcmd.h> > +#include <grub/env.h> > +#include <grub/lib/hexdump.h> > + > +GRUB_MOD_LICENSE ("GPLv3+"); > + > +static const struct grub_arg_option options[] = { > + {"format", 'f', GRUB_ARG_OPTION_OPTIONAL, N_("Parse EFI_VAR in > specific format (hex, uint8, ascii, dump). Default: hex."), > N_("FORMAT"), ARG_TYPE_STRING}, > + {"set", 's', GRUB_ARG_OPTION_OPTIONAL, N_("Save parsed result to > environment variable (does not work with dump)."), N_("ENV_VAR"), > ARG_TYPE_STRING}, > + {0, 0, 0, 0, 0, 0} > +}; > + > +enum efi_var_type > + { > + EFI_VAR_ASCII = 0, > + EFI_VAR_UINT8, > + EFI_VAR_HEX, > + EFI_VAR_DUMP, > + EFI_VAR_INVALID = -1 > + }; > + > +static enum efi_var_type > +parse_efi_var_type (const char *type) > +{ > + if (!grub_strcmp (type, "ascii")) > + return EFI_VAR_ASCII; > + > + if (!grub_strcmp (type, "uint8")) > + return EFI_VAR_UINT8; > + > + if (!grub_strcmp (type, "hex")) > + return EFI_VAR_HEX; > + > + if (!grub_strcmp (type, "dump")) > + return EFI_VAR_DUMP; > + > + return EFI_VAR_INVALID; > +} > + > +static int > +grub_print_ascii (char *str, char c) > +{ > + if (grub_iscntrl (c)) > + { > + switch (c) > + { > + case '\0': > + str[0] = '\\'; > + str[1] = '0'; > + return 2; > + > + case '\a': > + str[0] = '\\'; > + str[1] = 'a'; > + return 2; > + > + case '\b': > + str[0] = '\\'; > + str[1] = 'b'; > + return 2; > + > + case '\f': > + str[0] = '\\'; > + str[1] = 'f'; > + return 2; > + > + case '\n': > + str[0] = '\\'; > + str[1] = 'n'; > + return 2; > + > + case '\r': > + str[0] = '\\'; > + str[1] = 'r'; > + return 2; > + > + case '\t': > + str[0] = '\\'; > + str[1] = 't'; > + return 2; > + > + case '\v': > + str[0] = '\\'; > + str[1] = 'v'; > + return 2; > + > + default: > + str[0] = '.'; /* as in hexdump -C */ > + return 1; > + } > + } > + > + str[0] = c; > + return 1; > +} > + > +static grub_err_t > +grub_cmd_get_efi_var (struct grub_extcmd_context *ctxt, > + int argc, char **args) > +{ > + struct grub_arg_list *state = ctxt->state; > + grub_err_t status; > + void *efi_var = NULL; > + grub_size_t efi_var_size = 0; > + enum efi_var_type efi_type = EFI_VAR_HEX; > + grub_efi_guid_t global = GRUB_EFI_GLOBAL_VARIABLE_GUID; > + char *env_var = NULL; > + grub_size_t i; > + char *ptr; > + > + if (1 != argc) > + return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("one argument > expected")); > + > + if (state[0].set) > + efi_type = parse_efi_var_type (state[0].arg); > + > + if (EFI_VAR_INVALID == efi_type) > + return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("invalid format > specifier")); > + > + efi_var = grub_efi_get_variable (args[0], &global, &efi_var_size); > + if (!efi_var || !efi_var_size) > + { > + status = grub_error (GRUB_ERR_READ_ERROR, N_("cannot read > variable")); > + goto err; > + } > + > + switch (efi_type) > + { > + case EFI_VAR_ASCII: > + env_var = grub_malloc (efi_var_size * 2 + 1); > + if (!env_var) > + { > + status = grub_error (GRUB_ERR_OUT_OF_MEMORY, N_("out of > memory")); > + goto err; > + } > + > + ptr = env_var; > + > + for (i = 0; i < efi_var_size; i++) > + ptr += grub_print_ascii (ptr, ((const char *)efi_var)[i]); > + *ptr = '\0'; > + break; > + > + case EFI_VAR_UINT8: > + env_var = grub_malloc (4); > + if (!env_var) > + { > + status = grub_error (GRUB_ERR_OUT_OF_MEMORY, N_("out of > memory")); > + goto err; > + } > + grub_snprintf (env_var, 4, "%u", *((grub_uint8_t *)efi_var)); > + break; > + > + case EFI_VAR_HEX: > + env_var = grub_malloc (efi_var_size * 2 + 1); > + if (!env_var) > + { > + status = grub_error (GRUB_ERR_OUT_OF_MEMORY, N_("out of > memory")); > + goto err; > + } > + for (i = 0; i < efi_var_size; i++) > + grub_snprintf (env_var + (i * 2), 3, "%02x", ((grub_uint8_t > *)efi_var)[i]); > + break; > + > + case EFI_VAR_DUMP: > + if (state[1].set) > + status = grub_error (GRUB_ERR_BAD_ARGUMENT, N_("cannot set > variable with dump format specifier")); > + else > + { > + hexdump (0, (char *)efi_var, efi_var_size); > + status = GRUB_ERR_NONE; > + } > + break; > + > + default: > + status = grub_error (GRUB_ERR_BUG, N_("should not happen (bug > in module?)")); > + goto err; > + } > + > + if (efi_type != EFI_VAR_DUMP) > + { > + if (state[1].set) > + status = grub_env_set (state[1].arg, env_var); > + else > + { > + grub_printf ("%s\n", (const char *)env_var); > + status = GRUB_ERR_NONE; > + } > + } > + > +err: > + > + grub_free (env_var); > + grub_free (efi_var); > + > + return status; > +} > + > +static grub_extcmd_t cmd = NULL; > + > +GRUB_MOD_INIT (efivar) > +{ > + cmd = grub_register_extcmd ("get_efivar", grub_cmd_get_efi_var, 0, > N_("[-f FORMAT] [-s ENV_VAR] EFI_VAR"), > + N_("Read EFI variable and print it or save its contents to > environment variable."), options); > +} > + > +GRUB_MOD_FINI (efivar) > +{ > + if (cmd) > + grub_unregister_extcmd (cmd); > +} > > > On Mon, Dec 14, 2015 at 11:08 AM, Ignat Korchagin <ig...@cloudflare.com> > wrote: > >> Assuming uint8 remains - should not you check that variable size is > exactly 1 byte in this case? > > There are reports of a buggy firmware returning 4 bytes size for uint8 > > variables, however did not encounter them myself. > > > >> Do we really need unit8 at all? "hex" already provides exactly the same > functionality, not? Do you think there are cases when uint8 is really > required? > > Well, when checking for SecureBoot variable in grub configuration file > > hex mode makes it look weird and creates a point of confusion. For > > example to check if SecureBoot (suppose the result of the our command > > is stored in secure_boot env variable in hex mode) is enabled one > > should write: > > if [ secure_boot = "01" ] > > ... > > uint8 just allows to do a more straightforward config > > if [ secure_boot = 1] - this case would be false for hex mode - > > possible security breach > > ... > > > > Added goto err in the module as pointed, see patch below. I will do a > > follow-up patch for documentation once we get this confirmed. > > > > diff --git a/grub-core/Makefile.core.def b/grub-core/Makefile.core.def > > index 0cc40bb..aa7b927 100644 > > --- a/grub-core/Makefile.core.def > > +++ b/grub-core/Makefile.core.def > > @@ -735,6 +735,12 @@ module = { > > }; > > > > module = { > > + name = efivar; > > + efi = commands/efi/efivar.c; > > + enable = efi; > > +}; > > + > > +module = { > > name = blocklist; > > common = commands/blocklist.c; > > }; > > diff --git a/grub-core/commands/efi/efivar.c > b/grub-core/commands/efi/efivar.c > > new file mode 100644 > > index 0000000..7f5a957 > > --- /dev/null > > +++ b/grub-core/commands/efi/efivar.c > > @@ -0,0 +1,251 @@ > > +/* efivar.c - Read EFI global variables. */ > > +/* > > + * GRUB -- GRand Unified Bootloader > > + * Copyright (C) 2015 Free Software Foundation, Inc. > > + * Copyright (C) 2015 CloudFlare, 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/types.h> > > +#include <grub/mm.h> > > +#include <grub/misc.h> > > +#include <grub/efi/api.h> > > +#include <grub/efi/efi.h> > > +#include <grub/extcmd.h> > > +#include <grub/env.h> > > +#include <grub/lib/hexdump.h> > > + > > +GRUB_MOD_LICENSE ("GPLv3+"); > > + > > +static const struct grub_arg_option options[] = { > > + {"format", 'f', GRUB_ARG_OPTION_OPTIONAL, N_("Parse EFI_VAR in > > specific format (hex, uint8, ascii, raw, dump). Default: hex."), > > N_("FORMAT"), ARG_TYPE_STRING}, > > + {"set", 's', GRUB_ARG_OPTION_OPTIONAL, N_("Save parsed result to > > environment variable (does not work with dump)."), N_("ENV_VAR"), > > ARG_TYPE_STRING}, > > + {0, 0, 0, 0, 0, 0} > > +}; > > + > > +enum efi_var_type > > + { > > + EFI_VAR_ASCII = 0, > > + EFI_VAR_RAW, > > + EFI_VAR_UINT8, > > + EFI_VAR_HEX, > > + EFI_VAR_DUMP, > > + EFI_VAR_INVALID = -1 > > + }; > > + > > +static enum efi_var_type > > +parse_efi_var_type (const char *type) > > +{ > > + if (!grub_strncmp (type, "ascii", sizeof("ascii"))) > > + return EFI_VAR_ASCII; > > + > > + if (!grub_strncmp (type, "raw", sizeof("raw"))) > > + return EFI_VAR_ASCII; > > + > > + if (!grub_strncmp (type, "uint8", sizeof("uint8"))) > > + return EFI_VAR_UINT8; > > + > > + if (!grub_strncmp (type, "hex", sizeof("hex"))) > > + return EFI_VAR_HEX; > > + > > + if (!grub_strncmp (type, "dump", sizeof("dump"))) > > + return EFI_VAR_DUMP; > > + > > + return EFI_VAR_INVALID; > > +} > > + > > +static int > > +grub_print_ascii (char *str, char c) > > +{ > > + if (grub_iscntrl (c)) > > + { > > + switch (c) > > + { > > + case '\0': > > + str[0] = '\\'; > > + str[1] = '0'; > > + return 2; > > + > > + case '\a': > > + str[0] = '\\'; > > + str[1] = 'a'; > > + return 2; > > + > > + case '\b': > > + str[0] = '\\'; > > + str[1] = 'b'; > > + return 2; > > + > > + case '\f': > > + str[0] = '\\'; > > + str[1] = 'f'; > > + return 2; > > + > > + case '\n': > > + str[0] = '\\'; > > + str[1] = 'n'; > > + return 2; > > + > > + case '\r': > > + str[0] = '\\'; > > + str[1] = 'r'; > > + return 2; > > + > > + case '\t': > > + str[0] = '\\'; > > + str[1] = 't'; > > + return 2; > > + > > + case '\v': > > + str[0] = '\\'; > > + str[1] = 'v'; > > + return 2; > > + > > + default: > > + str[0] = '.'; /* as in hexdump -C */ > > + return 1; > > + } > > + } > > + > > + str[0] = c; > > + return 1; > > +} > > + > > +static grub_err_t > > +grub_cmd_get_efi_var (struct grub_extcmd_context *ctxt, > > + int argc, char **args) > > +{ > > + struct grub_arg_list *state = ctxt->state; > > + grub_err_t status; > > + void *efi_var = NULL; > > + grub_size_t efi_var_size = 0; > > + enum efi_var_type efi_type = EFI_VAR_HEX; > > + grub_efi_guid_t global = GRUB_EFI_GLOBAL_VARIABLE_GUID; > > + char *env_var = NULL; > > + grub_size_t i; > > + char *ptr; > > + > > + if (1 != argc) > > + return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("one argument > expected")); > > + > > + if (state[0].set) > > + efi_type = parse_efi_var_type (state[0].arg); > > + > > + if (EFI_VAR_INVALID == efi_type) > > + return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("invalid format > specifier")); > > + > > + efi_var = grub_efi_get_variable (args[0], &global, &efi_var_size); > > + if (!efi_var || !efi_var_size) > > + { > > + status = grub_error (GRUB_ERR_READ_ERROR, N_("cannot read > variable")); > > + goto err; > > + } > > + > > + switch (efi_type) > > + { > > + case EFI_VAR_ASCII: > > + env_var = grub_malloc (efi_var_size * 2 + 1); > > + if (!env_var) > > + { > > + status = grub_error (GRUB_ERR_OUT_OF_MEMORY, N_("out of > memory")); > > + goto err; > > + } > > + > > + ptr = env_var; > > + > > + for (i = 0; i < efi_var_size; i++) > > + ptr += grub_print_ascii (ptr, ((const char *)efi_var)[i]); > > + *ptr = '\0'; > > + break; > > + > > + case EFI_VAR_RAW: > > + env_var = grub_malloc (efi_var_size + 1); > > + if (!env_var) > > + { > > + status = grub_error (GRUB_ERR_OUT_OF_MEMORY, N_("out of > memory")); > > + goto err; > > + } > > + grub_memcpy (env_var, efi_var, efi_var_size); > > + env_var[efi_var_size] = '\0'; > > + break; > > + > > + case EFI_VAR_UINT8: > > + env_var = grub_malloc (4); > > + if (!env_var) > > + { > > + status = grub_error (GRUB_ERR_OUT_OF_MEMORY, N_("out of > memory")); > > + goto err; > > + } > > + grub_snprintf (env_var, 4, "%u", *((grub_uint8_t *)efi_var)); > > + break; > > + > > + case EFI_VAR_HEX: > > + env_var = grub_malloc (efi_var_size * 2 + 1); > > + if (!env_var) > > + { > > + status = grub_error (GRUB_ERR_OUT_OF_MEMORY, N_("out of > memory")); > > + goto err; > > + } > > + for (i = 0; i < efi_var_size; i++) > > + grub_snprintf (env_var + (i * 2), 3, "%02x", ((grub_uint8_t > > *)efi_var)[i]); > > + break; > > + > > + case EFI_VAR_DUMP: > > + if (state[1].set) > > + status = grub_error (GRUB_ERR_BAD_ARGUMENT, N_("cannot set > > variable with dump format specifier")); > > + else > > + { > > + hexdump (0, (char *)efi_var, efi_var_size); > > + status = GRUB_ERR_NONE; > > + } > > + break; > > + > > + default: > > + status = grub_error (GRUB_ERR_BUG, N_("should not happen (bug > > in module?)")); > > + goto err; > > + } > > + > > + if (efi_type != EFI_VAR_DUMP) > > + { > > + if (state[1].set) > > + status = grub_env_set (state[1].arg, env_var); > > + else > > + { > > + grub_printf ("%s\n", (const char *)env_var); > > + status = GRUB_ERR_NONE; > > + } > > + } > > + > > +err: > > + > > + grub_free (env_var); > > + grub_free (efi_var); > > + > > + return status; > > +} > > + > > +static grub_extcmd_t cmd = NULL; > > + > > +GRUB_MOD_INIT (efivar) > > +{ > > + cmd = grub_register_extcmd ("get_efivar", grub_cmd_get_efi_var, 0, > > N_("[-f FORMAT] [-s ENV_VAR] EFI_VAR"), > > + N_("Read EFI variable and print it or save its contents to > > environment variable."), options); > > +} > > + > > +GRUB_MOD_FINI (efivar) > > +{ > > + if (cmd) > > + grub_unregister_extcmd (cmd); > > +} >
_______________________________________________ Grub-devel mailing list Grub-devel@gnu.org https://lists.gnu.org/mailman/listinfo/grub-devel