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

Reply via email to