Skip to content

Commit

Permalink
efivar: Copy VarToFile to RTStorageVolatile file at ESP
Browse files Browse the repository at this point in the history
VarToFile: an EFI variable that holds all the BS,RT, NV variables and
can be copied to the file defined by RTStorageVolatile.

RTStorageVolatile: contains a filename, relative to the ESP. Make sure
to copy the filename to all ESPs to follow EFI standard.

Suggested-by: Ilias Apalodimas <[email protected]>
Signed-off-by: Javier Tia <[email protected]>
  • Loading branch information
jetm committed Jun 15, 2024
1 parent 2491825 commit 11f3d4e
Show file tree
Hide file tree
Showing 2 changed files with 176 additions and 1 deletion.
2 changes: 1 addition & 1 deletion src/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,7 @@ libefivar.so : private LIBS=dl
libefivar.so : private MAP=libefivar.map

efivar : $(EFIVAR_OBJECTS) | libefivar.so
efivar : private LIBS=efivar dl
efivar : private LIBS=efivar dl blkid

efivar-static : $(EFIVAR_OBJECTS) $(patsubst %.o,%.static.o,$(LIBEFIVAR_OBJECTS))
efivar-static : | $(GENERATED_SOURCES)
Expand Down
175 changes: 175 additions & 0 deletions src/efivar.c
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@
#include <errno.h>
#include <string.h>
#include <limits.h>
#include <blkid/blkid.h>
#include <mntent.h>

extern char *optarg;
extern int optind, opterr, optopt;
Expand All @@ -42,6 +44,11 @@ extern int optind, opterr, optopt;
#define SHOW_VERBOSE 0
#define SHOW_DECIMAL 1

#define EFI_VARTOFILE "b2ac5fc9-92b7-4acd-aeac-11e818c3130c-VarToFile"
#define EFI_RTSTORAGEVOLATILE "b2ac5fc9-92b7-4acd-aeac-11e818c3130c-RTStorageVolatile"

static void save_esp_filename();

static const char *attribute_names[] = {
"Non-Volatile",
"Boot Service Access",
Expand Down Expand Up @@ -382,6 +389,8 @@ edit_variable(const char *guid_name, void *data, size_t data_size,
show_errors();
exit(1);
}

save_esp_filename();
}

static void
Expand Down Expand Up @@ -424,6 +433,172 @@ prepare_data(const char *filename, uint8_t **data, size_t *data_size)
exit(1);
}

void
find_esp(char **esp_paths, size_t *esp_count)
{
blkid_cache cache;
blkid_dev_iterate iter;
blkid_dev dev;
const char *devname;
const char *parttype;
const char *esp_parttype = "c12a7328-f81f-11d2-ba4b-00a0c93ec93b"; // ESP UUID
FILE *mounts;
struct mntent *ent;
blkid_probe pr = NULL;
int r, size = 0;
*esp_count = 0;

// Initialize the blkid cache
if (blkid_get_cache(&cache, NULL) < 0) {
fprintf(stderr, "Failed to get blkid cache\n");
return;
}

// Probe all block devices
blkid_probe_all(cache);

// Create an iterator to go through all block devices
iter = blkid_dev_iterate_begin(cache);
if (!iter) {
fprintf(stderr, "Failed to create blkid iterator\n");
blkid_put_cache(cache);
return;
}

// Open /proc/mounts to find mount points
mounts = setmntent("/proc/mounts", "r");
if (!mounts) {
fprintf(stderr, "Failed to open /proc/mounts\n");
endmntent(mounts);
return;
}

while (blkid_dev_next(iter, &dev) == 0) {
dev = blkid_verify(cache, dev);
if (!dev) {
continue;
}
devname = blkid_dev_devname(dev);

pr = blkid_new_probe_from_filename(devname);
if (!pr) {
fprintf(stderr, "Failed to create blkid probe\n");
blkid_free_probe(pr);
return;
}

// Generate partition details
blkid_probe_enable_partitions(pr, 1);
blkid_probe_set_partitions_flags(pr, BLKID_PARTS_ENTRY_DETAILS);

r = blkid_do_safeprobe(pr);
if (r == -2) {
debug("File system %s is ambiguous\n", devname);
continue;
} else if (r != 0) {
debug("Failed to probe file system %s\n", devname);
continue;
}

// Get the PARTTYPE of the current device
r = blkid_probe_lookup_value(pr, "PART_ENTRY_TYPE", &parttype, NULL);
if (r != 0) {
debug("Failed to probe partition type UUID %s\n", devname);
continue;
}

if (parttype && strcmp(parttype, esp_parttype) == 0) {
// Iterate over mount points to find ESP matches
while ((ent = getmntent(mounts)) != NULL) {
if (strcmp(ent->mnt_fsname, devname) == 0) {
printf("ESP %s path is mounted at dev %s\n", ent->mnt_dir, devname);
size += strlen(ent->mnt_dir) + 1; // +1 for the null terminator
char *temp = realloc(*esp_paths, size);
if (temp == NULL) {
fprintf(stderr, "Failed to allocate memory for ESP paths\n");
free(*esp_paths);
*esp_count = 0;
return;
}
*esp_paths = temp;
strcpy(*esp_paths + size - strlen(ent->mnt_dir) - 1, ent->mnt_dir);
(*esp_count)++;
}
}
}

// Cleanup
blkid_free_probe(pr);
}

// Cleanup
endmntent(mounts);
blkid_dev_iterate_end(iter);
blkid_put_cache(cache);
}

static void
get_esp_filename(char **esp_filename)
{
char *dst_name = NULL;
efi_guid_t dst_guid = efi_guid_empty;
size_t filename_size;
uint32_t filename_attr;
uint8_t *filename = NULL;
int rc;

parse_name(EFI_RTSTORAGEVOLATILE, &dst_name, &dst_guid);
if (!dst_name || efi_guid_is_empty(&dst_guid)) {
fprintf(stderr, "efivar: could not parse %s\n", EFI_RTSTORAGEVOLATILE);
show_errors();
exit(1);
}

rc = efi_get_variable(dst_guid, dst_name, &filename, &filename_size, &filename_attr);
if (rc < 0) {
fprintf(stderr, "efivar: get ESP filename\n");
show_errors();
exit(1);
}

*esp_filename = (char *)filename;
}

static void
save_esp_filename()
{
char *esp_paths = NULL;
size_t esp_count = 0;
char *ptr;
char *esp_filename_path = NULL;
char *esp_filename = NULL;

get_esp_filename(&esp_filename);
if (esp_filename) {
fprintf(stderr, "efivar: No ESP filename found\n");
show_errors();
exit(1);
}

find_esp(&esp_paths, &esp_count);
if (esp_paths) {
ptr = esp_paths;
for (size_t i = 0; i < esp_count; i++) {
esp_filename_path = strcat(ptr, "/");
esp_filename_path = strcat(esp_filename_path, esp_filename);
save_variable(EFI_VARTOFILE, esp_filename_path, false);
printf("efivar: VarToFile content saved at %s\n", esp_filename_path);
ptr += strlen(ptr) + 1;
}
free(esp_paths);
}
else {
fprintf(stderr, "efivar: no EFI System Partitions (ESP) found\n");
show_errors();
exit(1);
}
}

static void __attribute__((__noreturn__))
usage(int ret)
{
Expand Down

0 comments on commit 11f3d4e

Please sign in to comment.