A few months ago, I got given a laptop with a very interesting condition. The BIOS setup menu was supposedly inaccessible, and nothing apart from the default boot option works. Time to investigate to see what is actually happening and what we can do about it.

The status quo

When starting the laptop without doing anything special, the default option boots just fine, as expected. However, while pressing F2 during boot causes a beep tone, it ends up falling through to the same behavior as if nothing was pressed. On the other hand, pressing F12 lands us in a very empty boot menu:

The broken boot menu The broken application menu

This, obviously, is not good. The boot menu should (at least) show all bootable UEFI devices in addition to the boot entries that have been created manually.

Populating the boot menu

Of course, the first thing that one would try is to reset the BIOS settings. Since the CMOS battery is quite hidden behind plastic shielding, I instead bridged the CL1_CL2 test point that is located under the RAM slot.

After the BIOS reinitialized, the boot menu looks like the following:

The partially fixed boot menu The partially fixed application menu

The manually created boot option is now gone, and device-based boot options show up instead. However, trying to enter the BIOS setup menu still shows the same fallthrough behavior as it did before.

Luckily, there now is the option to boot from USB storage, so the BIOS flash utilities provided by Fujitsu are a possibility going forward. Note that (at least for the AH532) there are multiple hardware revisions, so I had to go through the device serial number to arrive at the correct set of downloads.1 The website may also offer multiple major firmware revisions, which can’t be switched between outside the factory.2

After flashing the BIOS and rebooting, the boot menu looks normal and pressing F2 to enter the BIOS setup menu works like a charm:

The complete boot menu The complete application menu

Isolating a reproducer

Now that I was back in a working setup, the first thing I did was to make a backup of the current configuration. For that, I made an image of the Winbond 25Q32BVSIG SPI flash chip3 that is marked as “U35” on the motherboard, as it contains the whole UEFI PI firmware volume including executable code and data storage. Whenever something is broken, I can now just flash back the image instead of going through a full reset-CMOS-and-update-firmware cycle.

Location of the U35 chip on the motherboard

For easier testing, I also wanted a better reproducer than “reinstall your distribution of choice”. Therefore, I tried the first thing that came to mind, and it immediately broke the boot menu again:

# efibootmgr -c
BootOrder: 0000
Boot0000* Linux

Warning: Do NOT run this command twice. Doing so made the boot menu completely inaccessible.

Excursion: UEFI boot entry handling

At a high level, UEFI stores data in a large key-value store that is collectively called “UEFI variables”. Included in those variables are (among other things) boot entries and related settings. Variable access is done through standardized interfaces that are documented in the UEFI specification.

Boot entries are stored in entries named BootXXXX, where XXXX is a four digit hexadecimal number. Boot option order is determined through the BootOrder entry, which lists all four digit hexadecimal numbers in the order that they should appear in.

On my Framework laptop, the boot entries are set up as follows:

BootOrder: 0002, 0001, 2001, 2002, 2003
Boot0001: "Windows Boot Manager"
Boot0002: "GRUB"
Boot2001: "EFI USB Device"
Boot2002: "EFI DVD/CDROM"
Boot2003: "EFI Network"

Putting the pieces together

Suddenly, the efibootmgr -c output above doesn’t look all that confidence-inspiring. The command is supposed to create a new entry and insert it at the top of the boot entry list, but it ended up clearing the entire list instead. Running efibootmgr on a fresh boot also doesn’t result in quite the expected output:

# efibootmgr -v
Could not read variable 'BootNext': No such file or directory
Could not read variable 'BootCurrent': No such file or directory
Could not read variable 'BootTimeout': No such file or directory
Could not read variable 'BootOrder': No such file or directory
No BootOrder is set; firmware will attempt recovery
Could not read variable 'MirrorCurrent': No such file or directory
Could not read variable 'MirrorRequest': No such file or directory

It appears that Linux is unable to read existing variables from storage, which is immediately confirmed by inspecting the source of truth:

# ls -al /sys/firmware/efi/efivars/
total 0
drwxr-xr-x 2 root root 0 Jan 15 16:09 .
drwxr-xr-x 5 root root 0 Jan 15 16:09 ..

Note: At this point, I checked that Windows and various other UEFI tools are able to read the variables just fine, so Linux’ output is confirmed to be incorrect.

Now, this explains why the custom boot entries and the device-based boot entries end up being gone. efibootmgr can’t find any existing boot entry setup and just assumes that it can create a new setup without repercussions.

But why does it make the BIOS setup unusable? Using UEFITool, I inspected the flash image I made earlier, and reconstructed the following entries:

BootOrder: 000E, 000D, 0006, 0007, 0008, 0009, 000A, 000B
Boot0000: "BIOS Setup"
Boot0001: "Boot Menu"
Boot0002: "Diagnostic Screen"
Boot0003: "Recovery and Utility"
Boot0004: "Diagnostic Program"
Boot0005: "Diagnostic Progrogram ROM"
Boot0006: "Floppy Disk Drive"
Boot0007: "Drive0 HDD"
Boot0008: "CD/DVD Drive"
Boot0009: "NETWORK"
Boot000A: "USB HDD"
Boot000B: "USB CD/DVD"
Boot000C: "Erase Disk"
Boot000D: "Windows Boot Manager"
Boot000E: "proxmox"

Oh, no…

“BIOS Setup” is an actual boot menu entry.

And it gets overwritten by the new boot entry that gets placed erroneously.

Note: Attentive readers might have noticed the reason for why everything breaks completely when running efibootmgr -c twice: The second boot entry that is created would be Boot0001, which successfully replaces “Boot Menu”.

Creating a temporary band-aid

Now that I knew what went wrong, I was able to create a small program that resets the boot order, as well as the BIOS setup and boot menu entries to their expected contents.

Naturally, this isn’t a great solution, since users will continue to brick their installations initially, just like they did for the last 10 years. However, this is everything that I managed to research so far, and the band-aid fix makes it reasonable for publication.

I will look into fixing this properly at some point in the future, and if I manage to do so this post will probably get a part two, so stay tuned. (Apparently Jekyll supports RSS?)

  1. On incompatible hardware, the DOS-based flash utility fails with “BIOS part numbers do not match”. 

  2. On incompatible software revisions, the DOS-based flash utility fails with “BIOS layout does not match”. 

  3. This can be done using flashrom and a standard CH341A-based programmer (that is wired up for 25 series SPI and 3.3V).