bootstd: Support for distro specific EFI folders

Heinrich Schuchardt heinrich.schuchardt at canonical.com
Sun Dec 3 11:54:53 CET 2023


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.

Best regards

Heinrich


More information about the U-Boot mailing list