diff options
author | A. Wilcox <AWilcox@Wilcox-Tech.com> | 2023-10-21 21:21:15 -0500 |
---|---|---|
committer | A. Wilcox <AWilcox@Wilcox-Tech.com> | 2023-10-21 21:21:15 -0500 |
commit | 975b506cdd645edb75312a1e8ead9346e69b3ecf (patch) | |
tree | 5d090e739890e8edbcc11c0d98a0b7b6f52ef6ac | |
parent | 3575260e68030a6dec02aa933d1294416e725a49 (diff) | |
download | horizon-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.cc | 51 |
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 */ } |