From patchwork Wed Oct 28 21:11:23 2026 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: AdrianF X-Patchwork-Id: 102283 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.msgproc01-g2.7271.1793221928942056444 for ; Wed, 28 Oct 2026 14:12:10 -0700 Authentication-Results: mx.groups.io; dkim=pass header.i=adrian.freihofer@siemens.com header.s=fm2 header.b=c8kFzyfa; spf=pass (domain: rts-flowmailer.siemens.com, ip: 185.136.64.226, mailfrom: fm-1329275-20261028211205feab6d234a00020718-eteiuh@rts-flowmailer.siemens.com) Received: by mta-64-226.siemens.flowmailer.net with ESMTPSA id 20261028211205feab6d234a00020718 for ; Wed, 28 Oct 2026 22:12:06 +0100 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; s=fm2; 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=Gkp+PtZ06KQ6FQ7tE8isQeKC2lgaLA5KSibUze0Onvg=; b=c8kFzyfaiS3UKOt7OrQ89AgcpDEnLMpZRvXCYlIwAOngOK/aBA8WqevA6kXkM1xNsDSW+i gfUlmf0q79Dm4462o5jUNAHRhuJD7WFSQgvwBbWHUTIMplNb3ip/3aAq9j6UJFLlHp9d+PXp wTmNPBvaQ5QzKLwYZGZOZc/dpi80SIkcd5VSAq5khzTAGwBrUFgVRp5LM4bbKu1yMCf+AIYT 1zrqteeTdfyYqOD2tig4De11ZdwRK783ZUU5Q2r4TjRicVMlAtwXLTxCNPZFvVCxWvr62TQj qQynmrN40yosxhjZ/IMVlBL5tiI3XLNMUfCfStS5nsBXHnPZMk6ASu9Q==; From: AdrianF To: openembedded-core@lists.openembedded.org Cc: Adrian Freihofer Subject: [PATCH 1/3] oeqa/utils/commands: add get_bb_vars_flags Date: Wed, 28 Oct 2026 22:11:23 +0100 Message-ID: <20261028211203.3081460-2-adrian.freihofer@siemens.com> In-Reply-To: <20261028211203.3081460-1-adrian.freihofer@siemens.com> References: <20261028211203.3081460-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 45-33-107-173.ip.linodeusercontent.com [45.33.107.173] by lin-tor-korg-lkml-alma10-1 with HTTPS for ; Wed, 28 Oct 2026 21:12:18 -0000 X-Groupsio-URL: https://lists.openembedded.org/g/openembedded-core/message/248833 From: Adrian Freihofer Tests can not query variable flags with get_bb_vars. They either need another bitbake invocation per flag or the metadata needs to copy the flags into variable values just to make them visible to the tests. Add get_bb_vars_flags, a more generic variant of get_bb_vars which reads variables as well as variable flags with a single tinfoil session. get_bb_vars is implemented on top of it, its return values do not change. Signed-off-by: Adrian Freihofer --- meta/lib/oeqa/utils/commands.py | 49 ++++++++++++++++++++++++++------- 1 file changed, 39 insertions(+), 10 deletions(-) diff --git a/meta/lib/oeqa/utils/commands.py b/meta/lib/oeqa/utils/commands.py index 1ccc107aed..7486a39dc5 100644 --- a/meta/lib/oeqa/utils/commands.py +++ b/meta/lib/oeqa/utils/commands.py @@ -253,15 +253,32 @@ def get_bb_env(target=None, postconfig=None): else: return bitbake("-e", postconfig=postconfig).output -def get_bb_vars(variables=None, target=None, postconfig=None): - """Get values of multiple bitbake variables +def _opt_str(val): + return str(val) if val is not None else None - All values are read with a single tinfoil session. If variables is None, - all variables are returned. Unset or empty values are returned as None. +def get_bb_vars_flags(variables=None, flags=None, target=None, postconfig=None): + """Get values and flags of multiple bitbake variables + + Everything is read with a single tinfoil session. variables is a list of + variable names or None to get all variables which are set. flags maps + variable names to lists of flag names. For example: + + get_bb_vars_flags(['FIT_HASH_ALG'], + {'FIT_LOADABLE_LOADADDRESS': ['loadable1', 'loadable2']}, + 'linux-yocto-fitimage') + + returns a tuple of the values and the flags: + + ({'FIT_HASH_ALG': 'sha256'}, + {'FIT_LOADABLE_LOADADDRESS': {'loadable1': '0x1000', 'loadable2': None}}) + + Unset variables and flags are returned as None, empty ones as an empty + string. """ import bb.tinfoil values = {} + flag_values = {} with _postconfig_file(postconfig) as postfile, bb.tinfoil.Tinfoil() as tinfoil: config_params = None if postfile: @@ -278,14 +295,26 @@ def get_bb_vars(variables=None, target=None, postconfig=None): if var.startswith('__') or d.getVarFlag(var, 'func'): continue val = d.getVar(var) - if val is not None and val != '': + if val is not None: values[var] = str(val) - return values + else: + for var in variables: + values[var] = _opt_str(d.getVar(var)) - for var in variables: - val = d.getVar(var) - values[var] = str(val) if val is not None and val != '' else None - return values + for var, names in (flags or {}).items(): + flag_values[var] = {name: _opt_str(d.getVarFlag(var, name)) for name in names} + return values, flag_values + +def get_bb_vars(variables=None, target=None, postconfig=None): + """Get values of multiple bitbake variables + + All values are read with a single tinfoil session. If variables is None, + all variables are returned. Unset or empty values are returned as None. + """ + values, _ = get_bb_vars_flags(variables, None, target, postconfig) + if variables is None: + return {var: val for var, val in values.items() if val} + return {var: val or None for var, val in values.items()} def get_bb_var(var, target=None, postconfig=None): if postconfig: From patchwork Wed Oct 28 21:11:24 2026 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: AdrianF X-Patchwork-Id: 102282 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.msgproc01-g2.7270.1793221928941858292 for ; Wed, 28 Oct 2026 14:12:10 -0700 Authentication-Results: mx.groups.io; dkim=pass header.i=adrian.freihofer@siemens.com header.s=fm2 header.b=dZANv1aN; spf=pass (domain: rts-flowmailer.siemens.com, ip: 185.136.64.227, mailfrom: fm-1329275-20261028211206aca8fbf4a200020723-g1dckf@rts-flowmailer.siemens.com) Received: by mta-64-227.siemens.flowmailer.net with ESMTPSA id 20261028211206aca8fbf4a200020723 for ; Wed, 28 Oct 2026 22:12:06 +0100 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; s=fm2; 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=d6ECSMoUeNs3iPEYE4/uYYdpmxJ7W76ZMffiwr3bmxU=; b=dZANv1aN7WaKL47/wIRtIC82hiVUZC7eu+WQeCS2/GxKp/b9NdhotFautVwG1B7uL1J5S+ 3NoGY3nn1RB1rAjPsPIxiI9pkVZZHHVBJ9WE3Dfn0oelhBKhvhyYPgjoRb8bFuhaAkJ/vh2j ZSoENw0/1FLB1pmEnc6gqHeeHSud+IokW7J/ivxfn4Trlv1+tnu7rzqSCrU0EqPJt9MRnige 7+I2fH35992z8e8Gar2LwhYxA8pgoEiGT/RikFh9XaZUKn3C8nBbSfhj4kL0jZjx0DflhrhD WJ4g9urogfGCUeiS+3Q2OvecEo8LmVkapQOwP2uXICFN3lKZh5IC9kjA==; From: AdrianF To: openembedded-core@lists.openembedded.org Cc: Adrian Freihofer Subject: [PATCH 2/3] oeqa/utils/commands: use get_bb_vars_flags in get_bb_var Date: Wed, 28 Oct 2026 22:11:24 +0100 Message-ID: <20261028211203.3081460-3-adrian.freihofer@siemens.com> In-Reply-To: <20261028211203.3081460-1-adrian.freihofer@siemens.com> References: <20261028211203.3081460-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 45-33-107-173.ip.linodeusercontent.com [45.33.107.173] by lin-tor-korg-lkml-alma10-1 with HTTPS for ; Wed, 28 Oct 2026 21:12:18 -0000 X-Groupsio-URL: https://lists.openembedded.org/g/openembedded-core/message/248831 From: Adrian Freihofer Replace the bitbake-getvar subprocess of get_bb_var with get_bb_vars_flags. The return values do not change: unset variables are returned as None, empty ones as an empty string and values are stripped. This also fixes get_bb_var with a postconfig file. It ran "bitbake -e" and returned its whole output instead of the value of the variable. Without a target it even failed, because "-e %s" % target or "" evaluated to "-e None". It went unnoticed because no caller in oe-core passes a postconfig. One behavior change: a recipe which does not exist now raises bb.providers.NoProvider. bitbake-getvar exited with status 1 in this case and get_bb_var returned None. Signed-off-by: Adrian Freihofer --- meta/lib/oeqa/utils/commands.py | 21 +++++++-------------- 1 file changed, 7 insertions(+), 14 deletions(-) diff --git a/meta/lib/oeqa/utils/commands.py b/meta/lib/oeqa/utils/commands.py index 7486a39dc5..3473ffb74b 100644 --- a/meta/lib/oeqa/utils/commands.py +++ b/meta/lib/oeqa/utils/commands.py @@ -317,20 +317,13 @@ def get_bb_vars(variables=None, target=None, postconfig=None): return {var: val or None for var, val in values.items()} def get_bb_var(var, target=None, postconfig=None): - if postconfig: - return bitbake("-e %s" % target or "", postconfig=postconfig).output - else: - # Fast-path for the non-postconfig case - cmd = ["bitbake-getvar", "--quiet", "--value", var] - if target: - cmd.extend(["--recipe", target]) - try: - return subprocess.run(cmd, check=True, text=True, stdout=subprocess.PIPE).stdout.strip() - except subprocess.CalledProcessError as e: - # We need to return None not the empty string if the variable hasn't been set. - if e.returncode == 1: - return None - raise + """Get the value of a bitbake variable + + Unset variables are returned as None, empty values as an empty string. + """ + values, _ = get_bb_vars_flags([var], None, target, postconfig) + val = values[var] + return val.strip() if val is not None else None def get_test_layer(bblayers=None): if bblayers is None: From patchwork Wed Oct 28 21:11:25 2026 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: AdrianF X-Patchwork-Id: 102281 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.msgproc02-g2.7177.1793221929090469937 for ; Wed, 28 Oct 2026 14:12:10 -0700 Authentication-Results: mx.groups.io; dkim=pass header.i=adrian.freihofer@siemens.com header.s=fm2 header.b=hgtK0SC9; spf=pass (domain: rts-flowmailer.siemens.com, ip: 185.136.64.228, mailfrom: fm-1329275-20261028211206be661a5b85000207fe-b3tyk3@rts-flowmailer.siemens.com) Received: by mta-64-228.siemens.flowmailer.net with ESMTPSA id 20261028211206be661a5b85000207fe for ; Wed, 28 Oct 2026 22:12:06 +0100 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; s=fm2; 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=/xfwsoOkM9ZgI44tCRVWrbjUeRVyyYCqUeZ1/8f49ZA=; b=hgtK0SC9JRVuzSQ3gzhPXOh+1gcVzxnr/7afmYvnGz7PgcR1s8KokDfczvBhlB1rXT8lIb xGlF9I9J6Emb4DwZOfXM+fldBwmfXJbw2qDDPPl49r75Li5TI4peM7IZyD8r4yps2J88Zrlh bVzVyrMr3lYyte8d8a2A+O/T8j5LJGnC1Bx4iN+q+8IVhg+OD4BCZv+mXidx3cyjP+s3qGft AhLfuaLC0FbTKnvgdkQ3OD91gwnp1z3ERIQz96I8BBVST4hMho+TgEhBmWR1fUX1fMmWYhDT Q1fcv8yzCpCzahuSdahXPn4DHtlwBhkcmicqXZ2ELAu7Ugeeh+ZbvW9w==; From: AdrianF To: openembedded-core@lists.openembedded.org Cc: Adrian Freihofer Subject: [PATCH 3/3] kernel-fit-image: drop the synthetic FIT_LOADABLE_* values Date: Wed, 28 Oct 2026 22:11:25 +0100 Message-ID: <20261028211203.3081460-4-adrian.freihofer@siemens.com> In-Reply-To: <20261028211203.3081460-1-adrian.freihofer@siemens.com> References: <20261028211203.3081460-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 45-33-107-173.ip.linodeusercontent.com [45.33.107.173] by lin-tor-korg-lkml-alma10-1 with HTTPS for ; Wed, 28 Oct 2026 21:12:18 -0000 X-Groupsio-URL: https://lists.openembedded.org/g/openembedded-core/message/248830 From: Adrian Freihofer The anonymous function sets the FIT_LOADABLE_* variables to the flags of all loadables joined by " ? ", e.g. "0x86000000 ? 0x87000000". This was done only to make the flags visible to the selftests, which could read variables but not flags. do_compile reads the flags directly and does not need these values. get_bb_vars_flags can read variable flags now. Let the test request the FIT_LOADABLE_* flags of the loadables it configures and drop the synthetic values from the class. Signed-off-by: Adrian Freihofer --- meta/classes-recipe/kernel-fit-image.bbclass | 7 ++---- meta/lib/oeqa/selftest/cases/fitimage.py | 24 ++++++++++++-------- 2 files changed, 16 insertions(+), 15 deletions(-) diff --git a/meta/classes-recipe/kernel-fit-image.bbclass b/meta/classes-recipe/kernel-fit-image.bbclass index a238de1aa2..abf7327c97 100644 --- a/meta/classes-recipe/kernel-fit-image.bbclass +++ b/meta/classes-recipe/kernel-fit-image.bbclass @@ -32,8 +32,8 @@ python () { # Parse loadables config loadables = d.getVar('FIT_LOADABLES') if loadables: - # Forbid direct assignment, set synthetic values for testability and - # add the vars to vardeps so their flags are part of the signature. + # Only flags are supported. Add the vars to vardeps so their flags are + # part of the signature. loadable_vars = ['FIT_LOADABLE_ARCH', 'FIT_LOADABLE_COMPRESSION', 'FIT_LOADABLE_DESCRIPTION', 'FIT_LOADABLE_ENTRYPOINT', 'FIT_LOADABLE_FILENAME', 'FIT_LOADABLE_LOADADDRESS', @@ -41,9 +41,6 @@ python () { for v in loadable_vars: if d.getVar(v): raise bb.parse.SkipRecipe("You cannot use %s as a variable, you can only set flags." % v) - - synt_value = " ? ".join([ d.getVarFlag(v, loadable) or "" for loadable in loadables.split() ]) - d.setVar(v, synt_value) d.appendVarFlag('do_compile', 'vardeps', ' ' + ' '.join(loadable_vars)) } diff --git a/meta/lib/oeqa/selftest/cases/fitimage.py b/meta/lib/oeqa/selftest/cases/fitimage.py index 81d2be5013..1fad53b16c 100644 --- a/meta/lib/oeqa/selftest/cases/fitimage.py +++ b/meta/lib/oeqa/selftest/cases/fitimage.py @@ -14,7 +14,7 @@ import oe.fitimage from bb import BBHandledException from oeqa.selftest.case import OESelftestTestCase -from oeqa.utils.commands import runCmd, bitbake, get_bb_vars, get_bb_var +from oeqa.utils.commands import runCmd, bitbake, get_bb_vars, get_bb_vars_flags, get_bb_var class BbVarsMockGenKeys: @@ -662,10 +662,12 @@ class FitImageTestCase(OESelftestTestCase): class KernelFitImageBase(FitImageTestCase): """Test cases for the linux-yocto-fitimage recipe""" - def _fit_get_bb_vars(self, additional_vars=[]): + def _fit_get_bb_vars(self, additional_vars=[], flags=None): """Retrieve BitBake variables specific to the test case. - Call the get_bb_vars function once and get all variables needed by the test case. + Call the get_bb_vars_flags function once and get all variables needed by + the test case. flags maps variable names to lists of flag names. The + flags are returned as dict {flag name: value} for their variable name. """ internal_used = { 'DEPLOY_DIR_IMAGE', @@ -676,8 +678,6 @@ class KernelFitImageBase(FitImageTestCase): 'FIT_HASH_ALG', 'FIT_KERNEL_COMP_ALG', 'FIT_LOADABLES', - 'FIT_LOADABLE_ENTRYPOINT', - 'FIT_LOADABLE_LOADADDRESS', 'FIT_OS', 'FIT_SIGN_ALG', 'FIT_SIGN_INDIVIDUAL', @@ -712,7 +712,9 @@ class KernelFitImageBase(FitImageTestCase): 'UBOOT_FIT_TEE_LOADADDRESS', 'UBOOT_FIT_TEE_ENTRYPOINT', } - bb_vars = get_bb_vars(list(internal_used | set(additional_vars)), self.kernel_recipe) + bb_vars, bb_flags = get_bb_vars_flags([*internal_used, *additional_vars], flags, self.kernel_recipe) + bb_vars = {var: val or None for var, val in bb_vars.items()} + bb_vars.update(bb_flags) self.logger.debug("bb_vars: %s" % pprint.pformat(bb_vars, indent=4)) return bb_vars @@ -1025,10 +1027,10 @@ class KernelFitImageBase(FitImageTestCase): "Entry Point": bb_vars['UBOOT_RD_ENTRYPOINT'] } # Create one section per loadable - for index,loadable in enumerate(loadables): - loadaddress = bb_vars['FIT_LOADABLE_LOADADDRESS'].split("?")[index].strip() + for loadable in loadables: + loadaddress = bb_vars['FIT_LOADABLE_LOADADDRESS'][loadable] req_sections[loadable] = { "Load Address": loadaddress } - entrypoint = bb_vars['FIT_LOADABLE_ENTRYPOINT'].split("?")[index].strip() + entrypoint = bb_vars['FIT_LOADABLE_ENTRYPOINT'][loadable] if entrypoint: req_sections[loadable]['Entry Point'] = entrypoint # Create a configuration section for each DTB @@ -1204,7 +1206,9 @@ FIT_LOADABLE_TYPE[loadable2] = "firmware" config = FitImageTestCase._config_add_machine_settings(config, machine, keys=["KERNEL_DEVICETREE", "FIT_CONF_DEFAULT_DTB"]) config = self._config_add_kernel_classes(config) self.write_config(config) - bb_vars = self._fit_get_bb_vars() + loadables = ['loadable1', 'loadable2'] + bb_vars = self._fit_get_bb_vars(flags={'FIT_LOADABLE_ENTRYPOINT': loadables, + 'FIT_LOADABLE_LOADADDRESS': loadables}) self._gen_atf_tee_dummy_images(bb_vars) self._test_fitimage(bb_vars)