1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74
|
From: Heinrich Schuchardt <heinrich.schuchardt@canonical.com>
Date: Fri, 18 Mar 2022 15:21:33 +0100
Subject: efivar: check that efivarfs is writeable
Some UEFI implementations (notably U-Boot) don't implement the
SetVariable() runtime service. On these systems the GRUB installation
must be completed manually. Write a warning in this case but avoid
throwing an error. (LP: #1965288)
Signed-off-by: Heinrich Schuchardt <heinrich.schuchardt@canonical.com>
---
grub-core/osdep/unix/efivar.c | 34 ++++++++++++++++++++++++++++++++++
1 file changed, 34 insertions(+)
diff --git a/grub-core/osdep/unix/efivar.c b/grub-core/osdep/unix/efivar.c
index 4a58328..b53f32d 100644
--- a/grub-core/osdep/unix/efivar.c
+++ b/grub-core/osdep/unix/efivar.c
@@ -37,7 +37,10 @@
#include <grub/list.h>
#include <grub/misc.h>
#include <grub/emu/exec.h>
+#include <linux/magic.h>
#include <sys/types.h>
+#include <sys/vfs.h>
+#include <sys/statvfs.h>
#include <ctype.h>
#include <errno.h>
#include <stdlib.h>
@@ -398,6 +401,29 @@ err:
return NULL;
}
+/**
+ * efivar_is_rw - detect if the efivar file system exists and is writeable
+ *
+ * Return: true if efivarfs is writeable
+ */
+static bool
+efivar_is_rw (void)
+{
+ int ret;
+ const char *mount = "/sys/firmware/efi/efivars";
+ struct statfs stat;
+
+ ret = statfs(mount, &stat);
+ if (ret == -1)
+ return false;
+ if (stat.f_type != EFIVARFS_MAGIC)
+ return false;
+ if (stat.f_flags & ST_RDONLY)
+ return false;
+
+ return true;
+}
+
int
grub_install_efivar_register_efi (grub_device_t efidir_grub_dev,
const char *efifile_path,
@@ -410,6 +436,14 @@ grub_install_efivar_register_efi (grub_device_t efidir_grub_dev,
int entry_num = -1;
int rc;
+ /* Check if EFI variable can be written */
+ if (!efivar_is_rw ())
+ {
+ grub_util_warn ("EFI variables cannot be set on this system");
+ grub_util_warn ("You will have to complete the GRUB setup manually");
+ return 0;
+ }
+
efidir_disk = grub_util_biosdisk_get_osdev (efidir_grub_dev->disk);
efidir_part = efidir_grub_dev->disk->partition ? efidir_grub_dev->disk->partition->number + 1 : 1;
|