summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorA. Wilcox <AWilcox@Wilcox-Tech.com>2023-10-21 21:21:15 -0500
committerA. Wilcox <AWilcox@Wilcox-Tech.com>2023-10-21 21:21:15 -0500
commit975b506cdd645edb75312a1e8ead9346e69b3ecf (patch)
tree5d090e739890e8edbcc11c0d98a0b7b6f52ef6ac
parent3575260e68030a6dec02aa933d1294416e725a49 (diff)
downloadhorizon-975b506cdd645edb75312a1e8ead9346e69b3ecf.tar.gz
horizon-975b506cdd645edb75312a1e8ead9346e69b3ecf.tar.bz2
horizon-975b506cdd645edb75312a1e8ead9346e69b3ecf.tar.xz
horizon-975b506cdd645edb75312a1e8ead9346e69b3ecf.zip
hscript: bootloader: Really, truly revamp EFI
This should handle every single scenario we could be in regarding efivarfs. It also makes efivarfs errors non-fatal, as grub-install has --no-nvram for such situations. Closes: #370 Fixes: bad8487c53 ("hscript: bootloader: Hopefully fix EFI once and for all")
-rw-r--r--hscript/meta.cc51
1 files changed, 41 insertions, 10 deletions
diff --git a/hscript/meta.cc b/hscript/meta.cc
index abf0792..9ba1b40 100644
--- a/hscript/meta.cc
+++ b/hscript/meta.cc
@@ -18,6 +18,8 @@
#ifdef HAS_INSTALL_ENV
# include <cstring>
# include <sys/mount.h>
+# include <sys/syscall.h> /* SYS_mount_setattr */
+# include <linux/mount.h> /* MOUNT_ATTR_RDONLY, struct mount_attr */
# include "util/filesystem.hh"
#endif /* HAS_INSTALL_ENV */
#include <unistd.h> /* access - used by tz code even in RT env */
@@ -853,25 +855,54 @@ bool Bootloader::execute() const {
return false;
}
- /* remount EFI vars r/w */
+ std::vector<std::string> grub_params = {script->targetDirectory(),
+ "grub-install"};
+ /* handle EFI vars partition */
const auto efipath{script->targetDirectory() +
"/sys/firmware/efi/efivars"};
- if(mount("efivarfs", efipath.c_str(), "efivarfs", MS_NOEXEC |
- MS_NODEV | MS_NOSUID | MS_RELATIME, nullptr) != 0) {
- output_error(pos, "bootloader: failed to mount writable efivarfs",
- ::strerror(errno));
- return false;
+ bool efivarfs = false;
+ bool umount = false;
+ if(fs::exists(efipath)) {
+ if(mount("efivarfs", efipath.c_str(), "efivarfs", MS_NOEXEC |
+ MS_NODEV | MS_NOSUID | MS_RELATIME, nullptr) != 0) {
+ if(errno == EBUSY) {
+ struct mount_attr attr = {};
+ attr.attr_clr = MS_RDONLY;
+ if(syscall(SYS_mount_setattr, -1, efipath.c_str(), 0,
+ &attr, sizeof(attr)) != 0) {
+ output_error(pos, "bootloader: failed to make NVRAM read/write",
+ ::strerror(errno));
+ } else {
+ efivarfs = true;
+ }
+ }
+ output_error(pos, "bootloader: failed to mount efivarfs",
+ ::strerror(errno));
+ } else {
+ efivarfs = true;
+ umount = true; /* We mounted it ourselves. */
+ }
}
- if(run_command("chroot",
- {script->targetDirectory(), "grub-install", _device})
- != 0) {
+ if(!efivarfs) {
+ output_warning(pos, "bootloader: efivarfs is not available",
+ "NVRAM variables cannot be updated!");
+ grub_params.push_back("--no-nvram");
+ }
+
+ if(fs::exists(script->targetDirectory() + "/boot/efi")) {
+ grub_params.push_back("--efi-directory=/boot/efi");
+ }
+
+ grub_params.push_back(_device);
+
+ if(run_command("chroot", grub_params) != 0) {
output_error(pos, "bootloader: failed to install GRUB");
return false;
}
/* done, back to r/o */
- umount(efipath.c_str());
+ if(umount) ::umount(efipath.c_str());
goto updateboot;
#endif /* HAS_INSTALL_ENV */
}