[PATCH] environment: support reading and writing of efivar
Jonas Licht
jonas.licht at gmail.com
Tue Mar 11 07:17:13 PDT 2025
scripts/bareboxenv: skip file creation to allow reading the destination
file, when existing.
Signed-off-by: Jonas Licht <jonas.licht at gmail.com>
Fixes #29
---
common/environment.c | 62 +++++++++++++++++++++++++++++++++++++++-----
scripts/bareboxenv.c | 11 +-------
2 files changed, 57 insertions(+), 16 deletions(-)
diff --git a/common/environment.c b/common/environment.c
index 37adb5d678..dee746a6b2 100644
--- a/common/environment.c
+++ b/common/environment.c
@@ -305,9 +305,10 @@ int envfs_save(const char *filename, const char *dirname, unsigned flags)
struct envfs_super *super;
int envfd, size, ret;
struct action_data data = {};
- void *buf = NULL, *wbuf;
+ void *buf = NULL, *wbuf, *bufWithEfi;
struct envfs_entry *env;
const char *defenv_path = default_environment_path_get();
+ uint32_t magic;
if (!filename)
filename = defenv_path;
@@ -342,7 +343,9 @@ int envfs_save(const char *filename, const char *dirname, unsigned flags)
}
}
- buf = xzalloc(size + sizeof(struct envfs_super));
+ bufWithEfi = xzalloc(size + sizeof(struct envfs_super) +
+ 4); // four byte efi attributes
+ buf = bufWithEfi + 4;
data.writep = buf + sizeof(struct envfs_super);
super = buf;
@@ -370,7 +373,7 @@ int envfs_save(const char *filename, const char *dirname, unsigned flags)
super->crc = ENVFS_32(crc32(0, buf + sizeof(struct envfs_super), size));
super->sb_crc = ENVFS_32(crc32(0, buf, sizeof(struct envfs_super) - 4));
- envfd = open(filename, O_WRONLY | O_CREAT, S_IRUSR | S_IWUSR);
+ envfd = open(filename, O_RDWR | O_CREAT, S_IRUSR | S_IWUSR);
if (envfd < 0) {
printf("could not open %s: %m\n", filename);
ret = -errno;
@@ -385,6 +388,34 @@ int envfs_save(const char *filename, const char *dirname, unsigned flags)
goto out;
}
+ wbuf = buf;
+
+ /* check if we writing efi vars */
+ ret = pread(envfd, &magic, sizeof(uint32_t),
+ 4); // four byte efi var attributes
+ if (ret == -1 && errno == ENOENT) {
+ // skip as file don't exist
+ goto skip_efi_read;
+ }
+ if (ret < sizeof(u_int32_t)) {
+ perror("read of destination file failed");
+ ret = -errno;
+ goto skip_efi_read;
+ }
+
+ if (ENVFS_32(magic) == ENVFS_MAGIC) {
+ pr_info("looks like we writing efi vars, keep attributes\n");
+ ret = pread(envfd, bufWithEfi, sizeof(uint32_t), 0);
+ if (ret < sizeof(uint32_t)) {
+ perror("read of efi attributes failed");
+ ret = -errno;
+ goto out;
+ }
+ size += sizeof(uint32_t);
+ wbuf = bufWithEfi;
+ }
+
+skip_efi_read:
ret = erase(envfd, ERASE_SIZE_ALL, 0, ERASE_TO_WRITE);
/* ENOSYS and EOPNOTSUPP aren't errors here, many devices don't need it */
@@ -395,8 +426,6 @@ int envfs_save(const char *filename, const char *dirname, unsigned flags)
size += sizeof(struct envfs_super);
- wbuf = buf;
-
while (size) {
ssize_t now = write(envfd, wbuf, size);
if (now < 0) {
@@ -425,7 +454,7 @@ int envfs_save(const char *filename, const char *dirname, unsigned flags)
out:
close(envfd);
out1:
- free(buf);
+ free(bufWithEfi);
#ifdef __BAREBOX__
unlink_recursive(TMPDIR, NULL);
#endif
@@ -449,6 +478,7 @@ int envfs_load(const char *filename, const char *dir, unsigned flags)
int envfd;
int ret = 0;
size_t size, rsize;
+ uint32_t magic;
if (!filename)
filename = default_environment_path_get();
@@ -466,6 +496,26 @@ int envfs_load(const char *filename, const char *dir, unsigned flags)
return -1;
}
+ /* check if we reading efi vars */
+ ret = pread(envfd, &magic, sizeof(uint32_t),
+ 4); // four byte efi var attributes
+ if (ret < sizeof(u_int32_t)) {
+ perror("read");
+ ret = -errno;
+ goto out;
+ }
+
+ if (ENVFS_32(magic) == ENVFS_MAGIC) {
+ pr_info("looks like we reading efi vars, skip attributes\n");
+ ret = read(envfd, &magic,
+ sizeof(uint32_t)); // simply reuse the memory
+ if (ret < sizeof(uint32_t)) {
+ perror("read");
+ ret = -errno;
+ goto out;
+ }
+ }
+
/* read superblock */
ret = read(envfd, &super, sizeof(struct envfs_super));
if ( ret < sizeof(struct envfs_super)) {
diff --git a/scripts/bareboxenv.c b/scripts/bareboxenv.c
index e954447015..6b9b8d90c4 100644
--- a/scripts/bareboxenv.c
+++ b/scripts/bareboxenv.c
@@ -117,7 +117,7 @@ static void usage(char *prgname)
int main(int argc, char *argv[])
{
int opt;
- int save = 0, load = 0, pad = 0, err = 0, fd;
+ int save = 0, load = 0, pad = 0, err = 0;
char *filename = NULL, *dirname = NULL;
unsigned envfs_flags = 0;
int verbose = 0;
@@ -156,15 +156,6 @@ int main(int argc, char *argv[])
exit(1);
}
- if (save) {
- fd = open(filename, O_CREAT | O_TRUNC | O_WRONLY, 0644);
- if (fd < 0) {
- perror("open");
- exit(1);
- }
- close(fd);
- }
-
if (save && pad) {
if (truncate(filename, pad)) {
perror("truncate");
--
2.45.3
More information about the barebox
mailing list