grub-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[PATCH 2/7] Add support for special envblk functions in GRUB


From: Paul Dagnelie
Subject: [PATCH 2/7] Add support for special envblk functions in GRUB
Date: Wed, 11 Mar 2020 10:37:10 -0700

This patch introducces the idea of envblk functions to GRUB. These functions
are used to interact with a grubenv file stored not in the usual grub tree,
but instead in a special filesystem-managed region that can more easily be
accessed at boot time. These functions interface between calling code and the
per-fs logic, an interface for which is also added as part of this patch.

Signed-off-by: Paul Dagnelie <address@hidden>
---
 grub-core/kern/file.c | 30 ++++++++++++++++++++++++++++--
 include/grub/file.h   | 10 ++++++++++
 include/grub/fs.h     | 12 ++++++++++++
 3 files changed, 50 insertions(+), 2 deletions(-)

diff --git a/grub-core/kern/file.c b/grub-core/kern/file.c
index 75eb5e2fa..f929f61a0 100644
--- a/grub-core/kern/file.c
+++ b/grub-core/kern/file.c
@@ -149,6 +149,27 @@ grub_file_open (const char *name, enum grub_file_type type)
   return 0;
 }
 
+grub_file_t
+grub_file_envblk_open (grub_fs_t fs, grub_device_t device, enum grub_file_type 
type)
+{
+  grub_file_t file = NULL;
+  file = (grub_file_t) grub_zalloc (sizeof (*file));
+  if (! file)
+    return NULL;
+  file->device = device;
+  file->special = 1;
+
+  if ((fs->fs_envblk_open) (file) != GRUB_ERR_NONE) {
+    grub_free(file);
+    return NULL;
+  }
+
+  file->fs = fs;
+  grub_errno = GRUB_ERR_NONE;
+
+  return grub_apply_file_filters(file, type, NULL);
+}
+
 grub_disk_read_hook_t grub_file_progress_hook;
 
 grub_ssize_t
@@ -185,7 +206,10 @@ grub_file_read (grub_file_t file, void *buf, grub_size_t 
len)
       file->read_hook_data = file;
       file->progress_offset = file->offset;
     }
-  res = (file->fs->fs_read) (file, buf, len);
+  if (grub_file_envblk (file))
+    res = (file->fs->fs_envblk_read) (file, buf, len);
+  else
+    res = (file->fs->fs_read) (file, buf, len);
   file->read_hook = read_hook;
   file->read_hook_data = read_hook_data;
   if (res > 0)
@@ -197,7 +221,9 @@ grub_file_read (grub_file_t file, void *buf, grub_size_t 
len)
 grub_err_t
 grub_file_close (grub_file_t file)
 {
-  if (file->fs->fs_close)
+  if (grub_file_envblk (file) && file->fs->fs_envblk_close)
+    (file->fs->fs_envblk_close) (file);
+  else if (file->fs->fs_close)
     (file->fs->fs_close) (file);
 
   if (file->device)
diff --git a/include/grub/file.h b/include/grub/file.h
index 31567483c..1cc688f55 100644
--- a/include/grub/file.h
+++ b/include/grub/file.h
@@ -170,6 +170,9 @@ struct grub_file
 
   /* Caller-specific data passed to the read hook.  */
   void *read_hook_data;
+
+  /* If the file is an FS's special file, which uses separate functions for 
interaction. */
+  int special;
 };
 typedef struct grub_file *grub_file_t;
 
@@ -211,6 +214,7 @@ grub_ssize_t EXPORT_FUNC(grub_file_read) (grub_file_t file, 
void *buf,
                                          grub_size_t len);
 grub_off_t EXPORT_FUNC(grub_file_seek) (grub_file_t file, grub_off_t offset);
 grub_err_t EXPORT_FUNC(grub_file_close) (grub_file_t file);
+grub_file_t EXPORT_FUNC(grub_file_envblk_open) (grub_fs_t fs, grub_device_t 
device, enum grub_file_type type);
 
 /* Return value of grub_file_size() in case file size is unknown. */
 #define GRUB_FILE_SIZE_UNKNOWN  0xffffffffffffffffULL
@@ -233,6 +237,12 @@ grub_file_seekable (const grub_file_t file)
   return !file->not_easily_seekable;
 }
 
+static inline int
+grub_file_envblk (const grub_file_t file)
+{
+  return file->special;
+}
+
 grub_file_t
 grub_file_offset_open (grub_file_t parent, enum grub_file_type type,
                       grub_off_t start, grub_off_t size);
diff --git a/include/grub/fs.h b/include/grub/fs.h
index 302e48d4b..ec1a7a50e 100644
--- a/include/grub/fs.h
+++ b/include/grub/fs.h
@@ -96,6 +96,18 @@ struct grub_fs
   /* Whether blocklist installs have a chance to work.  */
   int blocklist_install;
 #endif
+
+  /*
+   * The envblk functions are defined on filesystems that need to handle
+   * grub-writable files in a special way. This is most commonly the case for
+   * CoW filesystems like btrfs and ZFS.  The normal read and close functions
+   * should detect that they are being called on a special file and act
+   * appropriately.
+   */
+  grub_err_t (*fs_envblk_open) (struct grub_file *file);
+  grub_ssize_t (*fs_envblk_read) (struct grub_file *file, char *buf, 
grub_size_t len);
+  grub_err_t (*fs_envblk_write) (struct grub_file *file, char *buf, 
grub_size_t len);
+  grub_err_t (*fs_envblk_close) (struct grub_file *file);
 };
 typedef struct grub_fs *grub_fs_t;
 
-- 
2.19.0




reply via email to

[Prev in Thread] Current Thread [Next in Thread]