On Thu, Oct 02, 2025 at 02:46:15PM +0800, Michael Chang via Grub-devel wrote: > This patch adds the logic to locate and open an environment block that > is stored in a reserved area on the device. It introduces the function > fs_envblk_open together with helper routines to read the block pointed
s/fs_envblk_open/fs_envblk_open()/ > to by the env_block variable, and to create the block on disk when it > does not yet exist. When a block is created, the code records its s/yet exist/exist yet/ > location inside the file based envblk by setting env_block in block list > syntax of offset plus size in sectors. > > The env_block variable acts as a link from the file envblk to the raw > disk region so that later runs of grub editenv can follow it and access s/grub editenv/grub-editenv/ > the external block. The helper is exposed through a small ops table > attached to fs_envblk so that later patches can call > fs_envblk->ops->open without touching core code again. At this stage fs_envblk->ops->open() > variables are still stored in the file envblk and no redirection has > been applied. > > Signed-off-by: Michael Chang <[email protected]> > Reviewed-by: Neal Gompa <[email protected]> > --- > util/grub-editenv.c | 128 ++++++++++++++++++++++++++++++++++++++++++++ > 1 file changed, 128 insertions(+) > > diff --git a/util/grub-editenv.c b/util/grub-editenv.c > index 1f055ca43..829384392 100644 > --- a/util/grub-editenv.c > +++ b/util/grub-editenv.c > @@ -130,12 +130,23 @@ struct fs_envblk_spec { > }; > typedef struct fs_envblk_spec *fs_envblk_spec_t; > > +static grub_envblk_t fs_envblk_open (grub_envblk_t envblk); > + > +struct fs_envblk_ops { > + grub_envblk_t (*open) (grub_envblk_t); > +}; typedef struct fs_envblk_ops struct fs_envblk_ops_t; > struct fs_envblk { > struct fs_envblk_spec *spec; > + struct fs_envblk_ops *ops; fs_envblk_ops_t, etc... > const char *dev; > }; > typedef struct fs_envblk *fs_envblk_t; > > +static struct fs_envblk_ops fs_envblk_ops = { > + .open = fs_envblk_open > +}; > + > static struct fs_envblk_spec fs_envblk_spec[] = { > { "btrfs", ENV_BTRFS_OFFSET, GRUB_DISK_SECTOR_SIZE }, > { NULL, 0, 0 } > @@ -143,6 +154,122 @@ static struct fs_envblk_spec fs_envblk_spec[] = { > > static fs_envblk_t fs_envblk = NULL; > > +static int > +read_envblk_fs (const char *varname, const char *value, void *hook_data) s/read_envblk_fs/read_env_block_var/ > +{ > + grub_envblk_t *p_envblk = (grub_envblk_t *)hook_data; Missing space before hook_data... > + off_t off; > + size_t sz; > + char *p, *buf; > + FILE *fp; > + > + if (p_envblk == NULL || fs_envblk == NULL) > + return 1; > + > + if (strcmp (varname, "env_block") != 0) > + return 0; > + > + off = strtol (value, &p, 10); > + if (*p == '+') > + sz = strtol (p+1, &p, 10); s/p+1/p + 1/ > + else > + return 0; > + > + if (*p != '\0' || sz == 0) > + return 0; > + > + off <<= GRUB_DISK_SECTOR_BITS; > + sz <<= GRUB_DISK_SECTOR_BITS; > + > + fp = grub_util_fopen (fs_envblk->dev, "rb"); > + if (fp == NULL) > + grub_util_error (_("cannot open `%s': %s"), fs_envblk->dev, > + strerror (errno)); You do not need wrap lines in cases like that one. I am OK with lines (a bit) longer than 80 characters... > + > + if (fseek (fp, off, SEEK_SET) < 0) > + grub_util_error (_("cannot seek `%s': %s"), fs_envblk->dev, > + strerror (errno)); Ditto and below... > + buf = xmalloc (sz); > + if ((fread (buf, 1, sz, fp)) != sz) > + grub_util_error (_("cannot read `%s': %s"), fs_envblk->dev, > + strerror (errno)); > + > + fclose (fp); > + > + *p_envblk = grub_envblk_open (buf, sz); > + > + return 1; > +} > + > +static void > +create_envblk_fs (void) s/create_envblk_fs/create_env_on_block/ > +{ > + FILE *fp; > + char *buf; > + const char *device; > + off_t offset; > + size_t size; > + > + if (fs_envblk == NULL) > + return; > + > + device = fs_envblk->dev; > + offset = fs_envblk->spec->offset; > + size = fs_envblk->spec->size; > + > + fp = grub_util_fopen (device, "r+b"); > + if (fp == NULL) > + grub_util_error (_("cannot open `%s': %s"), device, strerror (errno)); > + > + buf = xmalloc (size); > + memcpy (buf, GRUB_ENVBLK_SIGNATURE, sizeof (GRUB_ENVBLK_SIGNATURE) - 1); > + memset (buf + sizeof (GRUB_ENVBLK_SIGNATURE) - 1, '#', size - sizeof > (GRUB_ENVBLK_SIGNATURE) + 1); > + > + if (fseek (fp, offset, SEEK_SET) < 0) > + grub_util_error (_("cannot seek `%s': %s"), device, strerror (errno)); > + > + if (fwrite (buf, 1, size, fp) != size) > + grub_util_error (_("cannot write to `%s': %s"), device, strerror > (errno)); > + > + grub_util_file_sync (fp); > + free (buf); > + fclose (fp); > +} > + > +static grub_envblk_t > +fs_envblk_open (grub_envblk_t envblk) > +{ > + grub_envblk_t envblk_fs = NULL; > + char *val; > + off_t offset; > + size_t size; > + > + if (envblk == NULL) > + return NULL; > + > + offset = fs_envblk->spec->offset; > + size = fs_envblk->spec->size; > + > + grub_envblk_iterate (envblk, &envblk_fs, read_envblk_fs); > + > + if (envblk_fs && grub_envblk_size (envblk_fs) == size) envblk_fs != NULL > + return envblk_fs; > + > + create_envblk_fs (); > + > + offset = offset >> GRUB_DISK_SECTOR_BITS; > + size = (size + GRUB_DISK_SECTOR_SIZE - 1) >> GRUB_DISK_SECTOR_BITS; > + > + val = xasprintf ("%ld+%lu", offset, size); val = xasprintf ("%lld+%zu", (long long) offset, size); > + if (! grub_envblk_set (envblk, "env_block", val)) > + grub_util_error ("%s", _("environment block too small")); > + grub_envblk_iterate (envblk, &envblk_fs, read_envblk_fs); > + free (val); > + > + return envblk_fs; > +} Daniel _______________________________________________ Grub-devel mailing list [email protected] https://lists.gnu.org/mailman/listinfo/grub-devel
