From patchwork Mon May 19 11:07:45 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Freihofer, Adrian" X-Patchwork-Id: 63207 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 6111BC54799 for ; Mon, 19 May 2025 11:09:03 +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.48707.1747652938131708898 for ; Mon, 19 May 2025 04:08:59 -0700 Authentication-Results: mx.groups.io; dkim=pass header.i=adrian.freihofer@siemens.com header.s=fm1 header.b=EPtUxxxg; spf=pass (domain: rts-flowmailer.siemens.com, ip: 185.136.64.226, mailfrom: fm-1329275-20250519110854b5cf2c036377cb8fc8-2q_sif@rts-flowmailer.siemens.com) Received: by mta-64-226.siemens.flowmailer.net with ESMTPSA id 20250519110854b5cf2c036377cb8fc8 for ; Mon, 19 May 2025 13:08: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=+V7L7UrkDSHNHV44YNopac1bfO1tz0SGJAn7/SYOXXg=; b=EPtUxxxgJbJvWVTLRLEtSdEI6TzOlxuQlQQ2WZcX7m3PbUI+AwvupuF1XUtfy3jJi4FVUT EATj/EVKQaFM2eaclpk14z3HV790Gmf0wB0KHZdPbQdFvbd5bNmhsjoLazrBd4+ajSiUVS7X cdoqt9dsUrh2lED42XaTig1mrWK+0Qk5Cr78qUl3SoAYbL5yXZ21XScbjQ0IvXGp4HDAXIp+ vmYcmWD67KuTmSI/5koBWUwV7BBYSVplE8qTCoWVdGoQIOAObxUropzGo6yl40tNfGXKP51S immXrAisPi4LIoZu3I7neBH4xTrCB/FlYRChXGuqVWJvh37aMnvVbwHQ==; From: AdrianF To: openembedded-core@lists.openembedded.org Cc: marex@denx.de, Adrian Freihofer Subject: [PATCH v4 01/16] oe-selftest: add new ext dtb recipe Date: Mon, 19 May 2025 13:07:45 +0200 Message-ID: <20250519110838.82978-2-adrian.freihofer@siemens.com> In-Reply-To: <20250519110838.82978-1-adrian.freihofer@siemens.com> References: <20250519110838.82978-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 ; Mon, 19 May 2025 11:09:03 -0000 X-Groupsio-URL: https://lists.openembedded.org/g/openembedded-core/message/216846 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 Mon May 19 11:07:46 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: "Freihofer, Adrian" X-Patchwork-Id: 63210 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 52C59C5479B for ; Mon, 19 May 2025 11:09:03 +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.48708.1747652938177223902 for ; Mon, 19 May 2025 04:08:59 -0700 Authentication-Results: mx.groups.io; dkim=pass header.i=adrian.freihofer@siemens.com header.s=fm1 header.b=XCTp0rBd; spf=pass (domain: rts-flowmailer.siemens.com, ip: 185.136.64.225, mailfrom: fm-1329275-202505191108553f598b1d43c84ab1ed-n6_rwv@rts-flowmailer.siemens.com) Received: by mta-64-225.siemens.flowmailer.net with ESMTPSA id 202505191108553f598b1d43c84ab1ed for ; Mon, 19 May 2025 13:08: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=AcvuOY2g3YF2/NGw1sTjLx/jnbsuEvLASeaPQT2Jegc=; b=XCTp0rBdxJLd+GFiYhuYkRSTEaEzP8lqRWNcr5Kb7uipKa5OlEAfwOWNCelhtVPb2JUPmu 6+r8dVp2XFQfQwOsXetfSmyN+aOeFvNnaQjHM10T5vzaOjw0HMEytWMLUvnctY3tb5RDTLsU oktYtqTySZiNb5hVuYZkJKUHCOKGbl6wRS3hQVVeDz9zMZ5oDk8UyLaEZONpjc+MwUNlq+B1 GyXlI8QQ9xDaCBPhd8VdHTHR1z7K/ZQxPv//4fqIGiXzMN4qIM4jHAvPAz20SKzmPu7+HUVN bdw4FwzcvQk2kqnFavOfe3sr0/BfTPuO6SN8+0hGLloM8mhcUlqZ7Rpw==; From: AdrianF To: openembedded-core@lists.openembedded.org Cc: marex@denx.de, Adrian Freihofer Subject: [PATCH v4 02/16] oe-selftest: fitimage: test coverage for ext dtb Date: Mon, 19 May 2025 13:07:46 +0200 Message-ID: <20250519110838.82978-3-adrian.freihofer@siemens.com> In-Reply-To: <20250519110838.82978-1-adrian.freihofer@siemens.com> References: <20250519110838.82978-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 ; Mon, 19 May 2025 11:09:03 -0000 X-Groupsio-URL: https://lists.openembedded.org/g/openembedded-core/message/216841 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 | 58 +++++++++++++++++++++--- 1 file changed, 51 insertions(+), 7 deletions(-) diff --git a/meta/lib/oeqa/selftest/cases/fitimage.py b/meta/lib/oeqa/selftest/cases/fitimage.py index b39f2622dff..c3554d4499a 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', @@ -585,10 +597,16 @@ class KernelFitImageTests(FitImageTestCase): # Create a configuration section for each DTB if dtb_files: for dtb in dtb_files: - req_sections['conf-' + dtb] = { - "Kernel": "kernel-1", - "FDT": 'fdt-' + dtb, - } + # dtb overlays do not refer to a kernel (yet?) + if dtb.endswith('.dtbo'): + req_sections['conf-' + dtb] = { + "FDT": 'fdt-' + dtb, + } + else: + req_sections['conf-' + dtb] = { + "Kernel": "kernel-1", + "FDT": 'fdt-' + dtb, + } if initramfs_image and initramfs_image_bundle != "1": req_sections['conf-' + dtb]['Init Ramdisk'] = "ramdisk-1" else: @@ -635,7 +653,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 +719,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 Mon May 19 11:07:47 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: "Freihofer, Adrian" X-Patchwork-Id: 63216 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 A4563C54EE3 for ; Mon, 19 May 2025 11:09:03 +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.48594.1747652938365782245 for ; Mon, 19 May 2025 04:08:59 -0700 Authentication-Results: mx.groups.io; dkim=pass header.i=adrian.freihofer@siemens.com header.s=fm1 header.b=EuoGt/XY; spf=pass (domain: rts-flowmailer.siemens.com, ip: 185.136.64.228, mailfrom: fm-1329275-202505191108552aef70887cf16b9e02-sxolmi@rts-flowmailer.siemens.com) Received: by mta-64-228.siemens.flowmailer.net with ESMTPSA id 202505191108552aef70887cf16b9e02 for ; Mon, 19 May 2025 13:08: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=lxjBHDiJIqkSeOHLKp75xTXLotOp2bdbjF5Tn+QlyOM=; b=EuoGt/XYbYebIm3hR36qCO6UgWVSp8P3HkVgW7/d4pXGvigUb25C+yCJUb4zPQUw1rANlu 2bilpVtcCKKORMOVrzZn8nkPseGB9Oqvdv+clOJGUrXU+/6qsBS6oReW2RN4rd+H1EOmg5bs VyV6Q4HeMyUQndIocvEQfxIcavf402kM68AdYi3QBfFAxCqAlqIphzf/z/xHD/MWJW7VqQfd CsIv91e18Le2MXX6gDEFpdwAJUnvkDsAYelNVOCB7jZ22Ief4EAXGf4Jx9Wx4pI3MSrrOFjk 6YEQY3McQ2Mrya63xfqPxpWV/xRPJvj0Hur/mIwsdr8swglKYa8WLiPw==; From: AdrianF To: openembedded-core@lists.openembedded.org Cc: marex@denx.de, Adrian Freihofer Subject: [PATCH v4 03/16] kernel-signing-keys-native: refactor key generation into a new recipe Date: Mon, 19 May 2025 13:07:47 +0200 Message-ID: <20250519110838.82978-4-adrian.freihofer@siemens.com> In-Reply-To: <20250519110838.82978-1-adrian.freihofer@siemens.com> References: <20250519110838.82978-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 ; Mon, 19 May 2025 11:09:03 -0000 X-Groupsio-URL: https://lists.openembedded.org/g/openembedded-core/message/216839 From: Adrian Freihofer The do_kernel_generate_rsa_keys function from kernel-fitimage.bbclass is moved to a new recipe, kernel-signing-keys-native.bb. This refactoring introduces no functional changes. Intention this change: - Remove the dependency of uboot-sign.bbclass on kernel-fitimage.bbclass. - Simplify the use of custom key generation implementations by isolating the functionality into a separate recipe. Known limitations of this (and also the previous) implementation: - When generating from an existing TMPDIR, the existing key is reused. However, when generating from an empty TMPDIR or an SDK using the sstate-cache, a new key is generated, which may lead to inconsistencies. - The use of random keys (via FIT_GENERATE_KEYS) is convenient for experiments but unsuitable for production environments requiring deterministic and secure key management. Future improvements to consider: - Ensure reproducibility, even when using the sstate-cache. However, simply storing the private key in a potentially shared sstate artifact may not always be ideal from a security perspective. - Support encrypted keys via `SRC_URI` for reliable key updates. - Enable signing with an HSM (Hardware Security Module) through mechanisms like PKCS#11 or post-processing scripts. Signed-off-by: Adrian Freihofer --- meta/classes-recipe/kernel-fitimage.bbclass | 52 +------------ meta/classes-recipe/uboot-sign.bbclass | 5 +- .../kernel-signing-keys-native.bb | 75 +++++++++++++++++++ 3 files changed, 82 insertions(+), 50 deletions(-) create mode 100644 meta/recipes-kernel/kernel-signing-keys/kernel-signing-keys-native.bb diff --git a/meta/classes-recipe/kernel-fitimage.bbclass b/meta/classes-recipe/kernel-fitimage.bbclass index 07786647e19..f5f02f30f0a 100644 --- a/meta/classes-recipe/kernel-fitimage.bbclass +++ b/meta/classes-recipe/kernel-fitimage.bbclass @@ -27,7 +27,10 @@ def get_fit_replacement_type(d): 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 ''}" +DEPENDS:append = " \ + ${@'u-boot-tools-native dtc-native' if 'fitImage' in (d.getVar('KERNEL_IMAGETYPES') or '').split() else ''} \ + ${@'kernel-signing-keys-native' if d.getVar('FIT_GENERATE_KEYS') == '1' else ''} \ +" python __anonymous () { # Override KERNEL_IMAGETYPE_FOR_MAKE variable, which is internal @@ -754,53 +757,6 @@ do_assemble_fitimage_initramfs() { 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 - - if [ "${UBOOT_SIGN_ENABLE}" = "1" ] && [ "${FIT_GENERATE_KEYS}" = "1" ]; then - - # 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 -} - -addtask kernel_generate_rsa_keys before do_assemble_fitimage after do_compile - kernel_do_deploy[vardepsexclude] = "DATETIME" kernel_do_deploy:append() { # Update deploy directory diff --git a/meta/classes-recipe/uboot-sign.bbclass b/meta/classes-recipe/uboot-sign.bbclass index e0771b54291..ae700515d25 100644 --- a/meta/classes-recipe/uboot-sign.bbclass +++ b/meta/classes-recipe/uboot-sign.bbclass @@ -108,13 +108,14 @@ UBOOT_FIT_CONF_USER_LOADABLES ?= '' UBOOT_FIT_UBOOT_LOADADDRESS ?= "${UBOOT_LOADADDRESS}" UBOOT_FIT_UBOOT_ENTRYPOINT ?= "${UBOOT_ENTRYPOINT}" + +DEPENDS:append = " ${@'kernel-signing-keys-native' if d.getVar('FIT_GENERATE_KEYS') == '1' else ''}" + python() { # We need u-boot-tools-native if we're creating a U-Boot fitImage sign = d.getVar('UBOOT_SIGN_ENABLE') == '1' if d.getVar('UBOOT_FITIMAGE_ENABLE') == '1' or sign: d.appendVar('DEPENDS', " u-boot-tools-native dtc-native") - if d.getVar('FIT_GENERATE_KEYS') == '1' and sign: - d.appendVarFlag('do_uboot_assemble_fitimage', 'depends', ' virtual/kernel:do_kernel_generate_rsa_keys') } concat_dtb() { diff --git a/meta/recipes-kernel/kernel-signing-keys/kernel-signing-keys-native.bb b/meta/recipes-kernel/kernel-signing-keys/kernel-signing-keys-native.bb new file mode 100644 index 00000000000..704973dffb7 --- /dev/null +++ b/meta/recipes-kernel/kernel-signing-keys/kernel-signing-keys-native.bb @@ -0,0 +1,75 @@ +# Automatically generate key pairs in UBOOT_SIGN_KEYDIR if they do not exist. +# The key pair is generated by the kernel-signing-keys-native recipe and is not +# stored in the sstate cache. This can be beneficial from a security standpoint, +# as it avoids unintentionally caching and distributing private keys. +# However, this behavior can lead to non-reproducible builds. For example, if +# the keys are deleted, they must be manually restored, or you must run: +# bitbake -c cleanall kernel-signing-keys-native +# before new key pairs are generated. +# +# However, this approach is only suitable for simple or local development use +# cases. For more advanced or production-grade scenarios, a more robust solution +# is usually required—such as external signing or re-signing using e.g a HSM. + + +SUMMARY = "Signing keys for the kernel FIT image" +LICENSE = "MIT" +LIC_FILES_CHKSUM = "file://${COREBASE}/meta/COPYING.MIT;md5=3da9cfbcb788c80a0384361b4de20420" + +require conf/image-fitimage.conf + +DEPENDS += "openssl-native" + +inherit native + +do_fetch[noexec] = "1" +do_unpack[noexec] = "1" +do_patch[noexec] = "1" +do_configure[noexec] = "1" +do_install[noexec] = "1" + + +do_compile() { + 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 + + if [ "${UBOOT_SIGN_ENABLE}" = "1" ] && [ "${FIT_GENERATE_KEYS}" = "1" ]; then + + # 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 +} From patchwork Mon May 19 11:07: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: 63211 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 5354FC54795 for ; Mon, 19 May 2025 11:09:03 +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.48711.1747652938325096988 for ; Mon, 19 May 2025 04:08:59 -0700 Authentication-Results: mx.groups.io; dkim=pass header.i=adrian.freihofer@siemens.com header.s=fm1 header.b=hVk//vpu; spf=pass (domain: rts-flowmailer.siemens.com, ip: 185.136.65.225, mailfrom: fm-1329275-20250519110855386702eaba32bbde5b-omyudt@rts-flowmailer.siemens.com) Received: by mta-65-225.siemens.flowmailer.net with ESMTPSA id 20250519110855386702eaba32bbde5b for ; Mon, 19 May 2025 13:08: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=KqmqVZan7/t5N3Q6U09RScxWIkVGDuAdTBjMfpOo3Mw=; b=hVk//vpugseLryZuZA76g49Hi8fswp+RlzzG5KEjexeRKH9k/g/uqI6e3jFvktf3SbLvvd ICebiBqDz7tKTp7GAo33mLE/YOMFrQYMJsasFMeCU+fJML+w+BtoEwTWlZfH46WZzw2sxqxx rVB09tQdkyXPdxeetnvh3kKjuJfms1WjgEbOdqQWGfltb+CNxJb8ygynkQrzarskKErEHxMn PjzR4Var9u9VzCWrH3kre4NFBd+R8AxKhre9yxWvVPiH45juSskokCZNxOYb9qu0xJuHOcv4 gj3xEQx4VUyIXvjtmBnMzuIBa2UoAx793Erld7TvIbXHivfx6c4s4Xug==; From: AdrianF To: openembedded-core@lists.openembedded.org Cc: marex@denx.de, Adrian Freihofer Subject: [PATCH v4 04/16] kernel-uboot.bbclass: do not require the kernel build folder Date: Mon, 19 May 2025 13:07:48 +0200 Message-ID: <20250519110838.82978-5-adrian.freihofer@siemens.com> In-Reply-To: <20250519110838.82978-1-adrian.freihofer@siemens.com> References: <20250519110838.82978-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 ; Mon, 19 May 2025 11:09:03 -0000 X-Groupsio-URL: https://lists.openembedded.org/g/openembedded-core/message/216848 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 Mon May 19 11:07:49 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Freihofer, Adrian" X-Patchwork-Id: 63212 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 762B8C54E65 for ; Mon, 19 May 2025 11:09:03 +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.48592.1747652938057625400 for ; Mon, 19 May 2025 04:08:59 -0700 Authentication-Results: mx.groups.io; dkim=pass header.i=adrian.freihofer@siemens.com header.s=fm1 header.b=Iva5mHZQ; spf=pass (domain: rts-flowmailer.siemens.com, ip: 185.136.65.225, mailfrom: fm-1329275-20250519110855dcd88f8a51959bb161-dlb1jt@rts-flowmailer.siemens.com) Received: by mta-65-225.siemens.flowmailer.net with ESMTPSA id 20250519110855dcd88f8a51959bb161 for ; Mon, 19 May 2025 13:08: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=wnypcO3iXUgNAB4z0FwOjJB5Kuq/bwCfyl5AwCRtNgE=; b=Iva5mHZQ+en+pClwsm+Zcjx0VWosXq7PnrPykft5FovqICbj7n9HmvRt4lbJooaXi17Lfg jj7zT5BIOQtGG3t0b/kVP1wU0IJ8RdDAlXWZLQhf2foDxrJjeQft+zFUnT8h1v0StmnflB/E GW0f6/U6RNXQg1F7LRhUm0w3waEdiW6czup3h8PtS9RBC3AhrjMxGv5iTdvjVKTUQYGeHpJ4 rFrQlV0Mhj30iL/LP9pHsj5tU7BQHMZFQosHU8Tx5cvXoZXTS1vp/kfAZkLLWRTtl/y6pmO2 TsXa1oR4QvRTl+LckMf3IKoGKUdtzCHtVRLNBQ/0Rtt8lt/ArJfbV4QQ==; From: AdrianF To: openembedded-core@lists.openembedded.org Cc: marex@denx.de, Adrian Freihofer Subject: [PATCH v4 05/16] kernel-uboot.bbclass: deploy the vmlinux kernel binary Date: Mon, 19 May 2025 13:07:49 +0200 Message-ID: <20250519110838.82978-6-adrian.freihofer@siemens.com> In-Reply-To: <20250519110838.82978-1-adrian.freihofer@siemens.com> References: <20250519110838.82978-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 ; Mon, 19 May 2025 11:09:03 -0000 X-Groupsio-URL: https://lists.openembedded.org/g/openembedded-core/message/216844 From: Adrian Freihofer Extend the kernel-uboot.bbclass to build and deploy the kernel binary intended for inclusion in a FIT image. Note that the kernel used in a FIT image is a stripped (and optionally compressed) vmlinux ELF binary - not a self-extracting format like zImage, which is already available in the deploy directory if needed separately. The kernel.bbclass inherits all classes listed in the KERNEL_CLASSES variable. By default, KERNEL_CLASSES is defined as: KERNEL_CLASSES ?= " kernel-uimage " Since kernel-uimage.bbclass inherits from kernel-uboot.bbclass, the creation and deployment of the kernel binary for inclusion in a FIT image happens automatically by default. Signed-off-by: Adrian Freihofer --- meta/classes-recipe/kernel-uboot.bbclass | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/meta/classes-recipe/kernel-uboot.bbclass b/meta/classes-recipe/kernel-uboot.bbclass index d2a63524ece..e26ba6f0aa9 100644 --- a/meta/classes-recipe/kernel-uboot.bbclass +++ b/meta/classes-recipe/kernel-uboot.bbclass @@ -56,4 +56,13 @@ uboot_prep_kimage() { fi printf "$linux_comp" > "$output_dir/linux_comp" -} \ No newline at end of file +} + +kernel_do_deploy:append() { + # Provide the kernel artifacts to post processing recipes e.g. for creating a FIT image + uboot_prep_kimage "$deployDir" + # For x86 a setup.bin needs to be include"d in a fitImage as well + if [ -e ${KERNEL_OUTPUT_DIR}/setup.bin ]; then + install -D "${B}/${KERNEL_OUTPUT_DIR}/setup.bin" "$deployDir/" + fi +} From patchwork Mon May 19 11:07: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: 63217 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 87E48C54E92 for ; Mon, 19 May 2025 11:09:03 +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.web10.48705.1747652938056963512 for ; Mon, 19 May 2025 04:08:59 -0700 Authentication-Results: mx.groups.io; dkim=pass header.i=adrian.freihofer@siemens.com header.s=fm1 header.b=e+fNN591; spf=pass (domain: rts-flowmailer.siemens.com, ip: 185.136.65.226, mailfrom: fm-1329275-2025051911085518558470c0ec986207-jcann8@rts-flowmailer.siemens.com) Received: by mta-65-226.siemens.flowmailer.net with ESMTPSA id 2025051911085518558470c0ec986207 for ; Mon, 19 May 2025 13:08: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=+8Z+cK8S3g8PYZggIErXPEt0hlYFD4qCXnJB7qt4N4s=; b=e+fNN591zheN/pUiGzfLG8DppvvHwIdBiVb+zniKOWKL1rRfLcrmTCeHHlkmxz7aC3/gzP HI37mDoVQ6Mvkt183+At9pKZAblHRVWY1EcCcbpyX6LbtKd7uGlbZm8W3g+BGxE1NncubRwl WOq9ZKs6xumAjyp3M9jsmbve/OlhAkqGIs7mInvrIEScEuACluSoM5R7OC9pqVmHlvYcFPhW tfcyUcrc/gm+XhJeXKE0BDA2o7L52HQGaz3C8EK6g2eVOtk4UDO1Hf8h02iSHKGhIwwdrx9P 8iPMOW3Oy9pcc3hbsGN0vygMsyFVmAhBQchy1I4dr40sVxiEamXLo3Cg==; From: AdrianF To: openembedded-core@lists.openembedded.org Cc: marex@denx.de, Adrian Freihofer Subject: [PATCH v4 06/16] kernel-fitimage: refactor order in its Date: Mon, 19 May 2025 13:07:50 +0200 Message-ID: <20250519110838.82978-7-adrian.freihofer@siemens.com> In-Reply-To: <20250519110838.82978-1-adrian.freihofer@siemens.com> References: <20250519110838.82978-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 ; Mon, 19 May 2025 11:09:03 -0000 X-Groupsio-URL: https://lists.openembedded.org/g/openembedded-core/message/216838 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 f5f02f30f0a..8e66f326766 100644 --- a/meta/classes-recipe/kernel-fitimage.bbclass +++ b/meta/classes-recipe/kernel-fitimage.bbclass @@ -128,11 +128,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 { @@ -177,10 +177,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"; @@ -215,10 +215,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"; }; @@ -252,11 +252,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 { @@ -301,11 +301,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 c3554d4499a..47fb8534b37 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 Mon May 19 11:07: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: 63218 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 614D3C54E71 for ; Mon, 19 May 2025 11:09:03 +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.48706.1747652938106996546 for ; Mon, 19 May 2025 04:08:59 -0700 Authentication-Results: mx.groups.io; dkim=pass header.i=adrian.freihofer@siemens.com header.s=fm1 header.b=Kh9N3+lT; spf=pass (domain: rts-flowmailer.siemens.com, ip: 185.136.65.228, mailfrom: fm-1329275-20250519110855b326274d3ad148e553-nutpro@rts-flowmailer.siemens.com) Received: by mta-65-228.siemens.flowmailer.net with ESMTPSA id 20250519110855b326274d3ad148e553 for ; Mon, 19 May 2025 13:08: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=kuwAMjO3ZY9JU50KpAnKREYhPTbBRDCnVFtuQ2D5PdQ=; b=Kh9N3+lTKMWuZxVVjhumULQ34bi1dlpaUTNSGF7RhGY7/+vlgfhSqqFKAuwkT0ry6IHG3z piX3TxwNwbg6ZzUpqCEqgNRCdGe4NFT+XPT1eFSvF70okk7ptEuWYiShWHyPXorWylKuqaMI Bg7gOFPK4yn6KDc2uHtivkMOl/Liv7OuiWbiVfmECTvfa/m617USD2ED6f05MSHsj2S/pumL xQjWNOuaHXNJ2Dwh4urBOB272bsktE/8TIXz5bUbrkfp+0XBdMKsVs/EwVkI+YCdA+YoYYD/ 5Hz6Faaz/B5viNvQbHCFemSMCvbmLHu/v4tSVZYP9TP81eiBiqcDUSnA==; From: AdrianF To: openembedded-core@lists.openembedded.org Cc: marex@denx.de, Adrian Freihofer Subject: [PATCH v4 07/16] kernel-fit-image.bbclass: add a new FIT image implementation Date: Mon, 19 May 2025 13:07:51 +0200 Message-ID: <20250519110838.82978-8-adrian.freihofer@siemens.com> In-Reply-To: <20250519110838.82978-1-adrian.freihofer@siemens.com> References: <20250519110838.82978-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 ; Mon, 19 May 2025 11:09:03 -0000 X-Groupsio-URL: https://lists.openembedded.org/g/openembedded-core/message/216849 From: Adrian Freihofer The new recipe linux-yocto-fitimage.bb and the new kernel-fit-image.bbclass are intended to become successors of the kernel-fitimage.bbclass. 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 an 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 recipe takes the kernel artifacts from the deploy folder. There was also a test implementation passing the kernel artifacts via sysroot directory. This requires changes on the kernel.bbclass to make it copying the artifacts also to the sysroot directory while the same artifacts are already in the sstate-cached deploy directory. The long story about this issue is here: [YOCTO #12912] Signed-off-by: Adrian Freihofer --- meta/classes-recipe/kernel-fit-image.bbclass | 184 +++++++ meta/classes/multilib.bbclass | 1 + meta/lib/oe/fitimage.py | 463 ++++++++++++++++++ .../linux/linux-yocto-fitimage_6.12.bb | 13 + 4 files changed, 661 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..67c717f88d5 --- /dev/null +++ b/meta/classes-recipe/kernel-fit-image.bbclass @@ -0,0 +1,184 @@ + +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 \ + ${@'kernel-signing-keys-native' if d.getVar('FIT_GENERATE_KEYS') == '1' else ''} \ +" + +python () { + image = d.getVar('INITRAMFS_IMAGE') + if image and d.getVar('INITRAMFS_IMAGE_BUNDLE') != '1': + 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") +} + +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" + kernel_deploydir = d.getVar('DEPLOY_DIR_IMAGE') + kernel_deploysubdir = d.getVar('KERNEL_DEPLOYSUBDIR') + if kernel_deploysubdir: + kernel_deploydir = os.path.join(kernel_deploydir, kernel_deploysubdir) + + # 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(kernel_deploydir, "linux.bin"), "linux.bin") + with open(os.path.join(kernel_deploydir, "linux_comp")) as linux_comp_f: + linux_comp = linux_comp_f.read() + root_node.fitimage_emit_section_kernel("kernel-1", "linux.bin", linux_comp, + 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(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(kernel_deploydir, 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(kernel_deploydir, "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 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-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_compile[depends] += "virtual/kernel:do_deploy" + +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 diff --git a/meta/classes/multilib.bbclass b/meta/classes/multilib.bbclass index a4151658a62..b959bbd93c0 100644 --- a/meta/classes/multilib.bbclass +++ b/meta/classes/multilib.bbclass @@ -21,6 +21,7 @@ python multilib_virtclass_handler () { bpn = d.getVar("BPN") if ("virtual/kernel" in provides or bb.data.inherits_class('module-base', d) + or bb.data.inherits_class('kernel-fit-image', d) or bpn in non_ml_recipes): raise bb.parse.SkipRecipe("We shouldn't have multilib variants for %s" % bpn) diff --git a/meta/lib/oe/fitimage.py b/meta/lib/oe/fitimage.py new file mode 100644 index 00000000000..735c09b151d --- /dev/null +++ b/meta/lib/oe/fitimage.py @@ -0,0 +1,463 @@ +# +# 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 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 Mon May 19 11:07: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: 63206 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 368DFC3ABD8 for ; Mon, 19 May 2025 11:09:03 +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.48593.1747652938203955123 for ; Mon, 19 May 2025 04:08:59 -0700 Authentication-Results: mx.groups.io; dkim=pass header.i=adrian.freihofer@siemens.com header.s=fm1 header.b=aZy8CL4I; spf=pass (domain: rts-flowmailer.siemens.com, ip: 185.136.64.225, mailfrom: fm-1329275-20250519110855b464b11f0fe5c04bf4-iyj2qn@rts-flowmailer.siemens.com) Received: by mta-64-225.siemens.flowmailer.net with ESMTPSA id 20250519110855b464b11f0fe5c04bf4 for ; Mon, 19 May 2025 13:08: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=QFAc+S7SVjqV2ao2AcN9QUJoObErPlU6v8Mjuz+NHS8=; b=aZy8CL4IeO1GqbK/eaJWCY22AtyZDorT6pGHX37r2ai7qQAJat6LDgTqz2ncjFkkQjIglj QtnQ14AS/j5+qxKzvs5HJDbYkhYR6ApdC7ShnenEFMu+H4byl/ypnseHpNNVsfp2I5b3dh+o qvIcKh0urN/N7KnHaJMa901Sp75glz+A21c3OHZ7n/235HvEYonf7JvucbSuV04LRD3NiFNe RCaJg6KEciailPfDgcVzkE7smvY9sdOj2vLMKNk41TayD2Cegfm8xftsNSX8ryxQw/3Am9c7 aor3d2sFa9zeO/xtrpetKvfvfBosmvxvC5XLgBlFuLCv/3S1l1AbzIJA==; From: AdrianF To: openembedded-core@lists.openembedded.org Cc: marex@denx.de, Adrian Freihofer Subject: [PATCH v4 08/16] maintainers: add myself for linux-yocto-fitimage Date: Mon, 19 May 2025 13:07:52 +0200 Message-ID: <20250519110838.82978-9-adrian.freihofer@siemens.com> In-Reply-To: <20250519110838.82978-1-adrian.freihofer@siemens.com> References: <20250519110838.82978-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 ; Mon, 19 May 2025 11:09:03 -0000 X-Groupsio-URL: https://lists.openembedded.org/g/openembedded-core/message/216837 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 6c19e306cfa..d7d157af4fe 100644 --- a/meta/conf/distro/include/maintainers.inc +++ b/meta/conf/distro/include/maintainers.inc @@ -471,6 +471,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 Mon May 19 11:07: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: 63219 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 96940C54EDA for ; Mon, 19 May 2025 11:09:03 +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.48709.1747652938204543435 for ; Mon, 19 May 2025 04:08:59 -0700 Authentication-Results: mx.groups.io; dkim=pass header.i=adrian.freihofer@siemens.com header.s=fm1 header.b=Ld1JJEpV; spf=pass (domain: rts-flowmailer.siemens.com, ip: 185.136.64.227, mailfrom: fm-1329275-20250519110856ea4ad4b732437143a4-brhflm@rts-flowmailer.siemens.com) Received: by mta-64-227.siemens.flowmailer.net with ESMTPSA id 20250519110856ea4ad4b732437143a4 for ; Mon, 19 May 2025 13:08: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=PhjmjClip/o9NSERA8G8Yw12V2dNnYUM3Z5JT3Tffhc=; b=Ld1JJEpV4v5Nc21aIAHHvifQY0yFSy2F4wCzwduaaMyq0J1ts1SrMHfAGIwvs9fsmRVDLF I6XaOipe9cTaeDbLWYlMsZ8F0Ic4SgX5uV+MEBgXHkoVDzEU7mJrN2QJw3q46dJ5KDmwshVt UkrMcyP7knPPHZ1Go98n2nm+40SiTIz/QD+H8zcfCeFs/ppdm+LpvDkSL6ow0YVQNN8nJQMy /w3+PwEPo0DusF+YnNGadKwycMw+kfGvBH2cBSITg4PyYaDcTMMjZGIB4oeFVIUIvv8K3ChT 0IfaJuq5yLR3gyXKu/1ZoXpgqDMjyGTgd6rvLPUqIs6Fb5aM3Xoa8a6g==; From: AdrianF To: openembedded-core@lists.openembedded.org Cc: marex@denx.de, Adrian Freihofer Subject: [PATCH v4 09/16] oe-selftest: fitimage add tests for fitimage.py Date: Mon, 19 May 2025 13:07:53 +0200 Message-ID: <20250519110838.82978-10-adrian.freihofer@siemens.com> In-Reply-To: <20250519110838.82978-1-adrian.freihofer@siemens.com> References: <20250519110838.82978-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 ; Mon, 19 May 2025 11:09:03 -0000 X-Groupsio-URL: https://lists.openembedded.org/g/openembedded-core/message/216843 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. Signed-off-by: Adrian Freihofer --- meta/lib/oeqa/selftest/cases/fitimage.py | 145 ++++++++++++++++++++++- 1 file changed, 141 insertions(+), 4 deletions(-) diff --git a/meta/lib/oeqa/selftest/cases/fitimage.py b/meta/lib/oeqa/selftest/cases/fitimage.py index 47fb8534b37..d9d1211b074 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 @@ -85,6 +108,25 @@ class FitImageTestCase(OESelftestTestCase): sing_key_path )) + @staticmethod + 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 + )) + @staticmethod def _gen_random_file(file_path, num_bytes=65536): with open(file_path, 'wb') as file_out: @@ -367,8 +409,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=[]): @@ -683,6 +724,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): """ @@ -928,6 +971,100 @@ 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 test_fitimage_py_default(self): + self._test_fitimage_py() + class UBootFitImageTests(FitImageTestCase): """Test cases for the uboot-sign bbclass""" From patchwork Mon May 19 11:07: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: 63215 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 7C79BC54E93 for ; Mon, 19 May 2025 11:09:03 +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.web10.48710.1747652938269988406 for ; Mon, 19 May 2025 04:08:59 -0700 Authentication-Results: mx.groups.io; dkim=pass header.i=adrian.freihofer@siemens.com header.s=fm1 header.b=Inv0lSp1; spf=pass (domain: rts-flowmailer.siemens.com, ip: 185.136.64.228, mailfrom: fm-1329275-20250519110856e47410f66fdee377c8-7nnshp@rts-flowmailer.siemens.com) Received: by mta-64-228.siemens.flowmailer.net with ESMTPSA id 20250519110856e47410f66fdee377c8 for ; Mon, 19 May 2025 13:08: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=2S4vWSQgMdKDL+vk9HmdqEoJDGHgtFghCsIH+t2ZJRc=; b=Inv0lSp1yDFpnEe9SXLxzj5rQv0DPt6XdArbXK/c6B6AsTWcOMeVFLOMPm/6oSEZQdfjW2 c5KlLJpdXc3TxtL1Y+dpDO/c5pkGeudHVhTic9/Sy9zBlFQAExnGb5cMC7pfG/jP4p+zMtQi kppemOHIDBcw7Y91qEKUkkLP2zjaCwAViQJ5bXyP2zTGeQFqLTcDhbkWpIHkS1Y8qwzaLyX0 T4HaXLxZE0q+2hMBAynE3CuNtp0G0WHDh8dyLCqQGCa8HZOKu05+fF27cEAqEmG3amDJtEk1 a2FrntvlWxArov5XVxtjH1b3c9fwDOt6VFipVpoCDjFf15hBVip6sC4A==; From: AdrianF To: openembedded-core@lists.openembedded.org Cc: marex@denx.de, Adrian Freihofer Subject: [PATCH v4 10/16] oe-selftest: fitimage support new FIT recipe as well Date: Mon, 19 May 2025 13:07:54 +0200 Message-ID: <20250519110838.82978-11-adrian.freihofer@siemens.com> In-Reply-To: <20250519110838.82978-1-adrian.freihofer@siemens.com> References: <20250519110838.82978-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 ; Mon, 19 May 2025 11:09:03 -0000 X-Groupsio-URL: https://lists.openembedded.org/g/openembedded-core/message/216842 From: Adrian Freihofer Enable all existing tests to be compatible with FIT images generated either by the new linux-yocto-fitimage recipe or the legacy kernel-fitimage.bbclass approach. - Make the following configurations optional: - KERNEL_IMAGETYPES += "fitImage" - KERNEL_CLASSES = "kernel-fitimage" - Allow the tests to specify which kernel recipe should be used for the build (e.g., linux-yocto, linux-yocto-fitimage, etc.) --- meta/lib/oeqa/selftest/cases/fitimage.py | 58 +++++++++++++++--------- 1 file changed, 37 insertions(+), 21 deletions(-) diff --git a/meta/lib/oeqa/selftest/cases/fitimage.py b/meta/lib/oeqa/selftest/cases/fitimage.py index d9d1211b074..693d48644af 100644 --- a/meta/lib/oeqa/selftest/cases/fitimage.py +++ b/meta/lib/oeqa/selftest/cases/fitimage.py @@ -428,6 +428,7 @@ class KernelFitImageBase(FitImageTestCase): 'INITRAMFS_IMAGE_BUNDLE', 'INITRAMFS_IMAGE_NAME', 'INITRAMFS_IMAGE', + 'KERNEL_DEPLOYSUBDIR', 'KERNEL_DEVICETREE', 'KERNEL_FIT_LINK_NAME', 'MACHINE', @@ -444,10 +445,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 @@ -461,7 +473,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) @@ -473,7 +485,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'] @@ -492,8 +504,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): @@ -683,6 +700,7 @@ class KernelFitImageBase(FitImageTestCase): uboot_sign_keyname = bb_vars['UBOOT_SIGN_KEYNAME'] uboot_sign_img_keyname = bb_vars['UBOOT_SIGN_IMG_KEYNAME'] deploy_dir_image = bb_vars['DEPLOY_DIR_IMAGE'] + kernel_deploysubdir = bb_vars['KERNEL_DEPLOYSUBDIR'] fit_sign_individual = bb_vars['FIT_SIGN_INDIVIDUAL'] fit_hash_alg_len = FitImageTestCase.MKIMAGE_HASH_LENGTHS[fit_hash_alg] fit_sign_alg_len = FitImageTestCase.MKIMAGE_SIGNATURE_LENGTHS[fit_sign_alg] @@ -696,6 +714,8 @@ class KernelFitImageBase(FitImageTestCase): self.assertEqual(len(sign_value), fit_sign_alg_len, 'Signature value for section %s not expected length' % section) dtb_file_name = section.replace('conf-', '') dtb_path = os.path.join(deploy_dir_image, dtb_file_name) + if kernel_deploysubdir: + dtb_path = os.path.join(deploy_dir_image, kernel_deploysubdir, 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): @@ -741,10 +761,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" @@ -757,6 +774,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) @@ -772,11 +790,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() @@ -801,13 +818,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) @@ -852,8 +868,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" @@ -862,6 +876,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() @@ -888,8 +903,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}" @@ -908,6 +921,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) @@ -948,8 +962,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}" @@ -966,11 +978,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""" @@ -1069,6 +1083,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 @@ -1110,13 +1126,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'] @@ -1634,7 +1650,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 Mon May 19 11:07: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: 63213 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 7C389C54E90 for ; Mon, 19 May 2025 11:09:03 +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.48593.1747652938203955123 for ; Mon, 19 May 2025 04:08:59 -0700 Authentication-Results: mx.groups.io; dkim=pass header.i=adrian.freihofer@siemens.com header.s=fm1 header.b=Pv21yK/6; spf=pass (domain: rts-flowmailer.siemens.com, ip: 185.136.64.225, mailfrom: fm-1329275-2025051911085645870ab3294c22058d-nizaen@rts-flowmailer.siemens.com) Received: by mta-64-225.siemens.flowmailer.net with ESMTPSA id 2025051911085645870ab3294c22058d for ; Mon, 19 May 2025 13:08: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=w4mkPFeRg5Zcd9msiPSkTdtvuipRk/dK13C984EaZgA=; b=Pv21yK/6hiE7teojHFH5TSf3jacV9bABDr2WvphZzKr0eAvNqsGBXzaWv6OmLeA76638n/ qajAKCiHZVcQlboL76NkMHrK+oIbZEGKnZz8IX4Zg5DSMPPcE14YPMab/K0kg18dBjrjLulg +Y7Zsm1/MsccaL3wkf6kMLd4CwJs4NYaY2petrTgKTo/rmVWOAXmR8QBCh3dvoJUrSSHX6Y3 gn1rg/1eVQO+1FKVdzeTE1fwCzM4+MA4oauN4tIPffOW1CZ9/kwgj1v3MylyBgc6jQOgCpS1 5eyrSKiChzv/KztJwzlzsrqYswu8BbtJI0jscrsP6zgmXJ7E6ibAh4Uw==; From: AdrianF To: openembedded-core@lists.openembedded.org Cc: marex@denx.de, Adrian Freihofer Subject: [PATCH v4 11/16] oe-selftest: fitimage: run all tests for both FIT implementations Date: Mon, 19 May 2025 13:07:55 +0200 Message-ID: <20250519110838.82978-12-adrian.freihofer@siemens.com> In-Reply-To: <20250519110838.82978-1-adrian.freihofer@siemens.com> References: <20250519110838.82978-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 ; Mon, 19 May 2025 11:09:03 -0000 X-Groupsio-URL: https://lists.openembedded.org/g/openembedded-core/message/216851 From: Adrian Freihofer Run all existing tests for kernel-fitimage.bbclass also with the new linux-yocto-fitimage recipe. Executing each test for both implementations helps ensure functional compatibility and consistency between them. This change will naturally double the test duration for FIT image-related tests, as each test now runs against both implementations. However, the goal is to eventually deprecate kernel-fitimage.bbclass, at which point the duplicate tests can be removed. Additionally, since the new implementation makes significantly more efficient use of the sstate cache compared to the old one, the overall test execution time may still be improved. 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 693d48644af..b08e991607d 100644 --- a/meta/lib/oeqa/selftest/cases/fitimage.py +++ b/meta/lib/oeqa/selftest/cases/fitimage.py @@ -984,6 +984,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 = "linux-yocto-fitimage"' + os.linesep + return config class FitImagePyTests(KernelFitImageBase): """Test cases for the fitimage.py module without calling bitbake""" From patchwork Mon May 19 11:07: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: 63221 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 A4793C54F2E for ; Mon, 19 May 2025 11:09:03 +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.web11.48595.1747652938591452163 for ; Mon, 19 May 2025 04:08:59 -0700 Authentication-Results: mx.groups.io; dkim=pass header.i=adrian.freihofer@siemens.com header.s=fm1 header.b=ZO85S8AP; spf=pass (domain: rts-flowmailer.siemens.com, ip: 185.136.65.228, mailfrom: fm-1329275-20250519110856f4bbcc0e7238ed7c4f-pcy7vn@rts-flowmailer.siemens.com) Received: by mta-65-228.siemens.flowmailer.net with ESMTPSA id 20250519110856f4bbcc0e7238ed7c4f for ; Mon, 19 May 2025 13:08: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=qXcbTlL79kE7PS7CvJzhaUCoGK5Kg1s0rVzR6cTGYoQ=; b=ZO85S8APh2CR8dZ6fTbGY+aRrvYQOLskhbCG9uiT2QZkNalfygUf2uN2vXlnHOJZbgYLxq 08Nih14gllSpqbCLzif4Qp7q8uY3+AaZBR82zh06T24midK6mcvc23iiQVJ9RjpMIkxDIRdB ocWmH1DuRB0+gu2WRRudyuJpulTpCWVX/0pFrT0vKw32sT7Bcj4kRYSorIKlH4jzTvwx3jMv LBl3AcTnsmXRuguAnpdVY7qBNreCxxMKpkHDGhlSJGVXTm+F6XGPazSlEJ9Px6S1n+1wF6PG An4fisyk8smFIkHcAUKXOyQYbZ5rfSpDyk5rJ8qYUcInDVF2ZIAlzfwg==; From: AdrianF To: openembedded-core@lists.openembedded.org Cc: marex@denx.de, Adrian Freihofer Subject: [PATCH v4 12/16] oe-selftest: fitimage refactor classes Date: Mon, 19 May 2025 13:07:56 +0200 Message-ID: <20250519110838.82978-13-adrian.freihofer@siemens.com> In-Reply-To: <20250519110838.82978-1-adrian.freihofer@siemens.com> References: <20250519110838.82978-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 ; Mon, 19 May 2025 11:09:03 -0000 X-Groupsio-URL: https://lists.openembedded.org/g/openembedded-core/message/216840 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 b08e991607d..e96f8beb806 100644 --- a/meta/lib/oeqa/selftest/cases/fitimage.py +++ b/meta/lib/oeqa/selftest/cases/fitimage.py @@ -410,7 +410,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. @@ -450,15 +450,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 = "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 @@ -744,7 +742,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): @@ -984,16 +982,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 = "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 Mon May 19 11:07: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: 63220 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 8E8CDC54ED0 for ; Mon, 19 May 2025 11:09:03 +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.web10.48712.1747652938727827145 for ; Mon, 19 May 2025 04:08:59 -0700 Authentication-Results: mx.groups.io; dkim=pass header.i=adrian.freihofer@siemens.com header.s=fm1 header.b=ECC2tU+6; spf=pass (domain: rts-flowmailer.siemens.com, ip: 185.136.65.226, mailfrom: fm-1329275-2025051911085648cd47898fc1427aae-jhat7i@rts-flowmailer.siemens.com) Received: by mta-65-226.siemens.flowmailer.net with ESMTPSA id 2025051911085648cd47898fc1427aae for ; Mon, 19 May 2025 13:08: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=8sCabJZYpnEoC+ehTtMjUTDktVL74X27cQ/aNRenU3s=; b=ECC2tU+6nLYGQftGbYlhRPn1Qjw+9URz9KBT+G8/yFMAuncb7wq7evhJbIIgyDsxiUN8lr XwwhO1jhxEV7R0LKvbsAmPT5TtK9OsFDFObbW/cAVqNtmShoqEtOzs+7Es10zivqR9WhBBIh kPkn8rp+SVLnRCo5vak0qLOx8TJGsIWFqDysa/srdTsKX92y2EwCUtoEe2fHVw1W0Pmo+AN8 xKeYh+Z5LD391xdDiCIhnAd073eFokaOJBw1FiqYhGPqWsUCUZYMlmMdswSSpY501krvO+Yt LdRwMnX2IbPJosNOKEfgHcJIhCdSypmkgZ6aQJzdd4m33zdybXBJFsFw==; From: AdrianF To: openembedded-core@lists.openembedded.org Cc: marex@denx.de, Adrian Freihofer Subject: [PATCH v4 13/16] kernel-fitimage: re-write its code in Python Date: Mon, 19 May 2025 13:07:57 +0200 Message-ID: <20250519110838.82978-14-adrian.freihofer@siemens.com> In-Reply-To: <20250519110838.82978-1-adrian.freihofer@siemens.com> References: <20250519110838.82978-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 ; Mon, 19 May 2025 11:09:03 -0000 X-Groupsio-URL: https://lists.openembedded.org/g/openembedded-core/message/216847 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. This commit opens the path for different strategies going forward: - Just replace the old implementations with the new one and ignoring this commit. - Add the new implementation and keep the old implementation without any change. - Add the new implementation and this commit and support the old architecture sharing most of the code with the new architecture and implementatiion. Signed-off-by: Adrian Freihofer --- meta/classes-recipe/kernel-fitimage.bbclass | 860 ++++---------------- meta/classes-recipe/kernel-uboot.bbclass | 45 + 2 files changed, 220 insertions(+), 685 deletions(-) diff --git a/meta/classes-recipe/kernel-fitimage.bbclass b/meta/classes-recipe/kernel-fitimage.bbclass index 8e66f326766..08e34a5d5af 100644 --- a/meta/classes-recipe/kernel-fitimage.bbclass +++ b/meta/classes-recipe/kernel-fitimage.bbclass @@ -56,680 +56,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 @@ -742,17 +232,17 @@ 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 diff --git a/meta/classes-recipe/kernel-uboot.bbclass b/meta/classes-recipe/kernel-uboot.bbclass index e26ba6f0aa9..678d851fd30 100644 --- a/meta/classes-recipe/kernel-uboot.bbclass +++ b/meta/classes-recipe/kernel-uboot.bbclass @@ -66,3 +66,48 @@ kernel_do_deploy:append() { install -D "${B}/${KERNEL_OUTPUT_DIR}/setup.bin" "$deployDir/" 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 Mon May 19 11:07: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: 63214 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 9663BC54ED1 for ; Mon, 19 May 2025 11:09:03 +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.web10.48713.1747652938844386768 for ; Mon, 19 May 2025 04:08:59 -0700 Authentication-Results: mx.groups.io; dkim=pass header.i=adrian.freihofer@siemens.com header.s=fm1 header.b=bbQHrJr6; spf=pass (domain: rts-flowmailer.siemens.com, ip: 185.136.64.228, mailfrom: fm-1329275-20250519110856ae7642f009fc75c8a5-ril3iq@rts-flowmailer.siemens.com) Received: by mta-64-228.siemens.flowmailer.net with ESMTPSA id 20250519110856ae7642f009fc75c8a5 for ; Mon, 19 May 2025 13:08: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=/W0N/oY63mzGutoj8VWQ6TNOGlEGwALUa0m4cqAN1S0=; b=bbQHrJr6L/xow97bjj1+19GH7nN/aGZ7sn9hMCVsjwuChu1c71MpJnWFB0pdd2aQPfWNC/ nNLfds66s13jpTOePqxj9v18tmjzMUgywld/8A8xoqUYMHQ2M7fxvcmykkoQj5xJxCpKxdd1 sEq2MqwCyhDU6aumfNmtxDaWN6oHq9s3eIpVRSI/Usagj60mf6YLmbMo4ojl2+imN0RI/2qk D+FvUMqHVXB94sSykHHzZReG9oyMBjLHnjWETU6vG41rR3L0OGU9sQySEiBDLV2lszQ3CnAd C+MVCc7FEVGrnv0chZYRl2cqez23SoK5URtS9Eqe1eNkIdcIRHf5xpfw==; From: AdrianF To: openembedded-core@lists.openembedded.org Cc: marex@denx.de, Adrian Freihofer Subject: [PATCH v4 14/16] oe-selftest: fitimage: remove kernel-fitimage tests Date: Mon, 19 May 2025 13:07:58 +0200 Message-ID: <20250519110838.82978-15-adrian.freihofer@siemens.com> In-Reply-To: <20250519110838.82978-1-adrian.freihofer@siemens.com> References: <20250519110838.82978-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 ; Mon, 19 May 2025 11:09:03 -0000 X-Groupsio-URL: https://lists.openembedded.org/g/openembedded-core/message/216845 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 e96f8beb806..5d3ae2bb1f8 100644 --- a/meta/lib/oeqa/selftest/cases/fitimage.py +++ b/meta/lib/oeqa/selftest/cases/fitimage.py @@ -449,11 +449,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 = "linux-yocto-fitimage"' + os.linesep - return config - @property def kernel_recipe(self): return "linux-yocto-fitimage" @@ -772,7 +767,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) @@ -791,7 +785,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() @@ -821,7 +814,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) @@ -874,7 +866,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() @@ -919,7 +910,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) @@ -976,26 +966,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 Mon May 19 11:07: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: 63209 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 40ADFC2D0CD for ; Mon, 19 May 2025 11:09:03 +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.web10.48705.1747652938056963512 for ; Mon, 19 May 2025 04:08:59 -0700 Authentication-Results: mx.groups.io; dkim=pass header.i=adrian.freihofer@siemens.com header.s=fm1 header.b=huEaKE4a; spf=pass (domain: rts-flowmailer.siemens.com, ip: 185.136.65.226, mailfrom: fm-1329275-20250519110857380a7f374766b4b3b7-txa2aa@rts-flowmailer.siemens.com) Received: by mta-65-226.siemens.flowmailer.net with ESMTPSA id 20250519110857380a7f374766b4b3b7 for ; Mon, 19 May 2025 13:08: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=lLp+omfSVUXCBXbwnd0R2nKpHRLp1pskN6IOCQeSFT4=; b=huEaKE4almu7GAYv9fylD/uQRn3bGWERiHR6AUH/nhx1H0GyFIUQjI7OdidwfQL4jgV6VJ fYOvcrQo/+H2ufArCwy4R3xcRCKL+LN71tpZiSqke/0Q3idiQBYvijCGU+/ujS2RoFwvxTSr suKsTiX0DkPWnVnSwsRNc4M74ZHGVSQOcHPIX9thduzdZZufDSewCRqkT4t840NGnYfM0qXG 1uPyS7kRNnYjEDOmTgr6FTpVasyl/sZ8SYOzcOsG/Hp767icTEfcAv15HODpoAZVwjbOccV+ wf4nicC3klEVhOzvNQE1sEmFppE5om0apMt22zaVh6vcGZqFqLKyRfuw==; From: AdrianF To: openembedded-core@lists.openembedded.org Cc: marex@denx.de, Adrian Freihofer Subject: [PATCH v4 15/16] kernel.bbclass: remove support for type fitImage Date: Mon, 19 May 2025 13:07:59 +0200 Message-ID: <20250519110838.82978-16-adrian.freihofer@siemens.com> In-Reply-To: <20250519110838.82978-1-adrian.freihofer@siemens.com> References: <20250519110838.82978-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 ; Mon, 19 May 2025 11:09:03 -0000 X-Groupsio-URL: https://lists.openembedded.org/g/openembedded-core/message/216852 From: Adrian Freihofer kernel.bbclass is no longer involved in FIT image creation. Whether a FIT image is built now depends entirely on whether the linux-yocto-fitimage recipe (or any other recipe capable of producing a FIT image) is selected for the build. As a result, specifying the kernel image type "fitImage" in KERNEL_IMAGETYPE or KERNEL_IMAGETYPES is no longer necessary and gets removed. 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 36ce659762e..599996ceb0b 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 Mon May 19 11:08: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: 63208 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 473DCC3DA6D for ; Mon, 19 May 2025 11:09:03 +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.web11.48596.1747652939248657931 for ; Mon, 19 May 2025 04:08:59 -0700 Authentication-Results: mx.groups.io; dkim=pass header.i=adrian.freihofer@siemens.com header.s=fm1 header.b=bRjKw0VL; spf=pass (domain: rts-flowmailer.siemens.com, ip: 185.136.64.227, mailfrom: fm-1329275-20250519110857d6895ac226c5e5c191-pv_grf@rts-flowmailer.siemens.com) Received: by mta-64-227.siemens.flowmailer.net with ESMTPSA id 20250519110857d6895ac226c5e5c191 for ; Mon, 19 May 2025 13:08: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=sAzLpX34RrTSqIjyp2T2BDBt7Xqazj6Ses22W+kN0vU=; b=bRjKw0VLX/fqDF+SsifqGIcP8Yvgge79G/K9JdTTtbIxDneUjuSm6DpfH0D9r5ol5Oi8Tf r6Q4PtUTLUQ8cToeDfgVE9j9zGcYzT4wJka3IT113k+THlIuv+9uhcZAZfxYHd7IpfLjylrC +YqW/TiUAdeeYav+WZZkV8AayqCCLY9ZPdFsgro/ml9MXB9jVYqc1FjIjwnmzdvfo6uUz/+c vwMC9J2EriIuZa9na0WKPzKc81BX7DBWubGejLgzv8MmgmM/A5z9nxgb38S3gIuObAPHaaqn ltGRrnKyMawqbxlukh+IDpNI+rlO1gWfoaZK+Ibce4xYMbfFlnh2s+jg==; From: AdrianF To: openembedded-core@lists.openembedded.org Cc: marex@denx.de, Adrian Freihofer Subject: [PATCH v4 16/16] kernel-fitimage.bbclass: remove it Date: Mon, 19 May 2025 13:08:00 +0200 Message-ID: <20250519110838.82978-17-adrian.freihofer@siemens.com> In-Reply-To: <20250519110838.82978-1-adrian.freihofer@siemens.com> References: <20250519110838.82978-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 ; Mon, 19 May 2025 11:09:03 -0000 X-Groupsio-URL: https://lists.openembedded.org/g/openembedded-core/message/216850 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 | 285 -------------------- meta/classes-recipe/kernel-uboot.bbclass | 45 ---- 2 files changed, 330 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 08e34a5d5af..00000000000 --- a/meta/classes-recipe/kernel-fitimage.bbclass +++ /dev/null @@ -1,285 +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 ''} \ - ${@'kernel-signing-keys-native' if d.getVar('FIT_GENERATE_KEYS') == '1' 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 - -SYSROOT_DIRS:append = " /sysroot-only" -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 - -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 678d851fd30..e26ba6f0aa9 100644 --- a/meta/classes-recipe/kernel-uboot.bbclass +++ b/meta/classes-recipe/kernel-uboot.bbclass @@ -66,48 +66,3 @@ kernel_do_deploy:append() { install -D "${B}/${KERNEL_OUTPUT_DIR}/setup.bin" "$deployDir/" 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