[PATCH 1/1] efi_loader: expose the device-tree file name

Forward and backward compatibility of Linux kernel device-trees is sometimes missing. One solution approach is to load a kernel specific device-tree. This can either be done via a U-Boot scripts (like the one generated by Debian package flash-kernel or by a boot loader like GRUB. The boot loader approach currently requires to know the device-tree name before first boot which makes it unusable for generic images.
Expose the device-tree file name as EFI variable FdtFile. This will allow bootloaders to load a kernel specific device-tree.
Signed-off-by: Heinrich Schuchardt heinrich.schuchardt@canonical.com --- lib/efi_loader/efi_setup.c | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+)
diff --git a/lib/efi_loader/efi_setup.c b/lib/efi_loader/efi_setup.c index e6de685e87..b24feb94dc 100644 --- a/lib/efi_loader/efi_setup.c +++ b/lib/efi_loader/efi_setup.c @@ -26,6 +26,27 @@ void __weak allow_unaligned(void) { }
+/** + * efi_init_fdtfile() - set EFI variable FdtFile + * + * Return: status code + */ +static efi_status_t efi_init_fdtfile(void) +{ + char *val; + + val = env_get("fdtfile"); + if (!val) + return EFI_SUCCESS; + + return efi_set_variable_int(u"FdtFile", + &efi_u_boot_guid, + EFI_VARIABLE_BOOTSERVICE_ACCESS | + EFI_VARIABLE_RUNTIME_ACCESS | + EFI_VARIABLE_READ_ONLY, + strlen(val) + 1, val, false); +} + /** * efi_init_platform_lang() - define supported languages * @@ -250,6 +271,11 @@ efi_status_t efi_init_obj_list(void) if (ret != EFI_SUCCESS) goto out;
+ /* Define EFI variable FdtFile */ + ret = efi_init_fdtfile(); + if (ret != EFI_SUCCESS) + goto out; + /* Indicate supported features */ ret = efi_init_os_indications(); if (ret != EFI_SUCCESS)

Hi Heinrich,
On Tue, 17 Oct 2023 at 11:55, Heinrich Schuchardt < heinrich.schuchardt@canonical.com> wrote:
Forward and backward compatibility of Linux kernel device-trees is sometimes missing. One solution approach is to load a kernel specific device-tree. This can either be done via a U-Boot scripts (like the one generated by Debian package flash-kernel or by a boot loader like GRUB. The boot loader approach currently requires to know the device-tree name before first boot which makes it unusable for generic images.
Expose the device-tree file name as EFI variable FdtFile. This will allow bootloaders to load a kernel specific device-tree.
Signed-off-by: Heinrich Schuchardt heinrich.schuchardt@canonical.com
lib/efi_loader/efi_setup.c | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+)
diff --git a/lib/efi_loader/efi_setup.c b/lib/efi_loader/efi_setup.c index e6de685e87..b24feb94dc 100644 --- a/lib/efi_loader/efi_setup.c +++ b/lib/efi_loader/efi_setup.c @@ -26,6 +26,27 @@ void __weak allow_unaligned(void) { }
+/**
- efi_init_fdtfile() - set EFI variable FdtFile
- Return: status code
- */
+static efi_status_t efi_init_fdtfile(void) +{
char *val;
val = env_get("fdtfile");
if (!val)
return EFI_SUCCESS;
return efi_set_variable_int(u"FdtFile",
&efi_u_boot_guid,
EFI_VARIABLE_BOOTSERVICE_ACCESS |
EFI_VARIABLE_RUNTIME_ACCESS |
Why is runtime access needed? Wouldn't the choice be done before ExitBootServices?
[...]
Thanks /Ilias

On 17.10.23 11:14, Ilias Apalodimas wrote:
Hi Heinrich,
On Tue, 17 Oct 2023 at 11:55, Heinrich Schuchardt <heinrich.schuchardt@canonical.com mailto:heinrich.schuchardt@canonical.com> wrote:
Forward and backward compatibility of Linux kernel device-trees is sometimes missing. One solution approach is to load a kernel specific device-tree. This can either be done via a U-Boot scripts (like the one generated by Debian package flash-kernel or by a boot loader like GRUB. The boot loader approach currently requires to know the device-tree name before first boot which makes it unusable for generic images. Expose the device-tree file name as EFI variable FdtFile. This will allow bootloaders to load a kernel specific device-tree. Signed-off-by: Heinrich Schuchardt <heinrich.schuchardt@canonical.com <mailto:heinrich.schuchardt@canonical.com>> --- lib/efi_loader/efi_setup.c | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/lib/efi_loader/efi_setup.c b/lib/efi_loader/efi_setup.c index e6de685e87..b24feb94dc 100644 --- a/lib/efi_loader/efi_setup.c +++ b/lib/efi_loader/efi_setup.c @@ -26,6 +26,27 @@ void __weak allow_unaligned(void) { } +/** + * efi_init_fdtfile() - set EFI variable FdtFile + * + * Return: status code + */ +static efi_status_t efi_init_fdtfile(void) +{ + char *val; + + val = env_get("fdtfile"); + if (!val) + return EFI_SUCCESS; + + return efi_set_variable_int(u"FdtFile", + &efi_u_boot_guid, + EFI_VARIABLE_BOOTSERVICE_ACCESS | + EFI_VARIABLE_RUNTIME_ACCESS |
Why is runtime access needed? Wouldn't the choice be done before ExitBootServices?
Having runtime access will allow to use the content of the variable to write a devicetree command to grub.cfg or to copy the relevant device-tree to a predefined location.
As GRUB cannot read EFI variables, yet, this would be the easiest short-term approach.
Best regards
Heinrich
[...]
Thanks /Ilias

On Tue, 17 Oct 2023 at 12:23, Heinrich Schuchardt < heinrich.schuchardt@canonical.com> wrote:
On 17.10.23 11:14, Ilias Apalodimas wrote:
Hi Heinrich,
On Tue, 17 Oct 2023 at 11:55, Heinrich Schuchardt <heinrich.schuchardt@canonical.com mailto:heinrich.schuchardt@canonical.com> wrote:
Forward and backward compatibility of Linux kernel device-trees is sometimes missing. One solution approach is to load a kernel specific device-tree. This can either be done via a U-Boot scripts (like the
one
generated by Debian package flash-kernel or by a boot loader like
GRUB.
The boot loader approach currently requires to know the device-tree
name
before first boot which makes it unusable for generic images. Expose the device-tree file name as EFI variable FdtFile. This will allow bootloaders to load a kernel specific device-tree. Signed-off-by: Heinrich Schuchardt <heinrich.schuchardt@canonical.com <mailto:heinrich.schuchardt@canonical.com>> --- lib/efi_loader/efi_setup.c | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/lib/efi_loader/efi_setup.c b/lib/efi_loader/efi_setup.c index e6de685e87..b24feb94dc 100644 --- a/lib/efi_loader/efi_setup.c +++ b/lib/efi_loader/efi_setup.c @@ -26,6 +26,27 @@ void __weak allow_unaligned(void) { } +/** + * efi_init_fdtfile() - set EFI variable FdtFile + * + * Return: status code + */ +static efi_status_t efi_init_fdtfile(void) +{ + char *val; + + val = env_get("fdtfile"); + if (!val) + return EFI_SUCCESS; + + return efi_set_variable_int(u"FdtFile", + &efi_u_boot_guid, + EFI_VARIABLE_BOOTSERVICE_ACCESS | + EFI_VARIABLE_RUNTIME_ACCESS |
Why is runtime access needed? Wouldn't the choice be done before ExitBootServices?
Having runtime access will allow to use the content of the variable to write a devicetree command to grub.cfg or to copy the relevant device-tree to a predefined location.
As GRUB cannot read EFI variables, yet, this would be the easiest short-term approach.
Do you mean to write EFI variables? If you want GRUB to be able to do
that, wouldn't it be better to use a generic GUID instead of the U-Boot one?
Regards /Ilias
Best regards
Heinrich
[...]
Thanks /Ilias

On 17.10.23 11:49, Ilias Apalodimas wrote:
On Tue, 17 Oct 2023 at 12:23, Heinrich Schuchardt <heinrich.schuchardt@canonical.com mailto:heinrich.schuchardt@canonical.com> wrote:
On 17.10.23 11:14, Ilias Apalodimas wrote: > Hi Heinrich, > > On Tue, 17 Oct 2023 at 11:55, Heinrich Schuchardt > <heinrich.schuchardt@canonical.com <mailto:heinrich.schuchardt@canonical.com> > <mailto:heinrich.schuchardt@canonical.com <mailto:heinrich.schuchardt@canonical.com>>> wrote: > > Forward and backward compatibility of Linux kernel device-trees is > sometimes missing. One solution approach is to load a kernel specific > device-tree. This can either be done via a U-Boot scripts (like the one > generated by Debian package flash-kernel or by a boot loader like GRUB. > The boot loader approach currently requires to know the device-tree name > before first boot which makes it unusable for generic images. > > Expose the device-tree file name as EFI variable FdtFile. > This will allow bootloaders to load a kernel specific device-tree. > > Signed-off-by: Heinrich Schuchardt > <heinrich.schuchardt@canonical.com <mailto:heinrich.schuchardt@canonical.com> > <mailto:heinrich.schuchardt@canonical.com <mailto:heinrich.schuchardt@canonical.com>>> > --- > lib/efi_loader/efi_setup.c | 26 ++++++++++++++++++++++++++ > 1 file changed, 26 insertions(+) > > diff --git a/lib/efi_loader/efi_setup.c b/lib/efi_loader/efi_setup.c > index e6de685e87..b24feb94dc 100644 > --- a/lib/efi_loader/efi_setup.c > +++ b/lib/efi_loader/efi_setup.c > @@ -26,6 +26,27 @@ void __weak allow_unaligned(void) > { > } > > +/** > + * efi_init_fdtfile() - set EFI variable FdtFile > + * > + * Return: status code > + */ > +static efi_status_t efi_init_fdtfile(void) > +{ > + char *val; > + > + val = env_get("fdtfile"); > + if (!val) > + return EFI_SUCCESS; > + > + return efi_set_variable_int(u"FdtFile", > + &efi_u_boot_guid, > + EFI_VARIABLE_BOOTSERVICE_ACCESS | > + EFI_VARIABLE_RUNTIME_ACCESS | > > > Why is runtime access needed? Wouldn't the choice be done before > ExitBootServices? Having runtime access will allow to use the content of the variable to write a devicetree command to grub.cfg or to copy the relevant device-tree to a predefined location. As GRUB cannot read EFI variables, yet, this would be the easiest short-term approach.
Do you mean to write EFI variables? If you want GRUB to be able to do that, wouldn't it be better to use a generic GUID instead of the U-Boot one?
No, I meant read. It is U-Boot writing the variable.
Concerning the GUID the UEFI 2.10 specification requires a unique VendorGuid other than EFI_GLOBAL_VARIABLE.
If we think about adding a recommendation to the EBBR, it might make sense to use a GUID other than a U-Boot specific one (at the expense of 16 bytes of code).
Best regards
Heinrich

Hi Heinrich,
On Tue, 17 Oct 2023 at 13:12, Heinrich Schuchardt < heinrich.schuchardt@canonical.com> wrote:
On 17.10.23 11:49, Ilias Apalodimas wrote:
On Tue, 17 Oct 2023 at 12:23, Heinrich Schuchardt <heinrich.schuchardt@canonical.com mailto:heinrich.schuchardt@canonical.com> wrote:
On 17.10.23 11:14, Ilias Apalodimas wrote: > Hi Heinrich, > > On Tue, 17 Oct 2023 at 11:55, Heinrich Schuchardt > <heinrich.schuchardt@canonical.com <mailto:heinrich.schuchardt@canonical.com> > <mailto:heinrich.schuchardt@canonical.com <mailto:heinrich.schuchardt@canonical.com>>> wrote: > > Forward and backward compatibility of Linux kernel device-trees is > sometimes missing. One solution approach is to load a kernel specific > device-tree. This can either be done via a U-Boot scripts (like the one > generated by Debian package flash-kernel or by a boot loader like GRUB. > The boot loader approach currently requires to know the device-tree name > before first boot which makes it unusable for generic images. > > Expose the device-tree file name as EFI variable FdtFile. > This will allow bootloaders to load a kernel specific device-tree. > > Signed-off-by: Heinrich Schuchardt > <heinrich.schuchardt@canonical.com <mailto:heinrich.schuchardt@canonical.com> > <mailto:heinrich.schuchardt@canonical.com <mailto:heinrich.schuchardt@canonical.com>>> > --- > lib/efi_loader/efi_setup.c | 26 ++++++++++++++++++++++++++ > 1 file changed, 26 insertions(+) > > diff --git a/lib/efi_loader/efi_setup.c b/lib/efi_loader/efi_setup.c > index e6de685e87..b24feb94dc 100644 > --- a/lib/efi_loader/efi_setup.c > +++ b/lib/efi_loader/efi_setup.c > @@ -26,6 +26,27 @@ void __weak allow_unaligned(void) > { > } > > +/** > + * efi_init_fdtfile() - set EFI variable FdtFile > + * > + * Return: status code > + */ > +static efi_status_t efi_init_fdtfile(void) > +{ > + char *val; > + > + val = env_get("fdtfile"); > + if (!val) > + return EFI_SUCCESS; > + > + return efi_set_variable_int(u"FdtFile", > + &efi_u_boot_guid, > + EFI_VARIABLE_BOOTSERVICE_ACCESS | > +
EFI_VARIABLE_RUNTIME_ACCESS |
> > > Why is runtime access needed? Wouldn't the choice be done before > ExitBootServices? Having runtime access will allow to use the content of the variable
to
write a devicetree command to grub.cfg or to copy the relevant device-tree to a predefined location. As GRUB cannot read EFI variables, yet, this would be the easiest short-term approach.
Do you mean to write EFI variables? If you want GRUB to be able to do that, wouldn't it be better to use a generic GUID instead of the U-Boot
one?
No, I meant read. It is U-Boot writing the variable.
Concerning the GUID the UEFI 2.10 specification requires a unique VendorGuid other than EFI_GLOBAL_VARIABLE.
If we think about adding a recommendation to the EBBR, it might make sense to use a GUID other than a U-Boot specific one (at the expense of 16 bytes of code).
Best regards
Heinrich
Ok, I like the idea of standardizing it, since GRUB needs to pick this up eventually. I guess we can use the u-boot GUID until is there, so
Reviewed-by: Ilias Apalodimas ilias.apalodimas@linaro.org

From: Heinrich Schuchardt heinrich.schuchardt@canonical.com Date: Tue, 17 Oct 2023 10:55:07 +0200
Forward and backward compatibility of Linux kernel device-trees is sometimes missing. One solution approach is to load a kernel specific device-tree. This can either be done via a U-Boot scripts (like the one generated by Debian package flash-kernel or by a boot loader like GRUB. The boot loader approach currently requires to know the device-tree name before first boot which makes it unusable for generic images.
Even if the device trees are compatile, we often see that additonal nodes get added at a later stage. So the ability to load a more complete device tree for the OS is useful and means a user doesn't necessarily need to update U-Boot to make additional devices work in their OS.
Expose the device-tree file name as EFI variable FdtFile. This will allow bootloaders to load a kernel specific device-tree.
Right. I'm considering adding support for loading device trees to the OpenBSD bootloader and this feature would be really useful since it would allow me to automagically load the right device tree from the root filesystem of the OS.
Is my understanding right that this is a null-terminated (8-bit) ASCII string? Can this variable be documented somewhere, maybe together with the EFI_DT_FIXUP_PROTOCOL?
Signed-off-by: Heinrich Schuchardt heinrich.schuchardt@canonical.com
lib/efi_loader/efi_setup.c | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+)
diff --git a/lib/efi_loader/efi_setup.c b/lib/efi_loader/efi_setup.c index e6de685e87..b24feb94dc 100644 --- a/lib/efi_loader/efi_setup.c +++ b/lib/efi_loader/efi_setup.c @@ -26,6 +26,27 @@ void __weak allow_unaligned(void) { }
+/**
- efi_init_fdtfile() - set EFI variable FdtFile
- Return: status code
- */
+static efi_status_t efi_init_fdtfile(void) +{
- char *val;
- val = env_get("fdtfile");
- if (!val)
return EFI_SUCCESS;
- return efi_set_variable_int(u"FdtFile",
&efi_u_boot_guid,
EFI_VARIABLE_BOOTSERVICE_ACCESS |
EFI_VARIABLE_RUNTIME_ACCESS |
EFI_VARIABLE_READ_ONLY,
strlen(val) + 1, val, false);
+}
/**
- efi_init_platform_lang() - define supported languages
@@ -250,6 +271,11 @@ efi_status_t efi_init_obj_list(void) if (ret != EFI_SUCCESS) goto out;
- /* Define EFI variable FdtFile */
- ret = efi_init_fdtfile();
- if (ret != EFI_SUCCESS)
goto out;
- /* Indicate supported features */ ret = efi_init_os_indications(); if (ret != EFI_SUCCESS)
-- 2.40.1

On 17.10.23 17:17, Mark Kettenis wrote:
From: Heinrich Schuchardt heinrich.schuchardt@canonical.com Date: Tue, 17 Oct 2023 10:55:07 +0200
Forward and backward compatibility of Linux kernel device-trees is sometimes missing. One solution approach is to load a kernel specific device-tree. This can either be done via a U-Boot scripts (like the one generated by Debian package flash-kernel or by a boot loader like GRUB. The boot loader approach currently requires to know the device-tree name before first boot which makes it unusable for generic images.
Even if the device trees are compatible, we often see that additonal nodes get added at a later stage. So the ability to load a more complete device tree for the OS is useful and means a user doesn't necessarily need to update U-Boot to make additional devices work in their OS.
OpenBSD should call the EFI_DT_FIXUP_PROTOCOL exposed by U-Boot after loading device-trees.
https://github.com/U-Boot-EFI/EFI_DT_FIXUP_PROTOCOL
Expose the device-tree file name as EFI variable FdtFile. This will allow bootloaders to load a kernel specific device-tree.
Right. I'm considering adding support for loading device trees to the OpenBSD bootloader and this feature would be really useful since it would allow me to automagically load the right device tree from the root filesystem of the OS.
Is my understanding right that this is a null-terminated (8-bit) ASCII string? Can this variable be documented somewhere, maybe together with the EFI_DT_FIXUP_PROTOCOL?
Yes, the string is NUL terminated ASCII. The best place for documentation would be the EBBR specification.
Best regards
Heinrich
Signed-off-by: Heinrich Schuchardt heinrich.schuchardt@canonical.com
lib/efi_loader/efi_setup.c | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+)
diff --git a/lib/efi_loader/efi_setup.c b/lib/efi_loader/efi_setup.c index e6de685e87..b24feb94dc 100644 --- a/lib/efi_loader/efi_setup.c +++ b/lib/efi_loader/efi_setup.c @@ -26,6 +26,27 @@ void __weak allow_unaligned(void) { }
+/**
- efi_init_fdtfile() - set EFI variable FdtFile
- Return: status code
- */
+static efi_status_t efi_init_fdtfile(void) +{
- char *val;
- val = env_get("fdtfile");
- if (!val)
return EFI_SUCCESS;
- return efi_set_variable_int(u"FdtFile",
&efi_u_boot_guid,
EFI_VARIABLE_BOOTSERVICE_ACCESS |
EFI_VARIABLE_RUNTIME_ACCESS |
EFI_VARIABLE_READ_ONLY,
strlen(val) + 1, val, false);
+}
- /**
- efi_init_platform_lang() - define supported languages
@@ -250,6 +271,11 @@ efi_status_t efi_init_obj_list(void) if (ret != EFI_SUCCESS) goto out;
- /* Define EFI variable FdtFile */
- ret = efi_init_fdtfile();
- if (ret != EFI_SUCCESS)
goto out;
- /* Indicate supported features */ ret = efi_init_os_indications(); if (ret != EFI_SUCCESS)
-- 2.40.1
participants (3)
-
Heinrich Schuchardt
-
Ilias Apalodimas
-
Mark Kettenis