From patchwork Sun May 4 13:04:48 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Freihofer, Adrian" X-Patchwork-Id: 62390 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from aws-us-west-2-korg-lkml-1.web.codeaurora.org (localhost.localdomain [127.0.0.1]) by smtp.lore.kernel.org (Postfix) with ESMTP id BF1ACC369DC for ; Sun, 4 May 2025 13:06:58 +0000 (UTC) Received: from mta-64-225.siemens.flowmailer.net (mta-64-225.siemens.flowmailer.net [185.136.64.225]) by mx.groups.io with SMTP id smtpd.web10.28202.1746364017576098550 for ; Sun, 04 May 2025 06:06:58 -0700 Authentication-Results: mx.groups.io; dkim=pass header.i=adrian.freihofer@siemens.com header.s=fm1 header.b=OsYk4BCL; spf=pass (domain: rts-flowmailer.siemens.com, ip: 185.136.64.225, mailfrom: fm-1329275-20250504130653ea31010bf5a1594332-z2uqpg@rts-flowmailer.siemens.com) Received: by mta-64-225.siemens.flowmailer.net with ESMTPSA id 20250504130653ea31010bf5a1594332 for ; Sun, 04 May 2025 15:06:54 +0200 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; s=fm1; d=siemens.com; i=adrian.freihofer@siemens.com; h=Date:From:Subject:To:Message-ID:MIME-Version:Content-Type:Content-Transfer-Encoding:Cc; bh=+V7L7UrkDSHNHV44YNopac1bfO1tz0SGJAn7/SYOXXg=; b=OsYk4BCL0cF76BLR5sdQ2DoZuOvtxLnIyX7tM8O7BPPf0rMIEmrLyzSPWWE2Kvqo6kc34C npRg0QIbOqQ1sPaZ0GRPbRF57CLGlF6Qc8m42E3HXbgMUuCqt0UIADXOJY/3D+vZJs9t19VB zGY76iLtRD0RPHKsaLOWd76IJDSBreQQA3HCK8LE/2lPMv+P5M19KWFhlD0zzi6fD0QSCqC1 t1bTA8lWzRS40fHwbl6ETXNBUI/kV9TgvxjLxhMFuZXAH5peYoRRxeK5Gi8YeSvSwu/re4sn 1DyqQE+FCfsok46cwxX9dlON/jO0gDAVoKT3cDnSpwIh8RXcejpME4fg==; From: AdrianF To: openembedded-core@lists.openembedded.org Cc: marex@denx.de, l.anderweit@phytec.de, richard.purdie@linuxfoundation.org, ross.burton@arm.com, bruce.ashfield@gmail.com, rogerio.borin@toradex.com, sean.anderson@seco.com, m.felsch@pengutronix.de, ejo@pengutronix.de, Adrian Freihofer Subject: [PATCH 01/20] oe-selftest: add new ext dtb recipe Date: Sun, 4 May 2025 15:04:48 +0200 Message-ID: <20250504130507.717954-1-adrian.freihofer@siemens.com> MIME-Version: 1.0 X-Flowmailer-Platform: Siemens Feedback-ID: 519:519-1329275:519-21489:flowmailer List-Id: X-Webhook-Received: from li982-79.members.linode.com [45.33.32.79] by aws-us-west-2-korg-lkml-1.web.codeaurora.org with HTTPS for ; Sun, 04 May 2025 13:06:58 -0000 X-Groupsio-URL: https://lists.openembedded.org/g/openembedded-core/message/215950 From: Adrian Freihofer There is no test coverage for the devicetree.bbclass class. Add a minimalist recipe that uses this class. This recipe compiles a devicetree overlay that does not include any sources from the kernel build folder to keep it simple and also usable for testing a kernel from the sstate-cache. Signed-off-by: Adrian Freihofer --- .../recipes-test/ext-dtb/bborg-relay-00a2.bb | 14 ++++++ .../ext-dtb/files/BBORG_RELAY-00A2.dts | 49 +++++++++++++++++++ 2 files changed, 63 insertions(+) create mode 100644 meta-selftest/recipes-test/ext-dtb/bborg-relay-00a2.bb create mode 100644 meta-selftest/recipes-test/ext-dtb/files/BBORG_RELAY-00A2.dts diff --git a/meta-selftest/recipes-test/ext-dtb/bborg-relay-00a2.bb b/meta-selftest/recipes-test/ext-dtb/bborg-relay-00a2.bb new file mode 100644 index 00000000000..dcd32320ada --- /dev/null +++ b/meta-selftest/recipes-test/ext-dtb/bborg-relay-00a2.bb @@ -0,0 +1,14 @@ + +LICENSE = "GPL-2.0-only" +LIC_FILES_CHKSUM = "file://${COMMON_LICENSE_DIR}/GPL-2.0-only;md5=801f80980d171dd6425610833a22dbe6 " + +# Borrowed an example dts file from +# https://raw.githubusercontent.com/beagleboard/linux/refs/heads/5.10/arch/arm/boot/dts/overlays/BBORG_RELAY-00A2.dts +SRC_URI = "file://BBORG_RELAY-00A2.dts" + +# No need for compiling the kernel. The trivial dts file does not include something. +KERNEL_INCLUDE = "" + +COMPATIBLE_MACHINE = "^beaglebone-yocto$" + +inherit devicetree diff --git a/meta-selftest/recipes-test/ext-dtb/files/BBORG_RELAY-00A2.dts b/meta-selftest/recipes-test/ext-dtb/files/BBORG_RELAY-00A2.dts new file mode 100644 index 00000000000..9530fa50fe5 --- /dev/null +++ b/meta-selftest/recipes-test/ext-dtb/files/BBORG_RELAY-00A2.dts @@ -0,0 +1,49 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (C) 2015 Robert Nelson + * Copyright (C) 2019 Amilcar Lucas + */ + +/dts-v1/; +/plugin/; + +&{/chosen} { + overlays { + BBORG_RELAY-00A2.kernel = __TIMESTAMP__; + }; +}; + +&ocp { + P9_41_pinmux { pinctrl-0 = <&P9_41_gpio_pin>;}; + P9_42_pinmux { pinctrl-0 = <&P9_42_gpio_pin>;}; + P9_30_pinmux { pinctrl-0 = <&P9_30_gpio_pin>;}; + P9_27_pinmux { pinctrl-0 = <&P9_27_gpio_pin>;}; +}; + +// relay1 +&bone_led_P9_41 { + status = "okay"; + label = "relay1"; + default-state = "keep"; +}; + +// relay2 +&bone_led_P9_42 { + status = "okay"; + label = "relay2"; + default-state = "keep"; +}; + +// realy3 +&bone_led_P9_30 { + status = "okay"; + label = "relay3"; + default-state = "keep"; +}; + +// realy4 +&bone_led_P9_27 { + status = "okay"; + label = "relay4"; + default-state = "keep"; +}; From patchwork Sun May 4 13:04:49 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: "Freihofer, Adrian" X-Patchwork-Id: 62389 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from aws-us-west-2-korg-lkml-1.web.codeaurora.org (localhost.localdomain [127.0.0.1]) by smtp.lore.kernel.org (Postfix) with ESMTP id C0673C3ABAC for ; Sun, 4 May 2025 13:06:58 +0000 (UTC) Received: from mta-64-225.siemens.flowmailer.net (mta-64-225.siemens.flowmailer.net [185.136.64.225]) by mx.groups.io with SMTP id smtpd.web10.28200.1746364017415901514 for ; Sun, 04 May 2025 06:06:58 -0700 Authentication-Results: mx.groups.io; dkim=pass header.i=adrian.freihofer@siemens.com header.s=fm1 header.b=GBbLduS4; spf=pass (domain: rts-flowmailer.siemens.com, ip: 185.136.64.225, mailfrom: fm-1329275-20250504130654018b8a70060015eed4-luh_98@rts-flowmailer.siemens.com) Received: by mta-64-225.siemens.flowmailer.net with ESMTPSA id 20250504130654018b8a70060015eed4 for ; Sun, 04 May 2025 15:06:54 +0200 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; s=fm1; d=siemens.com; i=adrian.freihofer@siemens.com; h=Date:From:Subject:To:Message-ID:MIME-Version:Content-Type:Content-Transfer-Encoding:Cc:References:In-Reply-To; bh=TZ4WNbZ8ZNrzpyM8Q/8BDk18xkr43EPXZqCpe6qpIW4=; b=GBbLduS43p2RmWM4poFpEFfWocmyiir7JrBaRGdAaOwAoXTu2VPmEnJsF9EMeaD8crq1Hy d4eXrL8xKvrpIlx48vrhc3X1AjXArDTSf4h+D28F1v+W+9I/RhTOBifTfd0Vuycc+I47Aj2U MusGDo+FMc4GLeBWQ7CRGyTASdujCieMT5ZTGOqWprc3Xh6mFbCozS2hzjiUJaPmMPV8iYQm ZHWtv32dHOyhxYi5ONfE220gXoe3MCtD6s2S7AwMgBJEGYq4P2MJ3/+sKEkKlauAKjBrDEB3 tT+5qYIGB1WHe3J23ZoN1tL2b0LgkxLcRQ745hwzGrnxhwUEpqTaZtMQ==; From: AdrianF To: openembedded-core@lists.openembedded.org Cc: marex@denx.de, l.anderweit@phytec.de, richard.purdie@linuxfoundation.org, ross.burton@arm.com, bruce.ashfield@gmail.com, rogerio.borin@toradex.com, sean.anderson@seco.com, m.felsch@pengutronix.de, ejo@pengutronix.de, Adrian Freihofer Subject: [PATCH 02/20] oe-selftest: fitimage: test coverage for ext dtb Date: Sun, 4 May 2025 15:04:49 +0200 Message-ID: <20250504130507.717954-2-adrian.freihofer@siemens.com> In-Reply-To: <20250504130507.717954-1-adrian.freihofer@siemens.com> References: <20250504130507.717954-1-adrian.freihofer@siemens.com> MIME-Version: 1.0 X-Flowmailer-Platform: Siemens Feedback-ID: 519:519-1329275:519-21489:flowmailer List-Id: X-Webhook-Received: from li982-79.members.linode.com [45.33.32.79] by aws-us-west-2-korg-lkml-1.web.codeaurora.org with HTTPS for ; Sun, 04 May 2025 13:06:58 -0000 X-Groupsio-URL: https://lists.openembedded.org/g/openembedded-core/message/215949 From: Adrian Freihofer There are several ways to insert external devicetrees and devicetree overlays into the kernel and thus at least to some extent into the FIT image. So far there is no test coverage. Let's improve this as much as possible without fully understanding all use cases. This first test adds a devicetree overlay to a build configuration without signing, since signing is apparently not yet meaningful when PREFERRED_PROVIDER_virtual/dtb = “bborg-relay-00a2” is used. It is also not entirely clear how these external devicetree overlays are used by the configuration nodes of the FIT image. Currently, one configuration is created per dtb dtbo node, which is not really useful for dtbo nodes. Before this test can be extended to test devicetree overlays and signing, the code that creates the configuration nodes in its file probably needs some improvements in terms of more flexibility in defining the references from configuration nodes to image nodes. Signed-off-by: Adrian Freihofer --- meta/lib/oeqa/selftest/cases/fitimage.py | 44 ++++++++++++++++++++++-- 1 file changed, 41 insertions(+), 3 deletions(-) diff --git a/meta/lib/oeqa/selftest/cases/fitimage.py b/meta/lib/oeqa/selftest/cases/fitimage.py index b39f2622dff..ba5adaa9b67 100644 --- a/meta/lib/oeqa/selftest/cases/fitimage.py +++ b/meta/lib/oeqa/selftest/cases/fitimage.py @@ -161,10 +161,21 @@ class FitImageTestCase(OESelftestTestCase): @staticmethod def _get_dtb_files(bb_vars): + """Return a list of devicetree names + + The list should be used to check the dtb and conf nodes in the FIT image or its file. + In addition to the entries from KERNEL_DEVICETREE, the external devicetree overlay + added by the test recipe bborg-relay-00a2.bb is also handled. + """ kernel_devicetree = bb_vars.get('KERNEL_DEVICETREE') + all_dtbs = [] if kernel_devicetree: - return [os.path.basename(dtb) for dtb in kernel_devicetree.split()] - return [] + all_dtbs += [os.path.basename(dtb) for dtb in kernel_devicetree.split()] + # Support only the test recipe which provides 1 devicetree overlay + pref_prov_dtb = bb_vars.get('PREFERRED_PROVIDER_virtual/dtb') + if pref_prov_dtb == "bborg-relay-00a2": + all_dtbs.append("BBORG_RELAY-00A2.dtbo") + return all_dtbs def _is_req_dict_in_dict(self, found_dict, req_dict): """ @@ -379,6 +390,7 @@ class KernelFitImageTests(FitImageTestCase): 'KERNEL_DEVICETREE', 'KERNEL_FIT_LINK_NAME', 'MACHINE', + 'PREFERRED_PROVIDER_virtual/dtb', 'UBOOT_ARCH', 'UBOOT_ENTRYPOINT', 'UBOOT_LOADADDRESS', @@ -635,7 +647,12 @@ class KernelFitImageTests(FitImageTestCase): self.assertEqual(sign_algo, req_sign_algo, 'Signature algorithm for %s not expected value' % section) sign_value = values.get('Sign value', None) self.assertEqual(len(sign_value), fit_sign_alg_len, 'Signature value for section %s not expected length' % section) - dtb_path = os.path.join(deploy_dir_image, section.replace('conf-', '')) + dtb_file_name = section.replace('conf-', '') + dtb_path = os.path.join(deploy_dir_image, dtb_file_name) + # External devicetrees created by devicetree.bbclass are in a subfolder and have priority + dtb_path_ext = os.path.join(deploy_dir_image, "devicetree", dtb_file_name) + if os.path.exists(dtb_path_ext): + dtb_path = dtb_path_ext self._verify_fit_image_signature(uboot_tools_bindir, fitimage_path, dtb_path, section) else: # Image nodes always need a hash which gets indirectly signed by the config signature @@ -696,6 +713,27 @@ FIT_DESC = "A model description" self._test_fitimage(bb_vars) + def test_fit_image_ext_dtbo(self): + """ + Summary: Check if FIT image and Image Tree Source (its) are created correctly. + Expected: 1) its and FIT image are built successfully + 2) The its file contains also the external devicetree overlay + 3) Dumping the FIT image indicates the devicetree overlay + """ + config = """ +# Enable creation of fitImage +MACHINE = "beaglebone-yocto" +KERNEL_IMAGETYPES += " fitImage " +KERNEL_CLASSES = " kernel-fitimage " +# Add a devicetree overlay which does not need kernel sources +PREFERRED_PROVIDER_virtual/dtb = "bborg-relay-00a2" +""" + config = self._config_add_uboot_env(config) + self.write_config(config) + bb_vars = self._fit_get_bb_vars() + self._test_fitimage(bb_vars) + + def test_sign_fit_image_configurations(self): """ Summary: Check if FIT image and Image Tree Source (its) are created From patchwork Sun May 4 13:04:50 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Freihofer, Adrian" X-Patchwork-Id: 62393 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from aws-us-west-2-korg-lkml-1.web.codeaurora.org (localhost.localdomain [127.0.0.1]) by smtp.lore.kernel.org (Postfix) with ESMTP id CCD1BC3ABBA for ; Sun, 4 May 2025 13:06:58 +0000 (UTC) Received: from mta-64-226.siemens.flowmailer.net (mta-64-226.siemens.flowmailer.net [185.136.64.226]) by mx.groups.io with SMTP id smtpd.web10.28201.1746364017481237771 for ; Sun, 04 May 2025 06:06:58 -0700 Authentication-Results: mx.groups.io; dkim=pass header.i=adrian.freihofer@siemens.com header.s=fm1 header.b=VrhfhUyq; spf=pass (domain: rts-flowmailer.siemens.com, ip: 185.136.64.226, mailfrom: fm-1329275-20250504130654997f8f7c41cb8cb044-zzjf4a@rts-flowmailer.siemens.com) Received: by mta-64-226.siemens.flowmailer.net with ESMTPSA id 20250504130654997f8f7c41cb8cb044 for ; Sun, 04 May 2025 15:06:54 +0200 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; s=fm1; d=siemens.com; i=adrian.freihofer@siemens.com; h=Date:From:Subject:To:Message-ID:MIME-Version:Content-Type:Content-Transfer-Encoding:Cc:References:In-Reply-To; bh=KqmqVZan7/t5N3Q6U09RScxWIkVGDuAdTBjMfpOo3Mw=; b=VrhfhUyqn3gQuq23JcossYWX2xyTyq3PhCAbW3SAGdGySa+zzu9/Lexe/lYiWrvMEmQ7FO cBOV8QVmkfA0RHyxxDylOeyjBv6sOl9VrVJIg5u8cU3B4wazJ9PASDTBHdM6/2vzPDB3ACgN TupbMna8hapoxnuNMVnb5RqwKIjKomRlFY335o6j0fdBp7F/N3oFDuZ5HV6mOU7Ig4M/r22m BefCvPbgixus7Fs1FwDErtR7dmPKIfpwyNIc7UuqSqzAk2Et0XD5OiZ9BwDuyXyBOMQGcPJp VIB711bvOre9Fb81QDp5WgEHVWXOnLuf5ZiUhJ2dzKT2E0xvAtoP7BAA==; From: AdrianF To: openembedded-core@lists.openembedded.org Cc: marex@denx.de, l.anderweit@phytec.de, richard.purdie@linuxfoundation.org, ross.burton@arm.com, bruce.ashfield@gmail.com, rogerio.borin@toradex.com, sean.anderson@seco.com, m.felsch@pengutronix.de, ejo@pengutronix.de, Adrian Freihofer Subject: [PATCH 03/20] kernel-uboot: do not require the kernel build folder Date: Sun, 4 May 2025 15:04:50 +0200 Message-ID: <20250504130507.717954-3-adrian.freihofer@siemens.com> In-Reply-To: <20250504130507.717954-1-adrian.freihofer@siemens.com> References: <20250504130507.717954-1-adrian.freihofer@siemens.com> MIME-Version: 1.0 X-Flowmailer-Platform: Siemens Feedback-ID: 519:519-1329275:519-21489:flowmailer List-Id: X-Webhook-Received: from li982-79.members.linode.com [45.33.32.79] by aws-us-west-2-korg-lkml-1.web.codeaurora.org with HTTPS for ; Sun, 04 May 2025 13:06:58 -0000 X-Groupsio-URL: https://lists.openembedded.org/g/openembedded-core/message/215947 From: Adrian Freihofer The function must be executed in CWD. Make it more flexible by specifying the kernel build folder as a parameter. This is a refactoring without functional change. But later this change will allow to use this function also with a kernel from the sstate-cache instead of requiring the full kernel build folder structure. Another preparation for using a kernel from sstate-cache is to persist the linux_comp variable in a file next to the linux.bin file rather than using a global shell variable. This change also requires to adapt the kernel-uimage.bbclass accordingly. This change also fixes a minor detail: the kernel-uimage.bbclass used ${ instead of $ for evaluatiing a local shell variable. Signed-off-by: Adrian Freihofer --- meta/classes-recipe/kernel-uboot.bbclass | 40 ++++++++++++++--------- meta/classes-recipe/kernel-uimage.bbclass | 3 +- 2 files changed, 26 insertions(+), 17 deletions(-) diff --git a/meta/classes-recipe/kernel-uboot.bbclass b/meta/classes-recipe/kernel-uboot.bbclass index 6d4aff6b11b..d2a63524ece 100644 --- a/meta/classes-recipe/kernel-uboot.bbclass +++ b/meta/classes-recipe/kernel-uboot.bbclass @@ -12,19 +12,27 @@ FIT_KERNEL_COMP_ALG_EXTENSION ?= ".gz" UBOOT_MKIMAGE_KERNEL_TYPE ?= "kernel" uboot_prep_kimage() { - if [ -e arch/${ARCH}/boot/compressed/vmlinux ]; then + output_dir=$1 + # For backward compatibility with kernel-fitimage.bbclass and kernel-uboot.bbclass + # support calling without parameter as well + if [ -z "$output_dir" ]; then + output_dir='.' + fi + + linux_bin=$output_dir/linux.bin + if [ -e "arch/${ARCH}/boot/compressed/vmlinux" ]; then vmlinux_path="arch/${ARCH}/boot/compressed/vmlinux" linux_suffix="" linux_comp="none" - elif [ -e arch/${ARCH}/boot/vmlinuz.bin ]; then - rm -f linux.bin - cp -l arch/${ARCH}/boot/vmlinuz.bin linux.bin + elif [ -e "arch/${ARCH}/boot/vmlinuz.bin" ]; then + rm -f "$linux_bin" + cp -l "arch/${ARCH}/boot/vmlinuz.bin" "$linux_bin" vmlinux_path="" linux_suffix="" linux_comp="none" else vmlinux_path="vmlinux" - # Use vmlinux.initramfs for linux.bin when INITRAMFS_IMAGE_BUNDLE set + # Use vmlinux.initramfs for $linux_bin when INITRAMFS_IMAGE_BUNDLE set # As per the implementation in kernel.bbclass. # See do_bundle_initramfs function if [ "${INITRAMFS_IMAGE_BUNDLE}" = "1" ] && [ -e vmlinux.initramfs ]; then @@ -34,18 +42,18 @@ uboot_prep_kimage() { linux_comp="${FIT_KERNEL_COMP_ALG}" fi - [ -n "${vmlinux_path}" ] && ${KERNEL_OBJCOPY} -O binary -R .note -R .comment -S "${vmlinux_path}" linux.bin + [ -n "$vmlinux_path" ] && ${KERNEL_OBJCOPY} -O binary -R .note -R .comment -S "$vmlinux_path" "$linux_bin" - if [ "${linux_comp}" != "none" ] ; then - if [ "${linux_comp}" = "gzip" ] ; then - gzip -9 linux.bin - elif [ "${linux_comp}" = "lzo" ] ; then - lzop -9 linux.bin - elif [ "${linux_comp}" = "lzma" ] ; then - xz --format=lzma -f -6 linux.bin + if [ "$linux_comp" != "none" ] ; then + if [ "$linux_comp" = "gzip" ] ; then + gzip -9 "$linux_bin" + elif [ "$linux_comp" = "lzo" ] ; then + lzop -9 "$linux_bin" + elif [ "$linux_comp" = "lzma" ] ; then + xz --format=lzma -f -6 "$linux_bin" fi - mv -f "linux.bin${linux_suffix}" linux.bin + mv -f "$linux_bin$linux_suffix" "$linux_bin" fi - echo "${linux_comp}" -} + printf "$linux_comp" > "$output_dir/linux_comp" +} \ No newline at end of file diff --git a/meta/classes-recipe/kernel-uimage.bbclass b/meta/classes-recipe/kernel-uimage.bbclass index 1a599e656c8..e353232a0e9 100644 --- a/meta/classes-recipe/kernel-uimage.bbclass +++ b/meta/classes-recipe/kernel-uimage.bbclass @@ -29,6 +29,7 @@ python __anonymous () { do_uboot_mkimage[dirs] += "${B}" do_uboot_mkimage() { uboot_prep_kimage + linux_comp="$(cat linux_comp)" ENTRYPOINT=${UBOOT_ENTRYPOINT} if [ -n "${UBOOT_ENTRYSYMBOL}" ]; then @@ -36,6 +37,6 @@ do_uboot_mkimage() { awk '$3=="${UBOOT_ENTRYSYMBOL}" {print "0x"$1;exit}'` fi - uboot-mkimage -A ${UBOOT_ARCH} -O linux -T ${UBOOT_MKIMAGE_KERNEL_TYPE} -C "${linux_comp}" -a ${UBOOT_LOADADDRESS} -e $ENTRYPOINT -n "${DISTRO_NAME}/${PV}/${MACHINE}" -d linux.bin ${B}/arch/${ARCH}/boot/uImage + uboot-mkimage -A ${UBOOT_ARCH} -O linux -T ${UBOOT_MKIMAGE_KERNEL_TYPE} -C "$linux_comp" -a ${UBOOT_LOADADDRESS} -e $ENTRYPOINT -n "${DISTRO_NAME}/${PV}/${MACHINE}" -d linux.bin ${B}/arch/${ARCH}/boot/uImage rm -f linux.bin } From patchwork Sun May 4 13:04:51 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Freihofer, Adrian" X-Patchwork-Id: 62391 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from aws-us-west-2-korg-lkml-1.web.codeaurora.org (localhost.localdomain [127.0.0.1]) by smtp.lore.kernel.org (Postfix) with ESMTP id D9EC6C3ABB9 for ; Sun, 4 May 2025 13:06:58 +0000 (UTC) Received: from mta-64-227.siemens.flowmailer.net (mta-64-227.siemens.flowmailer.net [185.136.64.227]) by mx.groups.io with SMTP id smtpd.web10.28199.1746364017323825654 for ; Sun, 04 May 2025 06:06:58 -0700 Authentication-Results: mx.groups.io; dkim=pass header.i=adrian.freihofer@siemens.com header.s=fm1 header.b=G/+ImoYg; spf=pass (domain: rts-flowmailer.siemens.com, ip: 185.136.64.227, mailfrom: fm-1329275-202505041306541a327009ff3ce773a6-rxqvfn@rts-flowmailer.siemens.com) Received: by mta-64-227.siemens.flowmailer.net with ESMTPSA id 202505041306541a327009ff3ce773a6 for ; Sun, 04 May 2025 15:06:54 +0200 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; s=fm1; d=siemens.com; i=adrian.freihofer@siemens.com; h=Date:From:Subject:To:Message-ID:MIME-Version:Content-Type:Content-Transfer-Encoding:Cc:References:In-Reply-To; bh=Rzni6iaY70dKUayc/tWEL2wUKwWH+EMxTBbyTrVmDTA=; b=G/+ImoYgdAvev/cYNQms+UvOSEI/i8scp1WIjGC+e2Fj0miA0zpOcPGl+iSOAmi/Hdac/v no4jiG75eNG3je/woCw0E2CQRpEWCdkt8OQwGOEtYp7P2uDny86Cs/80FBuX6imMgP6XykW6 2sAkBOf2UA6O6PQDKLZ0gFVWkfBumeCKftbCqsca06lrN9OxIoyHXKC4pD0oJVR5oy5dNdmd 9Aawvt9J6wYZ+ZLgJnwW/KPRrlxVezinGwbm8fg7zbisz3Xi6H0yETGk3gr7VK5B9tEUZQ2o EeSoJKBoNxv3YJA5icPrDCbgousitBJTMET/W6sTkG3mP80ZqQN2FwRg==; From: AdrianF To: openembedded-core@lists.openembedded.org Cc: marex@denx.de, l.anderweit@phytec.de, richard.purdie@linuxfoundation.org, ross.burton@arm.com, bruce.ashfield@gmail.com, rogerio.borin@toradex.com, sean.anderson@seco.com, m.felsch@pengutronix.de, ejo@pengutronix.de, Adrian Freihofer Subject: [PATCH 04/20] kernel-devicetree: export dtbs to sysroot Date: Sun, 4 May 2025 15:04:51 +0200 Message-ID: <20250504130507.717954-4-adrian.freihofer@siemens.com> In-Reply-To: <20250504130507.717954-1-adrian.freihofer@siemens.com> References: <20250504130507.717954-1-adrian.freihofer@siemens.com> MIME-Version: 1.0 X-Flowmailer-Platform: Siemens Feedback-ID: 519:519-1329275:519-21489:flowmailer List-Id: X-Webhook-Received: from li982-79.members.linode.com [45.33.32.79] by aws-us-west-2-korg-lkml-1.web.codeaurora.org with HTTPS for ; Sun, 04 May 2025 13:06:58 -0000 X-Groupsio-URL: https://lists.openembedded.org/g/openembedded-core/message/215946 From: Adrian Freihofer Forward the devicetree blobs via sstate-cached sysroot directory to other recipes. The intention is to create FIT images independently from the kernel build folder structure later on. Signed-off-by: Adrian Freihofer --- meta/classes-recipe/kernel-devicetree.bbclass | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/meta/classes-recipe/kernel-devicetree.bbclass b/meta/classes-recipe/kernel-devicetree.bbclass index eff052b4029..75e394c5826 100644 --- a/meta/classes-recipe/kernel-devicetree.bbclass +++ b/meta/classes-recipe/kernel-devicetree.bbclass @@ -88,6 +88,10 @@ do_install:append() { dtb=$dtb_base_name.$dtb_ext fi install -Dm 0644 $dtb_path ${D}/${KERNEL_DTBDEST}/$dtb + + # Provide the DTBs also to other recipes + install -d ${D}/sysroot-only + install -Dm 0644 $dtb_path ${D}/sysroot-only/$dtb done } From patchwork Sun May 4 13:04:52 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Freihofer, Adrian" X-Patchwork-Id: 62388 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from aws-us-west-2-korg-lkml-1.web.codeaurora.org (localhost.localdomain [127.0.0.1]) by smtp.lore.kernel.org (Postfix) with ESMTP id C0EB7C3ABB6 for ; Sun, 4 May 2025 13:06:58 +0000 (UTC) Received: from mta-65-227.siemens.flowmailer.net (mta-65-227.siemens.flowmailer.net [185.136.65.227]) by mx.groups.io with SMTP id smtpd.web10.28203.1746364017576302694 for ; Sun, 04 May 2025 06:06:58 -0700 Authentication-Results: mx.groups.io; dkim=pass header.i=adrian.freihofer@siemens.com header.s=fm1 header.b=eNeM59HN; spf=pass (domain: rts-flowmailer.siemens.com, ip: 185.136.65.227, mailfrom: fm-1329275-20250504130655e2e9b8a1b743f5b1b2-6sozoe@rts-flowmailer.siemens.com) Received: by mta-65-227.siemens.flowmailer.net with ESMTPSA id 20250504130655e2e9b8a1b743f5b1b2 for ; Sun, 04 May 2025 15:06:55 +0200 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; s=fm1; d=siemens.com; i=adrian.freihofer@siemens.com; h=Date:From:Subject:To:Message-ID:MIME-Version:Content-Type:Content-Transfer-Encoding:Cc:References:In-Reply-To; bh=82ZqDkF8zgUzb+Zm9l4gxYoBf1cmRL6c6leSdYlcTfU=; b=eNeM59HNqDoOSMj7BJJ2m7cbKaG31v3mpNYNZ1RIvptkC0S4ztRa0bl4qQdx4w2U31XeV5 bkKHI4TDaQZDGhnwZCj0FEfyD2kjBckRsJxnrh1pfhIUH2nFpU2/uUQRRJ08M4esSFqgItlj HYg4aMqGQ7oDwzvdMJDla4LREj9PXoPryYlvFUOGanyiHktHOa3jE8lRU/W4pkBBRN4nZsfH K4B1+pzGZw3/1tzmw/KO28jcr3WsSibenLBTsPnTUJbAl150d7yBqAQpfqtRhfLS+u4gNFsa RdfNisu9TZd4JdHbegVzkp8lmLxIC8IOdD46GnrVpEBA4PP0szGcgBoQ==; From: AdrianF To: openembedded-core@lists.openembedded.org Cc: marex@denx.de, l.anderweit@phytec.de, richard.purdie@linuxfoundation.org, ross.burton@arm.com, bruce.ashfield@gmail.com, rogerio.borin@toradex.com, sean.anderson@seco.com, m.felsch@pengutronix.de, ejo@pengutronix.de, Adrian Freihofer Subject: [PATCH 05/20] kernel.bbclass: stage the sysroot-only folder Date: Sun, 4 May 2025 15:04:52 +0200 Message-ID: <20250504130507.717954-5-adrian.freihofer@siemens.com> In-Reply-To: <20250504130507.717954-1-adrian.freihofer@siemens.com> References: <20250504130507.717954-1-adrian.freihofer@siemens.com> MIME-Version: 1.0 X-Flowmailer-Platform: Siemens Feedback-ID: 519:519-1329275:519-21489:flowmailer List-Id: X-Webhook-Received: from li982-79.members.linode.com [45.33.32.79] by aws-us-west-2-korg-lkml-1.web.codeaurora.org with HTTPS for ; Sun, 04 May 2025 13:06:58 -0000 X-Groupsio-URL: https://lists.openembedded.org/g/openembedded-core/message/215945 From: Adrian Freihofer Move the configuration for staging the sysroot-only directory from the kernel-fitimage.bbclass to the kernel.bbclass. This is a preparation for using the FIT image related artifacts also from an independent recipe which creates the FIT image from artifacts going via sstate-cache. Signed-off-by: Adrian Freihofer --- meta/classes-recipe/kernel-fitimage.bbclass | 1 - meta/classes-recipe/kernel.bbclass | 4 ++-- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/meta/classes-recipe/kernel-fitimage.bbclass b/meta/classes-recipe/kernel-fitimage.bbclass index 07786647e19..765776a562b 100644 --- a/meta/classes-recipe/kernel-fitimage.bbclass +++ b/meta/classes-recipe/kernel-fitimage.bbclass @@ -731,7 +731,6 @@ do_assemble_fitimage() { addtask assemble_fitimage before do_install after do_compile -SYSROOT_DIRS:append = " /sysroot-only" do_install:append() { if echo ${KERNEL_IMAGETYPES} | grep -wq "fitImage" && \ [ "${UBOOT_SIGN_ENABLE}" = "1" ]; then diff --git a/meta/classes-recipe/kernel.bbclass b/meta/classes-recipe/kernel.bbclass index 36ce659762e..1a7a60eadfc 100644 --- a/meta/classes-recipe/kernel.bbclass +++ b/meta/classes-recipe/kernel.bbclass @@ -631,8 +631,8 @@ do_shared_workdir () { } -# We don't need to stage anything, not the modules/firmware since those would clash with linux-firmware -SYSROOT_DIRS = "" +# Stage the sysroot-only folder e.g. for FIT image related artifacts +SYSROOT_DIRS = "/sysroot-only" KERNEL_CONFIG_COMMAND ?= "oe_runmake_call -C ${S} O=${B} olddefconfig || oe_runmake -C ${S} O=${B} oldnoconfig" From patchwork Sun May 4 13:04:53 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Freihofer, Adrian" X-Patchwork-Id: 62392 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from aws-us-west-2-korg-lkml-1.web.codeaurora.org (localhost.localdomain [127.0.0.1]) by smtp.lore.kernel.org (Postfix) with ESMTP id CCCE6C3ABB8 for ; Sun, 4 May 2025 13:06:58 +0000 (UTC) Received: from mta-65-227.siemens.flowmailer.net (mta-65-227.siemens.flowmailer.net [185.136.65.227]) by mx.groups.io with SMTP id smtpd.web10.28204.1746364017644731354 for ; Sun, 04 May 2025 06:06:58 -0700 Authentication-Results: mx.groups.io; dkim=pass header.i=adrian.freihofer@siemens.com header.s=fm1 header.b=UFgvCJzp; spf=pass (domain: rts-flowmailer.siemens.com, ip: 185.136.65.227, mailfrom: fm-1329275-2025050413065584b60616f37155f910-f_vxvv@rts-flowmailer.siemens.com) Received: by mta-65-227.siemens.flowmailer.net with ESMTPSA id 2025050413065584b60616f37155f910 for ; Sun, 04 May 2025 15:06:55 +0200 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; s=fm1; d=siemens.com; i=adrian.freihofer@siemens.com; h=Date:From:Subject:To:Message-ID:MIME-Version:Content-Type:Content-Transfer-Encoding:Cc:References:In-Reply-To; bh=nhMgxIzZ3iXlaOg+kmuGvadbhHiHFjNEdNIsjBj7FIc=; b=UFgvCJzp2uaoT1dgx+ga5MkqDB68vygGpDmdRblLXwqhTox4YD4z25UaT1PfYLugOG7nMJ ODrmAYnbFb021YMIAvjmtDbbiQGn58upmo6lCGV+p4l6Qci24NtHnsgEBEqj6a7PkSiFPs/i pv41k332ZComLLVL9dELvfuLysdpi9uh0iK3amvfcqi+STHRJg68cLw6SoeuX7Uz3HSMdJrK hhbDEQ5Or6ov8Ie1oMccCHJJ1zz3b516EBX3blh3x9RmbR75g6Virnnuy5GdnVnF4bogAfrH 8H4Uey2/xKU5Mbweyl7ANUM3ZTj9EzPmZlq1thGzQsXcBiyv0bNdcraQ==; From: AdrianF To: openembedded-core@lists.openembedded.org Cc: marex@denx.de, l.anderweit@phytec.de, richard.purdie@linuxfoundation.org, ross.burton@arm.com, bruce.ashfield@gmail.com, rogerio.borin@toradex.com, sean.anderson@seco.com, m.felsch@pengutronix.de, ejo@pengutronix.de, Adrian Freihofer Subject: [PATCH 06/20] kernel-uboot.bbclass: stage the kernel binary Date: Sun, 4 May 2025 15:04:53 +0200 Message-ID: <20250504130507.717954-6-adrian.freihofer@siemens.com> In-Reply-To: <20250504130507.717954-1-adrian.freihofer@siemens.com> References: <20250504130507.717954-1-adrian.freihofer@siemens.com> MIME-Version: 1.0 X-Flowmailer-Platform: Siemens Feedback-ID: 519:519-1329275:519-21489:flowmailer List-Id: X-Webhook-Received: from li982-79.members.linode.com [45.33.32.79] by aws-us-west-2-korg-lkml-1.web.codeaurora.org with HTTPS for ; Sun, 04 May 2025 13:06:58 -0000 X-Groupsio-URL: https://lists.openembedded.org/g/openembedded-core/message/215948 From: Adrian Freihofer Extend the kernel-uboot.bbclass to expport the kernel binary which is needed for creating a FIT image to the sysroot-only directory. This will allow to use KERNEL_CLASSES += "kernel-uboot" and a recipe which creates the FIT image using artifacts from sysroot-only instead of the kernel-fitimage.bbclass KERNEL_CLASSES = " kernel-fitimage " which does not work with sstate-cache. Signed-off-by: Adrian Freihofer --- meta/classes-recipe/kernel-uboot.bbclass | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/meta/classes-recipe/kernel-uboot.bbclass b/meta/classes-recipe/kernel-uboot.bbclass index d2a63524ece..7aafd4757c2 100644 --- a/meta/classes-recipe/kernel-uboot.bbclass +++ b/meta/classes-recipe/kernel-uboot.bbclass @@ -56,4 +56,14 @@ uboot_prep_kimage() { fi printf "$linux_comp" > "$output_dir/linux_comp" -} \ No newline at end of file +} + +do_install:append() { + # Provide the kernel artifacts to post processing recipes e.g. for creating a FIT image + install -d ${D}/sysroot-only + uboot_prep_kimage ${D}/sysroot-only + # For x86 a setup.bin needs to be included in a fitImage as well + if [ -e ${KERNEL_OUTPUT_DIR}/setup.bin ]; then + install -D ${B}/${KERNEL_OUTPUT_DIR}/setup.bin ${D}/sysroot-only/setup.bin + fi +} From patchwork Sun May 4 13:04:54 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Freihofer, Adrian" X-Patchwork-Id: 62395 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from aws-us-west-2-korg-lkml-1.web.codeaurora.org (localhost.localdomain [127.0.0.1]) by smtp.lore.kernel.org (Postfix) with ESMTP id E9DB0C3ABBD for ; Sun, 4 May 2025 13:06:58 +0000 (UTC) Received: from mta-65-225.siemens.flowmailer.net (mta-65-225.siemens.flowmailer.net [185.136.65.225]) by mx.groups.io with SMTP id smtpd.web11.28295.1746364017939619232 for ; Sun, 04 May 2025 06:06:58 -0700 Authentication-Results: mx.groups.io; dkim=pass header.i=adrian.freihofer@siemens.com header.s=fm1 header.b=KTD3kXPT; spf=pass (domain: rts-flowmailer.siemens.com, ip: 185.136.65.225, mailfrom: fm-1329275-202505041306551a4bf2494686c21ee5-mkymze@rts-flowmailer.siemens.com) Received: by mta-65-225.siemens.flowmailer.net with ESMTPSA id 202505041306551a4bf2494686c21ee5 for ; Sun, 04 May 2025 15:06:55 +0200 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; s=fm1; d=siemens.com; i=adrian.freihofer@siemens.com; h=Date:From:Subject:To:Message-ID:MIME-Version:Content-Type:Content-Transfer-Encoding:Cc:References:In-Reply-To; bh=sfUJYt4gDjRBsgEKELMmVL77GaFWYba2RxQz29CUCK0=; b=KTD3kXPTekiZhI6PTR5NNZb4wjYr2L6xv8reoC9Sm807tY5B8s4J+BYqsZSMTXhLwkcf/3 Xe3bjZif3TfiJq4IXtc9+eUpoLcXOPSm4FYUC8wJaBsnDfnA2KyF0/Gy8FV5S8phMOkZjpYl KAtxiJhzVAzmLvwOaXhg50LiRx9nN3K+l1/m5o73c4QKBd5Kxx74RbGBlMUwqZQVAhXOvyJj 7ZFkb5hi9xrie1n4SNl6+to6+ru5GAOKjIVLOS2Uc8liOhHDSnnT9ylGHMzX5O+r7HziQEao lhJUIjJAGTVaI66tk5zwmBhElvDTcAHDz5tCyORNi95cX8opifYLAyYQ==; From: AdrianF To: openembedded-core@lists.openembedded.org Cc: marex@denx.de, l.anderweit@phytec.de, richard.purdie@linuxfoundation.org, ross.burton@arm.com, bruce.ashfield@gmail.com, rogerio.borin@toradex.com, sean.anderson@seco.com, m.felsch@pengutronix.de, ejo@pengutronix.de, Adrian Freihofer Subject: [PATCH 07/20] kernel-fitimage: refactor order in its Date: Sun, 4 May 2025 15:04:54 +0200 Message-ID: <20250504130507.717954-7-adrian.freihofer@siemens.com> In-Reply-To: <20250504130507.717954-1-adrian.freihofer@siemens.com> References: <20250504130507.717954-1-adrian.freihofer@siemens.com> MIME-Version: 1.0 X-Flowmailer-Platform: Siemens Feedback-ID: 519:519-1329275:519-21489:flowmailer List-Id: X-Webhook-Received: from li982-79.members.linode.com [45.33.32.79] by aws-us-west-2-korg-lkml-1.web.codeaurora.org with HTTPS for ; Sun, 04 May 2025 13:06:58 -0000 X-Groupsio-URL: https://lists.openembedded.org/g/openembedded-core/message/215951 From: Adrian Freihofer When the ITS file is created, the mandatory properties are written first before the optional properties are written. This is not really useful for the current implementation. But it is a preparation for a new Python-based implementation that will expect mandatory properties first. This change makes it possible to run the tests with both the old and the new implementation. Signed-off-by: Adrian Freihofer --- meta/classes-recipe/kernel-fitimage.bbclass | 20 ++++++++++---------- meta/lib/oeqa/selftest/cases/fitimage.py | 4 ++-- 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/meta/classes-recipe/kernel-fitimage.bbclass b/meta/classes-recipe/kernel-fitimage.bbclass index 765776a562b..1ef7b1b4483 100644 --- a/meta/classes-recipe/kernel-fitimage.bbclass +++ b/meta/classes-recipe/kernel-fitimage.bbclass @@ -125,11 +125,11 @@ fitimage_emit_section_kernel() { cat << EOF >> $1 kernel-$2 { description = "Linux kernel"; - data = /incbin/("$3"); type = "${UBOOT_MKIMAGE_KERNEL_TYPE}"; + compression = "$4"; + data = /incbin/("$3"); arch = "${UBOOT_ARCH}"; os = "linux"; - compression = "$4"; load = <${UBOOT_LOADADDRESS}>; entry = <$ENTRYPOINT>; hash-1 { @@ -174,10 +174,10 @@ fitimage_emit_section_dtb() { cat << EOF >> $1 fdt-$2 { description = "Flattened Device Tree blob"; - data = /incbin/("$3"); type = "flat_dt"; - arch = "${UBOOT_ARCH}"; compression = "none"; + data = /incbin/("$3"); + arch = "${UBOOT_ARCH}"; $dtb_loadline hash-1 { algo = "$dtb_csum"; @@ -212,10 +212,10 @@ fitimage_emit_section_boot_script() { cat << EOF >> $1 bootscr-$2 { description = "U-boot script"; - data = /incbin/("$3"); type = "script"; - arch = "${UBOOT_ARCH}"; compression = "none"; + data = /incbin/("$3"); + arch = "${UBOOT_ARCH}"; hash-1 { algo = "$bootscr_csum"; }; @@ -249,11 +249,11 @@ fitimage_emit_section_setup() { cat << EOF >> $1 setup-$2 { description = "Linux setup.bin"; - data = /incbin/("$3"); type = "x86_setup"; + compression = "none"; + data = /incbin/("$3"); arch = "${UBOOT_ARCH}"; os = "linux"; - compression = "none"; load = <0x00090000>; entry = <0x00090000>; hash-1 { @@ -298,11 +298,11 @@ fitimage_emit_section_ramdisk() { cat << EOF >> $1 ramdisk-$2 { description = "${INITRAMFS_IMAGE}"; - data = /incbin/("$3"); type = "ramdisk"; + compression = "none"; + data = /incbin/("$3"); arch = "${UBOOT_ARCH}"; os = "linux"; - compression = "none"; $ramdisk_loadline $ramdisk_entryline hash-1 { diff --git a/meta/lib/oeqa/selftest/cases/fitimage.py b/meta/lib/oeqa/selftest/cases/fitimage.py index ba5adaa9b67..81585aa10b3 100644 --- a/meta/lib/oeqa/selftest/cases/fitimage.py +++ b/meta/lib/oeqa/selftest/cases/fitimage.py @@ -509,11 +509,11 @@ class KernelFitImageTests(FitImageTestCase): its_field_check = [ 'description = "%s";' % bb_vars['FIT_DESC'], 'description = "Linux kernel";', - 'data = /incbin/("linux.bin");', 'type = "' + str(bb_vars['UBOOT_MKIMAGE_KERNEL_TYPE']) + '";', + # 'compression = "' + str(bb_vars['FIT_KERNEL_COMP_ALG']) + '";', defined based on files in TMPDIR, not ideal... + 'data = /incbin/("linux.bin");', 'arch = "' + str(bb_vars['UBOOT_ARCH']) + '";', 'os = "linux";', - # 'compression = "' + str(bb_vars['FIT_KERNEL_COMP_ALG']) + '";', defined based on files in TMPDIR, not ideal... 'load = <' + str(bb_vars['UBOOT_LOADADDRESS']) + '>;', 'entry = <' + str(bb_vars['UBOOT_ENTRYPOINT']) + '>;', ] From patchwork Sun May 4 13:04:55 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Freihofer, Adrian" X-Patchwork-Id: 62394 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from aws-us-west-2-korg-lkml-1.web.codeaurora.org (localhost.localdomain [127.0.0.1]) by smtp.lore.kernel.org (Postfix) with ESMTP id E9D05C3ABBB for ; Sun, 4 May 2025 13:06:58 +0000 (UTC) Received: from mta-64-225.siemens.flowmailer.net (mta-64-225.siemens.flowmailer.net [185.136.64.225]) by mx.groups.io with SMTP id smtpd.web11.28294.1746364017931472630 for ; Sun, 04 May 2025 06:06:58 -0700 Authentication-Results: mx.groups.io; dkim=pass header.i=adrian.freihofer@siemens.com header.s=fm1 header.b=D0qGMt3o; spf=pass (domain: rts-flowmailer.siemens.com, ip: 185.136.64.225, mailfrom: fm-1329275-20250504130656b7bd46a0a5c832e61b-u1taka@rts-flowmailer.siemens.com) Received: by mta-64-225.siemens.flowmailer.net with ESMTPSA id 20250504130656b7bd46a0a5c832e61b for ; Sun, 04 May 2025 15:06:56 +0200 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; s=fm1; d=siemens.com; i=adrian.freihofer@siemens.com; h=Date:From:Subject:To:Message-ID:MIME-Version:Content-Type:Content-Transfer-Encoding:Cc:References:In-Reply-To; bh=6TiYs0mCAjnfXF1wCYRITvCUvS7ajQ7WLtBopFAARrg=; b=D0qGMt3o3n9PDSOPgGUoCk6DSXQWlUypJ1f7tLNUEL+9Ghmph7sE9I64xA663VM/c6bcti 5SB0OX8Jeo/37Ls/svb/EIcHvYAgHgYJAbgI9Fdqk8p2VP8JmQuITfmYrQXdRKa67K0jEBaG VOy13coF/GecE7pySIRrsF88iZylUvqxSUExHnP1JF+7iVUTLo7E7ZcVw29neWobQKxLplM6 nBQP2rvDjkSnTDZCnmx/Jg2lxnLLAcF9vVlVhxgVGVlC5FYAYBRN22F5Zc0A2/z6u/GrF+iv 4y7GtHN96a713PTn8A5UgCJWa+J7TxR2Sp5BtgNOL2TphxxCGS5Qm7OA==; From: AdrianF To: openembedded-core@lists.openembedded.org Cc: marex@denx.de, l.anderweit@phytec.de, richard.purdie@linuxfoundation.org, ross.burton@arm.com, bruce.ashfield@gmail.com, rogerio.borin@toradex.com, sean.anderson@seco.com, m.felsch@pengutronix.de, ejo@pengutronix.de, Adrian Freihofer Subject: [PATCH 08/20] kernel-fit-image.bbclass: add a new FIT image implementation Date: Sun, 4 May 2025 15:04:55 +0200 Message-ID: <20250504130507.717954-8-adrian.freihofer@siemens.com> In-Reply-To: <20250504130507.717954-1-adrian.freihofer@siemens.com> References: <20250504130507.717954-1-adrian.freihofer@siemens.com> MIME-Version: 1.0 X-Flowmailer-Platform: Siemens Feedback-ID: 519:519-1329275:519-21489:flowmailer List-Id: X-Webhook-Received: from li982-79.members.linode.com [45.33.32.79] by aws-us-west-2-korg-lkml-1.web.codeaurora.org with HTTPS for ; Sun, 04 May 2025 13:06:58 -0000 X-Groupsio-URL: https://lists.openembedded.org/g/openembedded-core/message/215952 From: Adrian Freihofer This new recipe and the new kernel-fit-image.bbclass are intended to become the successor of the kernel-fitimage.bbclass. This recipe is an alternative implementation of what the kernel-fitimage.bbclass provides. Instead of injecting the FIT image related build steps into the kernel recipe, the new recipe takes the kernel artifacts from the kernel recipe and creates the FIT image as a independent task. This solves some basic problems: * sstate does not work well when a fitImage contains an initramfs. The kernel is rebuilt from scratch if the build runs from an empty TMPDIR. * A fitImage kernel is not available as a package, but all other kernel image types are. * The task dependencies in the kernel are very complex and difficult to debug if something goes wrong. As a separate, downstream recipe, this is now much easier. The long storry about this issue is here: [YOCTO #12912] Signed-off-by: Adrian Freihofer --- meta/classes-recipe/kernel-fit-image.bbclass | 206 ++++++++ meta/lib/oe/fitimage.py | 481 ++++++++++++++++++ .../linux/linux-yocto-fitimage_6.12.bb | 13 + 3 files changed, 700 insertions(+) create mode 100644 meta/classes-recipe/kernel-fit-image.bbclass create mode 100644 meta/lib/oe/fitimage.py create mode 100644 meta/recipes-kernel/linux/linux-yocto-fitimage_6.12.bb diff --git a/meta/classes-recipe/kernel-fit-image.bbclass b/meta/classes-recipe/kernel-fit-image.bbclass new file mode 100644 index 00000000000..3c40fbb0ffa --- /dev/null +++ b/meta/classes-recipe/kernel-fit-image.bbclass @@ -0,0 +1,206 @@ + +inherit kernel-arch kernel-artifact-names uboot-config deploy +require conf/image-fitimage.conf + +S = "${WORKDIR}/sources" +UNPACKDIR = "${S}" + +PACKAGE_ARCH = "${MACHINE_ARCH}" + +DEPENDS += "u-boot-tools-native dtc-native virtual/kernel" + +python () { + image = d.getVar('INITRAMFS_IMAGE') + if image and not bb.utils.to_boolean(d.getVar('INITRAMFS_IMAGE_BUNDLE')): + if d.getVar('INITRAMFS_MULTICONFIG'): + mc = d.getVar('BB_CURRENT_MC') + d.appendVarFlag('do_compile', 'mcdepends', ' mc:' + mc + ':${INITRAMFS_MULTICONFIG}:${INITRAMFS_IMAGE}:do_image_complete') + else: + d.appendVarFlag('do_compile', 'depends', ' ${INITRAMFS_IMAGE}:do_image_complete') + + #check if there are any dtb providers + providerdtb = d.getVar("PREFERRED_PROVIDER_virtual/dtb") + if providerdtb: + d.appendVarFlag('do_compile', 'depends', ' virtual/dtb:do_populate_sysroot') + d.setVar('EXTERNAL_KERNEL_DEVICETREE', "${RECIPE_SYSROOT}/boot/devicetree") + + # Maybe more for develpoment purpose, support generating a set of keys + if oe.types.boolean(d.getVar('UBOOT_SIGN_ENABLE')) and oe.types.boolean(d.getVar('FIT_GENERATE_KEYS')): + bb.build.addtask('do_generate_rsa_keys', 'do_compile', '', d) +} + +do_configure[noexec] = "1" + +UBOOT_MKIMAGE_KERNEL_TYPE ?= "kernel" +KERNEL_IMAGEDEST ?= "/boot" + +python do_compile() { + import shutil + import oe.fitimage + + itsfile = "fit-image.its" + fitname = "fitImage" + recipe_sysroot = d.getVar('RECIPE_SYSROOT') + + # Collect all the its nodes before the its file is generated and mkimage gets executed + root_node = oe.fitimage.ItsNodeRootKernel( + d.getVar("FIT_DESC"), d.getVar("FIT_ADDRESS_CELLS"), + d.getVar('HOST_PREFIX'), d.getVar('UBOOT_ARCH'), d.getVar("FIT_CONF_PREFIX"), + oe.types.boolean(d.getVar('UBOOT_SIGN_ENABLE')), d.getVar("UBOOT_SIGN_KEYDIR"), + d.getVar("UBOOT_MKIMAGE"), d.getVar("UBOOT_MKIMAGE_DTCOPTS"), + d.getVar("UBOOT_MKIMAGE_SIGN"), d.getVar("UBOOT_MKIMAGE_SIGN_ARGS"), + d.getVar('FIT_HASH_ALG'), d.getVar('FIT_SIGN_ALG'), d.getVar('FIT_PAD_ALG'), + d.getVar('UBOOT_SIGN_KEYNAME'), + oe.types.boolean(d.getVar('FIT_SIGN_INDIVIDUAL')), d.getVar('UBOOT_SIGN_IMG_KEYNAME') + ) + + # Prepare a kernel image section. + shutil.copyfile(os.path.join(recipe_sysroot, "sysroot-only", "linux.bin"), "linux.bin") + with open(os.path.join(recipe_sysroot, "sysroot-only", "linux_comp")) as linux_comp_f: + linux_comp = linux_comp_f.read() + 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")) + + # Prepare a DTB image section + kernel_devicetree = d.getVar('KERNEL_DEVICETREE') + external_kernel_devicetree = d.getVar("EXTERNAL_KERNEL_DEVICETREE") + if kernel_devicetree: + for dtb in kernel_devicetree.split(): + dtb_name = os.path.basename(dtb) + + # Skip DTB if it's also provided in EXTERNAL_KERNEL_DEVICETREE directory + if external_kernel_devicetree: + ext_dtb_path = os.path.join(d.getVar("EXTERNAL_KERNEL_DEVICETREE"), dtb_name) + if os.path.exists(ext_dtb_path) and os.path.getsize(ext_dtb_path) > 0: + continue + + # Copy the dtb or dtbo file into the FIT image assembly directory + shutil.copyfile(os.path.join(recipe_sysroot, "sysroot-only", dtb_name), dtb_name) + root_node.fitimage_emit_section_dtb(dtb_name, dtb_name, + d.getVar("UBOOT_DTB_LOADADDRESS"), d.getVar("UBOOT_DTBO_LOADADDRESS")) + + if external_kernel_devicetree: + # iterate over all .dtb and .dtbo files in the external kernel devicetree directory + # and copy them to the FIT image assembly directory + for dtb_name in os.listdir(external_kernel_devicetree): + if dtb_name.endswith('.dtb') or dtb_name.endswith('.dtbo'): + dtb_path = os.path.join(external_kernel_devicetree, dtb_name) + + # Also skip if a symlink. We'll later have each config section point at it + if oe.fitimage.symlink_points_below(dtb_name, external_kernel_devicetree): + continue + + shutil.copyfile(dtb_path, dtb_name) + root_node.fitimage_emit_section_dtb(dtb_name, dtb_name, + d.getVar("UBOOT_DTB_LOADADDRESS"), d.getVar("UBOOT_DTBO_LOADADDRESS")) + + # Prepare a u-boot script section + fit_uboot_env = d.getVar("FIT_UBOOT_ENV") + if fit_uboot_env: + root_node.fitimage_emit_section_boot_script("bootscr-"+fit_uboot_env , fit_uboot_env) + + # Prepare a setup section (For x86) + setup_bin_path = os.path.join(recipe_sysroot, "sysroot-only", "setup.bin") + if os.path.exists(setup_bin_path): + shutil.copyfile(setup_bin_path, "setup.bin") + root_node.fitimage_emit_section_setup("setup-1", "setup.bin") + + # Prepare a ramdisk section. + initramfs_image = d.getVar('INITRAMFS_IMAGE') + if initramfs_image and not oe.types.boolean(d.getVar("INITRAMFS_IMAGE_BUNDLE")): + # Find and use the first initramfs image archive type we find + found = False + for img in d.getVar("FIT_SUPPORTED_INITRAMFS_FSTYPES").split(): + initramfs_path = os.path.join(d.getVar("DEPLOY_DIR_IMAGE"), "%s.%s" % (d.getVar('INITRAMFS_IMAGE_NAME'), img)) + if os.path.exists(initramfs_path): + bb.note("Found initramfs image: " + initramfs_path) + found = True + root_node.fitimage_emit_section_ramdisk("ramdisk-1", initramfs_path, + initramfs_image, + d.getVar("UBOOT_RD_LOADADDRESS"), + d.getVar("UBOOT_RD_ENTRYPOINT")) + break + else: + bb.note("Did not find initramfs image: " + initramfs_path) + + if not found: + bb.fatal("Could not find a valid initramfs type for %s, the supported types are: %s" % (d.getVar('INITRAMFS_IMAGE_NAME'), d.getVar('FIT_SUPPORTED_INITRAMFS_FSTYPES'))) + + # Generate the configuration section + root_node.fitimage_emit_section_config() + + # Write the its file + root_node.write_its_file(itsfile) + + # Assemble the FIT image + root_node.run_mkimage_assemble(itsfile, fitname) + + # Sign the FIT image if required + root_node.run_mkimage_sign(fitname) +} + +do_install() { + install -d "${D}/${KERNEL_IMAGEDEST}" + install -m 0644 "${B}/fitImage" "${D}/${KERNEL_IMAGEDEST}/fitImage" +} + +FILES:${PN} = "${KERNEL_IMAGEDEST}" + + +do_deploy() { + deploy_dir="${DEPLOYDIR}" + if [ -n "${KERNEL_DEPLOYSUBDIR}" ]; then + deploy_dir="${DEPLOYDIR}/${KERNEL_DEPLOYSUBDIR}" + fi + install -d "$deploy_dir" + install -m 0644 "${B}/fitImage" "$deploy_dir/fitImage" + install -m 0644 "${B}/fit-image.its" "$deploy_dir/fit-image.its" + + if [ "${INITRAMFS_IMAGE_BUNDLE}" != "1" ]; then + ln -snf fit-image.its "$deploy_dir/fitImage-its-${KERNEL_FIT_NAME}.its" + if [ -n "${KERNEL_FIT_LINK_NAME}" ] ; then + ln -snf fit-image.its "$deploy_dir/fitImage-its-${KERNEL_FIT_LINK_NAME}" + fi + fi + + if [ -n "${INITRAMFS_IMAGE}" ]; then + ln -snf fit-image-its "$deploy_dir/fitImage-its-${INITRAMFS_IMAGE_NAME}-${KERNEL_FIT_NAME}.its" + if [ -n "${KERNEL_FIT_LINK_NAME}" ]; then + ln -snf fit-image.its "$deploy_dir/fitImage-its-${INITRAMFS_IMAGE_NAME}-${KERNEL_FIT_LINK_NAME}" + fi + + if [ "${INITRAMFS_IMAGE_BUNDLE}" != "1" ]; then + ln -snf fitImage "$deploy_dir/fitImage-${INITRAMFS_IMAGE_NAME}-${KERNEL_FIT_NAME}${KERNEL_FIT_BIN_EXT}" + if [ -n "${KERNEL_FIT_LINK_NAME}" ] ; then + ln -snf fitImage "$deploy_dir/fitImage-${INITRAMFS_IMAGE_NAME}-${KERNEL_FIT_LINK_NAME}" + fi + fi + fi +} +addtask deploy after do_compile before do_build + + +# Genreate some signing keys if FIT_GENERATE_KEYS is enabled. +python do_generate_rsa_keys() { + import oe.fitimage + + sign_keydir = d.getVar('UBOOT_SIGN_KEYDIR') + sign_keyname = d.getVar('UBOOT_SIGN_KEYNAME') + sign_kc_path = os.path.join(sign_keydir, sign_keyname) + if not os.path.exists(sign_kc_path + '.key') or not os.path.exists(sign_kc_path + '.crt'): + bb.note("Generating RSA private key and certificate for signing fitImage configurations") + oe.fitimage.generate_rsa_key(sign_keydir, sign_keyname, + d.getVar('FIT_SIGN_NUMBITS'), d.getVar('FIT_KEY_GENRSA_ARGS'), + d.getVar('FIT_KEY_REQ_ARGS'), d.getVar('FIT_KEY_SIGN_PKCS')) + + if oe.types.boolean(d.getVar('FIT_SIGN_INDIVIDUAL')): + sign_img_keyname = d.getVar('UBOOT_SIGN_IMG_KEYNAME') + sign_img_kc_path = os.path.join(sign_keydir, sign_img_keyname) + if not os.path.exists(sign_img_kc_path + '.key') or not os.path.exists(sign_img_kc_path + '.crt'): + bb.note("Generating RSA private key and certificate for signing fitImage individual images") + oe.fitimage.generate_rsa_key(sign_keydir, sign_img_keyname, + d.getVar('FIT_SIGN_NUMBITS'), d.getVar('FIT_KEY_GENRSA_ARGS'), + d.getVar('FIT_KEY_REQ_ARGS'), d.getVar('FIT_KEY_SIGN_PKCS')) +} +do_generate_rsa_keys[depends] += "openssl-native:do_populate_sysroot" diff --git a/meta/lib/oe/fitimage.py b/meta/lib/oe/fitimage.py new file mode 100644 index 00000000000..d30d0995ca5 --- /dev/null +++ b/meta/lib/oe/fitimage.py @@ -0,0 +1,481 @@ +# +# Copyright OpenEmbedded Contributors +# +# SPDX-License-Identifier: GPL-2.0-only +# +# This file contains common functions for the fitimage generation + +import os +import shlex +import subprocess +import bb + +from oeqa.utils.commands import runCmd + +class ItsNode: + INDENT_SIZE = 8 + + def __init__(self, name, parent_node, sub_nodes=None, properties=None): + self.name = name + self.parent_node = parent_node + + self.sub_nodes = [] + if sub_nodes: + self.sub_nodes = sub_nodes + + self.properties = {} + if properties: + self.properties = properties + + if parent_node: + parent_node.add_sub_node(self) + + def add_sub_node(self, sub_node): + self.sub_nodes.append(sub_node) + + def add_property(self, key, value): + self.properties[key] = value + + def emit(self, f, indent): + indent_str_name = " " * indent + indent_str_props = " " * (indent + self.INDENT_SIZE) + f.write("%s%s {\n" % (indent_str_name, self.name)) + for key, value in self.properties.items(): + bb.debug(1, "key: %s, value: %s" % (key, str(value))) + # Single integer: <0x12ab> + if isinstance(value, int): + f.write(indent_str_props + key + ' = <0x%x>;\n' % value) + # list of strings: "string1", "string2" or integers: <0x12ab 0x34cd> + elif isinstance(value, list): + if len(value) == 0: + f.write(indent_str_props + key + ' = "";\n') + elif isinstance(value[0], int): + list_entries = ' '.join('0x%x' % entry for entry in value) + f.write(indent_str_props + key + ' = <%s>;\n' % list_entries) + else: + list_entries = ', '.join('"%s"' % entry for entry in value) + f.write(indent_str_props + key + ' = %s;\n' % list_entries) + elif isinstance(value, str): + # path: /incbin/("path/to/file") + if key in ["data"] and value.startswith('/incbin/('): + f.write(indent_str_props + key + ' = %s;\n' % value) + # Integers which are already string formatted + elif value.startswith("<") and value.endswith(">"): + f.write(indent_str_props + key + ' = %s;\n' % value) + else: + f.write(indent_str_props + key + ' = "%s";\n' % value) + else: + bb.fatal("%s has unexpexted data type." % str(value)) + for sub_node in self.sub_nodes: + sub_node.emit(f, indent + self.INDENT_SIZE) + f.write(indent_str_name + '};\n') + +class ItsNodeImages(ItsNode): + def __init__(self, parent_node): + super().__init__("images", parent_node) + +class ItsNodeConfigurations(ItsNode): + def __init__(self, parent_node): + super().__init__("configurations", parent_node) + +class ItsNodeHash(ItsNode): + def __init__(self, name, parent_node, algo, opt_props=None): + properties = { + "algo": algo + } + if opt_props: + properties.update(opt_props) + super().__init__(name, parent_node, None, properties) + +class ItsImageSignature(ItsNode): + def __init__(self, name, parent_node, algo, keyname, opt_props=None): + properties = { + "algo": algo, + "key-name-hint": keyname + } + if opt_props: + properties.update(opt_props) + super().__init__(name, parent_node, None, properties) + +class ItsNodeImage(ItsNode): + def __init__(self, name, parent_node, description, type, compression, sub_nodes=None, opt_props=None): + properties = { + "description": description, + "type": type, + "compression": compression, + } + if opt_props: + properties.update(opt_props) + super().__init__(name, parent_node, sub_nodes, properties) + +class ItsNodeConfigurationSignature(ItsNode): + def __init__(self, name, parent_node, algo, keyname, opt_props=None): + properties = { + "algo": algo, + "key-name-hint": keyname + } + if opt_props: + properties.update(opt_props) + super().__init__(name, parent_node, None, properties) + +class ItsNodeConfiguration(ItsNode): + def __init__(self, name, parent_node, description, sub_nodes=None, opt_props=None): + properties = { + "description": description, + } + if opt_props: + properties.update(opt_props) + super().__init__(name, parent_node, sub_nodes, properties) + +class ItsNodeRootKernel(ItsNode): + """Create FIT images for the kernel + + Currently only a single kernel (no less or more) can be added to the FIT + image along with 0 or more device trees and 0 or 1 ramdisk. + + If a device tree included in the FIT image, the default configuration is the + firt DTB. If there is no dtb present than the default configuation the kernel. + """ + def __init__(self, description, address_cells, host_prefix, arch, conf_prefix, + sign_enable=False, sign_keydir=None, + mkimage=None, mkimage_dtcopts=None, + mkimage_sign=None, mkimage_sign_args=None, + hash_algo=None, sign_algo=None, pad_algo=None, + sign_keyname_conf=None, + sign_individual=False, sign_keyname_img=None): + props = { + "description": description, + "#address-cells": f"<{address_cells}>" + } + super().__init__("/", None, None, props) + self.images = ItsNodeImages(self) + self.configurations = ItsNodeConfigurations(self) + + self._host_prefix = host_prefix + self._arch = arch + self._conf_prefix = conf_prefix + + # Signature related properties + self._sign_enable = sign_enable + self._sign_keydir = sign_keydir + self._mkimage = mkimage + self._mkimage_dtcopts = mkimage_dtcopts + self._mkimage_sign = mkimage_sign + self._mkimage_sign_args = mkimage_sign_args + self._hash_algo = hash_algo + self._sign_algo = sign_algo + self._pad_algo = pad_algo + self._sign_keyname_conf = sign_keyname_conf + self._sign_individual = sign_individual + self._sign_keyname_img = sign_keyname_img + self._sanitize_sign_config() + + self._dtbs = [] + self._kernel = None + self._ramdisk = None + self._bootscr = None + self._setup = None + + def _sanitize_sign_config(self): + if self._sign_enable: + if not self._hash_algo: + bb.fatal("FIT image signing is enabled but no hash algorithm is provided.") + if not self._sign_algo: + bb.fatal("FIT image signing is enabled but no signature algorithm is provided.") + if not self._pad_algo: + bb.fatal("FIT image signing is enabled but no padding algorithm is provided.") + if not self._sign_keyname_conf: + bb.fatal("FIT image signing is enabled but no configuration key name is provided.") + if self._sign_individual and not self._sign_keyname_img: + bb.fatal("FIT image signing is enabled for individual images but no image key name is provided.") + + def write_its_file(self, itsfile): + with open(itsfile, 'w') as f: + f.write("/dts-v1/;\n\n") + self.emit(f, 0) + + def its_add_node_image(self, image_id, description, image_type, compression, opt_props): + image_node = ItsNodeImage( + image_id, + self.images, + description, + image_type, + compression, + opt_props=opt_props + ) + if self._hash_algo: + ItsNodeHash( + "hash-1", + image_node, + self._hash_algo + ) + if self._sign_individual: + ItsImageSignature( + "signature-1", + image_node, + f"{self._hash_algo},{self._sign_algo}", + self._sign_keyname_img + ) + return image_node + + def fitimage_emit_section_kernel(self, kernel_id, kernel_path, compression, + load, entrypoint, mkimage_kernel_type, entrysymbol=None): + """Emit the fitImage ITS kernel section""" + if self._kernel: + bb.fatal("Kernel section already exists in the ITS file.") + if entrysymbol: + result = subprocess.run([self._host_prefix + "nm", "vmlinux"], capture_output=True, text=True) + for line in result.stdout.splitlines(): + parts = line.split() + if len(parts) == 3 and parts[2] == entrysymbol: + entrypoint = "<0x%s>" % parts[0] + break + kernel_node = self.its_add_node_image( + kernel_id, + "Linux kernel", + mkimage_kernel_type, + compression, + { + "data": '/incbin/("' + kernel_path + '")', + "arch": self._arch, + "os": "linux", + "load": f"<{load}>", + "entry": f"<{entrypoint}>" + } + ) + self._kernel = kernel_node + + def fitimage_emit_section_dtb(self, dtb_id, dtb_path, dtb_loadaddress=None, dtbo_loadaddress=None): + """Emit the fitImage ITS DTB section""" + load=None + dtb_ext = os.path.splitext(dtb_path)[1] + if dtb_ext == ".dtbo": + if dtbo_loadaddress: + load = dtbo_loadaddress + elif dtb_loadaddress: + load = dtb_loadaddress + + opt_props = { + "data": '/incbin/("' + dtb_path + '")', + "arch": self._arch + } + if load: + opt_props["load"] = f"<{load}>" + + dtb_node = self.its_add_node_image( + "fdt-" + dtb_id, + "Flattened Device Tree blob", + "flat_dt", + "none", + opt_props + ) + self._dtbs.append(dtb_node) + + def fitimage_emit_section_boot_script(self, bootscr_id, bootscr_path): + """Emit the fitImage ITS u-boot script section""" + if self._bootscr: + bb.fatal("U-boot script section already exists in the ITS file.") + bootscr_node = self.its_add_node_image( + bootscr_id, + "U-boot script", + "script", + "none", + { + "data": '/incbin/("' + bootscr_path + '")', + "arch": self._arch, + "type": "script" + } + ) + self._bootscr = bootscr_node + + def fitimage_emit_section_setup(self, setup_id, setup_path): + """Emit the fitImage ITS setup section""" + if self._setup: + bb.fatal("Setup section already exists in the ITS file.") + load = "<0x00090000>" + entry = "<0x00090000>" + setup_node = self.its_add_node_image( + setup_id, + "Linux setup.bin", + "x86_setup", + "none", + { + "data": '/incbin/("' + setup_path + '")', + "arch": self._arch, + "os": "linux", + "load": load, + "entry": entry + } + ) + self._setup = setup_node + + def fitimage_emit_section_ramdisk(self, ramdisk_id, ramdisk_path, description="ramdisk", load=None, entry=None): + """Emit the fitImage ITS ramdisk section""" + if self._ramdisk: + bb.fatal("Ramdisk section already exists in the ITS file.") + opt_props = { + "data": '/incbin/("' + ramdisk_path + '")', + "type": "ramdisk", + "arch": self._arch, + "os": "linux" + } + if load: + opt_props["load"] = f"<{load}>" + if entry: + opt_props["entry"] = f"<{entry}>" + + ramdisk_node = self.its_add_node_image( + ramdisk_id, + description, + "ramdisk", + "none", + opt_props + ) + self._ramdisk = ramdisk_node + + def _fitimage_emit_one_section_config(self, conf_node_name, dtb=None): + """Emit the fitImage ITS configuration section""" + opt_props = {} + conf_desc = [] + sign_entries = [] + + if self._kernel: + conf_desc.append("Linux kernel") + opt_props["kernel"] = self._kernel.name + if self._sign_enable: + sign_entries.append("kernel") + + if dtb: + conf_desc.append("FDT blob") + opt_props["fdt"] = dtb.name + if self._sign_enable: + sign_entries.append("fdt") + + if self._ramdisk: + conf_desc.append("ramdisk") + opt_props["ramdisk"] = self._ramdisk.name + if self._sign_enable: + sign_entries.append("ramdisk") + + if self._bootscr: + conf_desc.append("u-boot script") + opt_props["bootscr"] = self._bootscr.name + if self._sign_enable: + sign_entries.append("bootscr") + + if self._setup: + conf_desc.append("setup") + opt_props["setup"] = self._setup.name + if self._sign_enable: + sign_entries.append("setup") + + # First added configuration is the default configuration + default_flag = "0" + if len(self.configurations.sub_nodes) == 0: + default_flag = "1" + + conf_node = ItsNodeConfiguration( + conf_node_name, + self.configurations, + f"{default_flag} {', '.join(conf_desc)}", + opt_props=opt_props + ) + if self._hash_algo: + ItsNodeHash( + "hash-1", + conf_node, + self._hash_algo + ) + if self._sign_enable: + ItsNodeConfigurationSignature( + "signature-1", + conf_node, + f"{self._hash_algo},{self._sign_algo}", + self._sign_keyname_conf, + opt_props={ + "padding": self._pad_algo, + "sign-images": sign_entries + } + ) + + def fitimage_emit_section_config(self): + if self._dtbs: + for dtb in self._dtbs: + self._fitimage_emit_one_section_config('conf-' + dtb.name.lstrip("fdt-"), dtb) + else: + self._fitimage_emit_one_section_config("conf-1") + self.configurations.add_property('default', self.configurations.sub_nodes[0].name) + + def run_mkimage_assemble(self, itsfile, fitfile): + cmd = [ + self._mkimage, + '-f', itsfile, + fitfile + ] + if self._mkimage_dtcopts: + cmd.insert(1, '-D') + cmd.insert(2, self._mkimage_dtcopts) + try: + subprocess.run(cmd, check=True, capture_output=True) + except subprocess.CalledProcessError as e: + bb.fatal(f"Command '{' '.join(cmd)}' failed with return code {e.returncode}\nstdout: {e.stdout.decode()}\nstderr: {e.stderr.decode()}\nitsflile: {os.path.abspath(itsfile)}") + + def run_mkimage_sign(self, fitfile): + if not self._sign_enable: + bb.debug(1, "FIT image signing is disabled. Skipping signing.") + return + + # Some sanity checks because mkimage exits with 0 also without needed keys + sign_key_path = os.path.join(self._sign_keydir, self._sign_keyname_conf) + if not os.path.exists(sign_key_path + '.key') or not os.path.exists(sign_key_path + '.crt'): + bb.fatal("%s.key or .crt does not exist" % sign_key_path) + if self._sign_individual: + sign_key_img_path = os.path.join(self._sign_keydir, self._sign_keyname_img) + if not os.path.exists(sign_key_img_path + '.key') or not os.path.exists(sign_key_img_path + '.crt'): + bb.fatal("%s.key or .crt does not exist" % sign_key_img_path) + + cmd = [ + self._mkimage_sign, + '-F', + '-k', self._sign_keydir, + '-r', fitfile + ] + if self._mkimage_dtcopts: + cmd.extend(['-D', self._mkimage_dtcopts]) + if self._mkimage_sign_args: + cmd.extend(shlex.split(self._mkimage_sign_args)) + try: + subprocess.run(cmd, check=True, capture_output=True) + except subprocess.CalledProcessError as e: + bb.fatal(f"Command '{' '.join(cmd)}' failed with return code {e.returncode}\nstdout: {e.stdout.decode()}\nstderr: {e.stderr.decode()}") + + +def symlink_points_below(file_or_symlink, expected_parent_dir): + """returns symlink destination if it points below directory""" + file_path = os.path.join(expected_parent_dir, file_or_symlink) + if not os.path.islink(file_path): + return None + + realpath = os.path.relpath(os.path.realpath(file_path), expected_parent_dir) + if realpath.startswith(".."): + return None + + return realpath + +def generate_rsa_key(keydir, keyname, numbits, genrsa_args, req_args, sign_pkcs, openssl_path="openssl"): + sing_key_path = os.path.join(keydir, keyname) + if not os.path.isdir(keydir): + os.makedirs(keydir) + runCmd("%s genrsa %s -out %s.key %s" % ( + openssl_path, + genrsa_args, + sing_key_path, + numbits + )) + runCmd("%s req %s %s -key %s.key -out %s.crt" % ( + openssl_path, + req_args, + sign_pkcs, + sing_key_path, + sing_key_path + )) diff --git a/meta/recipes-kernel/linux/linux-yocto-fitimage_6.12.bb b/meta/recipes-kernel/linux/linux-yocto-fitimage_6.12.bb new file mode 100644 index 00000000000..d5efc60737e --- /dev/null +++ b/meta/recipes-kernel/linux/linux-yocto-fitimage_6.12.bb @@ -0,0 +1,13 @@ +SUMMARY = "The Linux kernel as a FIT image (optionally with initramfs)" +SECTION = "kernel" + +# If an initramfs is included in the FIT image more licenses apply. +# But also the kernel uses more than one license (see Documentation/process/license-rules.rst) +LICENSE = "GPL-2.0-with-Linux-syscall-note" +LIC_FILES_CHKSUM = "file://${COREBASE}/meta/files/common-licenses/GPL-2.0-with-Linux-syscall-note;md5=0bad96c422c41c3a94009dcfe1bff992" + +LINUX_VERSION ?= "6.12.23" + +PV = "${LINUX_VERSION}+git" + +inherit kernel-fit-image From patchwork Sun May 4 13:04:56 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Freihofer, Adrian" X-Patchwork-Id: 62396 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from aws-us-west-2-korg-lkml-1.web.codeaurora.org (localhost.localdomain [127.0.0.1]) by smtp.lore.kernel.org (Postfix) with ESMTP id EBC69C3ABAC for ; Sun, 4 May 2025 13:07:08 +0000 (UTC) Received: from mta-64-226.siemens.flowmailer.net (mta-64-226.siemens.flowmailer.net [185.136.64.226]) by mx.groups.io with SMTP id smtpd.web11.28297.1746364018399646036 for ; Sun, 04 May 2025 06:06:58 -0700 Authentication-Results: mx.groups.io; dkim=pass header.i=adrian.freihofer@siemens.com header.s=fm1 header.b=FFyDQkCf; spf=pass (domain: rts-flowmailer.siemens.com, ip: 185.136.64.226, mailfrom: fm-1329275-20250504130656e7f14081e86858b59a-yjrzsa@rts-flowmailer.siemens.com) Received: by mta-64-226.siemens.flowmailer.net with ESMTPSA id 20250504130656e7f14081e86858b59a for ; Sun, 04 May 2025 15:06:56 +0200 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; s=fm1; d=siemens.com; i=adrian.freihofer@siemens.com; h=Date:From:Subject:To:Message-ID:MIME-Version:Content-Type:Content-Transfer-Encoding:Cc:References:In-Reply-To; bh=gAyVLEwkw8nsRs9oShjVxQrYtyUNWbc54Hai2D/SWW0=; b=FFyDQkCftMDN6fjdPzbjzLgnYP8H4bcLNoxgoHje2qse+2mI9Pc27Rji10zCF1vbokPqZW Y7fBwGxSu7Skdsjy50+qWHCNXg1yrnTn9BGVcsB0y6Ywbq/MlTr3QI+RWmWPygKPvK1j+N/Z ez5V88QaWPh0ZpQPzCd339S5cRFjcrQWAAInuU700aQxgbvBzf9IRdSknUs/VKNnDfl//gZz dSXs7Njf7VruCW75TyWV4Vhc0rq5scLLORMV7JmnE888WWMQJyykyFTxldGr8JFZPZtIjVOc 5b0cFqZR1GXon+15y8ft0KEdfsoSfDiB4RUhDDuSGjJ/1oAcPZuw4oCg==; From: AdrianF To: openembedded-core@lists.openembedded.org Cc: marex@denx.de, l.anderweit@phytec.de, richard.purdie@linuxfoundation.org, ross.burton@arm.com, bruce.ashfield@gmail.com, rogerio.borin@toradex.com, sean.anderson@seco.com, m.felsch@pengutronix.de, ejo@pengutronix.de, Adrian Freihofer Subject: [PATCH 09/20] maintainers: add myself for linux-yocto-fitimage Date: Sun, 4 May 2025 15:04:56 +0200 Message-ID: <20250504130507.717954-9-adrian.freihofer@siemens.com> In-Reply-To: <20250504130507.717954-1-adrian.freihofer@siemens.com> References: <20250504130507.717954-1-adrian.freihofer@siemens.com> MIME-Version: 1.0 X-Flowmailer-Platform: Siemens Feedback-ID: 519:519-1329275:519-21489:flowmailer List-Id: X-Webhook-Received: from li982-79.members.linode.com [45.33.32.79] by aws-us-west-2-korg-lkml-1.web.codeaurora.org with HTTPS for ; Sun, 04 May 2025 13:07:08 -0000 X-Groupsio-URL: https://lists.openembedded.org/g/openembedded-core/message/215953 From: Adrian Freihofer Signed-off-by: Adrian Freihofer --- meta/conf/distro/include/maintainers.inc | 1 + 1 file changed, 1 insertion(+) diff --git a/meta/conf/distro/include/maintainers.inc b/meta/conf/distro/include/maintainers.inc index 1932e3d0e83..fcb840010fd 100644 --- a/meta/conf/distro/include/maintainers.inc +++ b/meta/conf/distro/include/maintainers.inc @@ -465,6 +465,7 @@ RECIPE_MAINTAINER:pn-libxxf86vm = "Unassigned " RECIPE_MAINTAINER:pn-libyaml = "Wang Mingyu " RECIPE_MAINTAINER:pn-lighttpd = "Unassigned " RECIPE_MAINTAINER:pn-linux-dummy = "Unassigned " +RECIPE_MAINTAINER:pn-linux-yocto-fitimage = "Adrian Freihofer " RECIPE_MAINTAINER:pn-linux-firmware = "Otavio Salvador " RECIPE_MAINTAINER:pn-linux-libc-headers = "Bruce Ashfield " RECIPE_MAINTAINER:pn-linux-yocto = "Bruce Ashfield " From patchwork Sun May 4 13:04:57 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Freihofer, Adrian" X-Patchwork-Id: 62406 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from aws-us-west-2-korg-lkml-1.web.codeaurora.org (localhost.localdomain [127.0.0.1]) by smtp.lore.kernel.org (Postfix) with ESMTP id 3C766C3ABC1 for ; Sun, 4 May 2025 13:07:09 +0000 (UTC) Received: from mta-65-227.siemens.flowmailer.net (mta-65-227.siemens.flowmailer.net [185.136.65.227]) by mx.groups.io with SMTP id smtpd.web10.28206.1746364018480856130 for ; Sun, 04 May 2025 06:06:58 -0700 Authentication-Results: mx.groups.io; dkim=pass header.i=adrian.freihofer@siemens.com header.s=fm1 header.b=Lvv7ovgA; spf=pass (domain: rts-flowmailer.siemens.com, ip: 185.136.65.227, mailfrom: fm-1329275-2025050413065652715c90db1b6d5ebc-fsaygb@rts-flowmailer.siemens.com) Received: by mta-65-227.siemens.flowmailer.net with ESMTPSA id 2025050413065652715c90db1b6d5ebc for ; Sun, 04 May 2025 15:06:56 +0200 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; s=fm1; d=siemens.com; i=adrian.freihofer@siemens.com; h=Date:From:Subject:To:Message-ID:MIME-Version:Content-Type:Content-Transfer-Encoding:Cc:References:In-Reply-To; bh=7WxpuNa+eaFk2uq9TYs2zrqZBYsIQAxtmhWM+H6dcYo=; b=Lvv7ovgAh34TGSx1voK4OdCkQ8inBOQqjdVomdSYi4DUk0D8hK/DWZLBEgfXTjdmt4SDQP Q8aiapkkOku/e0y8PC9p0Y7qWYL1RA/MElGpPLLLzNmBzbYMjdgZOPnfwkgqrLX5g9u7xCyZ lyrHdFiQWymSoy4+ZB4p1EdLDqRjpH7iq5z8RhDkkIsEQ1UXrFbBpstrBwv4T0HAe3pq5yi8 omIOgSEQ/qWXsNWlxITgQ5MY55AUddrKY6+CwV96+69H3d01CvMOOMr31+BRvF49sIgQ3Ves 6vikLgw+GOJmylGzL2cwNzE4OYQy+25ml3+87NOdn4LY4+hHFob/SXtQ==; From: AdrianF To: openembedded-core@lists.openembedded.org Cc: marex@denx.de, l.anderweit@phytec.de, richard.purdie@linuxfoundation.org, ross.burton@arm.com, bruce.ashfield@gmail.com, rogerio.borin@toradex.com, sean.anderson@seco.com, m.felsch@pengutronix.de, ejo@pengutronix.de, Adrian Freihofer Subject: [PATCH 10/20] oe-selftest: fitimage add tests for fitimage.py Date: Sun, 4 May 2025 15:04:57 +0200 Message-ID: <20250504130507.717954-10-adrian.freihofer@siemens.com> In-Reply-To: <20250504130507.717954-1-adrian.freihofer@siemens.com> References: <20250504130507.717954-1-adrian.freihofer@siemens.com> MIME-Version: 1.0 X-Flowmailer-Platform: Siemens Feedback-ID: 519:519-1329275:519-21489:flowmailer List-Id: X-Webhook-Received: from li982-79.members.linode.com [45.33.32.79] by aws-us-west-2-korg-lkml-1.web.codeaurora.org with HTTPS for ; Sun, 04 May 2025 13:07:09 -0000 X-Groupsio-URL: https://lists.openembedded.org/g/openembedded-core/message/215954 From: Adrian Freihofer Having the FIT image generator code as a separate class, which is essentially independent of BitBake, also allows testing the code separately from BitBake. Take advantage of this enables testing more use cases with significantly faster tests. Add also test cases for the new gen rsa keys function. Signed-off-by: Adrian Freihofer --- meta/lib/oeqa/selftest/cases/fitimage.py | 201 +++++++++++++++++++---- 1 file changed, 173 insertions(+), 28 deletions(-) diff --git a/meta/lib/oeqa/selftest/cases/fitimage.py b/meta/lib/oeqa/selftest/cases/fitimage.py index 81585aa10b3..7e81f155e7a 100644 --- a/meta/lib/oeqa/selftest/cases/fitimage.py +++ b/meta/lib/oeqa/selftest/cases/fitimage.py @@ -4,13 +4,36 @@ # SPDX-License-Identifier: MIT # -from oeqa.selftest.case import OESelftestTestCase -from oeqa.utils.commands import runCmd, bitbake, get_bb_vars import os import re import shlex import logging import pprint +import tempfile + +import oe.fitimage + +from oeqa.selftest.case import OESelftestTestCase +from oeqa.utils.commands import runCmd, bitbake, get_bb_vars + + +class BbVarsMockGenKeys: + def __init__(self, keydir, gen_keys="0", sign_enabled="0", keyname="", sign_ind="0", img_keyname=""): + self.bb_vars = { + 'FIT_GENERATE_KEYS': gen_keys, + 'FIT_KEY_GENRSA_ARGS': "-F4", + 'FIT_KEY_REQ_ARGS': "-batch -new", + 'FIT_KEY_SIGN_PKCS': "-x509", + 'FIT_SIGN_INDIVIDUAL': sign_ind, + 'FIT_SIGN_NUMBITS': "2048", + 'UBOOT_SIGN_ENABLE': sign_enabled, + 'UBOOT_SIGN_IMG_KEYNAME': img_keyname, + 'UBOOT_SIGN_KEYDIR': keydir, + 'UBOOT_SIGN_KEYNAME': keyname, + } + + def getVar(self, var): + return self.bb_vars[var] class FitImageTestCase(OESelftestTestCase): """Test functions usable for testing kernel-fitimage.bbclass and uboot-sign.bbclass @@ -56,34 +79,19 @@ class FitImageTestCase(OESelftestTestCase): # Define some variables which are usually defined by the kernel-fitimage.bbclass. # But for testing purpose check if the uboot-sign.bbclass is independent from # the kernel-fitimage.bbclass - fit_sign_numbits = bb_vars.get('FIT_SIGN_NUMBITS', "2048") - fit_key_genrsa_args = bb_vars.get('FIT_KEY_GENRSA_ARGS', "-F4") - fit_key_req_args = bb_vars.get('FIT_KEY_REQ_ARGS', "-batch -new") - fit_key_sign_pkcs = bb_vars.get('FIT_KEY_SIGN_PKCS', "-x509") + numbits = bb_vars.get('FIT_SIGN_NUMBITS', "2048") + genrsa_args = bb_vars.get('FIT_KEY_GENRSA_ARGS', "-F4") + req_args = bb_vars.get('FIT_KEY_REQ_ARGS', "-batch -new") + sign_pkcs = bb_vars.get('FIT_KEY_SIGN_PKCS', "-x509") - uboot_sign_keydir = bb_vars['UBOOT_SIGN_KEYDIR'] + keydir = bb_vars['UBOOT_SIGN_KEYDIR'] sign_keys = [bb_vars['UBOOT_SIGN_KEYNAME']] if bb_vars['FIT_SIGN_INDIVIDUAL'] == "1": sign_keys.append(bb_vars['UBOOT_SIGN_IMG_KEYNAME']) - for sign_key in sign_keys: - sing_key_path = os.path.join(uboot_sign_keydir, sign_key) - if not os.path.isdir(uboot_sign_keydir): - os.makedirs(uboot_sign_keydir) - openssl_bindir = FitImageTestCase._setup_native('openssl-native') - openssl_path = os.path.join(openssl_bindir, 'openssl') - runCmd("%s genrsa %s -out %s.key %s" % ( - openssl_path, - fit_key_genrsa_args, - sing_key_path, - fit_sign_numbits - )) - runCmd("%s req %s %s -key %s.key -out %s.crt" % ( - openssl_path, - fit_key_req_args, - fit_key_sign_pkcs, - sing_key_path, - sing_key_path - )) + openssl_bindir = FitImageTestCase._setup_native('openssl-native') + openssl_path = os.path.join(openssl_bindir, 'openssl') + for keyname in sign_keys: + oe.fitimage.generate_rsa_key(keydir, keyname, numbits, genrsa_args, req_args, sign_pkcs, openssl_path) @staticmethod def _gen_random_file(file_path, num_bytes=65536): @@ -367,8 +375,7 @@ class FitImageTestCase(OESelftestTestCase): # Verify the FIT image self._check_fitimage(bb_vars, fitimage_path, uboot_tools_bindir) - -class KernelFitImageTests(FitImageTestCase): +class KernelFitImageBase(FitImageTestCase): """Test cases for the kernel-fitimage bbclass""" def _fit_get_bb_vars(self, additional_vars=[]): @@ -677,6 +684,8 @@ class KernelFitImageTests(FitImageTestCase): self.assertEqual(found_comments, num_signatures, "Expected %d signed and commented (%s) sections in the fitImage." % (num_signatures, a_comment)) +class KernelFitImageTests(KernelFitImageBase): + """Test cases for the kernel-fitimage bbclass""" def test_fit_image(self): """ @@ -922,6 +931,142 @@ FIT_HASH_ALG = "sha256" bb_vars = self._fit_get_bb_vars() self._test_fitimage(bb_vars) +class FitImagePyTests(KernelFitImageBase): + """Test cases for the fitimage.py module without calling bitbake""" + + def _test_fitimage_py(self, bb_vars_overrides=None): + topdir = os.path.join(os.environ['BUILDDIR']) + fitimage_its_path = os.path.join(topdir, self._testMethodName + '.its') + + # Provide variables without calling bitbake + bb_vars = { + # image-fitimage.conf + 'FIT_DESC': "Kernel fitImage for a dummy distro", + 'FIT_HASH_ALG': "sha256", + 'FIT_SIGN_ALG': "rsa2048", + 'FIT_PAD_ALG': "pkcs-1.5", + 'FIT_GENERATE_KEYS': "0", + 'FIT_SIGN_NUMBITS': "2048", + 'FIT_KEY_GENRSA_ARGS': "-F4", + 'FIT_KEY_REQ_ARGS': "-batch -new", + 'FIT_KEY_SIGN_PKCS': "-x509", + 'FIT_SIGN_INDIVIDUAL': "0", + 'FIT_CONF_PREFIX': "conf-", + 'FIT_SUPPORTED_INITRAMFS_FSTYPES': "cpio.lz4 cpio.lzo cpio.lzma cpio.xz cpio.zst cpio.gz ext2.gz cpio", + 'FIT_CONF_DEFAULT_DTB': "", + 'FIT_ADDRESS_CELLS': "1", + 'FIT_UBOOT_ENV': "", + # kernel.bbclass + 'UBOOT_ENTRYPOINT': "0x20008000", + 'UBOOT_LOADADDRESS': "0x20008000", + 'INITRAMFS_IMAGE': "", + 'INITRAMFS_IMAGE_BUNDLE': "", + # kernel-uboot.bbclass + 'FIT_KERNEL_COMP_ALG': "gzip", + 'FIT_KERNEL_COMP_ALG_EXTENSION': ".gz", + 'UBOOT_MKIMAGE_KERNEL_TYPE': "kernel", + # uboot-config.bbclass + 'UBOOT_MKIMAGE_DTCOPTS': "", + 'UBOOT_MKIMAGE': "uboot-mkimage", + 'UBOOT_MKIMAGE_SIGN': "uboot-mkimage", + 'UBOOT_MKIMAGE_SIGN_ARGS': "", + 'UBOOT_SIGN_ENABLE': "0", + 'UBOOT_SIGN_KEYDIR': None, + 'UBOOT_SIGN_KEYNAME': None, + 'UBOOT_SIGN_IMG_KEYNAME': None, + # others + 'MACHINE': "qemux86-64", + 'UBOOT_ARCH': "x86", + 'HOST_PREFIX': "x86_64-poky-linux-" + } + if bb_vars_overrides: + bb_vars.update(bb_vars_overrides) + + root_node = oe.fitimage.ItsNodeRootKernel( + bb_vars["FIT_DESC"], bb_vars["FIT_ADDRESS_CELLS"], + bb_vars['HOST_PREFIX'], bb_vars['UBOOT_ARCH'], bb_vars["FIT_CONF_PREFIX"], + oe.types.boolean(bb_vars['UBOOT_SIGN_ENABLE']), bb_vars["UBOOT_SIGN_KEYDIR"], + bb_vars["UBOOT_MKIMAGE"], bb_vars["UBOOT_MKIMAGE_DTCOPTS"], + bb_vars["UBOOT_MKIMAGE_SIGN"], bb_vars["UBOOT_MKIMAGE_SIGN_ARGS"], + bb_vars['FIT_HASH_ALG'], bb_vars['FIT_SIGN_ALG'], bb_vars['FIT_PAD_ALG'], + bb_vars['UBOOT_SIGN_KEYNAME'], + oe.types.boolean(bb_vars['FIT_SIGN_INDIVIDUAL']), bb_vars['UBOOT_SIGN_IMG_KEYNAME'] + ) + + root_node.fitimage_emit_section_kernel("kernel-1", "linux.bin", "none", + bb_vars.get('UBOOT_LOADADDRESS'), bb_vars.get('UBOOT_ENTRYPOINT'), + bb_vars.get('UBOOT_MKIMAGE_KERNEL_TYPE'), bb_vars.get("UBOOT_ENTRYSYMBOL") + ) + + dtb_files = FitImageTestCase._get_dtb_files(bb_vars) + for dtb in dtb_files: + root_node.fitimage_emit_section_dtb("fdt-" + dtb, os.path.join("a-dir", dtb), + bb_vars.get("UBOOT_DTB_LOADADDRESS"), bb_vars.get("UBOOT_DTBO_LOADADDRESS")) + + if bb_vars.get('FIT_UBOOT_ENV'): + root_node.fitimage_emit_section_boot_script( + "bootscr-" + bb_vars['FIT_UBOOT_ENV'], bb_vars['FIT_UBOOT_ENV']) + + if bb_vars['MACHINE'] == "qemux86-64": # Not really the right if + root_node.fitimage_emit_section_setup("setup-1", "setup1.bin") + + if bb_vars.get('INITRAMFS_IMAGE') and bb_vars.get("INITRAMFS_IMAGE_BUNDLE") != "1": + root_node.fitimage_emit_section_ramdisk("ramdisk-1", "a-dir/a-initramfs-1", + "core-image-minimal-initramfs", + bb_vars.get("UBOOT_RD_LOADADDRESS"), bb_vars.get("UBOOT_RD_ENTRYPOINT")) + + root_node.fitimage_emit_section_config() + root_node.write_its_file(fitimage_its_path) + + self.assertExists(fitimage_its_path, "%s image tree source doesn't exist" % (fitimage_its_path)) + self.logger.debug("Checking its: %s" % fitimage_its_path) + self._check_its_file(bb_vars, fitimage_its_path) + + def _generate_rsa_keys(self, d): + sign_keydir = d.getVar('UBOOT_SIGN_KEYDIR') + sign_keyname = d.getVar('UBOOT_SIGN_KEYNAME') + sign_kc_path = os.path.join(sign_keydir, sign_keyname) + if not os.path.exists(sign_kc_path + '.key') or not os.path.exists(sign_kc_path + '.crt'): + self.logger.debug("Generating RSA private key and certificate for signing fitImage configurations") + oe.fitimage.generate_rsa_key(sign_keydir, sign_keyname, + d.getVar('FIT_SIGN_NUMBITS'), d.getVar('FIT_KEY_GENRSA_ARGS'), + d.getVar('FIT_KEY_REQ_ARGS'), d.getVar('FIT_KEY_SIGN_PKCS')) + + if oe.types.boolean(d.getVar('FIT_SIGN_INDIVIDUAL')): + sign_img_keyname = d.getVar('UBOOT_SIGN_IMG_KEYNAME') + sign_img_kc_path = os.path.join(sign_keydir, sign_img_keyname) + if not os.path.exists(sign_img_kc_path + '.key') or not os.path.exists(sign_img_kc_path + '.crt'): + self.logger.debug("Generating RSA private key and certificate for signing fitImage individual images") + oe.fitimage.generate_rsa_key(sign_keydir, sign_img_keyname, + d.getVar('FIT_SIGN_NUMBITS'), d.getVar('FIT_KEY_GENRSA_ARGS'), + d.getVar('FIT_KEY_REQ_ARGS'), d.getVar('FIT_KEY_SIGN_PKCS')) + + + def test_fitimage_py_default(self): + self._test_fitimage_py() + + def test_fitimage_py_generate_keys_one(self): + """Test if generating one key works""" + with tempfile.TemporaryDirectory() as keydir: + keyname = "a-foo-key" + bb_vars = BbVarsMockGenKeys(keydir, "1", "1", keyname) + self._generate_rsa_keys(bb_vars) + self.assertExists(os.path.join(keydir, keyname + '.key')) + self.assertExists(os.path.join(keydir, keyname + '.crt')) + self.assertEqual(len(os.listdir(keydir)), 2) + + def test_fitimage_py_generate_keys_two(self): + """Test if generating two keys as used with FIT_SIGN_INDIVIDUAL=1 works""" + with tempfile.TemporaryDirectory() as keydir: + keyname = "a-foo-config-key" + img_keyname = "a-foo-image-key" + bb_vars = BbVarsMockGenKeys(keydir, "1", "1", keyname, "1", img_keyname) + self._generate_rsa_keys(bb_vars) + self.assertExists(os.path.join(keydir, keyname + '.key')) + self.assertExists(os.path.join(keydir, keyname + '.crt')) + self.assertExists(os.path.join(keydir, img_keyname + '.key')) + self.assertExists(os.path.join(keydir, img_keyname + '.crt')) + self.assertEqual(len(os.listdir(keydir)), 4) class UBootFitImageTests(FitImageTestCase): """Test cases for the uboot-sign bbclass""" From patchwork Sun May 4 13:04:58 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Freihofer, Adrian" X-Patchwork-Id: 62400 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from aws-us-west-2-korg-lkml-1.web.codeaurora.org (localhost.localdomain [127.0.0.1]) by smtp.lore.kernel.org (Postfix) with ESMTP id 12201C3ABBC for ; Sun, 4 May 2025 13:07:09 +0000 (UTC) Received: from mta-64-228.siemens.flowmailer.net (mta-64-228.siemens.flowmailer.net [185.136.64.228]) by mx.groups.io with SMTP id smtpd.web11.28299.1746364018885948097 for ; Sun, 04 May 2025 06:06:59 -0700 Authentication-Results: mx.groups.io; dkim=pass header.i=adrian.freihofer@siemens.com header.s=fm1 header.b=FM7FMD6i; spf=pass (domain: rts-flowmailer.siemens.com, ip: 185.136.64.228, mailfrom: fm-1329275-2025050413065616808c3c863e8c5289-vaakzx@rts-flowmailer.siemens.com) Received: by mta-64-228.siemens.flowmailer.net with ESMTPSA id 2025050413065616808c3c863e8c5289 for ; Sun, 04 May 2025 15:06:57 +0200 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; s=fm1; d=siemens.com; i=adrian.freihofer@siemens.com; h=Date:From:Subject:To:Message-ID:MIME-Version:Content-Type:Content-Transfer-Encoding:Cc:References:In-Reply-To; bh=j4dOpDBVpkcSN9Hk4grBhX6DHPfFL1IpG+In39BGjIM=; b=FM7FMD6ixR3ZybW+2nNVwcRKfsoEciuBx+r+HFo+2DpW1rcnoI8R2p0VIP5Frf6pi/C8pz sOu9pSLMUhfEnHq233p5Ep3YM4v6a6kNROqCGiAUda2nzjaDiC5kmb2g6LyuMmi/HI1adBwJ /Nh1dRMtp4XSWyJLYpi1pBLw+WJ2y3nHzL15BxA5Wed7ZH5pynGVoH0apa2bpBoMsRl0EAwC JJpfDN+gpTZs7m+DaSqe+wRoA7+R1kPLiknBqE9Xt19sIQbIt8a2H1QZw7/2t+nbc7eWnX7z 6usVlp6nEqbpO/RF34TeGIwl9WGEfD1xbvh0nDN8qGuiE2QWJI+0g+eA==; From: AdrianF To: openembedded-core@lists.openembedded.org Cc: marex@denx.de, l.anderweit@phytec.de, richard.purdie@linuxfoundation.org, ross.burton@arm.com, bruce.ashfield@gmail.com, rogerio.borin@toradex.com, sean.anderson@seco.com, m.felsch@pengutronix.de, ejo@pengutronix.de, Adrian Freihofer Subject: [PATCH 11/20] oe-selftest: fitimage refactor kernel-fitimage.bbclass Date: Sun, 4 May 2025 15:04:58 +0200 Message-ID: <20250504130507.717954-11-adrian.freihofer@siemens.com> In-Reply-To: <20250504130507.717954-1-adrian.freihofer@siemens.com> References: <20250504130507.717954-1-adrian.freihofer@siemens.com> MIME-Version: 1.0 X-Flowmailer-Platform: Siemens Feedback-ID: 519:519-1329275:519-21489:flowmailer List-Id: X-Webhook-Received: from li982-79.members.linode.com [45.33.32.79] by aws-us-west-2-korg-lkml-1.web.codeaurora.org with HTTPS for ; Sun, 04 May 2025 13:07:09 -0000 X-Groupsio-URL: https://lists.openembedded.org/g/openembedded-core/message/215955 From: Adrian Freihofer Support that a recipe other than virtual/kernel provides the kernel FIT image. Therefore * Support building with either: - KERNEL_IMAGETYPES += " fitImage " - KERNEL_CLASSES = " kernel-fitimage " or - KERNEL_CLASSES = " kernel-uboot " * allow to specify which recipe gets bitbaked. --- meta/lib/oeqa/selftest/cases/fitimage.py | 55 +++++++++++++++--------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/meta/lib/oeqa/selftest/cases/fitimage.py b/meta/lib/oeqa/selftest/cases/fitimage.py index 7e81f155e7a..3a1d263eb9e 100644 --- a/meta/lib/oeqa/selftest/cases/fitimage.py +++ b/meta/lib/oeqa/selftest/cases/fitimage.py @@ -394,6 +394,7 @@ class KernelFitImageBase(FitImageTestCase): 'INITRAMFS_IMAGE_BUNDLE', 'INITRAMFS_IMAGE_NAME', 'INITRAMFS_IMAGE', + 'KERNEL_DEPLOYSUBDIR', 'KERNEL_DEVICETREE', 'KERNEL_FIT_LINK_NAME', 'MACHINE', @@ -410,10 +411,21 @@ class KernelFitImageBase(FitImageTestCase): 'UBOOT_SIGN_KEYDIR', 'UBOOT_SIGN_KEYNAME', } - bb_vars = get_bb_vars(list(internal_used | set(additional_vars)), "virtual/kernel") + bb_vars = get_bb_vars(list(internal_used | set(additional_vars)), self.kernel_recipe) self.logger.debug("bb_vars: %s" % pprint.pformat(bb_vars, indent=4)) return bb_vars + def _config_add_kernel_classes(self, config): + config += '# Use kernel-fitimage.bbclass for the creation of the fitImage' + os.linesep + config += 'KERNEL_IMAGETYPES += " fitImage "' + os.linesep + config += 'KERNEL_CLASSES = " kernel-fitimage "' + os.linesep + return config + + @property + def kernel_recipe(self): + # virtual/kernel does not work with SRC_URI:append:pn-%s + return "linux-yocto" + def _config_add_uboot_env(self, config): """Generate an u-boot environment @@ -427,7 +439,7 @@ class KernelFitImageBase(FitImageTestCase): config += '# Add an u-boot script to the fitImage' + os.linesep config += 'FIT_UBOOT_ENV = "%s"' % fit_uenv_file + os.linesep config += 'FILESEXTRAPATHS:prepend := "${TOPDIR}/%s:"' % test_files_dir + os.linesep - config += 'SRC_URI:append:pn-linux-yocto = " file://${FIT_UBOOT_ENV}"' + os.linesep + config += 'SRC_URI:append:pn-%s = " file://${FIT_UBOOT_ENV}"' % self.kernel_recipe + os.linesep if not os.path.isdir(test_files_dir): os.makedirs(test_files_dir) @@ -439,7 +451,7 @@ class KernelFitImageBase(FitImageTestCase): def _bitbake_fit_image(self, bb_vars): """Bitbake the kernel and return the paths to the its file and the FIT image""" - bitbake("virtual/kernel") + bitbake(self.kernel_recipe) # Find the right its file and the final fitImage and check if both files are available deploy_dir_image = bb_vars['DEPLOY_DIR_IMAGE'] @@ -458,8 +470,13 @@ class KernelFitImageBase(FitImageTestCase): fitimage_name = "fitImage" # or fitImage-${KERNEL_IMAGE_LINK_NAME}${KERNEL_IMAGE_BIN_EXT} else: self.fail('Invalid configuration: INITRAMFS_IMAGE_BUNDLE = "1" and not INITRAMFS_IMAGE') - fitimage_its_path = os.path.realpath(os.path.join(deploy_dir_image, fitimage_its_name)) - fitimage_path = os.path.realpath(os.path.join(deploy_dir_image, fitimage_name)) + kernel_deploysubdir = bb_vars['KERNEL_DEPLOYSUBDIR'] + if kernel_deploysubdir: + fitimage_its_path = os.path.realpath(os.path.join(deploy_dir_image, kernel_deploysubdir, fitimage_its_name)) + fitimage_path = os.path.realpath(os.path.join(deploy_dir_image, kernel_deploysubdir, fitimage_name)) + else: + fitimage_its_path = os.path.realpath(os.path.join(deploy_dir_image, fitimage_its_name)) + fitimage_path = os.path.realpath(os.path.join(deploy_dir_image, fitimage_name)) return (fitimage_its_path, fitimage_path) def _get_req_its_paths(self, bb_vars): @@ -701,10 +718,7 @@ class KernelFitImageTests(KernelFitImageBase): Author: Usama Arif """ config = """ -# Enable creation of fitImage KERNEL_IMAGETYPE = "Image" -KERNEL_IMAGETYPES += " fitImage " -KERNEL_CLASSES = " kernel-fitimage " # RAM disk variables including load address and entrypoint for kernel and RAM disk IMAGE_FSTYPES += "cpio.gz" @@ -717,6 +731,7 @@ UBOOT_LOADADDRESS = "0x80080000" UBOOT_ENTRYPOINT = "0x80080000" FIT_DESC = "A model description" """ + config = self._config_add_kernel_classes(config) self.write_config(config) bb_vars = self._fit_get_bb_vars() self._test_fitimage(bb_vars) @@ -732,11 +747,10 @@ FIT_DESC = "A model description" config = """ # Enable creation of fitImage MACHINE = "beaglebone-yocto" -KERNEL_IMAGETYPES += " fitImage " -KERNEL_CLASSES = " kernel-fitimage " # Add a devicetree overlay which does not need kernel sources PREFERRED_PROVIDER_virtual/dtb = "bborg-relay-00a2" """ + config = self._config_add_kernel_classes(config) config = self._config_add_uboot_env(config) self.write_config(config) bb_vars = self._fit_get_bb_vars() @@ -761,13 +775,12 @@ PREFERRED_PROVIDER_virtual/dtb = "bborg-relay-00a2" config = """ # Enable creation of fitImage MACHINE = "beaglebone-yocto" -KERNEL_IMAGETYPES += " fitImage " -KERNEL_CLASSES = " kernel-fitimage " UBOOT_SIGN_ENABLE = "1" UBOOT_SIGN_KEYDIR = "${TOPDIR}/signing-keys" UBOOT_SIGN_KEYNAME = "dev" UBOOT_MKIMAGE_SIGN_ARGS = "-c 'a smart comment'" """ + config = self._config_add_kernel_classes(config) config = self._config_add_uboot_env(config) self.write_config(config) @@ -812,8 +825,6 @@ UBOOT_MKIMAGE_SIGN_ARGS = "-c 'a smart comment'" config = """ # Enable creation of fitImage MACHINE = "beaglebone-yocto" -KERNEL_IMAGETYPES += " fitImage " -KERNEL_CLASSES = " kernel-fitimage " UBOOT_SIGN_ENABLE = "1" FIT_GENERATE_KEYS = "1" UBOOT_SIGN_KEYDIR = "${TOPDIR}/signing-keys" @@ -822,6 +833,7 @@ UBOOT_SIGN_KEYNAME = "cfg-oe-selftest" FIT_SIGN_INDIVIDUAL = "1" UBOOT_MKIMAGE_SIGN_ARGS = "-c 'a smart comment'" """ + config = self._config_add_kernel_classes(config) config = self._config_add_uboot_env(config) self.write_config(config) bb_vars = self._fit_get_bb_vars() @@ -848,8 +860,6 @@ MACHINE = "beaglebone-yocto" INITRAMFS_IMAGE = "core-image-minimal-initramfs" INITRAMFS_SCRIPTS = "" UBOOT_MACHINE = "am335x_evm_defconfig" -KERNEL_CLASSES = " kernel-fitimage " -KERNEL_IMAGETYPES = "fitImage" UBOOT_SIGN_ENABLE = "1" UBOOT_SIGN_KEYNAME = "beaglebonekey" UBOOT_SIGN_KEYDIR ?= "${DEPLOY_DIR_IMAGE}" @@ -868,6 +878,7 @@ KERNEL_IMAGETYPE_REPLACEMENT = "zImage" FIT_KERNEL_COMP_ALG = "none" FIT_HASH_ALG = "sha256" """ + config = self._config_add_kernel_classes(config) config = self._config_add_uboot_env(config) self.write_config(config) @@ -908,8 +919,6 @@ INITRAMFS_IMAGE_BUNDLE = "1" INITRAMFS_IMAGE = "core-image-minimal-initramfs" INITRAMFS_SCRIPTS = "" UBOOT_MACHINE = "am335x_evm_defconfig" -KERNEL_CLASSES = " kernel-fitimage " -KERNEL_IMAGETYPES = "fitImage" UBOOT_SIGN_ENABLE = "1" UBOOT_SIGN_KEYNAME = "beaglebonekey" UBOOT_SIGN_KEYDIR ?= "${DEPLOY_DIR_IMAGE}" @@ -926,11 +935,13 @@ KERNEL_IMAGETYPE_REPLACEMENT = "zImage" FIT_KERNEL_COMP_ALG = "none" FIT_HASH_ALG = "sha256" """ + config = self._config_add_kernel_classes(config) config = self._config_add_uboot_env(config) self.write_config(config) bb_vars = self._fit_get_bb_vars() self._test_fitimage(bb_vars) + class FitImagePyTests(KernelFitImageBase): """Test cases for the fitimage.py module without calling bitbake""" @@ -1071,6 +1082,8 @@ class FitImagePyTests(KernelFitImageBase): class UBootFitImageTests(FitImageTestCase): """Test cases for the uboot-sign bbclass""" + BOOTLOADER_RECIPE = "virtual/bootloader" + def _fit_get_bb_vars(self, additional_vars=[]): """Get bb_vars as needed by _test_sign_fit_image @@ -1112,13 +1125,13 @@ class UBootFitImageTests(FitImageTestCase): 'UBOOT_SIGN_KEYDIR', 'UBOOT_SIGN_KEYNAME', } - bb_vars = get_bb_vars(list(internal_used | set(additional_vars)), "virtual/bootloader") + bb_vars = get_bb_vars(list(internal_used | set(additional_vars)), UBootFitImageTests.BOOTLOADER_RECIPE) self.logger.debug("bb_vars: %s" % pprint.pformat(bb_vars, indent=4)) return bb_vars def _bitbake_fit_image(self, bb_vars): """Bitbake the bootloader and return the paths to the its file and the FIT image""" - bitbake("virtual/bootloader") + bitbake(UBootFitImageTests.BOOTLOADER_RECIPE) deploy_dir_image = bb_vars['DEPLOY_DIR_IMAGE'] machine = bb_vars['MACHINE'] @@ -1636,7 +1649,7 @@ FIT_SIGN_INDIVIDUAL = "1" # Using a static key. FIT_GENERATE_KEYS = "1" does not work without kernel-fitimage.bbclass self._gen_signing_key(bb_vars) - bitbake("virtual/bootloader") + bitbake(UBootFitImageTests.BOOTLOADER_RECIPE) # Just check the DTB of u-boot since there is no u-boot FIT image self._check_kernel_dtb(bb_vars) From patchwork Sun May 4 13:04:59 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Freihofer, Adrian" X-Patchwork-Id: 62404 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from aws-us-west-2-korg-lkml-1.web.codeaurora.org (localhost.localdomain [127.0.0.1]) by smtp.lore.kernel.org (Postfix) with ESMTP id 28137C3ABBE for ; Sun, 4 May 2025 13:07:09 +0000 (UTC) Received: from mta-65-228.siemens.flowmailer.net (mta-65-228.siemens.flowmailer.net [185.136.65.228]) by mx.groups.io with SMTP id smtpd.web10.28207.1746364019203323448 for ; Sun, 04 May 2025 06:06:59 -0700 Authentication-Results: mx.groups.io; dkim=pass header.i=adrian.freihofer@siemens.com header.s=fm1 header.b=JTh/MqTZ; spf=pass (domain: rts-flowmailer.siemens.com, ip: 185.136.65.228, mailfrom: fm-1329275-20250504130657c320ff091a81bd0db9-zvghl0@rts-flowmailer.siemens.com) Received: by mta-65-228.siemens.flowmailer.net with ESMTPSA id 20250504130657c320ff091a81bd0db9 for ; Sun, 04 May 2025 15:06:57 +0200 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; s=fm1; d=siemens.com; i=adrian.freihofer@siemens.com; h=Date:From:Subject:To:Message-ID:MIME-Version:Content-Type:Content-Transfer-Encoding:Cc:References:In-Reply-To; bh=NmwXkPmCjAStou+gV/9NdvFfxGVxx/qLq+N1/860jXU=; b=JTh/MqTZMAXKAorjBef1yADEINEthprG/+XrWetuZgZD+2RVwYYW9d3m66i/vSgnjl9O/I z5qxNbWxAvOR+TF3LQ7xSeO2R7bRUx6kgrSM1PVVK/QCTUN7m5zneYD5onnTFoyLIyjIUD2q 09nl8SvhZJpS2YeULyVzGL8DBa49wahFRmIizTKpGObShVRMVuX7YZKqGMOcvl6x8RFwWqlZ KPO4nifoAGfgSoX/YFhb4x2Oa0zfQe802LOVL/1h9dXgVxKlckLJnZRbWtO92IM2FNSlczKV ilM29wi+HkV9AfuHz1/XwiJUkmD5MxQTG0ShBXiRovrjeH9MpQ0iti1g==; From: AdrianF To: openembedded-core@lists.openembedded.org Cc: marex@denx.de, l.anderweit@phytec.de, richard.purdie@linuxfoundation.org, ross.burton@arm.com, bruce.ashfield@gmail.com, rogerio.borin@toradex.com, sean.anderson@seco.com, m.felsch@pengutronix.de, ejo@pengutronix.de, Adrian Freihofer Subject: [PATCH 12/20] oe-selftest: fitimage: run all tests for the FIT image recipe Date: Sun, 4 May 2025 15:04:59 +0200 Message-ID: <20250504130507.717954-12-adrian.freihofer@siemens.com> In-Reply-To: <20250504130507.717954-1-adrian.freihofer@siemens.com> References: <20250504130507.717954-1-adrian.freihofer@siemens.com> MIME-Version: 1.0 X-Flowmailer-Platform: Siemens Feedback-ID: 519:519-1329275:519-21489:flowmailer List-Id: X-Webhook-Received: from li982-79.members.linode.com [45.33.32.79] by aws-us-west-2-korg-lkml-1.web.codeaurora.org with HTTPS for ; Sun, 04 May 2025 13:07:09 -0000 X-Groupsio-URL: https://lists.openembedded.org/g/openembedded-core/message/215957 From: Adrian Freihofer Run all existing tests for the kernel-fitimage.bbclass also for the new linux-yocto-fitimage recipe. This also ensures that both implementations are compatible with each other. Note: The vmlinux kernel artifacts required by the new linux-yocto-fitimage recipe are exported by the kernel-uboot.bbclass, which is inherited from the kernel-uimage.bbclass, which in turn is inherited by default from the kernel.bbclass as follows: KERNEL_CLASSES = " kernel-uboot " It is therefore no longer necessary to add anything to KERNEL_CLASSES when creating a fitImage. Signed-off-by: Adrian Freihofer --- meta/lib/oeqa/selftest/cases/fitimage.py | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/meta/lib/oeqa/selftest/cases/fitimage.py b/meta/lib/oeqa/selftest/cases/fitimage.py index 3a1d263eb9e..d6be17c63b0 100644 --- a/meta/lib/oeqa/selftest/cases/fitimage.py +++ b/meta/lib/oeqa/selftest/cases/fitimage.py @@ -941,6 +941,17 @@ FIT_HASH_ALG = "sha256" bb_vars = self._fit_get_bb_vars() self._test_fitimage(bb_vars) +class KernelFitImageRecipeTests(KernelFitImageTests): + """Test cases for the linux-yocto-fitimage recipe""" + + @property + def kernel_recipe(self): + return "linux-yocto-fitimage" + + def _config_add_kernel_classes(self, config): + config += '# Avoid naming clashes in the deploy folder with kernel-fitimage.bbclass artifacts' + os.linesep + config += 'KERNEL_DEPLOYSUBDIR:pn-linux-yocto-fitimage = "linux-yocto-fitimage"' + os.linesep + return config class FitImagePyTests(KernelFitImageBase): """Test cases for the fitimage.py module without calling bitbake""" From patchwork Sun May 4 13:05:00 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Freihofer, Adrian" X-Patchwork-Id: 62401 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from aws-us-west-2-korg-lkml-1.web.codeaurora.org (localhost.localdomain [127.0.0.1]) by smtp.lore.kernel.org (Postfix) with ESMTP id 121D1C3ABBA for ; Sun, 4 May 2025 13:07:09 +0000 (UTC) Received: from mta-65-226.siemens.flowmailer.net (mta-65-226.siemens.flowmailer.net [185.136.65.226]) by mx.groups.io with SMTP id smtpd.web11.28300.1746364019682033305 for ; Sun, 04 May 2025 06:07:00 -0700 Authentication-Results: mx.groups.io; dkim=pass header.i=adrian.freihofer@siemens.com header.s=fm1 header.b=fn9pr/I4; spf=pass (domain: rts-flowmailer.siemens.com, ip: 185.136.65.226, mailfrom: fm-1329275-202505041306575724bde05aed7e64ae-_polpm@rts-flowmailer.siemens.com) Received: by mta-65-226.siemens.flowmailer.net with ESMTPSA id 202505041306575724bde05aed7e64ae for ; Sun, 04 May 2025 15:06:57 +0200 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; s=fm1; d=siemens.com; i=adrian.freihofer@siemens.com; h=Date:From:Subject:To:Message-ID:MIME-Version:Content-Type:Content-Transfer-Encoding:Cc:References:In-Reply-To; bh=Ba+doxPaw/UtZEqZPDrBtLGL4a/if/wupw2VaDVkoBU=; b=fn9pr/I4MOBhKqJCt6AQqoEJ6rUi9cqhzsEmL3nj2xlqHGR4rCId2As0K3T0JpRwFHUh48 gAlbOEcK/Gg0jKWCaXKLuY3BH78gF1ZRG5ibBQShXMmlXQb2ZQ01sihe7KlYpK9ndEQ7P1eJ fIHgLNNDF840/zz/KbcBkoLjsA6qwTx+If9O5qvTFjRtluc/ODd7H0nc4gE5ldW4H+/sOqOa pJov11qJx186hyhydnccpTQFXdwBH4fxbXw8mOYvbhvK47sj+vWEWjEnHxHOXlrzkswcFMdC CVkZBP3LBdv9yJ3a1m2ve92T9mnQiLKhPQhhpK0YDbgbgS9T8krM5N1w==; From: AdrianF To: openembedded-core@lists.openembedded.org Cc: marex@denx.de, l.anderweit@phytec.de, richard.purdie@linuxfoundation.org, ross.burton@arm.com, bruce.ashfield@gmail.com, rogerio.borin@toradex.com, sean.anderson@seco.com, m.felsch@pengutronix.de, ejo@pengutronix.de, Adrian Freihofer Subject: [PATCH 13/20] oe-selftest: fitimage refactor classes Date: Sun, 4 May 2025 15:05:00 +0200 Message-ID: <20250504130507.717954-13-adrian.freihofer@siemens.com> In-Reply-To: <20250504130507.717954-1-adrian.freihofer@siemens.com> References: <20250504130507.717954-1-adrian.freihofer@siemens.com> MIME-Version: 1.0 X-Flowmailer-Platform: Siemens Feedback-ID: 519:519-1329275:519-21489:flowmailer List-Id: X-Webhook-Received: from li982-79.members.linode.com [45.33.32.79] by aws-us-west-2-korg-lkml-1.web.codeaurora.org with HTTPS for ; Sun, 04 May 2025 13:07:09 -0000 X-Groupsio-URL: https://lists.openembedded.org/g/openembedded-core/message/215960 From: Adrian Freihofer Make the new KernelFitImageRecipeTests class the one that contains the code, and keep the KernelFitImageTests class as the one that just adds back the same tests. This will make it easier to delete the tests later, which will hopefully become obsolete when the kernel-fitimage.bbclass class is no longer needed. Signed-off-by: Adrian Freihofer --- meta/lib/oeqa/selftest/cases/fitimage.py | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/meta/lib/oeqa/selftest/cases/fitimage.py b/meta/lib/oeqa/selftest/cases/fitimage.py index d6be17c63b0..47619539073 100644 --- a/meta/lib/oeqa/selftest/cases/fitimage.py +++ b/meta/lib/oeqa/selftest/cases/fitimage.py @@ -376,7 +376,7 @@ class FitImageTestCase(OESelftestTestCase): self._check_fitimage(bb_vars, fitimage_path, uboot_tools_bindir) class KernelFitImageBase(FitImageTestCase): - """Test cases for the kernel-fitimage bbclass""" + """Test cases for the linux-yocto-fitimage recipe""" def _fit_get_bb_vars(self, additional_vars=[]): """Retrieve BitBake variables specific to the test case. @@ -416,15 +416,13 @@ class KernelFitImageBase(FitImageTestCase): return bb_vars def _config_add_kernel_classes(self, config): - config += '# Use kernel-fitimage.bbclass for the creation of the fitImage' + os.linesep - config += 'KERNEL_IMAGETYPES += " fitImage "' + os.linesep - config += 'KERNEL_CLASSES = " kernel-fitimage "' + os.linesep + config += '# Avoid naming clashes in the deploy folder with kernel-fitimage.bbclass artifacts' + os.linesep + config += 'KERNEL_DEPLOYSUBDIR:pn-linux-yocto-fitimage = "linux-yocto-fitimage"' + os.linesep return config @property def kernel_recipe(self): - # virtual/kernel does not work with SRC_URI:append:pn-%s - return "linux-yocto" + return "linux-yocto-fitimage" def _config_add_uboot_env(self, config): """Generate an u-boot environment @@ -701,7 +699,7 @@ class KernelFitImageBase(FitImageTestCase): self.assertEqual(found_comments, num_signatures, "Expected %d signed and commented (%s) sections in the fitImage." % (num_signatures, a_comment)) -class KernelFitImageTests(KernelFitImageBase): +class KernelFitImageRecipeTests(KernelFitImageBase): """Test cases for the kernel-fitimage bbclass""" def test_fit_image(self): @@ -941,16 +939,18 @@ FIT_HASH_ALG = "sha256" bb_vars = self._fit_get_bb_vars() self._test_fitimage(bb_vars) -class KernelFitImageRecipeTests(KernelFitImageTests): - """Test cases for the linux-yocto-fitimage recipe""" +class KernelFitImageTests(KernelFitImageRecipeTests): + """Test cases for the kernel-fitimage.bbclass""" @property def kernel_recipe(self): - return "linux-yocto-fitimage" + # virtual/kernel does not work with SRC_URI:append:pn-%s + return "linux-yocto" def _config_add_kernel_classes(self, config): - config += '# Avoid naming clashes in the deploy folder with kernel-fitimage.bbclass artifacts' + os.linesep - config += 'KERNEL_DEPLOYSUBDIR:pn-linux-yocto-fitimage = "linux-yocto-fitimage"' + os.linesep + config += '# Use kernel-fitimage.bbclass for the creation of the fitImage' + os.linesep + config += 'KERNEL_IMAGETYPES += " fitImage "' + os.linesep + config += 'KERNEL_CLASSES = " kernel-fitimage "' + os.linesep return config class FitImagePyTests(KernelFitImageBase): From patchwork Sun May 4 13:05:01 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Freihofer, Adrian" X-Patchwork-Id: 62407 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from aws-us-west-2-korg-lkml-1.web.codeaurora.org (localhost.localdomain [127.0.0.1]) by smtp.lore.kernel.org (Postfix) with ESMTP id 04A4CC3ABB8 for ; Sun, 4 May 2025 13:07:09 +0000 (UTC) Received: from mta-64-225.siemens.flowmailer.net (mta-64-225.siemens.flowmailer.net [185.136.64.225]) by mx.groups.io with SMTP id smtpd.web10.28208.1746364019754644020 for ; Sun, 04 May 2025 06:07:00 -0700 Authentication-Results: mx.groups.io; dkim=pass header.i=adrian.freihofer@siemens.com header.s=fm1 header.b=Ik1eIA8H; spf=pass (domain: rts-flowmailer.siemens.com, ip: 185.136.64.225, mailfrom: fm-1329275-20250504130657fddddcf63aa4e7bc83-_a6zrl@rts-flowmailer.siemens.com) Received: by mta-64-225.siemens.flowmailer.net with ESMTPSA id 20250504130657fddddcf63aa4e7bc83 for ; Sun, 04 May 2025 15:06:58 +0200 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; s=fm1; d=siemens.com; i=adrian.freihofer@siemens.com; h=Date:From:Subject:To:Message-ID:MIME-Version:Content-Type:Content-Transfer-Encoding:Cc:References:In-Reply-To; bh=ihDxaaFMr0HwRn+obGmgHMkuKpvJl6z2c5CsVwn+Fg4=; b=Ik1eIA8H/MYA5DDDxgDQBp8wyHIwmYr086Eebb2b1ic6iP39l+9IYy9+1/4ViJ38YWxxET 9hOYtWCQPwfIiT3Fd0xU2Iyrs5tV6d+zX/8nxcp/hrro4ejJVjQJwtQu1aoqZojYxPq7nyY/ 7GwIjahoAvtmMc3BLfOgpdt1/WLAvAhY3PrwBCDc1SXwVXptjeOyb/lSmcXAk6MY1OOfjT8K 21SII5KWHI2zOPK/IirRC5smEVjSjTaKWZKimrlXLFQqKtTPzueApLu+7lnBK+ziLoCk883n y0MbsSJtLFU5BNbwGELvVpBdnftQDSYOSeSXWzNZQzUmopdqGW6iiKBQ==; From: AdrianF To: openembedded-core@lists.openembedded.org Cc: marex@denx.de, l.anderweit@phytec.de, richard.purdie@linuxfoundation.org, ross.burton@arm.com, bruce.ashfield@gmail.com, rogerio.borin@toradex.com, sean.anderson@seco.com, m.felsch@pengutronix.de, ejo@pengutronix.de, Adrian Freihofer Subject: [PATCH 14/20] kernel-fitimage: re-write its code in Python Date: Sun, 4 May 2025 15:05:01 +0200 Message-ID: <20250504130507.717954-14-adrian.freihofer@siemens.com> In-Reply-To: <20250504130507.717954-1-adrian.freihofer@siemens.com> References: <20250504130507.717954-1-adrian.freihofer@siemens.com> MIME-Version: 1.0 X-Flowmailer-Platform: Siemens Feedback-ID: 519:519-1329275:519-21489:flowmailer List-Id: X-Webhook-Received: from li982-79.members.linode.com [45.33.32.79] by aws-us-west-2-korg-lkml-1.web.codeaurora.org with HTTPS for ; Sun, 04 May 2025 13:07:09 -0000 X-Groupsio-URL: https://lists.openembedded.org/g/openembedded-core/message/215962 From: Adrian Freihofer Rewrite the kernel-fitimage.bbclass file in Python. This allows the reuse of the new fitimage Python library and a clear alignment of the two implementations. Actually, the motivation for an implementation in Python was different. During the transition from the kernel-fitimage.bbclass to the new linux-yocto-fitimage.bb, the existing shell code was rewritten in Python so that the fitimage.py library could be extracted. The new kernel-fit-image.bbclass and linux-yocto-fitimage.bb were then developed on this basis. This approach makes it possible to run the same tests for all different implementations: - kernel-fitimage.bbclass in Shell - kernel-fitimage.bbclass in Python - linux-yocto-fitimage.bb Changing the commit order now enables a smooth transition. The two implementations can coexist. Maintenance and testing should be feasible for a few months with reasonable effort as they share most of the code. But of course, the goal is to remove the kernel-fitimage.bbclass as soon as possible. Signed-off-by: Adrian Freihofer --- meta/classes-recipe/kernel-fitimage.bbclass | 924 +++++--------------- meta/classes-recipe/kernel-uboot.bbclass | 45 + 2 files changed, 243 insertions(+), 726 deletions(-) diff --git a/meta/classes-recipe/kernel-fitimage.bbclass b/meta/classes-recipe/kernel-fitimage.bbclass index 1ef7b1b4483..ba90bddb5f4 100644 --- a/meta/classes-recipe/kernel-fitimage.bbclass +++ b/meta/classes-recipe/kernel-fitimage.bbclass @@ -53,680 +53,170 @@ python __anonymous () { d.setVar('EXTERNAL_KERNEL_DEVICETREE', "${RECIPE_SYSROOT}/boot/devicetree") } -# -# Emit the fitImage ITS header -# -# $1 ... .its filename -fitimage_emit_fit_header() { - cat << EOF >> $1 -/dts-v1/; - -/ { - description = "${FIT_DESC}"; - #address-cells = <${FIT_ADDRESS_CELLS}>; -EOF -} - -# -# Emit the fitImage section bits -# -# $1 ... .its filename -# $2 ... Section bit type: imagestart - image section start -# confstart - configuration section start -# sectend - section end -# fitend - fitimage end -# -fitimage_emit_section_maint() { - case $2 in - imagestart) - cat << EOF >> $1 - - images { -EOF - ;; - confstart) - cat << EOF >> $1 - - configurations { -EOF - ;; - sectend) - cat << EOF >> $1 - }; -EOF - ;; - fitend) - cat << EOF >> $1 -}; -EOF - ;; - esac -} - -# -# Emit the fitImage ITS kernel section -# -# $1 ... .its filename -# $2 ... Image counter -# $3 ... Path to kernel image -# $4 ... Compression type -fitimage_emit_section_kernel() { - - kernel_csum="${FIT_HASH_ALG}" - kernel_sign_algo="${FIT_SIGN_ALG}" - kernel_sign_keyname="${UBOOT_SIGN_IMG_KEYNAME}" - - ENTRYPOINT="${UBOOT_ENTRYPOINT}" - if [ -n "${UBOOT_ENTRYSYMBOL}" ]; then - ENTRYPOINT=`${HOST_PREFIX}nm vmlinux | \ - awk '$3=="${UBOOT_ENTRYSYMBOL}" {print "0x"$1;exit}'` - fi - - cat << EOF >> $1 - kernel-$2 { - description = "Linux kernel"; - type = "${UBOOT_MKIMAGE_KERNEL_TYPE}"; - compression = "$4"; - data = /incbin/("$3"); - arch = "${UBOOT_ARCH}"; - os = "linux"; - load = <${UBOOT_LOADADDRESS}>; - entry = <$ENTRYPOINT>; - hash-1 { - algo = "$kernel_csum"; - }; - }; -EOF - - if [ "${UBOOT_SIGN_ENABLE}" = "1" -a "${FIT_SIGN_INDIVIDUAL}" = "1" -a -n "$kernel_sign_keyname" ] ; then - sed -i '$ d' $1 - cat << EOF >> $1 - signature-1 { - algo = "$kernel_csum,$kernel_sign_algo"; - key-name-hint = "$kernel_sign_keyname"; - }; - }; -EOF - fi -} - -# -# Emit the fitImage ITS DTB section -# -# $1 ... .its filename -# $2 ... Image counter -# $3 ... Path to DTB image -fitimage_emit_section_dtb() { - - dtb_csum="${FIT_HASH_ALG}" - dtb_sign_algo="${FIT_SIGN_ALG}" - dtb_sign_keyname="${UBOOT_SIGN_IMG_KEYNAME}" - - dtb_loadline="" - dtb_ext=${DTB##*.} - if [ "${dtb_ext}" = "dtbo" ]; then - if [ -n "${UBOOT_DTBO_LOADADDRESS}" ]; then - dtb_loadline="load = <${UBOOT_DTBO_LOADADDRESS}>;" - fi - elif [ -n "${UBOOT_DTB_LOADADDRESS}" ]; then - dtb_loadline="load = <${UBOOT_DTB_LOADADDRESS}>;" - fi - cat << EOF >> $1 - fdt-$2 { - description = "Flattened Device Tree blob"; - type = "flat_dt"; - compression = "none"; - data = /incbin/("$3"); - arch = "${UBOOT_ARCH}"; - $dtb_loadline - hash-1 { - algo = "$dtb_csum"; - }; - }; -EOF - - if [ "${UBOOT_SIGN_ENABLE}" = "1" -a "${FIT_SIGN_INDIVIDUAL}" = "1" -a -n "$dtb_sign_keyname" ] ; then - sed -i '$ d' $1 - cat << EOF >> $1 - signature-1 { - algo = "$dtb_csum,$dtb_sign_algo"; - key-name-hint = "$dtb_sign_keyname"; - }; - }; -EOF - fi -} - -# -# Emit the fitImage ITS u-boot script section -# -# $1 ... .its filename -# $2 ... Image counter -# $3 ... Path to boot script image -fitimage_emit_section_boot_script() { - - bootscr_csum="${FIT_HASH_ALG}" - bootscr_sign_algo="${FIT_SIGN_ALG}" - bootscr_sign_keyname="${UBOOT_SIGN_IMG_KEYNAME}" - - cat << EOF >> $1 - bootscr-$2 { - description = "U-boot script"; - type = "script"; - compression = "none"; - data = /incbin/("$3"); - arch = "${UBOOT_ARCH}"; - hash-1 { - algo = "$bootscr_csum"; - }; - }; -EOF - - if [ "${UBOOT_SIGN_ENABLE}" = "1" -a "${FIT_SIGN_INDIVIDUAL}" = "1" -a -n "$bootscr_sign_keyname" ] ; then - sed -i '$ d' $1 - cat << EOF >> $1 - signature-1 { - algo = "$bootscr_csum,$bootscr_sign_algo"; - key-name-hint = "$bootscr_sign_keyname"; - }; - }; -EOF - fi -} - -# -# Emit the fitImage ITS setup section -# -# $1 ... .its filename -# $2 ... Image counter -# $3 ... Path to setup image -fitimage_emit_section_setup() { - - setup_csum="${FIT_HASH_ALG}" - setup_sign_algo="${FIT_SIGN_ALG}" - setup_sign_keyname="${UBOOT_SIGN_IMG_KEYNAME}" - - cat << EOF >> $1 - setup-$2 { - description = "Linux setup.bin"; - type = "x86_setup"; - compression = "none"; - data = /incbin/("$3"); - arch = "${UBOOT_ARCH}"; - os = "linux"; - load = <0x00090000>; - entry = <0x00090000>; - hash-1 { - algo = "$setup_csum"; - }; - }; -EOF - - if [ "${UBOOT_SIGN_ENABLE}" = "1" -a "${FIT_SIGN_INDIVIDUAL}" = "1" -a -n "$setup_sign_keyname" ] ; then - sed -i '$ d' $1 - cat << EOF >> $1 - signature-1 { - algo = "$setup_csum,$setup_sign_algo"; - key-name-hint = "$setup_sign_keyname"; - }; - }; -EOF - fi -} - -# -# Emit the fitImage ITS ramdisk section -# -# $1 ... .its filename -# $2 ... Image counter -# $3 ... Path to ramdisk image -fitimage_emit_section_ramdisk() { - - ramdisk_csum="${FIT_HASH_ALG}" - ramdisk_sign_algo="${FIT_SIGN_ALG}" - ramdisk_sign_keyname="${UBOOT_SIGN_IMG_KEYNAME}" - ramdisk_loadline="" - ramdisk_entryline="" - - if [ -n "${UBOOT_RD_LOADADDRESS}" ]; then - ramdisk_loadline="load = <${UBOOT_RD_LOADADDRESS}>;" - fi - if [ -n "${UBOOT_RD_ENTRYPOINT}" ]; then - ramdisk_entryline="entry = <${UBOOT_RD_ENTRYPOINT}>;" - fi - - cat << EOF >> $1 - ramdisk-$2 { - description = "${INITRAMFS_IMAGE}"; - type = "ramdisk"; - compression = "none"; - data = /incbin/("$3"); - arch = "${UBOOT_ARCH}"; - os = "linux"; - $ramdisk_loadline - $ramdisk_entryline - hash-1 { - algo = "$ramdisk_csum"; - }; - }; -EOF - - if [ "${UBOOT_SIGN_ENABLE}" = "1" -a "${FIT_SIGN_INDIVIDUAL}" = "1" -a -n "$ramdisk_sign_keyname" ] ; then - sed -i '$ d' $1 - cat << EOF >> $1 - signature-1 { - algo = "$ramdisk_csum,$ramdisk_sign_algo"; - key-name-hint = "$ramdisk_sign_keyname"; - }; - }; -EOF - fi -} - -# -# echoes symlink destination if it points below directory -# -# $1 ... file that's a potential symlink -# $2 ... expected parent directory -symlink_points_below() { - file="$2/$1" - dir=$2 - - if ! [ -L "$file" ]; then - return - fi - - realpath="$(realpath --relative-to=$dir $file)" - if [ -z "${realpath%%../*}" ]; then - return - fi - - echo "$realpath" -} - -# -# Emit the fitImage ITS configuration section -# -# $1 ... .its filename -# $2 ... Linux kernel ID -# $3 ... DTB image name -# $4 ... ramdisk ID -# $5 ... u-boot script ID -# $6 ... config ID -# $7 ... default flag -# $8 ... default DTB image name -fitimage_emit_section_config() { - - conf_csum="${FIT_HASH_ALG}" - conf_sign_algo="${FIT_SIGN_ALG}" - conf_padding_algo="${FIT_PAD_ALG}" - if [ "${UBOOT_SIGN_ENABLE}" = "1" ] ; then - conf_sign_keyname="${UBOOT_SIGN_KEYNAME}" - fi - - its_file="$1" - kernel_id="$2" - dtb_image="$3" - ramdisk_id="$4" - bootscr_id="$5" - config_id="$6" - default_flag="$7" - default_dtb_image="$8" - - # Test if we have any DTBs at all - sep="" - conf_desc="" - conf_node="${FIT_CONF_PREFIX}" - kernel_line="" - fdt_line="" - ramdisk_line="" - bootscr_line="" - setup_line="" - default_line="" - compatible_line="" - - dtb_image_sect=$(symlink_points_below $dtb_image "${EXTERNAL_KERNEL_DEVICETREE}") - if [ -z "$dtb_image_sect" ]; then - dtb_image_sect=$dtb_image - fi - - dtb_path="${EXTERNAL_KERNEL_DEVICETREE}/${dtb_image_sect}" - if [ -f "$dtb_path" ] || [ -L "$dtb_path" ]; then - compat=$(fdtget -t s "$dtb_path" / compatible | sed 's/ /", "/g') - if [ -n "$compat" ]; then - compatible_line="compatible = \"$compat\";" - fi - fi - - dtb_image=$(echo $dtb_image | tr '/' '_') - dtb_image_sect=$(echo "${dtb_image_sect}" | tr '/' '_') - - # conf node name is selected based on dtb ID if it is present, - # otherwise its selected based on kernel ID - if [ -n "$dtb_image" ]; then - conf_node=$conf_node$dtb_image - else - conf_node=$conf_node$kernel_id - fi - - if [ -n "$kernel_id" ]; then - conf_desc="Linux kernel" - sep=", " - kernel_line="kernel = \"kernel-$kernel_id\";" - fi - - if [ -n "$dtb_image" ]; then - conf_desc="$conf_desc${sep}FDT blob" - sep=", " - fdt_line="fdt = \"fdt-$dtb_image_sect\";" - fi - - if [ -n "$ramdisk_id" ]; then - conf_desc="$conf_desc${sep}ramdisk" - sep=", " - ramdisk_line="ramdisk = \"ramdisk-$ramdisk_id\";" - fi - - if [ -n "$bootscr_id" ]; then - conf_desc="$conf_desc${sep}u-boot script" - sep=", " - bootscr_line="bootscr = \"bootscr-$bootscr_id\";" - fi - - if [ -n "$config_id" ]; then - conf_desc="$conf_desc${sep}setup" - setup_line="setup = \"setup-$config_id\";" - fi - - if [ "$default_flag" = "1" ]; then - # default node is selected based on dtb ID if it is present, - # otherwise its selected based on kernel ID - if [ -n "$dtb_image" ]; then - # Select default node as user specified dtb when - # multiple dtb exists. - if [ -n "$default_dtb_image" ]; then - default_line="default = \"${FIT_CONF_PREFIX}$default_dtb_image\";" - else - default_line="default = \"${FIT_CONF_PREFIX}$dtb_image\";" - fi - else - default_line="default = \"${FIT_CONF_PREFIX}$kernel_id\";" - fi - fi - - cat << EOF >> $its_file - $default_line - $conf_node { - description = "$default_flag $conf_desc"; - $compatible_line - $kernel_line - $fdt_line - $ramdisk_line - $bootscr_line - $setup_line - hash-1 { - algo = "$conf_csum"; - }; -EOF - - if [ -n "$conf_sign_keyname" ] ; then - - sign_line="sign-images = " - sep="" - - if [ -n "$kernel_id" ]; then - sign_line="$sign_line${sep}\"kernel\"" - sep=", " - fi - - if [ -n "$dtb_image" ]; then - sign_line="$sign_line${sep}\"fdt\"" - sep=", " - fi - - if [ -n "$ramdisk_id" ]; then - sign_line="$sign_line${sep}\"ramdisk\"" - sep=", " - fi - - if [ -n "$bootscr_id" ]; then - sign_line="$sign_line${sep}\"bootscr\"" - sep=", " - fi - - if [ -n "$config_id" ]; then - sign_line="$sign_line${sep}\"setup\"" - fi - - sign_line="$sign_line;" - - cat << EOF >> $its_file - signature-1 { - algo = "$conf_csum,$conf_sign_algo"; - key-name-hint = "$conf_sign_keyname"; - padding = "$conf_padding_algo"; - $sign_line - }; -EOF - fi - - cat << EOF >> $its_file - }; -EOF -} - -# -# Assemble fitImage -# -# $1 ... .its filename -# $2 ... fitImage name -# $3 ... include ramdisk -fitimage_assemble() { - kernelcount=1 - dtbcount="" - DTBS="" - ramdiskcount=$3 - setupcount="" - bootscr_id="" - default_dtb_image="" - rm -f $1 arch/${ARCH}/boot/$2 - - if [ -n "${UBOOT_SIGN_IMG_KEYNAME}" -a "${UBOOT_SIGN_KEYNAME}" = "${UBOOT_SIGN_IMG_KEYNAME}" ]; then - bbfatal "Keys used to sign images and configuration nodes must be different." - fi - - fitimage_emit_fit_header $1 - - # - # Step 1: Prepare a kernel image section. - # - fitimage_emit_section_maint $1 imagestart - - uboot_prep_kimage - fitimage_emit_section_kernel $1 $kernelcount linux.bin "$linux_comp" - - # - # Step 2: Prepare a DTB image section - # - - if [ -n "${KERNEL_DEVICETREE}" ]; then - dtbcount=1 - for DTB in ${KERNEL_DEVICETREE}; do - if echo $DTB | grep -q '/dts/'; then - bbwarn "$DTB contains the full path to the the dts file, but only the dtb name should be used." - DTB=`basename $DTB | sed 's,\.dts$,.dtb,g'` - fi - - # Skip ${DTB} if it's also provided in ${EXTERNAL_KERNEL_DEVICETREE} - if [ -n "${EXTERNAL_KERNEL_DEVICETREE}" ] && [ -s ${EXTERNAL_KERNEL_DEVICETREE}/${DTB} ]; then - continue - fi - - DTB_PATH="${KERNEL_OUTPUT_DIR}/dts/$DTB" - if [ ! -e "$DTB_PATH" ]; then - DTB_PATH="${KERNEL_OUTPUT_DIR}/$DTB" - fi - - # Strip off the path component from the filename - if "${@'false' if oe.types.boolean(d.getVar('KERNEL_DTBVENDORED')) else 'true'}"; then - DTB=`basename $DTB` - fi - - # Set the default dtb image if it exists in the devicetree. - if [ "${FIT_CONF_DEFAULT_DTB}" = "$DTB" ];then - default_dtb_image=$(echo "$DTB" | tr '/' '_') - fi - - DTB=$(echo "$DTB" | tr '/' '_') - - # Skip DTB if we've picked it up previously - echo "$DTBS" | tr ' ' '\n' | grep -xq "$DTB" && continue - - DTBS="$DTBS $DTB" - DTB=$(echo $DTB | tr '/' '_') - fitimage_emit_section_dtb $1 $DTB $DTB_PATH - done - fi - - if [ -n "${EXTERNAL_KERNEL_DEVICETREE}" ]; then - dtbcount=1 - for DTB in $(find "${EXTERNAL_KERNEL_DEVICETREE}" -name '*.dtb' -printf '%P\n' | sort) \ - $(find "${EXTERNAL_KERNEL_DEVICETREE}" -name '*.dtbo' -printf '%P\n' | sort); do - # Set the default dtb image if it exists in the devicetree. - if [ ${FIT_CONF_DEFAULT_DTB} = $DTB ];then - default_dtb_image=$(echo "$DTB" | tr '/' '_') - fi - - DTB=$(echo "$DTB" | tr '/' '_') - - # Skip DTB/DTBO if we've picked it up previously - echo "$DTBS" | tr ' ' '\n' | grep -xq "$DTB" && continue - - DTBS="$DTBS $DTB" - - # Also skip if a symlink. We'll later have each config section point at it - [ $(symlink_points_below $DTB "${EXTERNAL_KERNEL_DEVICETREE}") ] && continue - - DTB=$(echo $DTB | tr '/' '_') - fitimage_emit_section_dtb $1 $DTB "${EXTERNAL_KERNEL_DEVICETREE}/$DTB" - done - fi - - if [ -n "${FIT_CONF_DEFAULT_DTB}" ] && [ -z $default_dtb_image ]; then - bbwarn "${FIT_CONF_DEFAULT_DTB} is not available in the list of device trees." - fi - - # - # Step 3: Prepare a u-boot script section - # - - if [ -n "${FIT_UBOOT_ENV}" ]; then - cp ${UNPACKDIR}/${FIT_UBOOT_ENV} ${B} - bootscr_id="${FIT_UBOOT_ENV}" - fitimage_emit_section_boot_script $1 "$bootscr_id" ${FIT_UBOOT_ENV} - fi - - # - # Step 4: Prepare a setup section. (For x86) - # - if [ -e ${KERNEL_OUTPUT_DIR}/setup.bin ]; then - setupcount=1 - fitimage_emit_section_setup $1 $setupcount ${KERNEL_OUTPUT_DIR}/setup.bin - fi - - # - # Step 5: Prepare a ramdisk section. - # - if [ "x${ramdiskcount}" = "x1" ] && [ "${INITRAMFS_IMAGE_BUNDLE}" != "1" ]; then - # Find and use the first initramfs image archive type we find - found= - for img in ${FIT_SUPPORTED_INITRAMFS_FSTYPES}; do - initramfs_path="${INITRAMFS_DEPLOY_DIR_IMAGE}/${INITRAMFS_IMAGE_NAME}.$img" - if [ -e "$initramfs_path" ]; then - bbnote "Found initramfs image: $initramfs_path" - found=true - fitimage_emit_section_ramdisk $1 "$ramdiskcount" "$initramfs_path" - break - else - bbnote "Did not find initramfs image: $initramfs_path" - fi - done - - if [ -z "$found" ]; then - bbfatal "Could not find a valid initramfs type for ${INITRAMFS_IMAGE_NAME}, the supported types are: ${FIT_SUPPORTED_INITRAMFS_FSTYPES}" - fi - fi - - fitimage_emit_section_maint $1 sectend - - # Force the first Kernel and DTB in the default config - kernelcount=1 - if [ -n "$dtbcount" ]; then - dtbcount=1 - fi - - # - # Step 6: Prepare a configurations section - # - fitimage_emit_section_maint $1 confstart - - # kernel-fitimage.bbclass currently only supports a single kernel (no less or - # more) to be added to the FIT image along with 0 or more device trees and - # 0 or 1 ramdisk. - # It is also possible to include an initramfs bundle (kernel and rootfs in one binary) - # When the initramfs bundle is used ramdisk is disabled. - # If a device tree is to be part of the FIT image, then select - # the default configuration to be used is based on the dtbcount. If there is - # no dtb present than select the default configuation to be based on - # the kernelcount. - if [ -n "$DTBS" ]; then - i=1 - for DTB in ${DTBS}; do - dtb_ext=${DTB##*.} - if [ "$dtb_ext" = "dtbo" ]; then - fitimage_emit_section_config $1 "" "$DTB" "" "$bootscr_id" "" "`expr $i = $dtbcount`" "$default_dtb_image" - else - fitimage_emit_section_config $1 $kernelcount "$DTB" "$ramdiskcount" "$bootscr_id" "$setupcount" "`expr $i = $dtbcount`" "$default_dtb_image" - fi - i=`expr $i + 1` - done - else - defaultconfigcount=1 - fitimage_emit_section_config $1 $kernelcount "" "$ramdiskcount" "$bootscr_id" "$setupcount" $defaultconfigcount "$default_dtb_image" - fi - - fitimage_emit_section_maint $1 sectend - - fitimage_emit_section_maint $1 fitend - - # - # Step 7: Assemble the image - # - ${UBOOT_MKIMAGE} \ - ${@'-D "${UBOOT_MKIMAGE_DTCOPTS}"' if len('${UBOOT_MKIMAGE_DTCOPTS}') else ''} \ - -f $1 \ - ${KERNEL_OUTPUT_DIR}/$2 - - # - # Step 8: Sign the image - # - if [ "x${UBOOT_SIGN_ENABLE}" = "x1" ] ; then - ${UBOOT_MKIMAGE_SIGN} \ - ${@'-D "${UBOOT_MKIMAGE_DTCOPTS}"' if len('${UBOOT_MKIMAGE_DTCOPTS}') else ''} \ - -F -k "${UBOOT_SIGN_KEYDIR}" \ - -r ${KERNEL_OUTPUT_DIR}/$2 \ - ${UBOOT_MKIMAGE_SIGN_ARGS} - fi -} - -do_assemble_fitimage() { - if echo ${KERNEL_IMAGETYPES} | grep -wq "fitImage"; then - cd ${B} - fitimage_assemble fit-image.its fitImage-none "" - if [ "${INITRAMFS_IMAGE_BUNDLE}" != "1" ]; then - ln -sf fitImage-none ${B}/${KERNEL_OUTPUT_DIR}/fitImage - fi - fi +def fitimage_assemble(d, itsfile, fitname, ramdiskcount): + import shutil + import glob + import oe.fitimage + + DTBS="" + default_dtb_image="" + + for f in [itsfile, os.path.join("arch", d.getVar("ARCH"), "boot", fitname)]: + if os.path.exists(f): + os.remove(f) + + root_node = oe.fitimage.ItsNodeRootKernel( + d.getVar("FIT_DESC"), d.getVar("FIT_ADDRESS_CELLS"), + d.getVar('HOST_PREFIX'), d.getVar('UBOOT_ARCH'), d.getVar("FIT_CONF_PREFIX"), + d.getVar('UBOOT_SIGN_ENABLE') == "1", d.getVar("UBOOT_SIGN_KEYDIR"), + d.getVar("UBOOT_MKIMAGE"), d.getVar("UBOOT_MKIMAGE_DTCOPTS"), + d.getVar("UBOOT_MKIMAGE_SIGN"), d.getVar("UBOOT_MKIMAGE_SIGN_ARGS"), + d.getVar('FIT_HASH_ALG'), d.getVar('FIT_SIGN_ALG'), d.getVar('FIT_PAD_ALG'), + d.getVar('UBOOT_SIGN_KEYNAME'), + d.getVar('FIT_SIGN_INDIVIDUAL') == "1", d.getVar('UBOOT_SIGN_IMG_KEYNAME') + ) + + # + # Step 1: Prepare a kernel image section. + # + linux_comp = uboot_prep_kimage_py(d) + 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")) + + # + # Step 2: Prepare a DTB image section + # + if d.getVar("KERNEL_DEVICETREE"): + for DTB in d.getVar("KERNEL_DEVICETREE").split(): + if "/dts/" in DTB: + bb.warn(f"{DTB} contains the full path to the dts file, but only the dtb name should be used.") + DTB = os.path.basename(DTB).replace(".dts", ".dtb") + + # Skip DTB if it's also provided in EXTERNAL_KERNEL_DEVICETREE + if d.getVar("EXTERNAL_KERNEL_DEVICETREE"): + ext_dtb_path = os.path.join(d.getVar("EXTERNAL_KERNEL_DEVICETREE"), DTB) + if os.path.exists(ext_dtb_path) and os.path.getsize(ext_dtb_path) > 0: + continue + + DTB_PATH = os.path.join(d.getVar("KERNEL_OUTPUT_DIR"), "dts", DTB) + if not os.path.exists(DTB_PATH): + DTB_PATH = os.path.join(d.getVar("KERNEL_OUTPUT_DIR"), DTB) + + # Strip off the path component from the filename + if not oe.types.boolean(d.getVar("KERNEL_DTBVENDORED")): + DTB = os.path.basename(DTB) + + # Set the default dtb image if it exists in the devicetree. + if d.getVar("FIT_CONF_DEFAULT_DTB") == DTB: + default_dtb_image = DTB.replace("/", "_") + + DTB = DTB.replace("/", "_") + + # Skip DTB if we've picked it up previously + if DTB in DTBS.split(): + continue + + DTBS += " " + DTB + + root_node.fitimage_emit_section_dtb(DTB, DTB_PATH, + d.getVar("UBOOT_DTB_LOADADDRESS"), d.getVar("UBOOT_DTBO_LOADADDRESS")) + + if d.getVar("EXTERNAL_KERNEL_DEVICETREE"): + dtb_files = [] + for ext in ['*.dtb', '*.dtbo']: + dtb_files.extend(sorted(glob.glob(os.path.join(d.getVar("EXTERNAL_KERNEL_DEVICETREE"), ext)))) + + for dtb_path in dtb_files: + dtb_name = os.path.relpath(dtb_path, d.getVar("EXTERNAL_KERNEL_DEVICETREE")) + dtb_name_underscore = dtb_name.replace('/', '_') + + # Set the default dtb image if it exists in the devicetree. + if d.getVar("FIT_CONF_DEFAULT_DTB") == dtb_name: + default_dtb_image = dtb_name_underscore + + # Skip DTB/DTBO if we've picked it up previously + if dtb_name_underscore in DTBS.split(): + continue + + DTBS += " " + dtb_name_underscore + + # Also skip if a symlink. We'll later have each config section point at it + if oe.fitimage.symlink_points_below(dtb_name, d.getVar("EXTERNAL_KERNEL_DEVICETREE")): + continue + + root_node.fitimage_emit_section_dtb(dtb_name_underscore, dtb_path, + d.getVar("UBOOT_DTB_LOADADDRESS"), d.getVar("UBOOT_DTBO_LOADADDRESS")) + + if d.getVar("FIT_CONF_DEFAULT_DTB") and not default_dtb_image: + bb.warn("%s is not available in the list of device trees." % d.getVar('FIT_CONF_DEFAULT_DTB')) + + # + # Step 3: Prepare a u-boot script section + # + fit_uboot_env = d.getVar("FIT_UBOOT_ENV") + if fit_uboot_env: + unpack_dir = d.getVar("UNPACKDIR") + shutil.copy(os.path.join(unpack_dir, fit_uboot_env), fit_uboot_env) + root_node.fitimage_emit_section_boot_script("bootscr-"+fit_uboot_env , fit_uboot_env) + + # + # Step 4: Prepare a setup section. (For x86) + # + setup_bin_path = os.path.join(d.getVar("KERNEL_OUTPUT_DIR"), "setup.bin") + if os.path.exists(setup_bin_path): + root_node.fitimage_emit_section_setup("setup-1", setup_bin_path) + + # + # Step 5: Prepare a ramdisk section. + # + if ramdiskcount == 1 and d.getVar("INITRAMFS_IMAGE_BUNDLE") != "1": + # Find and use the first initramfs image archive type we find + found = False + for img in d.getVar("FIT_SUPPORTED_INITRAMFS_FSTYPES").split(): + initramfs_path = os.path.join(d.getVar("DEPLOY_DIR_IMAGE"), "%s.%s" % (d.getVar('INITRAMFS_IMAGE_NAME'), img)) + if os.path.exists(initramfs_path): + bb.note("Found initramfs image: " + initramfs_path) + found = True + root_node.fitimage_emit_section_ramdisk("ramdisk-%d" % ramdiskcount, initramfs_path, + d.getVar('INITRAMFS_IMAGE'), + d.getVar("UBOOT_RD_LOADADDRESS"), + d.getVar("UBOOT_RD_ENTRYPOINT")) + break + else: + bb.note("Did not find initramfs image: " + initramfs_path) + + if not found: + bb.fatal("Could not find a valid initramfs type for %s, the supported types are: %s" % (d.getVar('INITRAMFS_IMAGE_NAME'), d.getVar('FIT_SUPPORTED_INITRAMFS_FSTYPES'))) + + # Generate the configuration section + root_node.fitimage_emit_section_config() + + # + # Write the ITS file + root_node.write_its_file(itsfile) + + # + # Step 7: Assemble the image + # + fitfile = os.path.join(d.getVar("KERNEL_OUTPUT_DIR"), fitname) + root_node.run_mkimage_assemble(itsfile, fitfile) + + # + # Step 8: Sign the image if required + # + root_node.run_mkimage_sign(fitfile) + + +python do_assemble_fitimage() { + if "fitImage" in d.getVar("KERNEL_IMAGETYPES").split(): + os.chdir(d.getVar("B")) + fitimage_assemble(d, "fit-image.its", "fitImage-none", "") + if d.getVar("INITRAMFS_IMAGE_BUNDLE") != "1": + link_name = os.path.join(d.getVar("B"), d.getVar("KERNEL_OUTPUT_DIR"), "fitImage") + if os.path.islink(link_name): + os.unlink(link_name) + os.symlink("fitImage-none", link_name) } addtask assemble_fitimage before do_install after do_compile @@ -738,64 +228,46 @@ do_install:append() { fi } -do_assemble_fitimage_initramfs() { - if echo ${KERNEL_IMAGETYPES} | grep -wq "fitImage" && \ - test -n "${INITRAMFS_IMAGE}" ; then - cd ${B} - if [ "${INITRAMFS_IMAGE_BUNDLE}" = "1" ]; then - fitimage_assemble fit-image-${INITRAMFS_IMAGE}.its fitImage-bundle "" - ln -sf fitImage-bundle ${B}/${KERNEL_OUTPUT_DIR}/fitImage - else - fitimage_assemble fit-image-${INITRAMFS_IMAGE}.its fitImage-${INITRAMFS_IMAGE} 1 - fi - fi +python do_assemble_fitimage_initramfs() { + if "fitImage" in d.getVar("KERNEL_IMAGETYPES").split() and d.getVar("INITRAMFS_IMAGE"): + os.chdir(d.getVar("B")) + if d.getVar("INITRAMFS_IMAGE_BUNDLE") == "1": + fitimage_assemble(d, "fit-image-%s.its" % d.getVar("INITRAMFS_IMAGE"), "fitImage-bundle", "") + link_name = os.path.join(d.getVar("B"), d.getVar("KERNEL_OUTPUT_DIR"), "fitImage") + if os.path.islink(link_name): + os.unlink(link_name) + os.symlink("fitImage-bundle", link_name) + else: + fitimage_assemble(d, "fit-image-%s.its" % d.getVar("INITRAMFS_IMAGE"), "fitImage-%s" % d.getVar("INITRAMFS_IMAGE"), 1) } addtask assemble_fitimage_initramfs before do_deploy after do_bundle_initramfs -do_kernel_generate_rsa_keys() { - if [ "${UBOOT_SIGN_ENABLE}" = "0" ] && [ "${FIT_GENERATE_KEYS}" = "1" ]; then - bbwarn "FIT_GENERATE_KEYS is set to 1 even though UBOOT_SIGN_ENABLE is set to 0. The keys will not be generated as they won't be used." - fi +python do_kernel_generate_rsa_keys() { + import oe.fitimage - if [ "${UBOOT_SIGN_ENABLE}" = "1" ] && [ "${FIT_GENERATE_KEYS}" = "1" ]; then + sign_enable = oe.types.boolean(d.getVar('UBOOT_SIGN_ENABLE')) + fit_generate_keys = oe.types.boolean(d.getVar('FIT_GENERATE_KEYS')) + if not sign_enable and fit_generate_keys: + bb.warn("FIT_GENERATE_KEYS is set to 1 even though UBOOT_SIGN_ENABLE is set to 0. The keys will not be generated as they won't be used.") + if sign_enable and fit_generate_keys: + sign_keydir = d.getVar('UBOOT_SIGN_KEYDIR') + sign_keyname = d.getVar('UBOOT_SIGN_KEYNAME') + sign_kc_path = os.path.join(sign_keydir, sign_keyname) + if not os.path.exists(sign_kc_path + '.key') or not os.path.exists(sign_kc_path + '.crt'): + bb.note("Generating RSA private key and certificate for signing fitImage configurations") + oe.fitimage.generate_rsa_key(sign_keydir, sign_keyname, + d.getVar('FIT_SIGN_NUMBITS'), d.getVar('FIT_KEY_GENRSA_ARGS'), + d.getVar('FIT_KEY_REQ_ARGS'), d.getVar('FIT_KEY_SIGN_PKCS')) - # Generate keys to sign configuration nodes, only if they don't already exist - if [ ! -f "${UBOOT_SIGN_KEYDIR}/${UBOOT_SIGN_KEYNAME}".key ] || \ - [ ! -f "${UBOOT_SIGN_KEYDIR}/${UBOOT_SIGN_KEYNAME}".crt ]; then - - # make directory if it does not already exist - mkdir -p "${UBOOT_SIGN_KEYDIR}" - - bbnote "Generating RSA private key for signing fitImage" - openssl genrsa ${FIT_KEY_GENRSA_ARGS} -out \ - "${UBOOT_SIGN_KEYDIR}/${UBOOT_SIGN_KEYNAME}".key \ - "${FIT_SIGN_NUMBITS}" - - bbnote "Generating certificate for signing fitImage" - openssl req ${FIT_KEY_REQ_ARGS} "${FIT_KEY_SIGN_PKCS}" \ - -key "${UBOOT_SIGN_KEYDIR}/${UBOOT_SIGN_KEYNAME}".key \ - -out "${UBOOT_SIGN_KEYDIR}/${UBOOT_SIGN_KEYNAME}".crt - fi - - # Generate keys to sign image nodes, only if they don't already exist - if [ ! -f "${UBOOT_SIGN_KEYDIR}/${UBOOT_SIGN_IMG_KEYNAME}".key ] || \ - [ ! -f "${UBOOT_SIGN_KEYDIR}/${UBOOT_SIGN_IMG_KEYNAME}".crt ]; then - - # make directory if it does not already exist - mkdir -p "${UBOOT_SIGN_KEYDIR}" - - bbnote "Generating RSA private key for signing fitImage" - openssl genrsa ${FIT_KEY_GENRSA_ARGS} -out \ - "${UBOOT_SIGN_KEYDIR}/${UBOOT_SIGN_IMG_KEYNAME}".key \ - "${FIT_SIGN_NUMBITS}" - - bbnote "Generating certificate for signing fitImage" - openssl req ${FIT_KEY_REQ_ARGS} "${FIT_KEY_SIGN_PKCS}" \ - -key "${UBOOT_SIGN_KEYDIR}/${UBOOT_SIGN_IMG_KEYNAME}".key \ - -out "${UBOOT_SIGN_KEYDIR}/${UBOOT_SIGN_IMG_KEYNAME}".crt - fi - fi + if oe.types.boolean(d.getVar('FIT_SIGN_INDIVIDUAL')): + sign_img_keyname = d.getVar('UBOOT_SIGN_IMG_KEYNAME') + sign_img_kc_path = os.path.join(sign_keydir, sign_img_keyname) + if not os.path.exists(sign_img_kc_path + '.key') or not os.path.exists(sign_img_kc_path + '.crt'): + bb.note("Generating RSA private key and certificate for signing fitImage individual images") + oe.fitimage.generate_rsa_key(sign_keydir, sign_img_keyname, + d.getVar('FIT_SIGN_NUMBITS'), d.getVar('FIT_KEY_GENRSA_ARGS'), + d.getVar('FIT_KEY_REQ_ARGS'), d.getVar('FIT_KEY_SIGN_PKCS')) } addtask kernel_generate_rsa_keys before do_assemble_fitimage after do_compile diff --git a/meta/classes-recipe/kernel-uboot.bbclass b/meta/classes-recipe/kernel-uboot.bbclass index 7aafd4757c2..888664678d1 100644 --- a/meta/classes-recipe/kernel-uboot.bbclass +++ b/meta/classes-recipe/kernel-uboot.bbclass @@ -67,3 +67,48 @@ do_install:append() { install -D ${B}/${KERNEL_OUTPUT_DIR}/setup.bin ${D}/sysroot-only/setup.bin fi } + +def uboot_prep_kimage_py(d): + import subprocess + + arch = d.getVar('ARCH') + initramfs_image_bundle = d.getVar('INITRAMFS_IMAGE_BUNDLE') + fit_kernel_comp_alg = d.getVar('FIT_KERNEL_COMP_ALG') or 'gzip' + fit_kernel_comp_alg_extension = d.getVar('FIT_KERNEL_COMP_ALG_EXTENSION') or '.gz' + kernel_objcopy = d.getVar('KERNEL_OBJCOPY') + + vmlinux_path = "" + linux_suffix = "" + linux_comp = "none" + + if os.path.exists(f'arch/{arch}/boot/compressed/vmlinux'): + vmlinux_path = f'arch/{arch}/boot/compressed/vmlinux' + elif os.path.exists(f'arch/{arch}/boot/vmlinuz.bin'): + if os.path.exists('linux.bin'): + os.remove('linux.bin') + os.link(f'arch/{arch}/boot/vmlinuz.bin', 'linux.bin') + else: + vmlinux_path = 'vmlinux' + # Use vmlinux.initramfs for linux.bin when INITRAMFS_IMAGE_BUNDLE set + # As per the implementation in kernel.bbclass. + # See do_bundle_initramfs function + if initramfs_image_bundle == '1' and os.path.exists('vmlinux.initramfs'): + vmlinux_path = 'vmlinux.initramfs' + linux_suffix = fit_kernel_comp_alg_extension + linux_comp = fit_kernel_comp_alg + + if vmlinux_path: + subprocess.run([kernel_objcopy.strip(), '-O', 'binary', '-R', '.note', '-R', '.comment', '-S', os.path.abspath(vmlinux_path), 'linux.bin'], check=True) + # if ret.returncode != 0: + # bb.fatal(f"Error: stderr: {ret.stderr.decode('utf-8')} stdout: {ret.stdout.decode('utf-8')}, vmlinux_path: {os.path.abspath(vmlinux_path)}, pwd: {os.getcwd()}, args: {ret.args}") + + if linux_comp != "none": + if linux_comp == "gzip": + subprocess.run(['gzip', '-9', 'linux.bin'], check=True) + elif linux_comp == "lzo": + subprocess.run(['lzop', '-9', 'linux.bin'], check=True) + elif linux_comp == "lzma": + subprocess.run(['xz', '--format=lzma', '-f', '-6', 'linux.bin'], check=True) + os.rename(f'linux.bin{linux_suffix}', 'linux.bin') + + return linux_comp From patchwork Sun May 4 13:05:02 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: "Freihofer, Adrian" X-Patchwork-Id: 62398 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from aws-us-west-2-korg-lkml-1.web.codeaurora.org (localhost.localdomain [127.0.0.1]) by smtp.lore.kernel.org (Postfix) with ESMTP id ECC0AC3ABB6 for ; Sun, 4 May 2025 13:07:08 +0000 (UTC) Received: from mta-65-225.siemens.flowmailer.net (mta-65-225.siemens.flowmailer.net [185.136.65.225]) by mx.groups.io with SMTP id smtpd.web10.28210.1746364020040291994 for ; Sun, 04 May 2025 06:07:00 -0700 Authentication-Results: mx.groups.io; dkim=pass header.i=adrian.freihofer@siemens.com header.s=fm1 header.b=VsBSC/LG; spf=pass (domain: rts-flowmailer.siemens.com, ip: 185.136.65.225, mailfrom: fm-1329275-20250504130658a18f2c69d98117c346-lqiseq@rts-flowmailer.siemens.com) Received: by mta-65-225.siemens.flowmailer.net with ESMTPSA id 20250504130658a18f2c69d98117c346 for ; Sun, 04 May 2025 15:06:58 +0200 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; s=fm1; d=siemens.com; i=adrian.freihofer@siemens.com; h=Date:From:Subject:To:Message-ID:MIME-Version:Content-Type:Content-Transfer-Encoding:Cc:References:In-Reply-To; bh=sUT+anTtqAh5U9H6EcQ+TeEW01qL2eH694EjAi/nvA8=; b=VsBSC/LGrnGLpQvpM+WNc4FhZ9qNOnHqxkbKbvm3V4i7BQvEV0xhiDubXtS0iRrL/7l72H K0PNJ3fBE7eh6tagiSKXQKJM884lvuLkR1Doann8y0OkAtDl+wrxi7lQUfJb6GyaXtUiIIxX hwtM2yJLZW/h0UkOPn6bgcSk8E6D+kg5XbMMERGK0cPEfZJYBqtYmiHLcik11javqmYk531L xj6LZWKEofcAz7YIT7m4+Ph95FFok7q0b4k6b8gUA0PoSS43NNdeVEpmRxBmDwITLpQ/yBhE /Qqzn9DVjfm+cEIzkuXUCkMoR/0HCFtxmvlJ4mAjlreikK/8Pswr35cA==; From: AdrianF To: openembedded-core@lists.openembedded.org Cc: marex@denx.de, l.anderweit@phytec.de, richard.purdie@linuxfoundation.org, ross.burton@arm.com, bruce.ashfield@gmail.com, rogerio.borin@toradex.com, sean.anderson@seco.com, m.felsch@pengutronix.de, ejo@pengutronix.de, Adrian Freihofer Subject: [PATCH 15/20] kernel.bbclass: remove support for type fitImage Date: Sun, 4 May 2025 15:05:02 +0200 Message-ID: <20250504130507.717954-15-adrian.freihofer@siemens.com> In-Reply-To: <20250504130507.717954-1-adrian.freihofer@siemens.com> References: <20250504130507.717954-1-adrian.freihofer@siemens.com> MIME-Version: 1.0 X-Flowmailer-Platform: Siemens Feedback-ID: 519:519-1329275:519-21489:flowmailer List-Id: X-Webhook-Received: from li982-79.members.linode.com [45.33.32.79] by aws-us-west-2-korg-lkml-1.web.codeaurora.org with HTTPS for ; Sun, 04 May 2025 13:07:08 -0000 X-Groupsio-URL: https://lists.openembedded.org/g/openembedded-core/message/215963 From: Adrian Freihofer Support for fitImage inf KERNEL_IMAGETYPE or KERNEL_IMAGETYPES has been removed from kernel.bbclass. There is now the new kernel-fit-image.bbclass which allows to write an independent recipe like the linux-yocto-fitimage.bb which provides the same functionality. This new recipe has the advantage that it can use kernel artifacts from the sstate-cache when the initramfs changes but the kernel remains unchanged. This was not possible with the old kernel-fitimage.bbclass. The combination of INITRAMFS_IMAGE_BUNDLE = “1” and the creation of a FIT image is no longer supported. But there is probably no real use case for such a configuration. The FIT image can contain multiple artifacts such as a kernel and an initramfs without bundling the initramfs into the kernel artifact. Bundling the initramfs into the kernel artifact also requires the full kernel build directory, which inherently prevents the use of the kernel from the sstate cache. Signed-off-by: Adrian Freihofer --- meta/classes-recipe/kernel.bbclass | 20 +++++++------------- 1 file changed, 7 insertions(+), 13 deletions(-) diff --git a/meta/classes-recipe/kernel.bbclass b/meta/classes-recipe/kernel.bbclass index 1a7a60eadfc..847eb2f046f 100644 --- a/meta/classes-recipe/kernel.bbclass +++ b/meta/classes-recipe/kernel.bbclass @@ -84,6 +84,10 @@ python __anonymous () { types = (alttype + ' ' + types).strip() d.setVar('KERNEL_IMAGETYPES', types) + # Since kernel-fitimage.bbclass got replaced by kernel-fit-image.bbclass + if "fitImage" in types: + bb.error("fitImage is no longer supported as a KERNEL_IMAGETYPE(S)") + # KERNEL_IMAGETYPES may contain a mixture of image types supported directly # by the kernel build system and types which are created by post-processing # the output of the kernel build system (e.g. compressing vmlinux -> @@ -477,17 +481,10 @@ kernel_do_install() { install -d ${D}/${KERNEL_IMAGEDEST} # - # When including an initramfs bundle inside a FIT image, the fitImage is created after the install task - # by do_assemble_fitimage_initramfs. - # This happens after the generation of the initramfs bundle (done by do_bundle_initramfs). - # So, at the level of the install task we should not try to install the fitImage. fitImage is still not - # generated yet. - # After the generation of the fitImage, the deploy task copies the fitImage from the build directory to - # the deploy folder. + # bundle_initramfs runs after do_install before do_deploy. do_deploy does what's needed therefore. # - for imageType in ${KERNEL_IMAGETYPES} ; do - if [ $imageType != "fitImage" ] || [ "${INITRAMFS_IMAGE_BUNDLE}" != "1" ] ; then + if [ "${INITRAMFS_IMAGE_BUNDLE}" != "1" ] ; then install -m 0644 ${KERNEL_OUTPUT_DIR}/$imageType ${D}/${KERNEL_IMAGEDEST}/$imageType-${KERNEL_VERSION} fi done @@ -843,11 +840,8 @@ kernel_do_deploy() { fi fi - if [ ! -z "${INITRAMFS_IMAGE}" -a x"${INITRAMFS_IMAGE_BUNDLE}" = x1 ]; then + if [ -n "${INITRAMFS_IMAGE}" ] && [ "${INITRAMFS_IMAGE_BUNDLE}" = "1" ]; then for imageType in ${KERNEL_IMAGETYPES} ; do - if [ "$imageType" = "fitImage" ] ; then - continue - fi initramfsBaseName=$imageType-${INITRAMFS_NAME} install -m 0644 ${KERNEL_OUTPUT_DIR}/$imageType.initramfs $deployDir/$initramfsBaseName${KERNEL_IMAGE_BIN_EXT} if [ -n "${INITRAMFS_LINK_NAME}" ] ; then From patchwork Sun May 4 13:05:03 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Freihofer, Adrian" X-Patchwork-Id: 62403 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from aws-us-west-2-korg-lkml-1.web.codeaurora.org (localhost.localdomain [127.0.0.1]) by smtp.lore.kernel.org (Postfix) with ESMTP id 2FD98C3ABBF for ; Sun, 4 May 2025 13:07:09 +0000 (UTC) Received: from mta-64-226.siemens.flowmailer.net (mta-64-226.siemens.flowmailer.net [185.136.64.226]) by mx.groups.io with SMTP id smtpd.web10.28201.1746364017481237771 for ; Sun, 04 May 2025 06:06:59 -0700 Authentication-Results: mx.groups.io; dkim=pass header.i=adrian.freihofer@siemens.com header.s=fm1 header.b=bjHzEvXE; spf=pass (domain: rts-flowmailer.siemens.com, ip: 185.136.64.226, mailfrom: fm-1329275-202505041306581ed23489ddc3bfcde9-kiy0bi@rts-flowmailer.siemens.com) Received: by mta-64-226.siemens.flowmailer.net with ESMTPSA id 202505041306581ed23489ddc3bfcde9 for ; Sun, 04 May 2025 15:06:58 +0200 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; s=fm1; d=siemens.com; i=adrian.freihofer@siemens.com; h=Date:From:Subject:To:Message-ID:MIME-Version:Content-Type:Content-Transfer-Encoding:Cc:References:In-Reply-To; bh=ZYGwuKhF3GivE86LyVewHPwUHatAdAMJeGgfP5XneAM=; b=bjHzEvXEiCC91tFcjVkgUXkZTojkiGCUBgGCWeYsCWfEuLwBcgbsc+Jh5JJvC9xk6m0zNh fFcFO3n0Ind+r1d7tCAn7YhXCLFDfMhv0asVkKnX7ZK8pcAThkg/trpH8Xv2+Q2nPF0G30jB kc7Fk+U+t3cKbiv8Gpd5NI304jSU/tOqPqC6ZjULDLhPhwkn0UXpBiIrr9aTwlGJOtuTvpWP GiPOILBWV2tCexd77ouT88jf4QBb2u3MkbpSIw3VkXbjvytEF7evQRuaHLS9RCxfXml29hkN Bn0NsA8KvqpeijcK2utPGkfP7fDOrqEuHjoINErPBs9Ov1Gw6Odz802g==; From: AdrianF To: openembedded-core@lists.openembedded.org Cc: marex@denx.de, l.anderweit@phytec.de, richard.purdie@linuxfoundation.org, ross.burton@arm.com, bruce.ashfield@gmail.com, rogerio.borin@toradex.com, sean.anderson@seco.com, m.felsch@pengutronix.de, ejo@pengutronix.de, Adrian Freihofer Subject: [PATCH 16/20] oe-selftest: fitimage: remove kernel-fitimage tests Date: Sun, 4 May 2025 15:05:03 +0200 Message-ID: <20250504130507.717954-16-adrian.freihofer@siemens.com> In-Reply-To: <20250504130507.717954-1-adrian.freihofer@siemens.com> References: <20250504130507.717954-1-adrian.freihofer@siemens.com> MIME-Version: 1.0 X-Flowmailer-Platform: Siemens Feedback-ID: 519:519-1329275:519-21489:flowmailer List-Id: X-Webhook-Received: from li982-79.members.linode.com [45.33.32.79] by aws-us-west-2-korg-lkml-1.web.codeaurora.org with HTTPS for ; Sun, 04 May 2025 13:07:09 -0000 X-Groupsio-URL: https://lists.openembedded.org/g/openembedded-core/message/215956 From: Adrian Freihofer Remove the test cases for the kernel-fitimage.bbclass. The _config_add_kernel_classes function is no longer needed since the kernel-fitimage.bbclass is no longer handled. Signed-off-by: Adrian Freihofer --- meta/lib/oeqa/selftest/cases/fitimage.py | 25 ------------------------ 1 file changed, 25 deletions(-) diff --git a/meta/lib/oeqa/selftest/cases/fitimage.py b/meta/lib/oeqa/selftest/cases/fitimage.py index 47619539073..aa6870278ae 100644 --- a/meta/lib/oeqa/selftest/cases/fitimage.py +++ b/meta/lib/oeqa/selftest/cases/fitimage.py @@ -415,11 +415,6 @@ class KernelFitImageBase(FitImageTestCase): self.logger.debug("bb_vars: %s" % pprint.pformat(bb_vars, indent=4)) return bb_vars - def _config_add_kernel_classes(self, config): - config += '# Avoid naming clashes in the deploy folder with kernel-fitimage.bbclass artifacts' + os.linesep - config += 'KERNEL_DEPLOYSUBDIR:pn-linux-yocto-fitimage = "linux-yocto-fitimage"' + os.linesep - return config - @property def kernel_recipe(self): return "linux-yocto-fitimage" @@ -729,7 +724,6 @@ UBOOT_LOADADDRESS = "0x80080000" UBOOT_ENTRYPOINT = "0x80080000" FIT_DESC = "A model description" """ - config = self._config_add_kernel_classes(config) self.write_config(config) bb_vars = self._fit_get_bb_vars() self._test_fitimage(bb_vars) @@ -748,7 +742,6 @@ MACHINE = "beaglebone-yocto" # Add a devicetree overlay which does not need kernel sources PREFERRED_PROVIDER_virtual/dtb = "bborg-relay-00a2" """ - config = self._config_add_kernel_classes(config) config = self._config_add_uboot_env(config) self.write_config(config) bb_vars = self._fit_get_bb_vars() @@ -778,7 +771,6 @@ UBOOT_SIGN_KEYDIR = "${TOPDIR}/signing-keys" UBOOT_SIGN_KEYNAME = "dev" UBOOT_MKIMAGE_SIGN_ARGS = "-c 'a smart comment'" """ - config = self._config_add_kernel_classes(config) config = self._config_add_uboot_env(config) self.write_config(config) @@ -831,7 +823,6 @@ UBOOT_SIGN_KEYNAME = "cfg-oe-selftest" FIT_SIGN_INDIVIDUAL = "1" UBOOT_MKIMAGE_SIGN_ARGS = "-c 'a smart comment'" """ - config = self._config_add_kernel_classes(config) config = self._config_add_uboot_env(config) self.write_config(config) bb_vars = self._fit_get_bb_vars() @@ -876,7 +867,6 @@ KERNEL_IMAGETYPE_REPLACEMENT = "zImage" FIT_KERNEL_COMP_ALG = "none" FIT_HASH_ALG = "sha256" """ - config = self._config_add_kernel_classes(config) config = self._config_add_uboot_env(config) self.write_config(config) @@ -933,26 +923,11 @@ KERNEL_IMAGETYPE_REPLACEMENT = "zImage" FIT_KERNEL_COMP_ALG = "none" FIT_HASH_ALG = "sha256" """ - config = self._config_add_kernel_classes(config) config = self._config_add_uboot_env(config) self.write_config(config) bb_vars = self._fit_get_bb_vars() self._test_fitimage(bb_vars) -class KernelFitImageTests(KernelFitImageRecipeTests): - """Test cases for the kernel-fitimage.bbclass""" - - @property - def kernel_recipe(self): - # virtual/kernel does not work with SRC_URI:append:pn-%s - return "linux-yocto" - - def _config_add_kernel_classes(self, config): - config += '# Use kernel-fitimage.bbclass for the creation of the fitImage' + os.linesep - config += 'KERNEL_IMAGETYPES += " fitImage "' + os.linesep - config += 'KERNEL_CLASSES = " kernel-fitimage "' + os.linesep - return config - class FitImagePyTests(KernelFitImageBase): """Test cases for the fitimage.py module without calling bitbake""" From patchwork Sun May 4 13:05:04 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Freihofer, Adrian" X-Patchwork-Id: 62405 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from aws-us-west-2-korg-lkml-1.web.codeaurora.org (localhost.localdomain [127.0.0.1]) by smtp.lore.kernel.org (Postfix) with ESMTP id 238F7C3ABBD for ; Sun, 4 May 2025 13:07:09 +0000 (UTC) Received: from mta-65-227.siemens.flowmailer.net (mta-65-227.siemens.flowmailer.net [185.136.65.227]) by mx.groups.io with SMTP id smtpd.web10.28204.1746364017644731354 for ; Sun, 04 May 2025 06:06:59 -0700 Authentication-Results: mx.groups.io; dkim=pass header.i=adrian.freihofer@siemens.com header.s=fm1 header.b=Jw8c7AAu; spf=pass (domain: rts-flowmailer.siemens.com, ip: 185.136.65.227, mailfrom: fm-1329275-202505041306582b5b0e1d36006dcd6e-ihgx2k@rts-flowmailer.siemens.com) Received: by mta-65-227.siemens.flowmailer.net with ESMTPSA id 202505041306582b5b0e1d36006dcd6e for ; Sun, 04 May 2025 15:06:58 +0200 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; s=fm1; d=siemens.com; i=adrian.freihofer@siemens.com; h=Date:From:Subject:To:Message-ID:MIME-Version:Content-Type:Content-Transfer-Encoding:Cc:References:In-Reply-To; bh=L+LeLi0NEJdNqP/9Vw0WPauX4rw4JCMW6AhxbbJLtWI=; b=Jw8c7AAuth8MHYNc70tmT8GZiRs6NO5tKfcbpBvA3rNRfZlltWy9sGIiKzGDEWZNDNwlK4 vUarcXfJjQX7/tLjAm8BMsh9I8LGDqJ9XxfcL/tDn97iRrZpgj5O56hD/N/NgzwXebJG/DY1 71ssWBeGgBoZ1Zy8hX+Fv1fhUaQOoIVFf9Ekns7mWRabKyqBiuiPcCVZ8omHjJte92NQWBa3 2FuH6ifNNQow3lpgUeuY7GkzxjwDzP1CPnEPuqn5X4wRe1hxrkGLLHjOPQ/O45+X9tI8olc/ l2bsnKkSIAlMo8rMg+S0IRNEUPCm+X3/GSN3qnHo3T5apDr9uYJa8j3A==; From: AdrianF To: openembedded-core@lists.openembedded.org Cc: marex@denx.de, l.anderweit@phytec.de, richard.purdie@linuxfoundation.org, ross.burton@arm.com, bruce.ashfield@gmail.com, rogerio.borin@toradex.com, sean.anderson@seco.com, m.felsch@pengutronix.de, ejo@pengutronix.de, Adrian Freihofer Subject: [PATCH 17/20] kernel-fitimage.bbclass: remove it Date: Sun, 4 May 2025 15:05:04 +0200 Message-ID: <20250504130507.717954-17-adrian.freihofer@siemens.com> In-Reply-To: <20250504130507.717954-1-adrian.freihofer@siemens.com> References: <20250504130507.717954-1-adrian.freihofer@siemens.com> MIME-Version: 1.0 X-Flowmailer-Platform: Siemens Feedback-ID: 519:519-1329275:519-21489:flowmailer List-Id: X-Webhook-Received: from li982-79.members.linode.com [45.33.32.79] by aws-us-west-2-korg-lkml-1.web.codeaurora.org with HTTPS for ; Sun, 04 May 2025 13:07:09 -0000 X-Groupsio-URL: https://lists.openembedded.org/g/openembedded-core/message/215958 From: Adrian Freihofer The integration of the FIT image-related build steps into the kernel recipe has proven to be not very good. The new implementation with kernel-fit-image.bbclass fixes some design issues: * sstate does not work well when a fitImage contains an initramfs. The kernel is rebuilt from scratch if the build runs from an empty TMPDIR. * A fitImage kernel is not available as a package, but all other kernel image types are. * The task dependencies in the kernel are very complex and difficult to debug if something goes wrong. As a separate, downstream recipe, this is now much easier. The long storry about this issue is here: [YOCTO #12912] Signed-off-by: Adrian Freihofer --- meta/classes-recipe/kernel-fitimage.bbclass | 310 -------------------- meta/classes-recipe/kernel-uboot.bbclass | 45 --- 2 files changed, 355 deletions(-) delete mode 100644 meta/classes-recipe/kernel-fitimage.bbclass diff --git a/meta/classes-recipe/kernel-fitimage.bbclass b/meta/classes-recipe/kernel-fitimage.bbclass deleted file mode 100644 index ba90bddb5f4..00000000000 --- a/meta/classes-recipe/kernel-fitimage.bbclass +++ /dev/null @@ -1,310 +0,0 @@ -# -# Copyright OpenEmbedded Contributors -# -# SPDX-License-Identifier: MIT -# - -inherit kernel-uboot kernel-artifact-names uboot-config -require conf/image-fitimage.conf - -def get_fit_replacement_type(d): - kerneltypes = d.getVar('KERNEL_IMAGETYPES') or "" - replacementtype = "" - if 'fitImage' in kerneltypes.split(): - uarch = d.getVar("UBOOT_ARCH") - if uarch == "arm64": - replacementtype = "Image" - elif uarch == "riscv": - replacementtype = "Image" - elif uarch == "mips": - replacementtype = "vmlinuz.bin" - elif uarch == "x86": - replacementtype = "bzImage" - elif uarch == "microblaze": - replacementtype = "linux.bin" - else: - replacementtype = "zImage" - return replacementtype - -KERNEL_IMAGETYPE_REPLACEMENT ?= "${@get_fit_replacement_type(d)}" -DEPENDS:append = " ${@'u-boot-tools-native dtc-native' if 'fitImage' in (d.getVar('KERNEL_IMAGETYPES') or '').split() else ''}" - -python __anonymous () { - # Override KERNEL_IMAGETYPE_FOR_MAKE variable, which is internal - # to kernel.bbclass . We have to override it, since we pack zImage - # (at least for now) into the fitImage . - typeformake = d.getVar("KERNEL_IMAGETYPE_FOR_MAKE") or "" - if 'fitImage' in typeformake.split(): - d.setVar('KERNEL_IMAGETYPE_FOR_MAKE', typeformake.replace('fitImage', d.getVar('KERNEL_IMAGETYPE_REPLACEMENT'))) - - image = d.getVar('INITRAMFS_IMAGE') - if image and not bb.utils.to_boolean(d.getVar('INITRAMFS_IMAGE_BUNDLE')): - if d.getVar('INITRAMFS_MULTICONFIG'): - mc = d.getVar('BB_CURRENT_MC') - d.appendVarFlag('do_assemble_fitimage_initramfs', 'mcdepends', ' mc:' + mc + ':${INITRAMFS_MULTICONFIG}:${INITRAMFS_IMAGE}:do_image_complete') - else: - d.appendVarFlag('do_assemble_fitimage_initramfs', 'depends', ' ${INITRAMFS_IMAGE}:do_image_complete') - - #check if there are any dtb providers - providerdtb = d.getVar("PREFERRED_PROVIDER_virtual/dtb") - if providerdtb: - d.appendVarFlag('do_assemble_fitimage', 'depends', ' virtual/dtb:do_populate_sysroot') - d.appendVarFlag('do_assemble_fitimage_initramfs', 'depends', ' virtual/dtb:do_populate_sysroot') - d.setVar('EXTERNAL_KERNEL_DEVICETREE', "${RECIPE_SYSROOT}/boot/devicetree") -} - -def fitimage_assemble(d, itsfile, fitname, ramdiskcount): - import shutil - import glob - import oe.fitimage - - DTBS="" - default_dtb_image="" - - for f in [itsfile, os.path.join("arch", d.getVar("ARCH"), "boot", fitname)]: - if os.path.exists(f): - os.remove(f) - - root_node = oe.fitimage.ItsNodeRootKernel( - d.getVar("FIT_DESC"), d.getVar("FIT_ADDRESS_CELLS"), - d.getVar('HOST_PREFIX'), d.getVar('UBOOT_ARCH'), d.getVar("FIT_CONF_PREFIX"), - d.getVar('UBOOT_SIGN_ENABLE') == "1", d.getVar("UBOOT_SIGN_KEYDIR"), - d.getVar("UBOOT_MKIMAGE"), d.getVar("UBOOT_MKIMAGE_DTCOPTS"), - d.getVar("UBOOT_MKIMAGE_SIGN"), d.getVar("UBOOT_MKIMAGE_SIGN_ARGS"), - d.getVar('FIT_HASH_ALG'), d.getVar('FIT_SIGN_ALG'), d.getVar('FIT_PAD_ALG'), - d.getVar('UBOOT_SIGN_KEYNAME'), - d.getVar('FIT_SIGN_INDIVIDUAL') == "1", d.getVar('UBOOT_SIGN_IMG_KEYNAME') - ) - - # - # Step 1: Prepare a kernel image section. - # - linux_comp = uboot_prep_kimage_py(d) - 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")) - - # - # Step 2: Prepare a DTB image section - # - if d.getVar("KERNEL_DEVICETREE"): - for DTB in d.getVar("KERNEL_DEVICETREE").split(): - if "/dts/" in DTB: - bb.warn(f"{DTB} contains the full path to the dts file, but only the dtb name should be used.") - DTB = os.path.basename(DTB).replace(".dts", ".dtb") - - # Skip DTB if it's also provided in EXTERNAL_KERNEL_DEVICETREE - if d.getVar("EXTERNAL_KERNEL_DEVICETREE"): - ext_dtb_path = os.path.join(d.getVar("EXTERNAL_KERNEL_DEVICETREE"), DTB) - if os.path.exists(ext_dtb_path) and os.path.getsize(ext_dtb_path) > 0: - continue - - DTB_PATH = os.path.join(d.getVar("KERNEL_OUTPUT_DIR"), "dts", DTB) - if not os.path.exists(DTB_PATH): - DTB_PATH = os.path.join(d.getVar("KERNEL_OUTPUT_DIR"), DTB) - - # Strip off the path component from the filename - if not oe.types.boolean(d.getVar("KERNEL_DTBVENDORED")): - DTB = os.path.basename(DTB) - - # Set the default dtb image if it exists in the devicetree. - if d.getVar("FIT_CONF_DEFAULT_DTB") == DTB: - default_dtb_image = DTB.replace("/", "_") - - DTB = DTB.replace("/", "_") - - # Skip DTB if we've picked it up previously - if DTB in DTBS.split(): - continue - - DTBS += " " + DTB - - root_node.fitimage_emit_section_dtb(DTB, DTB_PATH, - d.getVar("UBOOT_DTB_LOADADDRESS"), d.getVar("UBOOT_DTBO_LOADADDRESS")) - - if d.getVar("EXTERNAL_KERNEL_DEVICETREE"): - dtb_files = [] - for ext in ['*.dtb', '*.dtbo']: - dtb_files.extend(sorted(glob.glob(os.path.join(d.getVar("EXTERNAL_KERNEL_DEVICETREE"), ext)))) - - for dtb_path in dtb_files: - dtb_name = os.path.relpath(dtb_path, d.getVar("EXTERNAL_KERNEL_DEVICETREE")) - dtb_name_underscore = dtb_name.replace('/', '_') - - # Set the default dtb image if it exists in the devicetree. - if d.getVar("FIT_CONF_DEFAULT_DTB") == dtb_name: - default_dtb_image = dtb_name_underscore - - # Skip DTB/DTBO if we've picked it up previously - if dtb_name_underscore in DTBS.split(): - continue - - DTBS += " " + dtb_name_underscore - - # Also skip if a symlink. We'll later have each config section point at it - if oe.fitimage.symlink_points_below(dtb_name, d.getVar("EXTERNAL_KERNEL_DEVICETREE")): - continue - - root_node.fitimage_emit_section_dtb(dtb_name_underscore, dtb_path, - d.getVar("UBOOT_DTB_LOADADDRESS"), d.getVar("UBOOT_DTBO_LOADADDRESS")) - - if d.getVar("FIT_CONF_DEFAULT_DTB") and not default_dtb_image: - bb.warn("%s is not available in the list of device trees." % d.getVar('FIT_CONF_DEFAULT_DTB')) - - # - # Step 3: Prepare a u-boot script section - # - fit_uboot_env = d.getVar("FIT_UBOOT_ENV") - if fit_uboot_env: - unpack_dir = d.getVar("UNPACKDIR") - shutil.copy(os.path.join(unpack_dir, fit_uboot_env), fit_uboot_env) - root_node.fitimage_emit_section_boot_script("bootscr-"+fit_uboot_env , fit_uboot_env) - - # - # Step 4: Prepare a setup section. (For x86) - # - setup_bin_path = os.path.join(d.getVar("KERNEL_OUTPUT_DIR"), "setup.bin") - if os.path.exists(setup_bin_path): - root_node.fitimage_emit_section_setup("setup-1", setup_bin_path) - - # - # Step 5: Prepare a ramdisk section. - # - if ramdiskcount == 1 and d.getVar("INITRAMFS_IMAGE_BUNDLE") != "1": - # Find and use the first initramfs image archive type we find - found = False - for img in d.getVar("FIT_SUPPORTED_INITRAMFS_FSTYPES").split(): - initramfs_path = os.path.join(d.getVar("DEPLOY_DIR_IMAGE"), "%s.%s" % (d.getVar('INITRAMFS_IMAGE_NAME'), img)) - if os.path.exists(initramfs_path): - bb.note("Found initramfs image: " + initramfs_path) - found = True - root_node.fitimage_emit_section_ramdisk("ramdisk-%d" % ramdiskcount, initramfs_path, - d.getVar('INITRAMFS_IMAGE'), - d.getVar("UBOOT_RD_LOADADDRESS"), - d.getVar("UBOOT_RD_ENTRYPOINT")) - break - else: - bb.note("Did not find initramfs image: " + initramfs_path) - - if not found: - bb.fatal("Could not find a valid initramfs type for %s, the supported types are: %s" % (d.getVar('INITRAMFS_IMAGE_NAME'), d.getVar('FIT_SUPPORTED_INITRAMFS_FSTYPES'))) - - # Generate the configuration section - root_node.fitimage_emit_section_config() - - # - # Write the ITS file - root_node.write_its_file(itsfile) - - # - # Step 7: Assemble the image - # - fitfile = os.path.join(d.getVar("KERNEL_OUTPUT_DIR"), fitname) - root_node.run_mkimage_assemble(itsfile, fitfile) - - # - # Step 8: Sign the image if required - # - root_node.run_mkimage_sign(fitfile) - - -python do_assemble_fitimage() { - if "fitImage" in d.getVar("KERNEL_IMAGETYPES").split(): - os.chdir(d.getVar("B")) - fitimage_assemble(d, "fit-image.its", "fitImage-none", "") - if d.getVar("INITRAMFS_IMAGE_BUNDLE") != "1": - link_name = os.path.join(d.getVar("B"), d.getVar("KERNEL_OUTPUT_DIR"), "fitImage") - if os.path.islink(link_name): - os.unlink(link_name) - os.symlink("fitImage-none", link_name) -} - -addtask assemble_fitimage before do_install after do_compile - -do_install:append() { - if echo ${KERNEL_IMAGETYPES} | grep -wq "fitImage" && \ - [ "${UBOOT_SIGN_ENABLE}" = "1" ]; then - install -D ${B}/${KERNEL_OUTPUT_DIR}/fitImage-none ${D}/sysroot-only/fitImage - fi -} - -python do_assemble_fitimage_initramfs() { - if "fitImage" in d.getVar("KERNEL_IMAGETYPES").split() and d.getVar("INITRAMFS_IMAGE"): - os.chdir(d.getVar("B")) - if d.getVar("INITRAMFS_IMAGE_BUNDLE") == "1": - fitimage_assemble(d, "fit-image-%s.its" % d.getVar("INITRAMFS_IMAGE"), "fitImage-bundle", "") - link_name = os.path.join(d.getVar("B"), d.getVar("KERNEL_OUTPUT_DIR"), "fitImage") - if os.path.islink(link_name): - os.unlink(link_name) - os.symlink("fitImage-bundle", link_name) - else: - fitimage_assemble(d, "fit-image-%s.its" % d.getVar("INITRAMFS_IMAGE"), "fitImage-%s" % d.getVar("INITRAMFS_IMAGE"), 1) -} - -addtask assemble_fitimage_initramfs before do_deploy after do_bundle_initramfs - -python do_kernel_generate_rsa_keys() { - import oe.fitimage - - sign_enable = oe.types.boolean(d.getVar('UBOOT_SIGN_ENABLE')) - fit_generate_keys = oe.types.boolean(d.getVar('FIT_GENERATE_KEYS')) - if not sign_enable and fit_generate_keys: - bb.warn("FIT_GENERATE_KEYS is set to 1 even though UBOOT_SIGN_ENABLE is set to 0. The keys will not be generated as they won't be used.") - if sign_enable and fit_generate_keys: - sign_keydir = d.getVar('UBOOT_SIGN_KEYDIR') - sign_keyname = d.getVar('UBOOT_SIGN_KEYNAME') - sign_kc_path = os.path.join(sign_keydir, sign_keyname) - if not os.path.exists(sign_kc_path + '.key') or not os.path.exists(sign_kc_path + '.crt'): - bb.note("Generating RSA private key and certificate for signing fitImage configurations") - oe.fitimage.generate_rsa_key(sign_keydir, sign_keyname, - d.getVar('FIT_SIGN_NUMBITS'), d.getVar('FIT_KEY_GENRSA_ARGS'), - d.getVar('FIT_KEY_REQ_ARGS'), d.getVar('FIT_KEY_SIGN_PKCS')) - - if oe.types.boolean(d.getVar('FIT_SIGN_INDIVIDUAL')): - sign_img_keyname = d.getVar('UBOOT_SIGN_IMG_KEYNAME') - sign_img_kc_path = os.path.join(sign_keydir, sign_img_keyname) - if not os.path.exists(sign_img_kc_path + '.key') or not os.path.exists(sign_img_kc_path + '.crt'): - bb.note("Generating RSA private key and certificate for signing fitImage individual images") - oe.fitimage.generate_rsa_key(sign_keydir, sign_img_keyname, - d.getVar('FIT_SIGN_NUMBITS'), d.getVar('FIT_KEY_GENRSA_ARGS'), - d.getVar('FIT_KEY_REQ_ARGS'), d.getVar('FIT_KEY_SIGN_PKCS')) -} - -addtask kernel_generate_rsa_keys before do_assemble_fitimage after do_compile - -kernel_do_deploy[vardepsexclude] = "DATETIME" -kernel_do_deploy:append() { - # Update deploy directory - if echo ${KERNEL_IMAGETYPES} | grep -wq "fitImage"; then - - if [ "${INITRAMFS_IMAGE_BUNDLE}" != "1" ]; then - bbnote "Copying fit-image.its source file..." - install -m 0644 ${B}/fit-image.its "$deployDir/fitImage-its-${KERNEL_FIT_NAME}.its" - if [ -n "${KERNEL_FIT_LINK_NAME}" ] ; then - ln -snf fitImage-its-${KERNEL_FIT_NAME}.its "$deployDir/fitImage-its-${KERNEL_FIT_LINK_NAME}" - fi - - bbnote "Copying linux.bin file..." - install -m 0644 ${B}/linux.bin $deployDir/fitImage-linux.bin-${KERNEL_FIT_NAME}${KERNEL_FIT_BIN_EXT} - if [ -n "${KERNEL_FIT_LINK_NAME}" ] ; then - ln -snf fitImage-linux.bin-${KERNEL_FIT_NAME}${KERNEL_FIT_BIN_EXT} "$deployDir/fitImage-linux.bin-${KERNEL_FIT_LINK_NAME}" - fi - fi - - if [ -n "${INITRAMFS_IMAGE}" ]; then - bbnote "Copying fit-image-${INITRAMFS_IMAGE}.its source file..." - install -m 0644 ${B}/fit-image-${INITRAMFS_IMAGE}.its "$deployDir/fitImage-its-${INITRAMFS_IMAGE_NAME}-${KERNEL_FIT_NAME}.its" - if [ -n "${KERNEL_FIT_LINK_NAME}" ] ; then - ln -snf fitImage-its-${INITRAMFS_IMAGE_NAME}-${KERNEL_FIT_NAME}.its "$deployDir/fitImage-its-${INITRAMFS_IMAGE_NAME}-${KERNEL_FIT_LINK_NAME}" - fi - - if [ "${INITRAMFS_IMAGE_BUNDLE}" != "1" ]; then - bbnote "Copying fitImage-${INITRAMFS_IMAGE} file..." - install -m 0644 ${B}/${KERNEL_OUTPUT_DIR}/fitImage-${INITRAMFS_IMAGE} "$deployDir/fitImage-${INITRAMFS_IMAGE_NAME}-${KERNEL_FIT_NAME}${KERNEL_FIT_BIN_EXT}" - if [ -n "${KERNEL_FIT_LINK_NAME}" ] ; then - ln -snf fitImage-${INITRAMFS_IMAGE_NAME}-${KERNEL_FIT_NAME}${KERNEL_FIT_BIN_EXT} "$deployDir/fitImage-${INITRAMFS_IMAGE_NAME}-${KERNEL_FIT_LINK_NAME}" - fi - fi - fi - fi -} diff --git a/meta/classes-recipe/kernel-uboot.bbclass b/meta/classes-recipe/kernel-uboot.bbclass index 888664678d1..7aafd4757c2 100644 --- a/meta/classes-recipe/kernel-uboot.bbclass +++ b/meta/classes-recipe/kernel-uboot.bbclass @@ -67,48 +67,3 @@ do_install:append() { install -D ${B}/${KERNEL_OUTPUT_DIR}/setup.bin ${D}/sysroot-only/setup.bin fi } - -def uboot_prep_kimage_py(d): - import subprocess - - arch = d.getVar('ARCH') - initramfs_image_bundle = d.getVar('INITRAMFS_IMAGE_BUNDLE') - fit_kernel_comp_alg = d.getVar('FIT_KERNEL_COMP_ALG') or 'gzip' - fit_kernel_comp_alg_extension = d.getVar('FIT_KERNEL_COMP_ALG_EXTENSION') or '.gz' - kernel_objcopy = d.getVar('KERNEL_OBJCOPY') - - vmlinux_path = "" - linux_suffix = "" - linux_comp = "none" - - if os.path.exists(f'arch/{arch}/boot/compressed/vmlinux'): - vmlinux_path = f'arch/{arch}/boot/compressed/vmlinux' - elif os.path.exists(f'arch/{arch}/boot/vmlinuz.bin'): - if os.path.exists('linux.bin'): - os.remove('linux.bin') - os.link(f'arch/{arch}/boot/vmlinuz.bin', 'linux.bin') - else: - vmlinux_path = 'vmlinux' - # Use vmlinux.initramfs for linux.bin when INITRAMFS_IMAGE_BUNDLE set - # As per the implementation in kernel.bbclass. - # See do_bundle_initramfs function - if initramfs_image_bundle == '1' and os.path.exists('vmlinux.initramfs'): - vmlinux_path = 'vmlinux.initramfs' - linux_suffix = fit_kernel_comp_alg_extension - linux_comp = fit_kernel_comp_alg - - if vmlinux_path: - subprocess.run([kernel_objcopy.strip(), '-O', 'binary', '-R', '.note', '-R', '.comment', '-S', os.path.abspath(vmlinux_path), 'linux.bin'], check=True) - # if ret.returncode != 0: - # bb.fatal(f"Error: stderr: {ret.stderr.decode('utf-8')} stdout: {ret.stdout.decode('utf-8')}, vmlinux_path: {os.path.abspath(vmlinux_path)}, pwd: {os.getcwd()}, args: {ret.args}") - - if linux_comp != "none": - if linux_comp == "gzip": - subprocess.run(['gzip', '-9', 'linux.bin'], check=True) - elif linux_comp == "lzo": - subprocess.run(['lzop', '-9', 'linux.bin'], check=True) - elif linux_comp == "lzma": - subprocess.run(['xz', '--format=lzma', '-f', '-6', 'linux.bin'], check=True) - os.rename(f'linux.bin{linux_suffix}', 'linux.bin') - - return linux_comp From patchwork Sun May 4 13:05:05 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Freihofer, Adrian" X-Patchwork-Id: 62402 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from aws-us-west-2-korg-lkml-1.web.codeaurora.org (localhost.localdomain [127.0.0.1]) by smtp.lore.kernel.org (Postfix) with ESMTP id 1A5A2C3ABBB for ; Sun, 4 May 2025 13:07:09 +0000 (UTC) Received: from mta-64-226.siemens.flowmailer.net (mta-64-226.siemens.flowmailer.net [185.136.64.226]) by mx.groups.io with SMTP id smtpd.web11.28297.1746364018399646036 for ; Sun, 04 May 2025 06:06:59 -0700 Authentication-Results: mx.groups.io; dkim=pass header.i=adrian.freihofer@siemens.com header.s=fm1 header.b=KuFrTyle; spf=pass (domain: rts-flowmailer.siemens.com, ip: 185.136.64.226, mailfrom: fm-1329275-2025050413065976106ab09aa9a065e1-ymof7u@rts-flowmailer.siemens.com) Received: by mta-64-226.siemens.flowmailer.net with ESMTPSA id 2025050413065976106ab09aa9a065e1 for ; Sun, 04 May 2025 15:06:59 +0200 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; s=fm1; d=siemens.com; i=adrian.freihofer@siemens.com; h=Date:From:Subject:To:Message-ID:MIME-Version:Content-Type:Content-Transfer-Encoding:Cc:References:In-Reply-To; bh=WqFkUcHuRoIWxhdLDP4pRqY//pRB5VYYNsEd87Pc6fg=; b=KuFrTylegR6H5teFGm/qD+HX1d7Mg5kUq7rg3ShcrvkLJUeLZK9y6fTUCPyjyYnYCyJ+QR ee8+svIHcweCbS0Fg/rlS/MyGTUKkNJZd2gOU6PwvnAaO2Xq8eGhRUIptS4B/btHWsUhSyot bFCsOFbayFC5Bz9GpqFpHnr/4gld10VtO8DMSaNzj00YEwPVN4m2GFtaPtLcwEawQHV0GQBN oTe2byWcLr6DP+0FZ2PAOZn6Pwupe3iEyZQzSnrUpB5YTo5uavhazepCBIu9wMH51pbG//Jt a3B7KG2zOQEyzdhO/rhn+2tXzqjD1YdIX/alaK0jKoXkhtZ0RUEnLkng==; From: AdrianF To: openembedded-core@lists.openembedded.org Cc: marex@denx.de, l.anderweit@phytec.de, richard.purdie@linuxfoundation.org, ross.burton@arm.com, bruce.ashfield@gmail.com, rogerio.borin@toradex.com, sean.anderson@seco.com, m.felsch@pengutronix.de, ejo@pengutronix.de, Adrian Freihofer Subject: [PATCH 18/20] kernel-uboot.bbclass: merge it into kernel-uimage.bbclass Date: Sun, 4 May 2025 15:05:05 +0200 Message-ID: <20250504130507.717954-18-adrian.freihofer@siemens.com> In-Reply-To: <20250504130507.717954-1-adrian.freihofer@siemens.com> References: <20250504130507.717954-1-adrian.freihofer@siemens.com> MIME-Version: 1.0 X-Flowmailer-Platform: Siemens Feedback-ID: 519:519-1329275:519-21489:flowmailer List-Id: X-Webhook-Received: from li982-79.members.linode.com [45.33.32.79] by aws-us-west-2-korg-lkml-1.web.codeaurora.org with HTTPS for ; Sun, 04 May 2025 13:07:09 -0000 X-Groupsio-URL: https://lists.openembedded.org/g/openembedded-core/message/215959 From: Adrian Freihofer After the kernel-fitimage.bbclass has been removed, the kernel-uimage.bbclass is the only user of the kernel-uboot.bbclass. Simplify the implementation by merging these two classes into one. Until "uImage" is in KERNEL_IMAGETYPES the kernel-uimage.bbclass does nothing else than exporting the artifiacts which are required for creating the fitImage. It should also be remembered that the kernel.bbclass inherits the kernel-uimage.bbclass by default: KERNEL_CLASSES ?= " kernel-uimage " Signed-off-by: Adrian Freihofer --- meta/classes-recipe/kernel-uboot.bbclass | 69 ---------------------- meta/classes-recipe/kernel-uimage.bbclass | 71 +++++++++++++++++++++-- 2 files changed, 67 insertions(+), 73 deletions(-) delete mode 100644 meta/classes-recipe/kernel-uboot.bbclass diff --git a/meta/classes-recipe/kernel-uboot.bbclass b/meta/classes-recipe/kernel-uboot.bbclass deleted file mode 100644 index 7aafd4757c2..00000000000 --- a/meta/classes-recipe/kernel-uboot.bbclass +++ /dev/null @@ -1,69 +0,0 @@ -# -# Copyright OpenEmbedded Contributors -# -# SPDX-License-Identifier: MIT -# - -# fitImage kernel compression algorithm -FIT_KERNEL_COMP_ALG ?= "gzip" -FIT_KERNEL_COMP_ALG_EXTENSION ?= ".gz" - -# Kernel image type passed to mkimage (i.e. kernel kernel_noload...) -UBOOT_MKIMAGE_KERNEL_TYPE ?= "kernel" - -uboot_prep_kimage() { - output_dir=$1 - # For backward compatibility with kernel-fitimage.bbclass and kernel-uboot.bbclass - # support calling without parameter as well - if [ -z "$output_dir" ]; then - output_dir='.' - fi - - linux_bin=$output_dir/linux.bin - if [ -e "arch/${ARCH}/boot/compressed/vmlinux" ]; then - vmlinux_path="arch/${ARCH}/boot/compressed/vmlinux" - linux_suffix="" - linux_comp="none" - elif [ -e "arch/${ARCH}/boot/vmlinuz.bin" ]; then - rm -f "$linux_bin" - cp -l "arch/${ARCH}/boot/vmlinuz.bin" "$linux_bin" - vmlinux_path="" - linux_suffix="" - linux_comp="none" - else - vmlinux_path="vmlinux" - # Use vmlinux.initramfs for $linux_bin when INITRAMFS_IMAGE_BUNDLE set - # As per the implementation in kernel.bbclass. - # See do_bundle_initramfs function - if [ "${INITRAMFS_IMAGE_BUNDLE}" = "1" ] && [ -e vmlinux.initramfs ]; then - vmlinux_path="vmlinux.initramfs" - fi - linux_suffix="${FIT_KERNEL_COMP_ALG_EXTENSION}" - linux_comp="${FIT_KERNEL_COMP_ALG}" - fi - - [ -n "$vmlinux_path" ] && ${KERNEL_OBJCOPY} -O binary -R .note -R .comment -S "$vmlinux_path" "$linux_bin" - - if [ "$linux_comp" != "none" ] ; then - if [ "$linux_comp" = "gzip" ] ; then - gzip -9 "$linux_bin" - elif [ "$linux_comp" = "lzo" ] ; then - lzop -9 "$linux_bin" - elif [ "$linux_comp" = "lzma" ] ; then - xz --format=lzma -f -6 "$linux_bin" - fi - mv -f "$linux_bin$linux_suffix" "$linux_bin" - fi - - printf "$linux_comp" > "$output_dir/linux_comp" -} - -do_install:append() { - # Provide the kernel artifacts to post processing recipes e.g. for creating a FIT image - install -d ${D}/sysroot-only - uboot_prep_kimage ${D}/sysroot-only - # For x86 a setup.bin needs to be included in a fitImage as well - if [ -e ${KERNEL_OUTPUT_DIR}/setup.bin ]; then - install -D ${B}/${KERNEL_OUTPUT_DIR}/setup.bin ${D}/sysroot-only/setup.bin - fi -} diff --git a/meta/classes-recipe/kernel-uimage.bbclass b/meta/classes-recipe/kernel-uimage.bbclass index e353232a0e9..f04a2c6d691 100644 --- a/meta/classes-recipe/kernel-uimage.bbclass +++ b/meta/classes-recipe/kernel-uimage.bbclass @@ -4,7 +4,13 @@ # SPDX-License-Identifier: MIT # -inherit kernel-uboot +# fitImage kernel compression algorithm +FIT_KERNEL_COMP_ALG ?= "gzip" +FIT_KERNEL_COMP_ALG_EXTENSION ?= ".gz" + +# Kernel image type passed to mkimage (i.e. kernel kernel_noload...) +UBOOT_MKIMAGE_KERNEL_TYPE ?= "kernel" + python __anonymous () { if "uImage" in d.getVar('KERNEL_IMAGETYPES'): @@ -26,10 +32,67 @@ python __anonymous () { bb.build.addtask('do_uboot_mkimage', 'do_install', 'do_kernel_link_images', d) } +uboot_prep_kimage() { + output_dir=$1 + # For backward compatibility with kernel-fitimage.bbclass and kernel-uboot.bbclass + # support calling without parameter as well + if [ -z "$output_dir" ]; then + output_dir='.' + fi + + linux_bin=$output_dir/linux.bin + if [ -e "arch/${ARCH}/boot/compressed/vmlinux" ]; then + vmlinux_path="arch/${ARCH}/boot/compressed/vmlinux" + linux_suffix="" + linux_comp="none" + elif [ -e "arch/${ARCH}/boot/vmlinuz.bin" ]; then + rm -f "$linux_bin" + cp -l "arch/${ARCH}/boot/vmlinuz.bin" "$linux_bin" + vmlinux_path="" + linux_suffix="" + linux_comp="none" + else + vmlinux_path="vmlinux" + # Use vmlinux.initramfs for $linux_bin when INITRAMFS_IMAGE_BUNDLE set + # As per the implementation in kernel.bbclass. + # See do_bundle_initramfs function + if [ "${INITRAMFS_IMAGE_BUNDLE}" = "1" ] && [ -e vmlinux.initramfs ]; then + vmlinux_path="vmlinux.initramfs" + fi + linux_suffix="${FIT_KERNEL_COMP_ALG_EXTENSION}" + linux_comp="${FIT_KERNEL_COMP_ALG}" + fi + + [ -n "$vmlinux_path" ] && ${KERNEL_OBJCOPY} -O binary -R .note -R .comment -S "$vmlinux_path" "$linux_bin" + + if [ "$linux_comp" != "none" ] ; then + if [ "$linux_comp" = "gzip" ] ; then + gzip -9 "$linux_bin" + elif [ "$linux_comp" = "lzo" ] ; then + lzop -9 "$linux_bin" + elif [ "$linux_comp" = "lzma" ] ; then + xz --format=lzma -f -6 "$linux_bin" + fi + mv -f "$linux_bin$linux_suffix" "$linux_bin" + fi + + printf "$linux_comp" > "$output_dir/linux_comp" +} + +do_install:append() { + # Provide the kernel artifacts to post processing recipes e.g. for creating a FIT image + install -d ${D}/sysroot-only + uboot_prep_kimage ${D}/sysroot-only + # For x86 a setup.bin needs to be included in a fitImage as well + if [ -e ${KERNEL_OUTPUT_DIR}/setup.bin ]; then + install -D ${B}/${KERNEL_OUTPUT_DIR}/setup.bin ${D}/sysroot-only/setup.bin + fi +} + do_uboot_mkimage[dirs] += "${B}" do_uboot_mkimage() { - uboot_prep_kimage - linux_comp="$(cat linux_comp)" + linux_bin=${D}/sysroot-only/setup.bin + linux_comp=$(cat "${D}/sysroot-only/linux_comp") ENTRYPOINT=${UBOOT_ENTRYPOINT} if [ -n "${UBOOT_ENTRYSYMBOL}" ]; then @@ -37,6 +100,6 @@ do_uboot_mkimage() { awk '$3=="${UBOOT_ENTRYSYMBOL}" {print "0x"$1;exit}'` fi - uboot-mkimage -A ${UBOOT_ARCH} -O linux -T ${UBOOT_MKIMAGE_KERNEL_TYPE} -C "$linux_comp" -a ${UBOOT_LOADADDRESS} -e $ENTRYPOINT -n "${DISTRO_NAME}/${PV}/${MACHINE}" -d linux.bin ${B}/arch/${ARCH}/boot/uImage + uboot-mkimage -A ${UBOOT_ARCH} -O linux -T ${UBOOT_MKIMAGE_KERNEL_TYPE} -C "$linux_comp" -a ${UBOOT_LOADADDRESS} -e $ENTRYPOINT -n "${DISTRO_NAME}/${PV}/${MACHINE}" -d "$linux_bin" ${B}/arch/${ARCH}/boot/uImage rm -f linux.bin } From patchwork Sun May 4 13:05:06 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Freihofer, Adrian" X-Patchwork-Id: 62399 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from aws-us-west-2-korg-lkml-1.web.codeaurora.org (localhost.localdomain [127.0.0.1]) by smtp.lore.kernel.org (Postfix) with ESMTP id 0ABB7C3ABB9 for ; Sun, 4 May 2025 13:07:09 +0000 (UTC) Received: from mta-64-228.siemens.flowmailer.net (mta-64-228.siemens.flowmailer.net [185.136.64.228]) by mx.groups.io with SMTP id smtpd.web11.28299.1746364018885948097 for ; Sun, 04 May 2025 06:07:00 -0700 Authentication-Results: mx.groups.io; dkim=pass header.i=adrian.freihofer@siemens.com header.s=fm1 header.b=GAlFaec3; spf=pass (domain: rts-flowmailer.siemens.com, ip: 185.136.64.228, mailfrom: fm-1329275-20250504130659ba36202315f6ffc016-olo2_t@rts-flowmailer.siemens.com) Received: by mta-64-228.siemens.flowmailer.net with ESMTPSA id 20250504130659ba36202315f6ffc016 for ; Sun, 04 May 2025 15:06:59 +0200 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; s=fm1; d=siemens.com; i=adrian.freihofer@siemens.com; h=Date:From:Subject:To:Message-ID:MIME-Version:Content-Type:Content-Transfer-Encoding:Cc:References:In-Reply-To; bh=irHqTj40L+AbdW3dQZ/Dz/0JRmYvGWHu/1MbO1hbycA=; b=GAlFaec3HOuS+0tg2AaWMQPvWE5M6J1qeWoMmiR8fbdRq9S82Ra+jfBN5ewUqZETnWWVZq ZVv/npWUpNl678kIje+IPD+9wi+5eGyM9mRh2MGiKjaKv0we+DHMY9uNoDFXZl34vBfwWZDa SHTfBs+wLmOBlV+PY36HMhVZ7Z8FTdZBYma9FZMH/6NHCEHmFSVeuxzuRUtNITYNkCtHXS/u qV/+0+2iPtfnF0a0Jj+oviUJYGuTUqAZIavRYfqFntB/6ya3e1ivexwxiZ2NiGLrl1kCnd7r pXEZRgVy780bNphyD55NnHhkyf4v5p6eEwfF0GZ2oxSUlBh5cIgFkpwg==; From: AdrianF To: openembedded-core@lists.openembedded.org Cc: marex@denx.de, l.anderweit@phytec.de, richard.purdie@linuxfoundation.org, ross.burton@arm.com, bruce.ashfield@gmail.com, rogerio.borin@toradex.com, sean.anderson@seco.com, m.felsch@pengutronix.de, ejo@pengutronix.de, Adrian Freihofer Subject: [PATCH 19/20] oe-selftest: fitimage: drop initramfs bundle test Date: Sun, 4 May 2025 15:05:06 +0200 Message-ID: <20250504130507.717954-19-adrian.freihofer@siemens.com> In-Reply-To: <20250504130507.717954-1-adrian.freihofer@siemens.com> References: <20250504130507.717954-1-adrian.freihofer@siemens.com> MIME-Version: 1.0 X-Flowmailer-Platform: Siemens Feedback-ID: 519:519-1329275:519-21489:flowmailer List-Id: X-Webhook-Received: from li982-79.members.linode.com [45.33.32.79] by aws-us-west-2-korg-lkml-1.web.codeaurora.org with HTTPS for ; Sun, 04 May 2025 13:07:09 -0000 X-Groupsio-URL: https://lists.openembedded.org/g/openembedded-core/message/215961 From: Adrian Freihofer This test case is no longer useful. Sure, it is possible to build a kernel with an initramfs bundled. But since this is not the kernel which gets included into the FIT image, there is no need for testing this as part of the FIT image test suite. Signed-off-by: Adrian Freihofer --- meta/lib/oeqa/selftest/cases/fitimage.py | 42 ------------------------ 1 file changed, 42 deletions(-) diff --git a/meta/lib/oeqa/selftest/cases/fitimage.py b/meta/lib/oeqa/selftest/cases/fitimage.py index aa6870278ae..d7d850a1324 100644 --- a/meta/lib/oeqa/selftest/cases/fitimage.py +++ b/meta/lib/oeqa/selftest/cases/fitimage.py @@ -885,48 +885,6 @@ FIT_HASH_ALG = "sha256" self._test_fitimage(bb_vars) - def test_fit_image_sign_initramfs_bundle(self): - """ - Summary: Verifies the content of the initramfs bundle node in the FIT Image Tree Source (its) - The FIT settings are set by the test case. - The machine used is beaglebone-yocto. - Expected: 1. The ITS is generated with initramfs bundle support - 2. All the fields in the kernel node are as expected (matching the - conf settings) - 3. The kernel is included in all the available configurations and - its hash is included in the configuration signature - - Product: oe-core - Author: Abdellatif El Khlifi - """ - - config = """ -DISTRO="poky" -MACHINE = "beaglebone-yocto" -INITRAMFS_IMAGE_BUNDLE = "1" -INITRAMFS_IMAGE = "core-image-minimal-initramfs" -INITRAMFS_SCRIPTS = "" -UBOOT_MACHINE = "am335x_evm_defconfig" -UBOOT_SIGN_ENABLE = "1" -UBOOT_SIGN_KEYNAME = "beaglebonekey" -UBOOT_SIGN_KEYDIR ?= "${DEPLOY_DIR_IMAGE}" -UBOOT_DTB_BINARY = "u-boot.dtb" -UBOOT_ENTRYPOINT = "0x80000000" -UBOOT_LOADADDRESS = "0x80000000" -UBOOT_DTB_LOADADDRESS = "0x82000000" -UBOOT_ARCH = "arm" -UBOOT_MKIMAGE_DTCOPTS = "-I dts -O dtb -p 2000" -UBOOT_MKIMAGE_KERNEL_TYPE = "kernel" -UBOOT_EXTLINUX = "0" -FIT_GENERATE_KEYS = "1" -KERNEL_IMAGETYPE_REPLACEMENT = "zImage" -FIT_KERNEL_COMP_ALG = "none" -FIT_HASH_ALG = "sha256" -""" - config = self._config_add_uboot_env(config) - self.write_config(config) - bb_vars = self._fit_get_bb_vars() - self._test_fitimage(bb_vars) class FitImagePyTests(KernelFitImageBase): """Test cases for the fitimage.py module without calling bitbake""" From patchwork Sun May 4 13:05:07 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Freihofer, Adrian" X-Patchwork-Id: 62397 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from aws-us-west-2-korg-lkml-1.web.codeaurora.org (localhost.localdomain [127.0.0.1]) by smtp.lore.kernel.org (Postfix) with ESMTP id EBC30C369DC for ; Sun, 4 May 2025 13:07:08 +0000 (UTC) Received: from mta-64-226.siemens.flowmailer.net (mta-64-226.siemens.flowmailer.net [185.136.64.226]) by mx.groups.io with SMTP id smtpd.web10.28201.1746364017481237771 for ; Sun, 04 May 2025 06:07:00 -0700 Authentication-Results: mx.groups.io; dkim=pass header.i=adrian.freihofer@siemens.com header.s=fm1 header.b=fgjb1Xry; spf=pass (domain: rts-flowmailer.siemens.com, ip: 185.136.64.226, mailfrom: fm-1329275-20250504130659343d828884db26c604-ynoxhp@rts-flowmailer.siemens.com) Received: by mta-64-226.siemens.flowmailer.net with ESMTPSA id 20250504130659343d828884db26c604 for ; Sun, 04 May 2025 15:06:59 +0200 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; s=fm1; d=siemens.com; i=adrian.freihofer@siemens.com; h=Date:From:Subject:To:Message-ID:MIME-Version:Content-Type:Content-Transfer-Encoding:Cc:References:In-Reply-To; bh=MQhrn/swZFDbscT3tNXGsOu9PLvqx+fgDQJeqhZjuTg=; b=fgjb1Xryo0HWF8la2lcXWEGOriEHMSfLGdg60YedQVcGxW4AtDGL9hziSMn0uQT1hM1o58 1AYOPZ9hPdvc9qPrI58AQjh61Mo64WBBZ9wpwEFBzUbJi4OyNFQjeXS0MkUUVFPThsztR4cf pNy9v06Cl1CntLm5njMd8QM57pB/wVGkyvaZ2hK3gsiKKzId1JA/Ex5wePSjIMVH3ptSX5VK 4bbNs7MapPEnBkr7wwTZKVxcOcmx8g9HeTSOAri+oDGa7xJg8WPhv02l8aEPTf+sUhRNAcS+ DTB78lbaHZoW7w5jimQpdUltw4kkrzu56YZuFHNmYFefO5RK4UyymWpg==; From: AdrianF To: openembedded-core@lists.openembedded.org Cc: marex@denx.de, l.anderweit@phytec.de, richard.purdie@linuxfoundation.org, ross.burton@arm.com, bruce.ashfield@gmail.com, rogerio.borin@toradex.com, sean.anderson@seco.com, m.felsch@pengutronix.de, ejo@pengutronix.de, Adrian Freihofer Subject: [PATCH 20/20] kernel-fit-image.bbclass: ignore INITRAMFS_IMAGE_BUNDLE Date: Sun, 4 May 2025 15:05:07 +0200 Message-ID: <20250504130507.717954-20-adrian.freihofer@siemens.com> In-Reply-To: <20250504130507.717954-1-adrian.freihofer@siemens.com> References: <20250504130507.717954-1-adrian.freihofer@siemens.com> MIME-Version: 1.0 X-Flowmailer-Platform: Siemens Feedback-ID: 519:519-1329275:519-21489:flowmailer List-Id: X-Webhook-Received: from li982-79.members.linode.com [45.33.32.79] by aws-us-west-2-korg-lkml-1.web.codeaurora.org with HTTPS for ; Sun, 04 May 2025 13:07:08 -0000 X-Groupsio-URL: https://lists.openembedded.org/g/openembedded-core/message/215964 From: Adrian Freihofer The new recipe includes the initramfs unbundled anyway. Remove the code which does not work in the context of a recipe which takes the kernel artifacts from recipe-sysroot. The kernel in the recipe-sysroot is exported by the do_install function of the kernel which runs before do_bundle_initramfs. It would be possible to support the bundled in FIT image use case if the recipe would take the kernel artifacts from the deploy folder where also the bundled kernel artifact could be found. But what's the use case of a bundled artifact included in a FIT image? Rather than supporting something which does not work well with the sstate-cache lets guide the users to a better implementation and simplify the code where possible. Signed-off-by: Adrian Freihofer --- meta/classes-recipe/kernel-fit-image.bbclass | 20 ++++++++------------ 1 file changed, 8 insertions(+), 12 deletions(-) diff --git a/meta/classes-recipe/kernel-fit-image.bbclass b/meta/classes-recipe/kernel-fit-image.bbclass index 3c40fbb0ffa..b902bf3a164 100644 --- a/meta/classes-recipe/kernel-fit-image.bbclass +++ b/meta/classes-recipe/kernel-fit-image.bbclass @@ -11,7 +11,7 @@ DEPENDS += "u-boot-tools-native dtc-native virtual/kernel" python () { image = d.getVar('INITRAMFS_IMAGE') - if image and not bb.utils.to_boolean(d.getVar('INITRAMFS_IMAGE_BUNDLE')): + if image: if d.getVar('INITRAMFS_MULTICONFIG'): mc = d.getVar('BB_CURRENT_MC') d.appendVarFlag('do_compile', 'mcdepends', ' mc:' + mc + ':${INITRAMFS_MULTICONFIG}:${INITRAMFS_IMAGE}:do_image_complete') @@ -108,7 +108,7 @@ python do_compile() { # Prepare a ramdisk section. initramfs_image = d.getVar('INITRAMFS_IMAGE') - if initramfs_image and not oe.types.boolean(d.getVar("INITRAMFS_IMAGE_BUNDLE")): + if initramfs_image: # Find and use the first initramfs image archive type we find found = False for img in d.getVar("FIT_SUPPORTED_INITRAMFS_FSTYPES").split(): @@ -157,11 +157,9 @@ do_deploy() { install -m 0644 "${B}/fitImage" "$deploy_dir/fitImage" install -m 0644 "${B}/fit-image.its" "$deploy_dir/fit-image.its" - if [ "${INITRAMFS_IMAGE_BUNDLE}" != "1" ]; then - ln -snf fit-image.its "$deploy_dir/fitImage-its-${KERNEL_FIT_NAME}.its" - if [ -n "${KERNEL_FIT_LINK_NAME}" ] ; then - ln -snf fit-image.its "$deploy_dir/fitImage-its-${KERNEL_FIT_LINK_NAME}" - fi + ln -snf fit-image.its "$deploy_dir/fitImage-its-${KERNEL_FIT_NAME}.its" + if [ -n "${KERNEL_FIT_LINK_NAME}" ] ; then + ln -snf fit-image.its "$deploy_dir/fitImage-its-${KERNEL_FIT_LINK_NAME}" fi if [ -n "${INITRAMFS_IMAGE}" ]; then @@ -170,11 +168,9 @@ do_deploy() { ln -snf fit-image.its "$deploy_dir/fitImage-its-${INITRAMFS_IMAGE_NAME}-${KERNEL_FIT_LINK_NAME}" fi - if [ "${INITRAMFS_IMAGE_BUNDLE}" != "1" ]; then - ln -snf fitImage "$deploy_dir/fitImage-${INITRAMFS_IMAGE_NAME}-${KERNEL_FIT_NAME}${KERNEL_FIT_BIN_EXT}" - if [ -n "${KERNEL_FIT_LINK_NAME}" ] ; then - ln -snf fitImage "$deploy_dir/fitImage-${INITRAMFS_IMAGE_NAME}-${KERNEL_FIT_LINK_NAME}" - fi + ln -snf fitImage "$deploy_dir/fitImage-${INITRAMFS_IMAGE_NAME}-${KERNEL_FIT_NAME}${KERNEL_FIT_BIN_EXT}" + if [ -n "${KERNEL_FIT_LINK_NAME}" ] ; then + ln -snf fitImage "$deploy_dir/fitImage-${INITRAMFS_IMAGE_NAME}-${KERNEL_FIT_LINK_NAME}" fi fi }