grub2/0163-Add-efi-export-env-and-efi-load-env-commands.patch
Javier Martinez Canillas e1531466e1
Update to grub 2.04
This change updates grub to the 2.04 release. The new release changed how
grub is built, so the bootstrap and bootstrap.conf files have to be added
to the dist-git. Also, the gitignore file changed so it has to be updated.

Since the patches have been forward ported to 2.04, there's no need for a
logic to maintain a patch with the delta between the release and the grub
master branch. So the release-to-master.patch is dropped and no longer is
updated by the do-rebase script.

Also since gnulib isn't part of the grub repository anymore and cloned by
the boostrap tool, a gnulib tarball is included as other source file and
copied before calling the bootstrap tool. That way grub can be built even
in builders that only have access to the sources lookaside cache.

Resolves: rhbz#1727279

Signed-off-by: Javier Martinez Canillas <javierm@redhat.com>
2019-08-15 08:04:53 +02:00

361 lines
10 KiB
Diff

From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Peter Jones <pjones@redhat.com>
Date: Wed, 16 Jan 2019 13:21:46 -0500
Subject: [PATCH] Add efi-export-env and efi-load-env commands
This adds "efi-export-env VARIABLE" and "efi-load-env", which manipulate the
environment block stored in the EFI variable
GRUB_ENV-91376aff-cba6-42be-949d-06fde81128e8.
Signed-off-by: Peter Jones <pjones@redhat.com>
---
grub-core/Makefile.core.def | 6 ++
grub-core/commands/efi/env.c | 168 +++++++++++++++++++++++++++++++++++++++++++
grub-core/kern/efi/efi.c | 3 +
grub-core/kern/efi/init.c | 5 --
grub-core/lib/envblk.c | 43 +++++++++++
util/editenv.c | 2 -
util/grub-set-bootflag.c | 1 +
include/grub/efi/efi.h | 5 ++
include/grub/lib/envblk.h | 3 +
9 files changed, 229 insertions(+), 7 deletions(-)
create mode 100644 grub-core/commands/efi/env.c
diff --git a/grub-core/Makefile.core.def b/grub-core/Makefile.core.def
index 65ca74f9ad9..661994686e6 100644
--- a/grub-core/Makefile.core.def
+++ b/grub-core/Makefile.core.def
@@ -817,6 +817,12 @@ module = {
enable = efi;
};
+module = {
+ name = efienv;
+ common = commands/efi/env.c;
+ enable = efi;
+};
+
module = {
name = efifwsetup;
efi = commands/efi/efifwsetup.c;
diff --git a/grub-core/commands/efi/env.c b/grub-core/commands/efi/env.c
new file mode 100644
index 00000000000..a69079786aa
--- /dev/null
+++ b/grub-core/commands/efi/env.c
@@ -0,0 +1,168 @@
+/*
+ * GRUB -- GRand Unified Bootloader
+ * Copyright (C) 2012 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/mm.h>
+#include <grub/misc.h>
+#include <grub/types.h>
+#include <grub/mm.h>
+#include <grub/misc.h>
+#include <grub/efi/api.h>
+#include <grub/efi/efi.h>
+#include <grub/env.h>
+#include <grub/lib/envblk.h>
+#include <grub/command.h>
+
+GRUB_MOD_LICENSE ("GPLv3+");
+
+static const grub_efi_guid_t grub_env_guid = GRUB_EFI_GRUB_VARIABLE_GUID;
+
+static grub_err_t
+grub_efi_export_env(grub_command_t cmd __attribute__ ((unused)),
+ int argc, char *argv[])
+{
+ const char *value;
+ char *old_value;
+ struct grub_envblk envblk_s = { NULL, 0 };
+ grub_envblk_t envblk = &envblk_s;
+ grub_err_t err;
+ int changed = 1;
+ grub_efi_status_t status;
+
+ grub_dprintf ("efienv", "argc:%d\n", argc);
+ for (int i = 0; i < argc; i++)
+ grub_dprintf ("efienv", "argv[%d]: %s\n", i, argv[i]);
+
+ if (argc != 1)
+ return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("variable name expected"));
+
+ envblk_s.buf = grub_efi_get_variable ("GRUB_ENV", &grub_env_guid,
+ &envblk_s.size);
+ if (!envblk_s.buf || envblk_s.size < 1)
+ {
+ char *buf = grub_malloc (1025);
+ if (!buf)
+ return grub_errno;
+
+ grub_memcpy (buf, GRUB_ENVBLK_SIGNATURE, sizeof (GRUB_ENVBLK_SIGNATURE) - 1);
+ grub_memset (buf + sizeof (GRUB_ENVBLK_SIGNATURE) - 1, '#',
+ DEFAULT_ENVBLK_SIZE - sizeof (GRUB_ENVBLK_SIGNATURE) + 1);
+ buf[1024] = '\0';
+
+ envblk_s.buf = buf;
+ envblk_s.size = 1024;
+ }
+ else
+ {
+ char *buf = grub_realloc (envblk_s.buf, envblk_s.size + 1);
+ if (!buf)
+ return grub_errno;
+
+ envblk_s.buf = buf;
+ envblk_s.buf[envblk_s.size] = '\0';
+ }
+
+ err = grub_envblk_get(envblk, argv[0], &old_value);
+ if (err != GRUB_ERR_NONE)
+ {
+ grub_dprintf ("efienv", "grub_envblk_get returned %d\n", err);
+ return err;
+ }
+
+ value = grub_env_get(argv[0]);
+ if ((!value && !old_value) ||
+ (value && old_value && !grub_strcmp(old_value, value)))
+ changed = 0;
+
+ if (old_value)
+ grub_free(old_value);
+
+ if (changed == 0)
+ {
+ grub_dprintf ("efienv", "No changes necessary\n");
+ return 0;
+ }
+
+ if (value)
+ {
+ grub_dprintf ("efienv", "setting \"%s\" to \"%s\"\n", argv[0], value);
+ grub_envblk_set(envblk, argv[0], value);
+ }
+ else
+ {
+ grub_dprintf ("efienv", "deleting \"%s\" from envblk\n", argv[0]);
+ grub_envblk_delete(envblk, argv[0]);
+ }
+
+ grub_dprintf ("efienv", "envblk is %lu bytes:\n\"%s\"\n", envblk_s.size, envblk_s.buf);
+
+ grub_dprintf ("efienv", "removing GRUB_ENV\n");
+ status = grub_efi_set_variable ("GRUB_ENV", &grub_env_guid, NULL, 0);
+ if (status != GRUB_EFI_SUCCESS)
+ grub_dprintf ("efienv", "removal returned %ld\n", status);
+
+ grub_dprintf ("efienv", "setting GRUB_ENV\n");
+ status = grub_efi_set_variable ("GRUB_ENV", &grub_env_guid,
+ envblk_s.buf, envblk_s.size);
+ if (status != GRUB_EFI_SUCCESS)
+ grub_dprintf ("efienv", "setting GRUB_ENV returned %ld\n", status);
+
+ return 0;
+}
+
+static int
+set_var (const char *name, const char *value,
+ void *whitelist __attribute__((__unused__)))
+{
+ grub_env_set (name, value);
+ return 0;
+}
+
+static grub_err_t
+grub_efi_load_env(grub_command_t cmd __attribute__ ((unused)),
+ int argc, char *argv[] __attribute__((__unused__)))
+{
+ struct grub_envblk envblk_s = { NULL, 0 };
+ grub_envblk_t envblk = &envblk_s;
+
+ envblk_s.buf = grub_efi_get_variable ("GRUB_ENV", &grub_env_guid,
+ &envblk_s.size);
+ if (!envblk_s.buf || envblk_s.size < 1)
+ return 0;
+
+ if (argc > 0)
+ return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("unexpected argument"));
+
+ grub_envblk_iterate (envblk, NULL, set_var);
+ grub_free (envblk_s.buf);
+}
+
+static grub_command_t export_cmd, loadenv_cmd;
+
+GRUB_MOD_INIT(lsefi)
+{
+ export_cmd = grub_register_command ("efi-export-env", grub_efi_export_env,
+ N_("VARIABLE_NAME"), N_("Export environment variable to UEFI."));
+ loadenv_cmd = grub_register_command ("efi-load-env", grub_efi_load_env,
+ NULL, N_("Load the grub environment from UEFI."));
+}
+
+GRUB_MOD_FINI(lsefi)
+{
+ grub_unregister_command (export_cmd);
+ grub_unregister_command (loadenv_cmd);
+}
diff --git a/grub-core/kern/efi/efi.c b/grub-core/kern/efi/efi.c
index ada3004cfba..279394d85eb 100644
--- a/grub-core/kern/efi/efi.c
+++ b/grub-core/kern/efi/efi.c
@@ -224,6 +224,9 @@ grub_efi_set_variable(const char *var, const grub_efi_guid_t *guid,
if (status == GRUB_EFI_SUCCESS)
return GRUB_ERR_NONE;
+ if (status == GRUB_EFI_NOT_FOUND && datasize == 0)
+ return GRUB_ERR_NONE;
+
return grub_error (GRUB_ERR_IO, "could not set EFI variable `%s'", var);
}
diff --git a/grub-core/kern/efi/init.c b/grub-core/kern/efi/init.c
index e6183a4c44d..d1afa3af11e 100644
--- a/grub-core/kern/efi/init.c
+++ b/grub-core/kern/efi/init.c
@@ -29,11 +29,6 @@
grub_addr_t grub_modbase;
-#define GRUB_EFI_GRUB_VARIABLE_GUID \
- { 0x91376aff, 0xcba6, 0x42be, \
- { 0x94, 0x9d, 0x06, 0xfd, 0xe8, 0x11, 0x28, 0xe8 } \
- }
-
/* Helper for grub_efi_env_init */
static int
set_var (const char *name, const char *value,
diff --git a/grub-core/lib/envblk.c b/grub-core/lib/envblk.c
index 230e0e9d9ab..f89d86d4e8d 100644
--- a/grub-core/lib/envblk.c
+++ b/grub-core/lib/envblk.c
@@ -223,6 +223,49 @@ grub_envblk_delete (grub_envblk_t envblk, const char *name)
}
}
+struct get_var_state {
+ const char * const name;
+ char * value;
+ int found;
+};
+
+static int
+get_var (const char * const name, const char * const value, void *statep)
+{
+ struct get_var_state *state = (struct get_var_state *)statep;
+
+ if (!grub_strcmp(state->name, name))
+ {
+ state->found = 1;
+ state->value = grub_strdup(value);
+ if (!state->value)
+ grub_errno = grub_error (GRUB_ERR_OUT_OF_MEMORY, N_("out of memory"));
+
+ return 1;
+ }
+
+ return 0;
+}
+
+grub_err_t
+grub_envblk_get (grub_envblk_t envblk, const char * const name, char ** const value)
+{
+ struct get_var_state state = {
+ .name = name,
+ .value = NULL,
+ .found = 0,
+ };
+
+ grub_envblk_iterate(envblk, (void *)&state, get_var);
+
+ *value = state.value;
+
+ if (state.found && !state.value)
+ return grub_errno;
+
+ return GRUB_ERR_NONE;
+}
+
void
grub_envblk_iterate (grub_envblk_t envblk,
void *hook_data,
diff --git a/util/editenv.c b/util/editenv.c
index 1f7f6f3ae18..66f99f988ff 100644
--- a/util/editenv.c
+++ b/util/editenv.c
@@ -30,8 +30,6 @@
#include <string.h>
#include <libgen.h>
-#define DEFAULT_ENVBLK_SIZE 1024
-
void
grub_util_create_envblk_file (const char *name)
{
diff --git a/util/grub-set-bootflag.c b/util/grub-set-bootflag.c
index bb198f02351..6a79ee67444 100644
--- a/util/grub-set-bootflag.c
+++ b/util/grub-set-bootflag.c
@@ -25,6 +25,7 @@
#include <config-util.h> /* For *_DIR_NAME defines */
#include <grub/types.h>
+#include <grub/err.h>
#include <grub/lib/envblk.h> /* For GRUB_ENVBLK_DEFCFG define */
#include <errno.h>
#include <stdio.h>
diff --git a/include/grub/efi/efi.h b/include/grub/efi/efi.h
index 8ca3981d7a1..d24afbadbf6 100644
--- a/include/grub/efi/efi.h
+++ b/include/grub/efi/efi.h
@@ -24,6 +24,11 @@
#include <grub/dl.h>
#include <grub/efi/api.h>
+#define GRUB_EFI_GRUB_VARIABLE_GUID \
+ { 0x91376aff, 0xcba6, 0x42be, \
+ { 0x94, 0x9d, 0x06, 0xfd, 0xe8, 0x11, 0x28, 0xe8 } \
+ }
+
/* Variables. */
extern grub_efi_system_table_t *EXPORT_VAR(grub_efi_system_table);
extern grub_efi_handle_t EXPORT_VAR(grub_efi_image_handle);
diff --git a/include/grub/lib/envblk.h b/include/grub/lib/envblk.h
index c3e65592170..ab969af2461 100644
--- a/include/grub/lib/envblk.h
+++ b/include/grub/lib/envblk.h
@@ -22,6 +22,8 @@
#define GRUB_ENVBLK_SIGNATURE "# GRUB Environment Block\n"
#define GRUB_ENVBLK_DEFCFG "grubenv"
+#define DEFAULT_ENVBLK_SIZE 1024
+
#ifndef ASM_FILE
struct grub_envblk
@@ -33,6 +35,7 @@ typedef struct grub_envblk *grub_envblk_t;
grub_envblk_t grub_envblk_open (char *buf, grub_size_t size);
int grub_envblk_set (grub_envblk_t envblk, const char *name, const char *value);
+grub_err_t grub_envblk_get (grub_envblk_t envblk, const char * const name, char ** const value);
void grub_envblk_delete (grub_envblk_t envblk, const char *name);
void grub_envblk_iterate (grub_envblk_t envblk,
void *hook_data,