bootstd: Support for distro specific EFI folders

Heinrich Schuchardt heinrich.schuchardt at canonical.com
Sun Dec 3 19:33:46 CET 2023


On 12/3/23 19:22, Simon Glass wrote:
> Hi Heinrich,
> 
> On Sun, 3 Dec 2023 at 10:53, Heinrich Schuchardt
> <heinrich.schuchardt at canonical.com> wrote:
>>
>> On 12/3/23 18:44, Simon Glass wrote:
>>> Hi Heinrich,
>>>
>>> On Sun, 3 Dec 2023 at 03:55, Heinrich Schuchardt
>>> <heinrich.schuchardt at canonical.com> wrote:
>>>>
>>>> On 12/3/23 00:38, Shantur Rathore wrote:
>>>>> Hi Simon,
>>>>>
>>>>> On Sat, Dec 2, 2023 at 6:33 PM Simon Glass <sjg at chromium.org> wrote:
>>>>>>
>>>>>> Hi,
>>>>>>
>>>>>> On Mon, 20 Nov 2023 at 00:02, Ilias Apalodimas
>>>>>> <ilias.apalodimas at linaro.org> wrote:
>>>>>>>
>>>>>>> Hi Mark,
>>>>>>>
>>>>>>> On Sun, 19 Nov 2023 at 19:38, Mark Kettenis <mark.kettenis at xs4all.nl> wrote:
>>>>>>>>
>>>>>>>>> Date: Sat, 18 Nov 2023 23:52:11 +0100
>>>>>>>>> From: Heinrich Schuchardt <heinrich.schuchardt at canonical.com>
>>>>>>>>
>>>>>>>> Hi Heinrich,
>>>>>>>>
>>>>>>>>> On 11/18/23 22:28, Shantur Rathore wrote:
>>>>>>>>>> Hi Heinrich,
>>>>>>>>>>
>>>>>>>>>> On Fri, Nov 17, 2023 at 3:12 PM Heinrich Schuchardt
>>>>>>>>>> <heinrich.schuchardt at canonical.com> wrote:
>>>>>>>>>>>
>>>>>>>>>>> On 11/16/23 19:45, Shantur Rathore wrote:
>>>>>>>>>>>> On Thu, Nov 16, 2023 at 6:15 PM Heinrich Schuchardt
>>>>>>>>>>>> <heinrich.schuchardt at canonical.com> wrote:
>>>>>>>>>>>>>
>>>>>>>>>>>>> On 11/16/23 17:52, Shantur Rathore wrote:
>>>>>>>>>>>>>> Hi Simon,
>>>>>>>>>>>>>>
>>>>>>>>>>>>>> Currently bootstd - bootmethod_efi only looks for the default
>>>>>>>>>>>>>> bootxx64.efi in /EFI/boot folder only.
>>>>>>>>>>>>>> Generally many distros end up putting their bootloaders in
>>>>>>>>>>>>>> EFI/<distro> folders like EFI/ubuntu and EFI/debian etc.
>>>>>>>>>>>>>>
>>>>>>>>>>>>>> In x86 worlds, the NVRAM is modified and new boot entries are added to
>>>>>>>>>>>>>> support these but in the U-boot world the NVRAM variables are
>>>>>>>>>>>>>> read-only.
>>>>>>>>>>>>>
>>>>>>>>>>>>> I guess you are referring to UEFI boot options. These typically are not
>>>>>>>>>>>>> stored in non-volatile RAM but on a SPI flash device.
>>>>>>>>>>>>>
>>>>>>>>>>>>
>>>>>>>>>>>> Thanks for correcting me.
>>>>>>>>>>>>
>>>>>>>>>>>>>>
>>>>>>>>>>>>>> What would be the best way to implement this?
>>>>>>>>>>>>>>
>>>>>>>>>>>>>> I was thinking of having a "efi_prefixes" environment variable which
>>>>>>>>>>>>>> can be set to "ubuntu debian centos" etc and bootmethod_efi can try
>>>>>>>>>>>>>> all of them. Will bootmethod_efi be able to support multiple entries (
>>>>>>>>>>>>>> thinking of multiboot ) ?
>>>>>>>>>>>>>
>>>>>>>>>>>>> On my laptop I have:
>>>>>>>>>>>>>
>>>>>>>>>>>>> EFI/Microsoft/Boot/bootmgr.efi
>>>>>>>>>>>>> EFI/Microsoft/Boot/memtest.efi
>>>>>>>>>>>>> EFI/Boot/bootx64.efi
>>>>>>>>>>>>> EFI/Boot/fbx64.efi
>>>>>>>>>>>>> EFI/Boot/mmx64.efi
>>>>>>>>>>>>> EFI/debian/shimx64.efi
>>>>>>>>>>>>> EFI/debian/grubx64.efi
>>>>>>>>>>>>> EFI/debian/mmx64.efi
>>>>>>>>>>>>> EFI/debian/fbx64.efi
>>>>>>>>>>>>> EFI/ubuntu/grubx64.efi
>>>>>>>>>>>>> EFI/ubuntu/shimx64.efi
>>>>>>>>>>>>> EFI/ubuntu/mmx64.efi
>>>>>>>>>>>>>
>>>>>>>>>>>>> Obviously each installed operating system provides multiple EFI binaries
>>>>>>>>>>>>> and non uses the fallback file name BOOT<ARCH>.EFI. A value "ubuntu
>>>>>>>>>>>>> debian centos" would not be able to describe which file you are looking
>>>>>>>>>>>>> for.
>>>>>>>>>>>>>
>>>>>>>>>>>>> We already have the U-Boot command line eficonfig and efidebug commands
>>>>>>>>>>>>> to set up UEFI boot options which can describe which EFI binary to load
>>>>>>>>>>>>> and which command line to pass to it. These are considered by the
>>>>>>>>>>>>> existing boot flows.
>>>>>>>>>>>>
>>>>>>>>>>>> So, I am building a new RockPro64 based cluster and using Canonical
>>>>>>>>>>>> MAAS to set them up automatically, booting them up using DHCP and
>>>>>>>>>>>> installing them over the network.
>>>>>>>>>>>> I configured an Armbian image using Packer to be compatible with MAAS
>>>>>>>>>>>> and it happily installs it. As part of installation process, a
>>>>>>>>>>>> grub-install is run which installs the grub efi,
>>>>>>>>>>>> this EFI ends up in EFI/debian instead of expected EFI/boot.
>>>>>>>>>>>> To be able to make it boot, I have to add commands to move it to
>>>>>>>>>>>> EFI/boot. I am trying to find a way in U-Boot that would allow me to
>>>>>>>>>>>> skip this step.
>>>>>>>>>>>> With eficonfig if I understand correctly, it would need manual
>>>>>>>>>>>> intervention to create boot entries.
>>>>>>>>>>>>
>>>>>>>>>>>>>
>>>>>>>>>>>>> If you are installing the shim-signed package on Ubuntu, the EFI boot
>>>>>>>>>>>>> option for Ubuntu is set up by EFI/BOOT/BOOT<ARCH>.EFI using the content
>>>>>>>>>>>>> of EFI/ubuntu/BOOT<ARCH>.CSV. This is done before ExitBootServices() and
>>>>>>>>>>>>> therefore should work with current U-Boot.
>>>>>>>>>>>>>
>>>>>>>>>>>>> Patches are pending upstream to make EFI variables writable from Linux
>>>>>>>>>>>>> if they are stored in the RPMB partition in the eMMC. See this series:
>>>>>>>>>>>>>
>>>>>>>>>>>>> https://lore.kernel.org/linux-efi/20231107054057.1893-2-masahisa.kojima@linaro.org/
>>>>>>>>>>>>>
>>>>>>>>>>>>
>>>>>>>>>>>> Would it be possible to save it in SPI Flash as the U-Boot environment ?
>>>>>>>>>>>
>>>>>>>>>>> Currently this is not supported by U-Boot.
>>>>>>>>>>>
>>>>>>>>>>> The U-Boot environment variables can be stored in lots of different
>>>>>>>>>>> places SPI flash is only one of these. But none of these locations is
>>>>>>>>>>> protected from OS access which would be preferable for UEFI variables
>>>>>>>>>>> for security reasons.
>>>>>>>>>>>
>>>>>>>>>>> To support boards without eMMC the right way forward would be writing a
>>>>>>>>>>> new implementation of the OP-TEE standalone MM which writes the
>>>>>>>>>>> variables to SPI flash instead of the RPMB partition and ensures that
>>>>>>>>>>> the SPI flash' MMIO registers are protected against access from the
>>>>>>>>>>> non-secure world.
>>>>>>>>>>
>>>>>>>>>> Thanks for explaining this to me.
>>>>>>>>>> This seems like a long way to go, for now what would be an acceptable
>>>>>>>>>> solution, some options are
>>>>>>>>>>
>>>>>>>>>> 1. Allow to set a space separated efi_prefixes (e.g. "boot ubuntu
>>>>>>>>>> debian") variable which is ready by bootmeth_efi and used as
>>>>>>>>>> efi/<efi_prefix> instead of efi/boot.
>>>>>>>>>> 2. Improve bootmeth_efi to find all bootxxxx.efi in efi/ folder and
>>>>>>>>>> present all them as bootflows to bootstd.
>>>>>>>>>
>>>>>>>>> As mentioned in a prior mail ubuntu/bootxxxx.efi and debian/bootxxxx.efi
>>>>>>>>> don't exist. I would prefer not to add any distro specific stuff in
>>>>>>>>> upstream U-Boot. Instead we will continue to drive what Linaro has
>>>>>>>>> suggested to improve U-Boot EFI variables support in Linux.
>>>>>>>>
>>>>>>>> I agree that adding hacks like this is not a good idea.
>>>>>>>
>>>>>>> + 1
>>>>>>>
>>>>>>>>
>>>>>>>> The Linaro approach that involves OP-TEE makes for a fairly complex
>>>>>>>> solution.  And there are plenty of boards that have neither eMMC nor
>>>>>>>> SPI flash.  If Secure Boot is not a requirement (and I'd argue that
>>>>>>>> for most "hobbyist" boards it isn't) storing the EFI variables in a
>>>>>>>> file on the ESP (as implemented by the CONFIG_EFI_VARIABLE_FILE_STORE
>>>>>>>> Kconfig option) is a workable alternative.  And this is actually what
>>>>>>>> the rockpro64-rk3399_defconfig enables.
>>>>>>>
>>>>>>> Even in that case, preseeding the variables can enable uefi secure
>>>>>>> boot. But you have to establish a chain of trust since the
>>>>>>> authenticated EFI variables are part of  the u-boot binary.
>>>>>>>
>>>>>>>>
>>>>>>>> I noticed that the latest EBBR attempts to standardize this:
>>>>>>>>
>>>>>>>>      https://arm-software.github.io/ebbr/index.html#document-chapter5-variable-storage
>>>>>>>>
>>>>>>>> Not sure what the status here is.
>>>>>>>
>>>>>>> Heinrich and I were the ones who proposed the standardization. The
>>>>>>> idea is to eventually fix it for all boards and we are working on it,
>>>>>>>
>>>>>>>> But if the Linux kernel folks
>>>>>>>> accept that alternative implementations for runtime EFI variable
>>>>>>>> access are a thing, then a method that modifies the file would be
>>>>>>>> possible as well.  Or maybe it is good enough to implement support for
>>>>>>>> this in the efivar library.
>>>>>>>
>>>>>>> Yes to both. I discussed the idea during Linux Plumbers. All
>>>>>>> approaches have some pros and cons, you can find some details here
>>>>>>> [0].
>>>>>>> Implementing support to efitool is straightforward, but a bit too
>>>>>>> hacky for my taste. An obvious disadvantage is that it's hard to sync
>>>>>>> the kernel/file view after an update.
>>>>>>> The plan right now is to investigate overwriting RT functions and use
>>>>>>> kernel-provided ones that modify the file (which is probably going to
>>>>>>> be passed in a config table)
>>>>>>>
>>>>>>> [0] https://lpc.events/event/17/contributions/1653/
>>>>>>
>>>>>> I don't know much about this area, but it strikes me that things are
>>>>>> getting a little too complicated.
>>>>>>
>>>>>> U-Boot wants to show a menu of available Operating Systems. With UEFI
>>>>>> it isn't even possible to know what is being booted. We just have to
>>>>>> jump into the .efi file and hope.
>>>>>>
>>>>>> Can we work together on adding a new, separate file which lists the
>>>>>> .efi files and what they are for? Then the user can select one.
>>>>>>
>>>>> To add - EFI/BOOT/BOOTXXXX.efi is optional [0] and isn't installed by
>>>>> generic ARM
>>>>> distros (debian, armbian.. maybe more)
>>>>>
>>>>> +1 for this. This can be implemented as part of bootmeth_efi (in blk
>>>>> mode) where instead
>>>>> of checking hardcoded EFI/BOOT/BOOTXXXX.efi, it can follow one of the
>>>>> following options
>>>>>
>>>>> 1. Scan and list all available .efi files - EFI/**/*.efi
>>>>> Pros - Allows all the possible boot options to be shown to user
>>>>> Cons - A 'bootflow scan -b' might not boot the system by default as it
>>>>> might depend on
>>>>> which efi file is scanned first. Some installs have mmaa64.efi
>>>>>
>>>>> 2. Scan and list all available .efi files that match the
>>>>> "bootmeth_efi_regex" variable if available.
>>>>> This variable can be configured to allow valid names example
>>>>> "EFI\/.*\/(boot|grub|fb|shim).*efi"
>>>>> Pros - Allows to control only efi files that can boot the system by default.
>>>>> Cons - Might be an issue in environments without CONFIG_REGEX
>>>>>
>>>>> 3. Scan all the folders EFI/* for EFI file prefixes controlled by
>>>>> "bootmeth_efi_name_prefixes" variable
>>>>> This variable can be a space separated list of all valid prefixes the
>>>>> user is interested in. e.g. "boot grub fb shim"
>>>>> Pros - This allows control on what EFI files to look for without being
>>>>> depended on CONFIG_REGEX
>>>>> Cons - I can't think of, please do tell.
>>>>>
>>>>> After this, bootmeth_efi can set up more than 1 bootflows that are bootable.
>>>>>
>>>>> [0] - https://www.rodsbooks.com/efi-bootloaders/principles.html
>>>>>
>>>>> Kind regards,
>>>>> Shantur
>>>>
>>>> U-Boot should remain be a compliant UEFI implementation. We shall not
>>>> scan any other directories than those described in the UEFI specification.
>>>
>>> For the efi bootmeth we can actually do what we like, can't we? Its
>>> behaviour isn't defined by the spec as I understand it.
>>>
>>> I wonder how this works, if the user installs both Debian and Ubuntu
>>> on the machine? I suppose each one separately updates its grub.cfg
>>> with all the OSes it can find on the machine? Then just one of them
>>> gets to be the initial .efi app?
>>>
>>> Can we work together on adding a new, separate file which lists the
>>> .efi files and what they are for?
>>
>> There is already a place defined by the UEFI specification where to put
>> that information: the UEFI boot options defined in variables BOOT####.
>> And this is exactly what all operating system use. The information what
>> the entries are for are in the label part of the boot options. The
>> sequence in which to try loading is in variable BootOrder.
>>
>> There is no point in reinventing the wheel and making it square.
> 
> You have not addressed my question, or I don't understand your answer.
> 
> I am not worried about what the computer does. I am worried about what
> the user sees.
> 
> So far as I can tell there is currently no way to know what you are
> booting (Ubuntu, Debian) until you boot it

Of course I know. These are some of the boot options on my laptop:

Boot0000* Windows Boot Manager 
HD(2,GPT,54e58a37-c1db-4c6b-afda-24340c39cda5,0x109000,0x32000)/File(\EFI\Microsoft\Boot\bootmgfw.efi)WINDOWS.........x...B.C.D.O.B.J.E.C.T.=.{.9.d.e.a.8.6.2.c.-.5.c.d.d.-.4.e.7.0.-.a.c.c.1.-.f.3.2.b.3.4.4.d.5.3.7.2.}...M................
Boot0001* debian 
HD(2,GPT,54e58a14-c1db-4c6b-afda-24340c39cda5,0x109000,0x32000)/File(\EFI\debian\shimx64.efi)
Boot0002* ubuntu 
HD(2,GPT,54e58a14-c1db-4c6b-afda-24340c39cda5,0x109000,0x32000)/File(\EFI\ubuntu\shimx64.efi)
Boot0063* EFI Shell 
HD(2,GPT,54e58a14-c1db-4c6b-afda-24340c39cda5,0x109000,0x32000)/File(Shell.efi)

If I open the boot menu (F12 key on a Lenovo laptop, F8 key on an ASUS 
mainboards), I see a menu which allows me to choose which of Windows, 
Debian, Ubuntu, or the EFI Shell I want to boot.

In U-Boot we already have the same. Please, have a look at the section 
'UEFI boot variable enumeration' in doc/usage/cmd/bootmenu.rst.

Best regards

Heinrich


More information about the U-Boot mailing list