Closed mib1982 closed 9 months ago
Hello @mib1982, thank you for your well written bug report. Unfortunately I'm unable to reproduce the problem. I tried the steps you described on two different Arch Linux installations and on both the -e
switch and the UKIBAK_ESP
environment variable are working flawlessly.
Looking at your observed behavior, it looks to me that only the first /
of the option is used by ukibak
. Could you please check the following things:
/efi
is the default value for the mount point of the EFI partition. If your EFI partition is mounted as /efi
it should work without using the -e
switch or the UKIBAK_ESP
variable. Does ukibak
work if you call it without a command line option or set environment variable?ukibak
with the -d
switch set and post the result here?Hi,
I had the same issue @mib1982 mentioned, so I had a quick look and I believe the issue lies with use of the Path#join
method: since the loader image name in the EFI variable will always be absolute, joining it with the EFI path doesn't do anything, because joining anything with an absolute path returns that exact path; as shown by the example in the Path#join
documentation:
assert_eq!(Path::new("/etc").join("/bin/sh"), PathBuf::from("/bin/sh"));
My Rust-fu is pretty weak, but I managed to write some naive code that appears to fix it; which may be useful, so here goes:
--- a/src/main.rs
+++ b/src/main.rs
@@ -236,12 +236,18 @@ fn backup_uki(args: &Args) -> Result<(), Error> {
// Select a path from the list.
let esp_path = get_esp_path_from_list(&esp_paths, args.force)?;
- let active_esp: PathBuf = get_loader_image_name(&PathBuf::from(&args.efivarfs))?.into();
+ let mut active_esp: PathBuf = get_loader_image_name(&PathBuf::from(&args.efivarfs))?.into();
debug!("Active loader image name is '{}'.", active_esp.display());
+ if active_esp.is_absolute() {
+ active_esp = active_esp.strip_prefix("/").unwrap().to_path_buf()
+ }
+
// Combine the relative path of the active ESP with the mountpoint of the ESP
// specified on the command line (or the default).
let source_path = esp_path.join(active_esp);
+
+ debug!("Active loader image source path is '{}'.", source_path.display());
if !source_path.exists() {
Err(Error::SourceNotFound(source_path.clone()))?;
}
Thanks for creating this project BTW!
Hello @FlashSystems, thank you for taking the time to look into this issue.
First, here is an excerpt of /etc/fstab
showing the relevant line for /efi
:
/dev/sda2 /efi vfat umask=0077 0 2
ukibak
if I call it without a command line option and no environmental variable set. -> # ukibak ERROR [ukibak] Source image '/EFI/Linux/arch-linux.efi' not found.
ukibak -d
:-> # ukibak -d DEBUG [ukibak] Active loader image name is '/EFI/Linux/arch-linux.efi'. ERROR [ukibak] Source image '/EFI/Linux/arch-linux.efi' not found.
I assume it takes the active loader image name somewhere from /sys/firmware/efi/efivars/
, but it doesn't put it in relation to the mount-point of the EFI System Partition /efi
.
However, I was able to make it work by creating a symlink /EFI
which points to /efi/EFI
. This leads to the creation of a backup of the last bootable uki. Here is the output of ukibak -d
with the symlink in place:
-> # ukibak -d
DEBUG [ukibak] Active loader image name is '/EFI/Linux/arch-linux.efi'. DEBUG [ukibak] Parsing image /EFI/Linux/arch-linux.efi... DEBUG [ukibak] Found section .text DEBUG [ukibak] Found section .rodata DEBUG [ukibak] Found section .data DEBUG [ukibak] Found section .sbat DEBUG [ukibak] Found section .sdmagic DEBUG [ukibak] Found section .reloc DEBUG [ukibak] Found section .osrel DEBUG [ukibak] Found section .uname DEBUG [ukibak] Found section .cmdline DEBUG [ukibak] Found section .splash DEBUG [ukibak] Found section .linux DEBUG [ukibak] Found section .initrd DEBUG [ukibak] Image is self contained. DEBUG [ukibak] Time since last reboot is 910s DEBUG [ukibak] File was modified 84011s ago. Minimum age is 910s. DEBUG [ukibak] Parsing image /EFI/Linux/linux-last.efi... INFO [ukibak] Copying '/EFI/Linux/arch-linux.efi' to '/EFI/Linux/linux-last.efi'... DEBUG [ukibak] Copy succeeded.
For the time being, the workaround is a good solution which works for me. I leave it up to you if you would like to further investigate the problem or close this issue.
Edit: Thank you @d-tux for the potential fix. Your post overlapped with mine, but I am hopeful your insight into the behavior of Path::join
might fix this issue.
Hello @d-tux, you are absolutley right, this EFI implementations return an absolute path. On both of my systems, the returned path is relative. Maybe it depends on how the path was supplied to efibootmgr
command.
Thank you for your effort and for suggesting a fix. I'll update my code, add some tests and release a new version as soon as possible.
@mib1982: Thank you for supplying the log. This confirms @d-tux's assumption: DEBUG [ukibak] Active loader image name is '/EFI/Linux/arch-linux.efi'.
. The load image name starts with a slash.
I've fixed the bug and added a test to make sure there will be no regressions. Please test Version 1.1.0. It would be great if you could let me know whether it also works in practice.
It looks like it has been fixed for me. Here is the output of ukibak -d
after updating to Version 1.1.0:
-> # ukibak -d DEBUG [ukibak] Active loader image name is 'EFI/Linux/arch-linux.efi'. DEBUG [ukibak] Parsing image /efi/EFI/Linux/arch-linux.efi... DEBUG [ukibak] Found section .text DEBUG [ukibak] Found section .rodata DEBUG [ukibak] Found section .data DEBUG [ukibak] Found section .sbat DEBUG [ukibak] Found section .sdmagic DEBUG [ukibak] Found section .reloc DEBUG [ukibak] Found section .osrel DEBUG [ukibak] Found section .uname DEBUG [ukibak] Found section .cmdline DEBUG [ukibak] Found section .splash DEBUG [ukibak] Found section .linux DEBUG [ukibak] Found section .initrd DEBUG [ukibak] Image is self contained. DEBUG [ukibak] Time since last reboot is 16284s DEBUG [ukibak] File was modified 12537s ago. Minimum age is 16284s. INFO [ukibak] File '/efi/EFI/Linux/arch-linux.efi' was modified since the last reboot. Skipping copy.
Thanks for taking care of this issue so quickly and for creating this project.
Description: When running ukibak with the '-e /efi' command line option or the 'UKIBAK_ESP' environment variable set to '/efi', the program fails to locate the source image '/EFI/Linux/arch-linux.efi', despite its presence at '/efi/EFI/Linux/arch-linux.efi'. This issue persists regardless of using the command line option or the environment variable.
Steps to Reproduce:
Expected Behavior: The program should recognize the specified EFI partition mount point (either through the '-e' option or the 'UKIBAK_ESP' variable) and locate the source image at the provided path.
Actual Behavior: The program outputs an error message indicating it cannot find the source image, suggesting it does not correctly process the provided mount point path.
Additional Information:
Attempted Troubleshooting: I attempted different values for invoking ukibak with the command line option -e, including the whole path to the uki-image.