[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[PATCH 4/7] Use envblk file and fs functions to implement reading the gr
From: |
Paul Dagnelie |
Subject: |
[PATCH 4/7] Use envblk file and fs functions to implement reading the grubenv file from special FS regions |
Date: |
Wed, 11 Mar 2020 10:37:12 -0700 |
This patch modifies the loadenv command to take advantage of the new envblock
functions provided by a previous patch. These functions will be used instead
of the normal file-based functions if the boot filesystem is detected to
support them. There is also a config variable, grubenv_src, that can be used
to force the file or envblock logic to be used.
Signed-off-by: Paul Dagnelie <address@hidden>
---
grub-core/commands/loadenv.c | 122 ++++++++++++++++++++++++++++++-----
include/grub/lib/envblk.h | 2 +
2 files changed, 109 insertions(+), 15 deletions(-)
diff --git a/grub-core/commands/loadenv.c b/grub-core/commands/loadenv.c
index 3fd664aac..66f5345ec 100644
--- a/grub-core/commands/loadenv.c
+++ b/grub-core/commands/loadenv.c
@@ -79,6 +79,94 @@ open_envblk_file (char *filename,
return file;
}
+static grub_file_t
+open_envblk_block (grub_fs_t fs, grub_device_t dev, enum grub_file_type type)
+{
+ if (fs->fs_envblk_open)
+ return grub_file_envblk_open(fs, dev, type);
+ return NULL;
+}
+
+static grub_file_t
+open_envblk (grub_extcmd_context_t ctxt, enum grub_file_type type)
+{
+ struct grub_arg_list *state = ctxt->state;
+ grub_file_t file = NULL;
+ grub_device_t device = NULL;
+ const char *source;
+ grub_fs_t fs = NULL;
+ char *filename = state[0].set ? state[0].arg : NULL;
+
+ source = grub_env_get ("grubenv_src");
+ if (! source || ! grub_strcmp (source, GRUB_ENVBLK_SRC_BLK))
+ {
+ char *device_name;
+ const char *prefix;
+ grub_dprintf ("loadenv", "checking for envblk\n");
+
+ prefix = grub_env_get ("prefix");
+ if (! prefix)
+ {
+ grub_error (GRUB_ERR_FILE_NOT_FOUND, N_("variable `%s' isn't set"),
"prefix");
+ return NULL;
+ }
+
+ device_name = grub_file_get_device_name (prefix);
+ if (grub_errno)
+ return NULL;
+
+ device = grub_device_open (device_name);
+ if (! device)
+ return NULL;
+
+ fs = grub_fs_probe (device);
+ if (! fs) {
+ grub_device_close (device);
+ return NULL;
+ }
+
+ /* We have to reopen the device here because it was closed in
grub_fs_probe. */
+ device = grub_device_open (device_name);
+ grub_free (device_name);
+ if (! device)
+ return NULL;
+
+ }
+ if (! source)
+ {
+ if (fs->fs_envblk_open)
+ {
+ source = GRUB_ENVBLK_SRC_BLK;
+ grub_dprintf ("loadenv", "envblk support detected\n");
+ }
+ else
+ {
+ source = GRUB_ENVBLK_SRC_FILE;
+ grub_dprintf ("loadenv", "envblk support not detected\n");
+ }
+ }
+
+ if (! grub_strcmp (source, GRUB_ENVBLK_SRC_FILE))
+ {
+ if (device)
+ grub_device_close (device);
+ file = open_envblk_file (filename, type);
+
+ if (! file)
+ return NULL;
+ }
+ else if (! grub_strcmp (source, GRUB_ENVBLK_SRC_BLK))
+ {
+ file = open_envblk_block (fs, device, type);
+ if (! file)
+ {
+ grub_device_close (device);
+ return NULL;
+ }
+ }
+ return file;
+}
+
static grub_envblk_t
read_envblk_file (grub_file_t file)
{
@@ -165,11 +253,10 @@ grub_cmd_load_env (grub_extcmd_context_t ctxt, int argc,
char **args)
whitelist.len = argc;
whitelist.list = args;
- /* state[0] is the -f flag; state[1] is the --skip-sig flag */
- file = open_envblk_file ((state[0].set) ? state[0].arg : 0,
- GRUB_FILE_TYPE_LOADENV
- | (state[1].set
- ? GRUB_FILE_TYPE_SKIP_SIGNATURE :
GRUB_FILE_TYPE_NONE));
+ file = open_envblk (ctxt, GRUB_FILE_TYPE_LOADENV
+ | (state[1].set
+ ? GRUB_FILE_TYPE_SKIP_SIGNATURE :
+ GRUB_FILE_TYPE_NONE));
if (! file)
return grub_errno;
@@ -204,10 +291,9 @@ grub_cmd_list_env (grub_extcmd_context_t ctxt,
grub_file_t file;
grub_envblk_t envblk;
- file = open_envblk_file ((state[0].set) ? state[0].arg : 0,
- GRUB_FILE_TYPE_LOADENV
- | (state[1].set
- ? GRUB_FILE_TYPE_SKIP_SIGNATURE :
GRUB_FILE_TYPE_NONE));
+ file = open_envblk (ctxt, GRUB_FILE_TYPE_LOADENV
+ | (state[1].set
+ ? GRUB_FILE_TYPE_SKIP_SIGNATURE :
GRUB_FILE_TYPE_NONE));
if (! file)
return grub_errno;
@@ -379,7 +465,6 @@ save_env_read_hook (grub_disk_addr_t sector, unsigned
offset, unsigned length,
static grub_err_t
grub_cmd_save_env (grub_extcmd_context_t ctxt, int argc, char **args)
{
- struct grub_arg_list *state = ctxt->state;
grub_file_t file;
grub_envblk_t envblk;
struct grub_cmd_save_env_ctx ctx = {
@@ -390,9 +475,8 @@ grub_cmd_save_env (grub_extcmd_context_t ctxt, int argc,
char **args)
if (! argc)
return grub_error (GRUB_ERR_BAD_ARGUMENT, "no variable is specified");
- file = open_envblk_file ((state[0].set) ? state[0].arg : 0,
- GRUB_FILE_TYPE_SAVEENV
- | GRUB_FILE_TYPE_SKIP_SIGNATURE);
+ file = open_envblk (ctxt, GRUB_FILE_TYPE_SAVEENV
+ | GRUB_FILE_TYPE_SKIP_SIGNATURE);
if (! file)
return grub_errno;
@@ -409,7 +493,7 @@ grub_cmd_save_env (grub_extcmd_context_t ctxt, int argc,
char **args)
if (! envblk)
goto fail;
- if (check_blocklists (envblk, ctx.head, file))
+ if (! grub_file_envblk (file) && check_blocklists (envblk, ctx.head, file))
goto fail;
while (argc)
@@ -432,7 +516,15 @@ grub_cmd_save_env (grub_extcmd_context_t ctxt, int argc,
char **args)
args++;
}
- write_blocklists (envblk, ctx.head, file);
+ if (grub_file_envblk (file))
+ {
+ grub_file_seek (file, 0);
+ file->fs->fs_envblk_write (file, grub_envblk_buffer (envblk),
grub_envblk_size (envblk));
+ }
+ else
+ {
+ write_blocklists (envblk, ctx.head, file);
+ }
fail:
if (envblk)
diff --git a/include/grub/lib/envblk.h b/include/grub/lib/envblk.h
index c3e655921..287c87105 100644
--- a/include/grub/lib/envblk.h
+++ b/include/grub/lib/envblk.h
@@ -21,6 +21,8 @@
#define GRUB_ENVBLK_SIGNATURE "# GRUB Environment Block\n"
#define GRUB_ENVBLK_DEFCFG "grubenv"
+#define GRUB_ENVBLK_SRC_BLK "block"
+#define GRUB_ENVBLK_SRC_FILE "file"
#ifndef ASM_FILE
--
2.19.0
- [PATCH 0/7] ZFS/other CoW FS save_env support, Paul Dagnelie, 2020/03/11
- [PATCH 1/7] Factor out file filter function for reuse, Paul Dagnelie, 2020/03/11
- [PATCH 2/7] Add support for special envblk functions in GRUB, Paul Dagnelie, 2020/03/11
- [PATCH 3/7] Factor out envblk buffer creation for reuse, Paul Dagnelie, 2020/03/11
- [PATCH 4/7] Use envblk file and fs functions to implement reading the grubenv file from special FS regions,
Paul Dagnelie <=
- [PATCH 5/7] Add ZFS envblock functions, Paul Dagnelie, 2020/03/11
- [PATCH 6/7] Refactor default envblk size out for reuse, Paul Dagnelie, 2020/03/11
- [PATCH 7/7] Update editenv to support editing zfs envblock, fix whitespace, and autodetect bootenv support in libzfs, Paul Dagnelie, 2020/03/11
- Re: [PATCH 0/7] ZFS/other CoW FS save_env support, Daniel Kiper, 2020/03/25