[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[PATCH 2/2] core: commands: efi: add commands to get/set EFI vars
From: |
Flavio Suligoi |
Subject: |
[PATCH 2/2] core: commands: efi: add commands to get/set EFI vars |
Date: |
Wed, 29 Apr 2020 16:54:10 +0200 |
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 <address@hidden>
---
docs/grub.texi | 137 +++++++++++++++
grub-core/Makefile.core.def | 5 +
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, 491 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..12535ba 100644
--- a/grub-core/Makefile.core.def
+++ b/grub-core/Makefile.core.def
@@ -2534,3 +2534,8 @@ module = {
common = commands/i386/wrmsr.c;
enable = x86;
};
+
+module = {
+ name = efivar_get_set;
+ common = commands/efi/efivar_get_set.c;
+};
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