rhboot / shim

UEFI shim loader
Other
819 stars 289 forks source link

BOOTX64.EFI from the default /EFI/BOOT directory causes UEFI Reset System reboot loop #545

Closed kayrus closed 1 year ago

kayrus commented 1 year ago

Ubuntu 22.04, shim-signed 1.51+15.4-0ubuntu9, grub-efi-amd64-signed 1.182~22.04.1+2.06-2ubuntu10

grub-install command installs a fbx64.efi file into the EFI/BOOT directory along with shim and grub binaries. This file causes an EFI boot to fail with the Reset System text on the screen and further reboot.

Removing the fbx64.efi file from the shim binary directory fixes an issue and the shim boots a proper grubx64.efi loader.

I'm curious whether this issue occurs because of the alphabetical order of files and fbx64.efi stands earlier than grubx64.efi. I wonder why is this happening and how to fix this? If grub package is updated, the grub-install command is executed automatically and I need to remove the fbx64.efi file again.

See also my commant https://askubuntu.com/a/1446066

julian-klode commented 1 year ago

Your firmware is broken and/or has a write block for the variables or something.

The fbx64.efi adds the boot entries to the UEFI boot menu and then resets so your UEFI can boot into it.

Some day in the future fbx64.efi will be integrated into the main shimx64.efi and we can do without the reboots.

I'd have a look at your firmware settings to see if there's anything about protected boot options or something like that turned on in there

kayrus commented 1 year ago

I performed a couple of tests after reading the README.tpm. My laptop's BIOS (or maybe UEFI?) supports only \EFI\BOOT as a default entry. Even though I can see and manage boot options via efibootmgr they don't make sense during the boot process. Boot always happens from the \EFI\BOOT. I also removed everything from the \EFI\BOOT and executed grub-install, and it installed only shim, fb and mm efi files :\ So eventually it looks like I found a workaround by copying a grubx64.efi and grub.cfg into the \EFI\BOOT directory :\ But basically every time a regular fallback tries to boot into ubuntu, it creates a boot entry which is visible only via efibootmgr. It creates a lot of duplicates according to an amount of failed boot tries.

P.S. I noticed the same bug with HP 2170p and Lenovo X1 Carbon Gen 8. Probably it makes sense to rethink the logic of the fallback or probably you can give me some hints of how to debug the root cause for this behavior? Looks like there is something wrong with the fbx64 so it reboots the laptop, right? @julian-klode, can you provide some debug hints?

UPD: a removable USB media with ubuntu 22.04 image boots perfectly fine and doesn't reboot. I'm not quite sure why USB vs SSD (SATA with HP and NVME with Lenovo) behaviors are different.

UPD2: Ubuntu USB image doesn't have a fallback binary, only: ls /mnt/EFI/boot/ bootx64.efi grubx64.efi mmx64.efi

TriMoon commented 1 year ago

See also my commant https://askubuntu.com/a/1446066

Quoting from that link:

I don't know why (probably because I use MBR partitions, NOT GPT!)

You need GPT for UEFI to function correctly IIRC... (Because MBR is for legacy boot)

kayrus commented 1 year ago

I wrote this comment when I had MBR. I already switched to GPT and basically this hasn't changed the behaviors of the shim.

TriMoon commented 1 year ago

Then, see https://github.com/rhboot/shim/issues/545#issuecomment-1374930713 because that functionality is not new :woman_shrugging: Just to rule out any new bugs that cause it, did you try any older/newer versions as shim-signed 1.51+15.4-0ubuntu9?

slowpeek commented 1 year ago

@julian-klode

The fbx64.efi adds the boot entries to the UEFI boot menu and then resets so your UEFI can boot into it.

This is not quite true. Reset only happens under two conditions:

Otherwise it runs the first created entry

https://github.com/rhboot/shim/blob/f23883ccf78f1f605a272f9e5700f47e5494a71d/fallback.c#L1181-L1189

@kayrus

You can find details about the fallback binary in the dedicated README. Its sole use is populating boot entires with data from BOOTX64.CSV (or BOOT.CSV) found under its parent EFI/ dir. When done it either does reset or runs the first created entry right away (I outlined the logic above)

If your firmware only looks into EFI/BOOT/, you can install grub as removable: grub-install --removable .... Notice, the fallback binary is absent this way, shim (installed as EFI/BOOT/BOOTX64.EFI) just starts grubx64.efi.

Btw grub binaries installed into EFI/ubuntu and EFI/BOOT are not the same, you should not just copy one to another.

As for debugging. There are two shim efi vars to affect verbosity: SHIM_VERBOSE and FALLBACK_VERBOSE. Both can be set with mokutil, but not in jammy, the tool is too old there. You should boot with ubuntu 22.10 or debian 11.6.0 live image and issue:

sudo mokutil --set-verbosity true
sudo mokutil --set-fallback-verbosity true

If you still somehow have problems with the fallback, you can force it to never reset with FB_NO_REBOOT shim efi var (again, not with jammy's mokutil):

sudo mokutil --set-fallback-noreboot true
dennis-tseng99 commented 1 year ago

The fbx64.efi adds the boot entries to the UEFI boot menu and then resets so your UEFI can boot into it.

This is not quite true. Reset only happens under two conditions:

fallback_should_prefer_reset() is true (= tpm is present) get_fallback_no_reboot() is false (= FB_NO_REBOOT shim efi var is not set) Otherwise it runs the first created entry

Because the 1st boot entry is not created correctly, the first_new_option variable is always be NULL such that try_start_first_option(image) will do nothing but return EFI_SUCCESS right away. It will then just call ResetSystem() again, and have a loop finally. The possible reason why the 1st boot entry is not correctly created is your FileDevicePath() didn't work very well. Maybe you need to check whether your file DP can be printed out or not. Here is my file DP in my system:

file DP: PciRoot(0)/Pci(0x02,0x04)/Pci(0x0,0x0)/HD(1,GPT,875E2293-E4E5-482F-AEFD-234073DC3959)/\EFI\opensuse\shim.efi
full_device_path = FileDevicePath(this_image->DeviceHandle, fullpath);
if (!full_device_path) {
    efi_status = EFI_OUT_OF_RESOURCES;
    goto done;
}
dps = DevicePathToStr(full_device_path);
VerbosePrint(L"file DP: %s\n", dps);