Fit images and EFI_LOAD_FILE2_PROTOCOL
François Ozog
francois.ozog at linaro.org
Tue Oct 6 14:15:42 CEST 2020
On Tue, 6 Oct 2020 at 14:05, Heinrich Schuchardt <xypron.glpk at gmx.de> wrote:
> On 06.10.20 12:38, Grant Likely wrote:
> >
> >
> > On 06/10/2020 05:35, Heinrich Schuchardt wrote:
> >> Am 6. Oktober 2020 00:37:58 MESZ schrieb Grant Likely
> >> <grant.likely at arm.com>:
> >>>
> >>>
> >>> On 03/10/2020 09:51, Heinrich Schuchardt wrote:
> >>>> Hello Ilias, hello Christian,
> >>>>
> >>>> with commit ec80b4735a59 ("efi_loader: Implement FileLoad2 for
> >>> initramfs
> >>>> loading") Ilias provided the possibility to specify a device path
> >>>> (CONFIG_EFI_INITRD_FILESPEC) from which an initial RAM disk can be
> >>>> served via the EFI_FILE_LOAD2_PROTOCOL.
> >>>>
> >>>> Ard extended the Linux EFI stub to allow loading the initial RAM disk
> >>>> via the EFI_FILE_LOAD2_PROTOCOL with the utmost priority.
> >>>>
> >>>> With commit ecc7fdaa9ef1 ("bootm: Add a bootm command for type
> >>>> IH_OS_EFI") Cristian enabled signed FIT images that contain a device
> >>>> tree and a UEFI binary (enabled by CONFIG_BOOTM_EFI=y).
> >>>>
> >>>> In the DTE calls we have discussed that it is unfortunate that we do
> >>> not
> >>>> have a method to validate initial RAM images in the UEFI context.
> >>>>
> >>>> To me it would look like a good path forward to combine the two
> >>> ideas:
> >>>>
> >>>> * Let the signed FIT image (of type IH_OS_EFI) contain a RAM disk
> >>>> * Pass location and size to the UEFI subsystem and serve them via
> >>>> the EFI_FILE_LOAD2_PROTOCOL.
> >>>>
> >>>> We could also extend the bootefi command to be callable as
> >>>>
> >>>> bootefi $kernel_addr_r $ramdisk_addr_r:$filesize $fdt_addr_r
> >>>>
> >>>> like the booti command to serve an initial RAM disk.
> >>>>
> >>>> What are your thoughts?
> >>>
> >>> Hi Heinrich,
> >>>
> >>> I've got concerns about this approach. Even though it uses the UEFI
> >>> infrastructure, images deployed in this way are U-Boot specific and
> >>> won't ever be applicable on EDK2 or other UEFI implementations.
> >>>
> >>> However there is another way to approach it which I think Francois
> >>> touched on. If instead a UEFI stub was added to the FIT image, in the
> >>> same way that the kernel has a UEFI stub, then the logic of decoding
> >>> the
> >>> FIT and choosing the correct DTB & initrd can be part of the image and
> >>> it becomes applicable to any UEFI implementation. It would also address
> >>>
> >>> Ard's concern of loading the FIT into memory, and then copying due to
> >>> the EFI_FILE_LOAD2 path. The FIT stub would already know the image is
> >>> in
> >>> RAM, that is is reserved correctly, and just pass the correct addresses
> >>>
> >>> to the kernel as part of the normal boot flow.
> >>>
> >>> Signing would also be taken care of because the whole FIT can be
> >>> signed,
> >>> and that signature would be checked when it gets loaded.
> >>>
> >>> Thoughts?
> >>>
> >>
> >> The gain of a fit image in U-Boot used for calling the Linux kernel
> >> via the EFI stub vs calling the legacy entry point comes down to
> >> providing the EFI_RNG_PROTOCOL to be used for KASLR.
> >
> > I agree with that, but that is not my concern.
> >
> > My concern is that the FIT image format will only be supported by
> > U-Boot. Other UEFI implementations do not implement it.
> >
> > On the other hand, adding a UEFI Stub to the FIT image format makes it a
> > generic solution that can be used by any UEFI implementation. This would
> > be separate from the linux kernel's UEFI stub, and should only deal with
> > choosing the appropriate kernel/initrd/dtb from the FIT and then calling
> > into the kernel's stub to actually boot the kernel.
> >
> >> For initrd a stub UEFI binary will work. But if you want to provide a
> >> kernel specific dtb with the same stub binary it will require a new
> >> service for device-tree fixups.
> >
> > Devicetree fixups indeed needs to be solved. I would propose registering
> > a new protocol for fixups. If the protocol is present, then stub can
> > call it. If not, then the DTB from the fit should be used unmodified.
>
> For such a protocol we will need to decide who will make the memory
> reservation needed to encompass the increasing size of the device tree.
>
> As the caller of the protocol does not know how much memory is needed
> for the fixup I think the allocation should be done by the callee.
>
> A definition of the protocol could look like this:
>
> #define EFI_FDT_FIXUP_PROTOCOL_GUID \
> {0xfa68b9a7, 0xb5fd, 0x49f5, \
> {0x87, 0x93, 0x11, 0xfd, 0xb5, 0x6a, 0x8d, 0x41}
>
> typedef
> EFI_STATUS
> (EFIAPI *EFI_FDT_FIXUP) (
> IN EFI_FDT_FIXUP_PROTOCOL *This,
> IN OUT VOID **Fdt,
> IN BOOLEAN Install,
> };
>
> typedef struct _EFI_FDT_FIXUP_PROTOCOL {
> EFI_FIX_UP Fixup;
> } EFI_FDT_FIXUP_PROTOCOL;
>
> where
>
> * This - pointer to the calling context
> * Fdt - On entry pointer to the address of the original device tree,
> on exit pointer to the address of the new device tree.
> If an error is returned, the value of *Fdt is undefined.
> * Install - If TRUE, install the resulting device tree as
> configuration table.
>
> The 'Fixup' service
>
> * makes a memory reservation using EFI_BOOT_SERVICES.AllocatePages(),
> * copies the device tree to the new memory area,
> * applies the fixups,
> * installs the resulting device tree as configuration table
> if Install==TRUE.
>
> In case of an error the protocol implementation releases the memory by
> calling EFI_BOOT_SERVICES.FreePages().
>
> Return values:
>
> * EFI_INVALID_PARAMETER - Fdt is NULL.
> * EFI_INVALID_PARAMETER - *Fdt does not point to a valid device tree.
> * EFI_OUT_OF_RESOURCES - Not enough memory for the operation.
> * EFI_SUCCESS - The fixup was successful and the device-tree was
> installed if requested.
>
> I like the idea;
it can do for fixups what we have for firmware updates: UEFI update
capsules reach UEFI, there are UEFI drivers for underlying firmware
components to adapt the request.
Platforms can append relevant drivers to call in TF-A or OP-TEE for fixups.
The implementation is platform specific. For some platforms this would
result in an SMC call to get the fixups done, for others, this is about
reading memory locations.
In addition to presenting no constraints between platforms within an
architecture, it is also architecture agnostic.
Best regards
>
> Heinrich
>
--
François-Frédéric Ozog | *Director Linaro Edge & Fog Computing Group*
T: +33.67221.6485
francois.ozog at linaro.org | Skype: ffozog
More information about the U-Boot
mailing list