All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v1 2/2] core: commands: efi: add commands to get/set EFI vars
@ 2020-05-07  8:34 Flavio Suligoi
  0 siblings, 0 replies; only message in thread
From: Flavio Suligoi @ 2020-05-07  8:34 UTC (permalink / raw)
  To: The development of GNU GRUB; +Cc: Flavio Suligoi

Sometimes, using a GRUB boot script (i.e. grub.cfg), it is very important
to get/set an EFI variable, especially in embedded systems, to detect
some custom BIOS features.
For example, based on the content of some EFI variables, a script can decide
to boot a special kernel instead of the usual kernel, or add some custom boot
parameters to the kernel command line, etc.

This patch add two useful commands:

- efivar_get
- efivar_set

to get/set an EFI variable.

The "get" function can display the EFI variable in ASCII or in HEX+ASCII
mode (like the Linux command "hexdump"), while the "set" function can set the
EFI variable in ASCII mode only.

As GUID, the default GUID used is the standard EFI_GLOBAL_VARIABLE_GUID,
but it is possible to use any other GUID (standard or custom) using an
environment variable.

Example: set the EFI variable "Configuration"" to the ASCII value ‘Board_special
version 1.0.0’, with the following custom GUID:

‘Configuration-a87cb185-864c-4683-a93e-3666ad3cf6b6’

grub> set guid_used=a87cb185-864c-4683-a93e-3666ad3cf6b6
grub>
grub> efivar_set -g guid_used Configuration "Board_special version 1.0.0"
grub>
grub> efivar_get -g guid_used -xv Configuration
Configuration-a87cb185-864c-4683-a93e-3666ad3cf6b6 :

0000 - 42 6f 61 72 64 5f 73 70 65 63 69 61 6c 20 76 65 |Board_special ve|
0010 - 72 73 69 6f 6e 20 31 2e 30 2e 30 00             |rsion 1.0.0.    |

-----
Usage
-----

Usage: efivar_get [OPTIONS] VAR

Read EFI VAR variable (if not specified, use EFI_GLOBAL_VARIABLE_GUID as
default GUID: {8be4df61-93ca-11d2-aa0d-00e098032b8c}).
If --set is specified, the version is set to a variable.

-s, --set=VARNAME       Assign return value to variable VARNAME.
-g, --guid-var=GUIDVARNAME   Use the content of GUIDVARNAME as GUID
-x, --hexdump           Display EFI variable content in hex mode
-v, --verbose           Display more info about EFI variable.
-h, --help              Display this help and exit.
-u, --usage             Display the usage of this command and exit.

Usage: efivar_set [OPTIONS] VAR VALUE

Write VALUE to EFI variable VAR (if not specified, use EFI_GLOBAL_VARIABLE_GUID
as default GUID:{8be4df61-93ca-11d2-aa0d-00e098032b8c}).
If --set is specified, the same EFI variable value is set to a variable.
If --non-volatile is specified, the non-volatile EFI attribute is set.

Note: an existing EFI variable can be changed only maintainig the same
volatile/non-volatile attribute.

-s, --set=VARNAME       Assign the same EFI variable value to variable
VARNAME.
-g, --guid-var=GUIDVARNAME   Use the content of GUIDVARNAME as GUID
-n, --non-volatile      Set non-volatile attribute.
-v, --verbose           Display more info about EFI variable
-h, --help              Display this help and exit.
-u, --usage             Display the usage of this command and exit.

Signed-off-by: Flavio Suligoi <f.suligoi@asem.it>
---

Changes in v1: fix bug in grub-core/Makefile.core.def

 docs/grub.texi                          | 137 +++++++++++++++
 grub-core/Makefile.core.def             |   6 +
 grub-core/commands/efi/efivar_get_set.c | 288 ++++++++++++++++++++++++++++++++
 grub-core/kern/efi/efi.c                |  57 +++++++
 include/grub/efi/efi.h                  |   4 +
 5 files changed, 492 insertions(+)
 create mode 100644 grub-core/commands/efi/efivar_get_set.c

diff --git a/docs/grub.texi b/docs/grub.texi
index d6408d2..ee59079 100644
--- a/docs/grub.texi
+++ b/docs/grub.texi
@@ -3978,6 +3978,8 @@ you forget a command, you can run the command @command{help}
 * distrust::                    Remove a pubkey from trusted keys
 * drivemap::                    Map a drive to another
 * echo::                        Display a line of text
+* efivar_get::                  Get EFI variable
+* efivar_set::                  Set EFI variable
 * eval::                        Evaluate agruments as GRUB commands
 * export::                      Export an environment variable
 * false::                       Do nothing, unsuccessfully
@@ -4397,6 +4399,141 @@ character will print that character.
 @end deffn
 
 
+@node efivar_get
+@subsection efivar_get
+@deffn Command efivar_get [@option{--set} var] [@option{--guid-var} guidvarname] [@option{--hexdump}] [@option{--verbose}] efivar
+Get and display an EFI variable @var{efivar} in ASCII or hex+ASCII format.
+
+The EFI GUID can be loaded from an environment variable, using the option
+@option{--guid-var @var{guidvarname}}. If this option is not used and
+consequently no GUID is specified, the GUID:
+
+
+@center EFI_GLOBAL_VARIABLE_GUID = 8be4df61-93ca-11d2-aa0d-00e098032b8c
+
+is implicitly assumed.
+
+If the option @option{--set @var{var}} is specified, store the EFI variable to
+the environment variable @var{var} instead of printing it.
+
+If the option @option{--hexdump} is specified, the output is in hexdecimal
+format.
+
+The option @option{--verbose} improve the data information output.
+
+@emph{Example:} read the EFI variable:
+
+@center @samp{PlatformInfo-19ad5244-fd6b-4e5c-826a-414646d6da6a}
+
+@smallexample
+grub> set guid_used=19ad5244-fd6b-4e5c-826a-414646d6da6a
+grub> efivar_get -g guid_used -xv PlatformInfo
+PlatformInfo-19ad5244-fd6b-4e5c-826a-414646d6da6a :
+
+0000 - 00 00 e2 00 00 00 00 00 00 00 00 00 f0 5a 0d 00   |.............Z..|
+0010 - 00 00 00 00 00 00 00 00 00 a8 ff ff ff df 00 00   |................|
+0020 - 00 00 0f 00 00 00 ff ff ff ff 0f 00 00 00 00 00   |................|
+0030 - 00 e0 00 00 00 00 00 00 00 04 00 01 24 00 00 00   |............$...|
+0040 - 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00   |................|
+0050 - 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00   |................|
+0060 - 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00   |................|
+0070 - 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00   |................|
+0080 - 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00   |................|
+0090 - 00 00 00 00 00 00 00 00 00 00 00 00 00 00 a8 00   |................|
+00a0 - 00 00 a8 00 00 00 00 00 00 c0 a0 ef 7a 00 80 01   |............z...|
+00b0 - 00 00 00 f9 ff ff 8b 0d 9c f9 ff ff c1 e9 02 00   |................|
+00c0 - 00 00 00 0f 00 00 00 00 00 00 00 10 00 00 00 d0   |................|
+00d0 - e6 80 eb 80 05 01 00 00 00 00 00 00 00 00 00 00   |................|
+00e0 - 00 00 00 00 00 00 00 00 01 86 80 34 12 00 00 49   |...........4...I|
+00f0 - 4e 54 45 4c 20 20 20 45 44 4b 32 20 20 20 20 00   |NTEL   EDK2    .|
+0100 - 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00   |................|
+0110 - 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00   |................|
+0120 - 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00   |................|
+0130 - 00 00 00 00 00 00 00 00 00 00 30 32 b7 7a c8 3a   |..........02.z.:|
+0140 - b7 7a b0 34 b7 7a 88 3e b7 7a 00 00 00 00 00 00   |.z.4.z.>.z......|
+0150 - 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00   |................|
+0160 - 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00   |................|
+0170 - 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00   |................|
+0180 - 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00   |................|
+0190 - 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00   |................|
+01a0 - 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00   |................|
+01b0 - 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00   |................|
+01c0 - 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00   |................|
+01d0 - 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00   |................|
+01e0 - 00 00 00 00 00 00 00 00 00 fc 8b 3d 98            |...........=.   |
+grub>
+@end smallexample
+
+
+@emph{Note:} in Linux, the dump of any EFI var in
+@file{/sys/firmware/efi/efivars} shows, before the variable data, also the
+4 bytes of the variable attributes. In GRUB, instead, a dump of any EFI variable
+shows the variable data only.
+
+@end deffn
+
+
+@node efivar_set
+@subsection efivar_set
+@deffn Command efivar_set [@option{--set} var] [@option{--guid-var} guidvarname] [@option{--non-volatile}] [@option{--verbose}] efivar value
+Set an EFI variable @var{efivar} with the value @var{value} in ASCII format.
+
+The EFI GUID can be loaded from an environment variable, using the option
+@option{--guid-var @var{guidvarname}}. If this option is not used and consequently
+no GUID is specified, the GUID:
+
+
+@center EFI_GLOBAL_VARIABLE_GUID = 8be4df61-93ca-11d2-aa0d-00e098032b8c
+
+is implicitly assumed.
+
+About the EFI variable attributes, the following attributes are set:
+@itemize @bullet
+@item
+GRUB_EFI_VARIABLE_BOOTSERVICE_ACCESS
+@item
+GRUB_EFI_VARIABLE_RUNTIME_ACCESS
+@end itemize
+If the option @option{--non-volatile} is give, the variable is also set with
+the attribute:
+@itemize @bullet
+@item
+GRUB_EFI_VARIABLE_NON_VOLATILE
+@end itemize
+In this way the variable will be stored in the board NVRAM.
+
+If the option @option{--set @var{var}} is specified, in addition to set the EFI
+variable with the value @var{value}, also store this value to the environment
+variable @var{var}.
+
+The option @option{--verbose} improve the data information output.
+
+@emph{Example:} set the EFI variable @var{Configuration} to the ASCII value
+@samp{Board_special version 1.0.0}, with the following
+custom GUID:
+
+@center @samp{Configuration-a87cb185-864c-4683-a93e-3666ad3cf6b6}
+
+@smallexample
+grub> set guid_used=a87cb185-864c-4683-a93e-3666ad3cf6b6
+grub> efivar_set -g guid_used Configuration "Board_special version 1.0.0"
+grub> efivar_get -g guid_used -xv Configuration
+Configuration-a87cb185-864c-4683-a93e-3666ad3cf6b6 :
+
+0000 - 42 6f 61 72 64 5f 73 70 65 63 69 61 6c 20 76 65   |Board_special ve|
+0010 - 72 73 69 6f 6e 20 31 2e 30 2e 30 00               |rsion 1.0.0.    |
+grub>
+@end smallexample
+
+
+@emph{Note:} in Linux, the dump of any EFI var in
+@file{/sys/firmware/efi/efivars} shows, before the variable data, also the
+4 bytes of the variable attributes. In GRUB, instead, a dump of any EFI variable
+shows the variable data only.
+
+@end deffn
+
+
 @node eval
 @subsection eval
 
diff --git a/grub-core/Makefile.core.def b/grub-core/Makefile.core.def
index 48b82e7..1fd872c 100644
--- a/grub-core/Makefile.core.def
+++ b/grub-core/Makefile.core.def
@@ -2534,3 +2534,9 @@ module = {
   common = commands/i386/wrmsr.c;
   enable = x86;
 };
+
+module = {
+  name = efivar_get_set;
+  common = commands/efi/efivar_get_set.c;
+  enable = efi;
+};
diff --git a/grub-core/commands/efi/efivar_get_set.c b/grub-core/commands/efi/efivar_get_set.c
new file mode 100644
index 0000000..f1d1cd9
--- /dev/null
+++ b/grub-core/commands/efi/efivar_get_set.c
@@ -0,0 +1,288 @@
+/* efivar_get_set.c - command to get/set an EFI variable  */
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 2020  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 <http://www.gnu.org/licenses/>.
+ */
+
+#include <grub/dl.h>
+#include <grub/command.h>
+#include <grub/misc.h>
+#include <grub/mm.h>
+#include <grub/env.h>
+#include <grub/extcmd.h>
+#include <grub/i18n.h>
+#include <grub/efi/api.h>
+#include <grub/efi/efi.h>
+
+GRUB_MOD_LICENSE ("GPLv3+");
+
+static const struct grub_arg_option options_efivar_rd[] =
+{
+  { "set", 's', 0, N_("Assign return value to variable VARNAME."),
+    N_("VARNAME"), ARG_TYPE_STRING },
+  { "guid-var", 'g', 0, N_("Use the content of GUIDVARNAME as GUID"),
+    N_("GUIDVARNAME"), ARG_TYPE_STRING },
+  {"hexdump", 'x', 0, N_("Display EFI variable content in hex mode"), 0, 0},
+  {"verbose", 'v', 0, N_("Display more info about EFI variable."), 0, 0},
+  { 0, 0, 0, 0, 0, 0 }
+};
+
+static const struct grub_arg_option options_efivar_wr[] =
+{
+  { "set", 's', 0, N_("Assign the same EFI variable value to variable VARNAME."),
+    N_("VARNAME"), ARG_TYPE_STRING },
+  { "guid-var", 'g', 0, N_("Use the content of GUIDVARNAME as GUID"),
+    N_("GUIDVARNAME"), ARG_TYPE_STRING },
+  { "non-volatile", 'n', 0, N_("Set non-volatile attribute."), 0, ARG_TYPE_NONE },
+  { "verbose", 'v', 0, N_("Display more info about EFI variable"), 0, 0},
+  { 0, 0, 0, 0, 0, 0 }
+};
+
+static void
+dump_efi_var_hex (void *efi_var, grub_size_t efi_var_data_size,
+                  grub_uint8_t verbose)
+{
+  #define DUMP_EFI_VAR_HEX_ROW_LEN  16
+  grub_uint32_t i, j;
+  grub_uint8_t *val = efi_var;
+
+  grub_printf ("\n");
+  for (i = 0; i <= (efi_var_data_size / DUMP_EFI_VAR_HEX_ROW_LEN) ; i++)
+    {
+      if (verbose)
+        grub_printf ("%04x - ", i * DUMP_EFI_VAR_HEX_ROW_LEN);
+
+      /* Print numerical values */
+      for (j = 0; j < DUMP_EFI_VAR_HEX_ROW_LEN; j++)
+        {
+          if ((i * DUMP_EFI_VAR_HEX_ROW_LEN + j) < efi_var_data_size)
+            {
+              grub_printf ("%02x", (unsigned int) val[i * DUMP_EFI_VAR_HEX_ROW_LEN + j]);
+            }
+          else
+            grub_printf ("  ");
+          if (verbose)
+            grub_printf (" ");
+        }
+
+      /* If verbose is active, print ASCII chars */
+      if (verbose)
+        {
+          grub_printf ("  |");
+          for (j = 0; j < DUMP_EFI_VAR_HEX_ROW_LEN; j++)
+            {
+              if ((i * DUMP_EFI_VAR_HEX_ROW_LEN + j) < efi_var_data_size)
+                {
+                  if (grub_isprint (val[i * DUMP_EFI_VAR_HEX_ROW_LEN + j]))
+                    grub_printf ("%c", (unsigned int) val[i * DUMP_EFI_VAR_HEX_ROW_LEN + j]);
+                  else
+                    grub_printf(".");
+                }
+              else
+                grub_printf(" ");
+            }
+          grub_printf ("|\n");
+        }
+    }
+}
+
+static void
+dump_efi_guid (char *efi_var_name, grub_efi_guid_t guid)
+{
+  grub_printf ("%s-%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x :\n",
+               efi_var_name,
+               (unsigned) guid.data1,
+               (unsigned) guid.data2,
+               (unsigned) guid.data3,
+               (unsigned) guid.data4[0],
+               (unsigned) guid.data4[1],
+               (unsigned) guid.data4[2],
+               (unsigned) guid.data4[3],
+               (unsigned) guid.data4[4],
+               (unsigned) guid.data4[5],
+               (unsigned) guid.data4[6],
+               (unsigned) guid.data4[7]);
+}
+
+static grub_err_t
+grub_cmd_efivar_get (grub_extcmd_context_t ctxt, int argc, char **args)
+{
+  void *efi_var = NULL;
+  grub_size_t efi_var_data_size = 0;
+  char *buf = 0;
+  grub_efi_guid_t guid = GRUB_EFI_GLOBAL_VARIABLE_GUID;
+  const char *guid_str;
+  grub_err_t err;
+
+  /* One argument required */
+  if (argc != 1)
+    return grub_error (GRUB_ERR_BAD_ARGUMENT,
+                       N_("one argument required: EFI variable name"));
+
+  /* Get GUID from env variable */
+  if (ctxt->state[1].set)
+    {
+      guid_str = grub_env_get (ctxt->state[1].arg);
+      if (guid_str)
+        {
+          err = grub_efi_str_to_guid (guid_str, &guid);
+          if (err)
+            return err;
+        }
+      else
+        return grub_error (GRUB_ERR_BAD_ARGUMENT,
+                             N_("GUID environment variable not found"));
+    }
+  else
+    grub_printf ("No custom GUID provided, use EFI_GLOBAL_VARIABLE_GUID.\n");
+
+  /* Get EFI variable */
+  efi_var = grub_efi_get_variable (args[0], &guid, &efi_var_data_size);
+  if (!efi_var || !efi_var_data_size)
+    return grub_error (GRUB_ERR_READ_ERROR, N_("cannot read EFI variable"));
+
+  /* Get EFI var data string */
+  buf = grub_malloc (efi_var_data_size * 2 + 1);
+  if (!buf)
+    return grub_errno;
+
+  /* Copy EFI variable data */
+  grub_strncpy (buf, efi_var, efi_var_data_size);
+
+  /* Set env variable required? */
+  if (ctxt->state[0].set)
+    grub_env_set (ctxt->state[0].arg, buf);
+  else
+    {
+      /* Verbose ? */
+      if (ctxt->state[3].set)
+        {
+          /* Print GUID */
+          dump_efi_guid (args[0], guid);
+
+          /* Hexdump ? */
+          if (ctxt->state[2].set)
+            dump_efi_var_hex(efi_var, efi_var_data_size, 1);
+          else
+            grub_printf ("%s", buf);
+        }
+      else
+        /* Hexdump ? */
+        if (ctxt->state[2].set)
+          dump_efi_var_hex(efi_var, efi_var_data_size, 0);
+        else
+          grub_printf ("%s", buf);
+    }
+
+  grub_free (buf);
+
+  return 0;
+}
+
+static grub_err_t
+grub_cmd_efivar_set (grub_extcmd_context_t ctxt, int argc, char **args)
+{
+  grub_err_t efi_err;
+  grub_efi_guid_t guid = GRUB_EFI_GLOBAL_VARIABLE_GUID;
+  const char *guid_str;
+  grub_efi_boolean_t non_volatile = 0;
+  grub_err_t err;
+
+  /* Two arguments required */
+  if (argc != 2)
+    return grub_error (GRUB_ERR_BAD_ARGUMENT,
+                       N_("two arguments required: EFI variable name and value"));
+
+  /* Get GUID from env variable */
+  if (ctxt->state[1].set)
+    {
+      guid_str = grub_env_get (ctxt->state[1].arg);
+      if (guid_str)
+        {
+          err = grub_efi_str_to_guid (guid_str, &guid);
+          if (err)
+            return err;
+        }
+      else
+        return grub_error (GRUB_ERR_BAD_ARGUMENT,
+                           N_("GUID environment variable not found"));
+    }
+  else
+    grub_printf ("No custom GUID provided, use EFI_GLOBAL_VARIABLE_GUID.\n");
+
+  /* Volatile or non-volatile ? */
+  if (ctxt->state[2].set)
+    non_volatile = 1;
+
+  /* Set EFI variable */
+  efi_err = grub_efi_set_variable (args[0], &guid, args[1],
+                                   (grub_size_t) grub_strlen(args[1]) + 1,
+                                   non_volatile);
+  if (efi_err != GRUB_ERR_NONE)
+    return grub_error (GRUB_ERR_WRITE_ERROR, N_("cannot write EFI variable"));
+
+  /* Set env variable required? */
+  if (ctxt->state[0].set)
+    grub_env_set (ctxt->state[0].arg, args[1]);
+
+  /* Verbose ? */
+  if (ctxt->state[3].set)
+    {
+      /* Print GUID */
+      dump_efi_guid (args[0], guid);
+
+      grub_printf("%s EFI variable: %s set to value: %s\n",
+                non_volatile ? "Non-volatile" : "volatile",
+                args[0], args[1]);
+    }
+  return 0;
+}
+
+static grub_extcmd_t cmd_rd_efi_var, cmd_wr_efi_var;
+
+GRUB_MOD_INIT(version)
+{
+  cmd_rd_efi_var = grub_register_extcmd ("efivar_get",
+                                         grub_cmd_efivar_get, 0,
+                                         N_("[OPTIONS] VAR"),
+                                         N_("\nRead EFI VAR variable (if not specified, use "
+                                            "EFI_GLOBAL_VARIABLE_GUID as default GUID: "
+                                            "{8be4df61-93ca-11d2-aa0d-00e098032b8c}).\n"
+                                            "If --set is specified, the version is set to a variable."
+                                           ),
+                                         options_efivar_rd);
+
+  cmd_wr_efi_var = grub_register_extcmd ("efivar_set",
+                                         grub_cmd_efivar_set, 0,
+                                         N_("[OPTIONS] VAR VALUE"),
+                                         N_("\nWrite VALUE to EFI variable VAR (if not specified, use "
+                                            "EFI_GLOBAL_VARIABLE_GUID as default GUID:"
+                                            "{8be4df61-93ca-11d2-aa0d-00e098032b8c}).\n"
+                                            "If --set is specified, the same EFI variable value "
+                                            "is set to a variable.\n"
+                                            "If --non-volatile is specified, the non-volatile "
+                                            "EFI attribute is set.\n"
+                                            "\nNote: an existing EFI variable can be changed only "
+                                            "maintainig the same volatile/non-volatile attribute."
+                                           ),
+                                         options_efivar_wr);
+}
+
+GRUB_MOD_FINI(version)
+{
+	grub_unregister_extcmd (cmd_rd_efi_var);
+	grub_unregister_extcmd (cmd_wr_efi_var);
+}
diff --git a/grub-core/kern/efi/efi.c b/grub-core/kern/efi/efi.c
index dcb09b2..5d7a8ed 100644
--- a/grub-core/kern/efi/efi.c
+++ b/grub-core/kern/efi/efi.c
@@ -960,3 +960,60 @@ grub_efi_compare_device_paths (const grub_efi_device_path_t *dp1,
 
   return 0;
 }
+
+/* Convert a GUID from string format to grub_efi_guid_t format.
+ * For example:
+ *
+ * 8be4df61-93ca-11d2-aa0d-00e098032b8c -->
+ *
+ * --> { 0x8BE4DF61, 0x93CA, 0x11d2, \
+ *       { 0xAA, 0x0D, 0x00, 0xE0, 0x98, 0x03, 0x2B, 0x8C }}
+*/
+grub_err_t
+grub_efi_str_to_guid(const char *guid_str, grub_efi_guid_t *guid)
+{
+  char guid_str_tmp[32];
+  unsigned int i;
+  union
+    {
+      grub_uint64_t octet_64;
+      grub_uint8_t octet_8[8];
+    } guid_octet;
+
+  /* Check string size */
+  if (grub_strlen(guid_str) != EFI_GUID_STRING_LENGTH)
+    return grub_error (GRUB_ERR_BAD_ARGUMENT,
+                       N_("GUID string must be %d chars long\n"),
+                       EFI_GUID_STRING_LENGTH);
+
+  /* Remove dashes for string check */
+  grub_snprintf (&guid_str_tmp[0],   9, "%s", guid_str);
+  grub_snprintf (&guid_str_tmp[8],   5, "%s", guid_str + 9);
+  grub_snprintf (&guid_str_tmp[12],  5, "%s", guid_str + 14);
+  grub_snprintf (&guid_str_tmp[16],  5, "%s", guid_str + 19);
+  grub_snprintf (&guid_str_tmp[20], 13, "%s", guid_str + 24);
+
+  /* Check for hex digit only */
+  for (i = 0; i < grub_strlen (guid_str_tmp); i++)
+    {
+      guid_str_tmp[i] = grub_tolower(guid_str_tmp[i]);
+
+      if (!(grub_isxdigit (guid_str_tmp[i]))) {
+
+         return grub_error (GRUB_ERR_BAD_ARGUMENT,
+                            N_("GUID string must be like the following: 8be4df61-93ca-11d2-aa0d-00e098032b8c"));
+      }
+    }
+
+  /* Convert from string to GUID */
+  guid->data1 = grub_strtoul (&guid_str[0],  NULL, 16);
+  guid->data2 = grub_strtoul (&guid_str[9],  NULL, 16);
+  guid->data3 = grub_strtoul (&guid_str[14], NULL, 16);
+  guid_octet.octet_64 = grub_strtoull (&guid_str_tmp[16], NULL, 16);
+  for (i = 0; i <= 7; i++)
+    {
+      guid->data4[i] = guid_octet.octet_8[7 - i];
+    }
+
+  return GRUB_ERR_NONE;
+}
\ No newline at end of file
diff --git a/include/grub/efi/efi.h b/include/grub/efi/efi.h
index 9b04150..dc87cc2 100644
--- a/include/grub/efi/efi.h
+++ b/include/grub/efi/efi.h
@@ -24,6 +24,8 @@
 #include <grub/dl.h>
 #include <grub/efi/api.h>
 
+#define EFI_GUID_STRING_LENGTH 36
+
 /* Functions.  */
 void *EXPORT_FUNC(grub_efi_locate_protocol) (grub_efi_guid_t *protocol,
 					     void *registration);
@@ -90,6 +92,8 @@ EXPORT_FUNC (grub_efi_compare_device_paths) (const grub_efi_device_path_t *dp1,
 extern void (*EXPORT_VAR(grub_efi_net_config)) (grub_efi_handle_t hnd, 
 						char **device,
 						char **path);
+grub_err_t
+EXPORT_FUNC(grub_efi_str_to_guid)(const char *guid_str, grub_efi_guid_t *guid);
 
 #if defined(__arm__) || defined(__aarch64__) || defined(__riscv)
 void *EXPORT_FUNC(grub_efi_get_firmware_fdt)(void);
-- 
2.7.4



^ permalink raw reply related	[flat|nested] only message in thread

only message in thread, other threads:[~2020-05-07  8:35 UTC | newest]

Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2020-05-07  8:34 [PATCH v1 2/2] core: commands: efi: add commands to get/set EFI vars Flavio Suligoi

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.