Page MenuHomeFreeBSD

loader.efi: Build a boot menu based on UEFI boot manager
Needs ReviewPublic

Authored by stephane.rochoy_stormshield.eu on Thu, Mar 19, 1:49 PM.

Details

Summary

Following the disussion in D55559, here's a (very shy) first step starting to
demonstrate the use of the UEFI Boot Manager to build a menu with Lua to let the
user pick a partition.

The patch is enabled with the WITH_LOADER_EFIBOOTMGRMENU option and require to
manually populate ESP's /EFI/FreeBSD/lua directory with the content of
stand/lua/ (creating any missing directory).

This is a PoC, so it is advised to use the BootNext mechanism to boot the
resulting loader.efi ;)

It expose BootCurrent, Timeout and BootOrder under the efibootmgr Lua
module as follow:

  • boot_current: an integer, e.g., 5 for Boot0005.
  • timeout: an integer for the timeout duration in seconds.
  • boot_order: a table (with first index being 1) were each element is an associative array with the following keys:
    • bootnum: boot number as an integer, e.g., 5 for Boot0005
    • description: the description (a.k.a., label) as a string
    • attributes: attributes as an integer
    • is_active: boolean telling if the active attribute is set
    • is_hidden: boolean telling if the hidden attribute is set
    • devpath: device path as a string

It then start efibootmgr.lua instead of loader.lua.

It don't boot anything. I first wanted to validate I correctly understood the
target approach. I also need some guidance on how to convert a load option into
the required things necessary to boot a given kernel. E.g., how do I map it to
things like currdev, kernelname vfs.root.mountfrom, etc…

Some implementation notes:

  • it change liblua's LUAPATH from /boot/lua (in the booted partition) to

/EFI/FreeBSD/lua in the ESP

  • it conflict with LOADER_KBOOT (don't know why):
--- all_subdir_stand/kboot ---
ld: error: undefined symbol: efi_global_getenv
>>> referenced by lefibootmgr.c:29 (…/stand/liblua/lefibootmgr.c:29)
>>>               lefibootmgr.o:(luaopen_efibootmgr) in archive
…/amd64.amd64/stand
/liblua/liblua.a
Test Plan

Here is a sample output:

Setting currdev to disk0p1:
FreeBSD/amd64 EFI loader, Revision 3.0
(Thu Mar 19 14:09:07 CET 2026 stephaner@sns-ci-main.delta-amd64.labo.int)

   Command line arguments: loader.efi
   Image base: 0x6d36c000
   EFI version: 2.80
   EFI Firmware: American Megatrends (rev 5.27)
   Console: efi (0x1000)
   Load Path: \EFI\BOOT\efibootmgrmenu.efi
   Load Device: PciRoot(0x0)/Pci(0xD,0x0)/USB(0x1,0x0)/HD(1,MBR,0x90909090,0x1,0x10418)
   BootCurrent: 0006
   BootOrder: 0005 0006[*] 0001 0004 0002 0000 0003
package.path:    /EFI/FreeBSD/lua/?.lua
loader.lua_path: /EFI/FreeBSD/lua
>>> EFI Boot Manager Menu
[1]  Boot0005 UEFI OS*
        attributes: 0x1<ACTIVE,CATEGORY_BOOT,>
        devpath:    PciRoot(0x0)/Pci(0xD,0x0)/USB(0x1,0x0)/HD(1,MBR,0x90909090,0x1,0x10418)/\EFI\BOOT\BOOTX64.EFI
[2] +Boot0006 efibootmgr*
        attributes: 0x1<ACTIVE,CATEGORY_BOOT,>
        devpath:    HD(1,MBR,0x90909090,0x1,0x10418)/\EFI\BOOT\efibootmgrmenu.efi
[3]  Boot0001 UEFI OS*
        attributes: 0x1<ACTIVE,CATEGORY_BOOT,>
        devpath:    HD(4,GPT,7E15E2B7-CECA-11F0-8F93-000DB42C8588,0x401000,0x32000)/\EFI\BOOT\BOOTX64.EFI
[4]  Boot0004 BACKUP*
        attributes: 0x1<ACTIVE,CATEGORY_BOOT,>
        devpath:    HD(4,GPT,7E15E2B7-CECA-11F0-8F93-000DB42C8588,0x401000,0x32000)/\EFI\BOOT\backup.efi
[5]  Boot0002 MAIN*
        attributes: 0x1<ACTIVE,CATEGORY_BOOT,>
        devpath:    HD(4,GPT,7E15E2B7-CECA-11F0-8F93-000DB42C8588,0x401000,0x32000)/\EFI\BOOT\main.efi
[6]  Boot0000 TEST*
        attributes: 0x9<ACTIVE,HIDDEN,CATEGORY_BOOT,>
        devpath:    VenHw(99E275E7-75A0-4B37-A2E6-C5385E6C00CB)
[7]  Boot0003 debian*
        attributes: 0x9<ACTIVE,HIDDEN,CATEGORY_BOOT,>
        devpath:    VenHw(99E275E7-75A0-4B37-A2E6-C5385E6C00CB)
Default: Boot0005 UEFI OS
Choose:
Booting Boot0005 UEFI OS...
Loading kernel...
No kernel set, failed to load from module_path
can't load 'kernel'
<<< EFI Boot Manager Menu

can't load 'kernel'

Type '?' for a list of commands, 'help' for more detailed help.
OK

Diff Detail

Repository
rG FreeBSD src repository
Lint
Lint Passed
Unit
No Test Coverage
Build Status
Buildable 71510
Build 68393: arc lint + arc unit