diff mbox series

[meta,1/1] kernel-fit-image: skip kernel section if linux.bin is missing

Message ID 20250812091453.1760880-2-kavinaya@qti.qualcomm.com
State New
Headers show
Series kernel-fit-image: support UKI boot with independent DTB handling | expand

Commit Message

Kavinaya S Aug. 12, 2025, 9:14 a.m. UTC
Avoids errors during image generation by checking for the
presence of linux.bin before attempting to copy and emit the
kernel section. This ensures that the build process continues
gracefully when the kernel binary is not available.

A clean separation between firmware (including DTBs) and the
HLOS (Linux Kernel) is highly recommended and often necessary
to enable independent firmware updates, enforce trust boundaries,
and support running the same kernel across different hardware
platforms by simply swapping DTBs. One effective way to achieve
this separation is by using a Unified Kernel Image (UKI) that
contains only the Linux kernel and initramfs, while keeping the
DTBs in a separate FIT image, such as dtb.bin.

To support this setup, it's important to ensure that a FIT image
can be generated without requiring the Linux kernel binary,
allowing the build process to continue gracefully even when the
kernel is unavailable.

Additionally, this approach is very useful when the kernel-fit-
extra-artifacts class is not set, as it enables the creation of
an .its file without depending on the kernel.

Signed-off-by: Kavinaya S <kavinaya@qti.qualcomm.com>
---
 meta/classes-recipe/kernel-fit-image.bbclass | 22 ++++++++++++++++----
 1 file changed, 18 insertions(+), 4 deletions(-)

Comments

AdrianF Aug. 19, 2025, 8:50 a.m. UTC | #1
Hi Kavinaya

On Tue, 2025-08-12 at 14:44 +0530, Kavinaya S via
lists.openembedded.org wrote:
> Avoids errors during image generation by checking for the
> presence of linux.bin before attempting to copy and emit the
> kernel section. This ensures that the build process continues
> gracefully when the kernel binary is not available.

So far, the primary purpose of this code is to create a FIT image
containing a single kernel and more artifacts. If no kernel is found,
the process should fail immediately, as this is required for all
current use cases. Adhering to this approach ensures the code remains
robust and reliable for its intended function.

To address your use case, one approach could be to introduce a variable
in image-fitimage.conf which allows to configure your use case
explicitly. For example:
  FIT_LINUX_BIN ?= "linux.bin"

Then the kernel-fit-image.bbclass could:

  linux_bin = d.getVar('FIT_LINUX_BIN')
  if linux_bin:    
      shutil.copyfile... all the existing code

For your use case you could then override it to:
  FIT_LINUX_BIN = ""

Would that work?

> 
> A clean separation between firmware (including DTBs) and the
> HLOS (Linux Kernel) is highly recommended and often necessary
> to enable independent firmware updates, enforce trust boundaries,
> and support running the same kernel across different hardware
> platforms by simply swapping DTBs. One effective way to achieve
> this separation is by using a Unified Kernel Image (UKI) that
> contains only the Linux kernel and initramfs, while keeping the
> DTBs in a separate FIT image, such as dtb.bin.
> 
> To support this setup, it's important to ensure that a FIT image
> can be generated without requiring the Linux kernel binary,
> allowing the build process to continue gracefully even when the
> kernel is unavailable.
> 
> Additionally, this approach is very useful when the kernel-fit-
> extra-artifacts class is not set, as it enables the creation of
> an .its file without depending on the kernel.
> 
> Signed-off-by: Kavinaya S <kavinaya@qti.qualcomm.com>
> ---
>  meta/classes-recipe/kernel-fit-image.bbclass | 22 ++++++++++++++++--
> --
>  1 file changed, 18 insertions(+), 4 deletions(-)
> 
> diff --git a/meta/classes-recipe/kernel-fit-image.bbclass
> b/meta/classes-recipe/kernel-fit-image.bbclass
> index fd4c6a30fe..c0f925d90e 100644
> --- a/meta/classes-recipe/kernel-fit-image.bbclass
> +++ b/meta/classes-recipe/kernel-fit-image.bbclass
> @@ -59,12 +59,26 @@ python do_compile() {
>      )
>  
>      # Prepare a kernel image section.
> -    shutil.copyfile(os.path.join(kernel_deploydir, "linux.bin"),
> "linux.bin")
> -    with open(os.path.join(kernel_deploydir, "linux_comp")) as
> linux_comp_f:
> -        linux_comp = linux_comp_f.read()
> -    root_node.fitimage_emit_section_kernel("kernel-1", "linux.bin",
> linux_comp,
> +    # Construct the full path to linux.bin
> +    linux_bin_path = os.path.join(kernel_deploydir, "linux.bin")
> +
> +    # Check if linux.bin exists
> +    if os.path.exists(linux_bin_path):
> +        # Copy linux.bin to current directory

Please do not pollute the code with useless comments. Something like
that looks counter productive to me:

  # Calling foo bar
  foo_bar();

But reasonable comments for example like this are essential:

  # Support special use cases where the kernel binary is not included
  # in the FIT image itself or has a different name.
  # For example, if the kernel is provided as a uki image, this
  # variable can be set to empty string.
  FIT_LINUX_BIN ?= "linux.bin"

> +        shutil.copyfile(linux_bin_path, "linux.bin")
> +
> +        # Read linux_comp file
> +        linux_comp_path = os.path.join(kernel_deploydir,
> "linux_comp")
> +        with open(linux_comp_path, 'r') as linux_comp_f:
> +            linux_comp = linux_comp_f.read()
> +
> +        # Emit kernel image section
> +        root_node.fitimage_emit_section_kernel("kernel-1",
> "linux.bin", linux_comp,
>          d.getVar('UBOOT_LOADADDRESS'), d.getVar('UBOOT_ENTRYPOINT'),
>          d.getVar('UBOOT_MKIMAGE_KERNEL_TYPE'),
> d.getVar("UBOOT_ENTRYSYMBOL"))
> +    else:
> +        bb.note("linux.bin not found. Skipping kernel image
> preparation. ")
> +
>  
>      # Prepare a DTB image section
>      kernel_devicetree = d.getVar('KERNEL_DEVICETREE')

The FIT image and the uki code has plenty of test cases in 
https://git.yoctoproject.org/poky/tree/meta/lib/oeqa/selftest/cases/fitimage.py
https://git.yoctoproject.org/poky/tree/meta/lib/oeqa/selftest/cases/uki.py
Would it be possible to add a test case for your use case as well?


Thank you for the patch
Adrian


> 
> -=-=-=-=-=-=-=-=-=-=-=-
> Links: You receive all messages sent to this group.
> View/Reply Online (#221868):
> https://lists.openembedded.org/g/openembedded-core/message/221868
> Mute This Topic: https://lists.openembedded.org/mt/114706196/3616858
> Group Owner: openembedded-core+owner@lists.openembedded.org
> Unsubscribe:
> https://lists.openembedded.org/g/openembedded-core/unsub [
> adrian.freihofer@siemens.com]
> -=-=-=-=-=-=-=-=-=-=-=-
>
Viswanath Kraleti Aug. 19, 2025, 11:04 a.m. UTC | #2
On Tue, Aug 19, 2025 at 2:20 PM Adrian Freihofer via
lists.openembedded.org
<adrian.freihofer=siemens.com@lists.openembedded.org> wrote:
>
> Hi Kavinaya
>
> On Tue, 2025-08-12 at 14:44 +0530, Kavinaya S via
> lists.openembedded.org wrote:
> > Avoids errors during image generation by checking for the
> > presence of linux.bin before attempting to copy and emit the
> > kernel section. This ensures that the build process continues
> > gracefully when the kernel binary is not available.
>
> So far, the primary purpose of this code is to create a FIT image
> containing a single kernel and more artifacts. If no kernel is found,
> the process should fail immediately, as this is required for all
> current use cases. Adhering to this approach ensures the code remains
> robust and reliable for its intended function.
>
> To address your use case, one approach could be to introduce a variable
> in image-fitimage.conf which allows to configure your use case
> explicitly. For example:
>   FIT_LINUX_BIN ?= "linux.bin"

Thanks Adrian. Yes, this approach works for the use case we are trying
to address.
We'll refine this patch and reupload.

>
> Then the kernel-fit-image.bbclass could:
>
>   linux_bin = d.getVar('FIT_LINUX_BIN')
>   if linux_bin:
>       shutil.copyfile... all the existing code
>
> For your use case you could then override it to:
>   FIT_LINUX_BIN = ""
>
> Would that work?
>
> >
> > A clean separation between firmware (including DTBs) and the
> > HLOS (Linux Kernel) is highly recommended and often necessary
> > to enable independent firmware updates, enforce trust boundaries,
> > and support running the same kernel across different hardware
> > platforms by simply swapping DTBs. One effective way to achieve
> > this separation is by using a Unified Kernel Image (UKI) that
> > contains only the Linux kernel and initramfs, while keeping the
> > DTBs in a separate FIT image, such as dtb.bin.
> >
> > To support this setup, it's important to ensure that a FIT image
> > can be generated without requiring the Linux kernel binary,
> > allowing the build process to continue gracefully even when the
> > kernel is unavailable.
> >
> > Additionally, this approach is very useful when the kernel-fit-
> > extra-artifacts class is not set, as it enables the creation of
> > an .its file without depending on the kernel.
> >
> > Signed-off-by: Kavinaya S <kavinaya@qti.qualcomm.com>
> > ---
> >  meta/classes-recipe/kernel-fit-image.bbclass | 22 ++++++++++++++++--
> > --
> >  1 file changed, 18 insertions(+), 4 deletions(-)
> >
> > diff --git a/meta/classes-recipe/kernel-fit-image.bbclass
> > b/meta/classes-recipe/kernel-fit-image.bbclass
> > index fd4c6a30fe..c0f925d90e 100644
> > --- a/meta/classes-recipe/kernel-fit-image.bbclass
> > +++ b/meta/classes-recipe/kernel-fit-image.bbclass
> > @@ -59,12 +59,26 @@ python do_compile() {
> >      )
> >
> >      # Prepare a kernel image section.
> > -    shutil.copyfile(os.path.join(kernel_deploydir, "linux.bin"),
> > "linux.bin")
> > -    with open(os.path.join(kernel_deploydir, "linux_comp")) as
> > linux_comp_f:
> > -        linux_comp = linux_comp_f.read()
> > -    root_node.fitimage_emit_section_kernel("kernel-1", "linux.bin",
> > linux_comp,
> > +    # Construct the full path to linux.bin
> > +    linux_bin_path = os.path.join(kernel_deploydir, "linux.bin")
> > +
> > +    # Check if linux.bin exists
> > +    if os.path.exists(linux_bin_path):
> > +        # Copy linux.bin to current directory
>
> Please do not pollute the code with useless comments. Something like
> that looks counter productive to me:
>
>   # Calling foo bar
>   foo_bar();
>
> But reasonable comments for example like this are essential:
>
>   # Support special use cases where the kernel binary is not included
>   # in the FIT image itself or has a different name.
>   # For example, if the kernel is provided as a uki image, this
>   # variable can be set to empty string.
>   FIT_LINUX_BIN ?= "linux.bin"

We like this comment. Hope you don't mind if it is reused.

>
> > +        shutil.copyfile(linux_bin_path, "linux.bin")
> > +
> > +        # Read linux_comp file
> > +        linux_comp_path = os.path.join(kernel_deploydir,
> > "linux_comp")
> > +        with open(linux_comp_path, 'r') as linux_comp_f:
> > +            linux_comp = linux_comp_f.read()
> > +
> > +        # Emit kernel image section
> > +        root_node.fitimage_emit_section_kernel("kernel-1",
> > "linux.bin", linux_comp,
> >          d.getVar('UBOOT_LOADADDRESS'), d.getVar('UBOOT_ENTRYPOINT'),
> >          d.getVar('UBOOT_MKIMAGE_KERNEL_TYPE'),
> > d.getVar("UBOOT_ENTRYSYMBOL"))
> > +    else:
> > +        bb.note("linux.bin not found. Skipping kernel image
> > preparation. ")
> > +
> >
> >      # Prepare a DTB image section
> >      kernel_devicetree = d.getVar('KERNEL_DEVICETREE')
>
> The FIT image and the uki code has plenty of test cases in
> https://git.yoctoproject.org/poky/tree/meta/lib/oeqa/selftest/cases/fitimage.py
> https://git.yoctoproject.org/poky/tree/meta/lib/oeqa/selftest/cases/uki.py
> Would it be possible to add a test case for your use case as well?

Certainly. We'll add a test to validate this use case as well.
>
>
> Thank you for the patch
> Adrian
>
>
> >
> >
> >
>
>
> -=-=-=-=-=-=-=-=-=-=-=-
> Links: You receive all messages sent to this group.
> View/Reply Online (#222087): https://lists.openembedded.org/g/openembedded-core/message/222087
> Mute This Topic: https://lists.openembedded.org/mt/114706196/5192326
> Group Owner: openembedded-core+owner@lists.openembedded.org
> Unsubscribe: https://lists.openembedded.org/g/openembedded-core/unsub [viswanath.kraleti@oss.qualcomm.com]
> -=-=-=-=-=-=-=-=-=-=-=-
>
Robert Yang Aug. 28, 2025, 9:44 a.m. UTC | #3
Hi,

On 8/12/25 17:14, Kavinaya S via lists.openembedded.org wrote:
> Avoids errors during image generation by checking for the
> presence of linux.bin before attempting to copy and emit the
> kernel section. This ensures that the build process continues
> gracefully when the kernel binary is not available.
> 
> A clean separation between firmware (including DTBs) and the
> HLOS (Linux Kernel) is highly recommended and often necessary
> to enable independent firmware updates, enforce trust boundaries,
> and support running the same kernel across different hardware
> platforms by simply swapping DTBs. One effective way to achieve
> this separation is by using a Unified Kernel Image (UKI) that
> contains only the Linux kernel and initramfs, while keeping the
> DTBs in a separate FIT image, such as dtb.bin.
> 
> To support this setup, it's important to ensure that a FIT image
> can be generated without requiring the Linux kernel binary,
> allowing the build process to continue gracefully even when the
> kernel is unavailable.
> 
> Additionally, this approach is very useful when the kernel-fit-
> extra-artifacts class is not set, as it enables the creation of
> an .its file without depending on the kernel.
> 
> Signed-off-by: Kavinaya S <kavinaya@qti.qualcomm.com>
> ---
>   meta/classes-recipe/kernel-fit-image.bbclass | 22 ++++++++++++++++----
>   1 file changed, 18 insertions(+), 4 deletions(-)
> 
> diff --git a/meta/classes-recipe/kernel-fit-image.bbclass b/meta/classes-recipe/kernel-fit-image.bbclass
> index fd4c6a30fe..c0f925d90e 100644
> --- a/meta/classes-recipe/kernel-fit-image.bbclass
> +++ b/meta/classes-recipe/kernel-fit-image.bbclass
> @@ -59,12 +59,26 @@ python do_compile() {
>       )
>   
>       # Prepare a kernel image section.
> -    shutil.copyfile(os.path.join(kernel_deploydir, "linux.bin"), "linux.bin")
> -    with open(os.path.join(kernel_deploydir, "linux_comp")) as linux_comp_f:
> -        linux_comp = linux_comp_f.read()
> -    root_node.fitimage_emit_section_kernel("kernel-1", "linux.bin", linux_comp,
> +    # Construct the full path to linux.bin
> +    linux_bin_path = os.path.join(kernel_deploydir, "linux.bin")
> +
> +    # Check if linux.bin exists
> +    if os.path.exists(linux_bin_path):
> +        # Copy linux.bin to current directory
> +        shutil.copyfile(linux_bin_path, "linux.bin")
> +
> +        # Read linux_comp file
> +        linux_comp_path = os.path.join(kernel_deploydir, "linux_comp")
> +        with open(linux_comp_path, 'r') as linux_comp_f:
> +            linux_comp = linux_comp_f.read()
> +
> +        # Emit kernel image section
> +        root_node.fitimage_emit_section_kernel("kernel-1", "linux.bin", linux_comp,
>           d.getVar('UBOOT_LOADADDRESS'), d.getVar('UBOOT_ENTRYPOINT'),
>           d.getVar('UBOOT_MKIMAGE_KERNEL_TYPE'), d.getVar("UBOOT_ENTRYSYMBOL"))
> +    else:
> +        bb.note("linux.bin not found. Skipping kernel image preparation. ")

I think use linux_bin_path to replace linux.bin is easier for debug? E.g:

bb.note("% not found. Skipping kernel image preparation." % linux_bin_path)

// Robert

> +
>   
>       # Prepare a DTB image section
>       kernel_devicetree = d.getVar('KERNEL_DEVICETREE')
> 
> 
> 
> -=-=-=-=-=-=-=-=-=-=-=-
> Links: You receive all messages sent to this group.
> View/Reply Online (#221868): https://lists.openembedded.org/g/openembedded-core/message/221868
> Mute This Topic: https://lists.openembedded.org/mt/114706196/7304958
> Group Owner: openembedded-core+owner@lists.openembedded.org
> Unsubscribe: https://lists.openembedded.org/g/openembedded-core/unsub [liezhi.yang@eng.windriver.com]
> -=-=-=-=-=-=-=-=-=-=-=-
>
diff mbox series

Patch

diff --git a/meta/classes-recipe/kernel-fit-image.bbclass b/meta/classes-recipe/kernel-fit-image.bbclass
index fd4c6a30fe..c0f925d90e 100644
--- a/meta/classes-recipe/kernel-fit-image.bbclass
+++ b/meta/classes-recipe/kernel-fit-image.bbclass
@@ -59,12 +59,26 @@  python do_compile() {
     )
 
     # Prepare a kernel image section.
-    shutil.copyfile(os.path.join(kernel_deploydir, "linux.bin"), "linux.bin")
-    with open(os.path.join(kernel_deploydir, "linux_comp")) as linux_comp_f:
-        linux_comp = linux_comp_f.read()
-    root_node.fitimage_emit_section_kernel("kernel-1", "linux.bin", linux_comp,
+    # Construct the full path to linux.bin
+    linux_bin_path = os.path.join(kernel_deploydir, "linux.bin")
+
+    # Check if linux.bin exists
+    if os.path.exists(linux_bin_path):
+        # Copy linux.bin to current directory
+        shutil.copyfile(linux_bin_path, "linux.bin")
+
+        # Read linux_comp file
+        linux_comp_path = os.path.join(kernel_deploydir, "linux_comp")
+        with open(linux_comp_path, 'r') as linux_comp_f:
+            linux_comp = linux_comp_f.read()
+
+        # Emit kernel image section
+        root_node.fitimage_emit_section_kernel("kernel-1", "linux.bin", linux_comp,
         d.getVar('UBOOT_LOADADDRESS'), d.getVar('UBOOT_ENTRYPOINT'),
         d.getVar('UBOOT_MKIMAGE_KERNEL_TYPE'), d.getVar("UBOOT_ENTRYSYMBOL"))
+    else:
+        bb.note("linux.bin not found. Skipping kernel image preparation. ")
+
 
     # Prepare a DTB image section
     kernel_devicetree = d.getVar('KERNEL_DEVICETREE')