| Message ID | 20250930065117.2625998-2-kavinaya@qti.qualcomm.com |
|---|---|
| State | New |
| Headers | show |
| Series | Add support for custom compatible string via optional parameter | expand |
On Tue, 30 Sept 2025 at 08:51, Kavinaya S <kavinaya@qti.qualcomm.com> wrote: > --- a/meta/lib/oeqa/selftest/cases/fitimage.py > +++ b/meta/lib/oeqa/selftest/cases/fitimage.py > @@ -778,6 +778,8 @@ FIT_CONF_PREFIX = "foo-" > 1. bitbake bbb-dtbs-as-ext > 2. Check if symlink_points_below returns the path to the DTB > 3. Check if the expected compatible string is found by get_compatible_from_dtb() > + 4. Verify that a custom compatible string can be passed > + > """ > DTB_RECIPE = "bbb-dtbs-as-ext" > DTB_FILE = "am335x-bonegreen-ext.dtb" > @@ -788,6 +790,7 @@ FIT_CONF_PREFIX = "foo-" > config = """ > DISTRO = "poky" > MACHINE = "beaglebone-yocto" > +FIT_DTB_COMPATIBLE_OVERRIDE_am335x-bonegreen-ext.dtb = "custom,board custom,variant" > """ > self.write_config(config) > > @@ -819,6 +822,11 @@ MACHINE = "beaglebone-yocto" > # The alias is a symlink, therefore the compatible string is equal > self.assertEqual(comp_alias, comp) > > + # Test custom compatible string override via FIT_DTB_COMPATIBLE_OVERRIDE variable > + custom_override = get_bb_var("FIT_DTB_COMPATIBLE_OVERRIDE_am335x-bonegreen-ext.dtb", DTB_RECIPE) > + self.assertTrue(custom_override) > + self.assertEqual(str(custom_override).split(), ["custom,board", "custom,variant"]) > + I took a closer look at the selftest, and actually this is not right. This modifies a test that is intended specifically for testing get_compatible_from_dtb() (so it's not the right test to modify), and it doesn't check that passing in a custom compatible will result in a correct .its output, it only checks that getting a bitbake variable (after it's been set) works ok - not a useful check. Rather, I think you should take a look at test_fitimage_py_default() and test_fitimage_py_default_dtb(), and add one more test that sets the custom compatible. Adrian could probably give more authoritative advice. Alex
On Tue, Sep 30, 2025 at 12:21:17PM +0530, Kavinaya S wrote: > Currently, fitimage_emit_section_dtb() always derives the 'compatible' > property from the DTB using fdtget when add_compatible=True. In some > cases, it is desirable to override this with a custom compatible string In which cases? Could you please be more specific here? > defined in the build metadata. > > 1.The compatible string format that we require is different from what > dynamic generation allows. The format that we rely on is: > > compatible = "qcom,<SoC>[-<soc_version>][-<foundry_id>]-<board> > [/<subtype>][-<pmic>][-<board_version>]" > > This structure enables precise identification of the appropriate DTB > for each board variant. > > 2.As in the upstream kernel Makefile for QCOM platforms QCOM->Qualcomm > (https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/arch/arm64/boot/dts/qcom/Makefile ), overlays are used to generate composite DTBs: You should have gotten a warning from check-patch / b4 here. > > dtb-$(CONFIG_ARCH_QCOM) += qcs6490-rb3gen2.dtb > qcs6490-rb3gen2-vision-mezzanine-dtbs := qcs6490-rb3gen2.dtb qcs6490-rb3gen2-vision-mezzanine.dtbo > qcs6490-rb3gen2-industrial-mezzanine-dtbs := qcs6490-rb3gen2.dtb qcs6490-rb3gen2-industrial-mezzanine.dtbo > > In the above cases, the base DTB remains the same, but the > overlays differ. In such cases,we cannot assign unique compatible > strings to these variants. Of course you can. > > This patch introduces an optional 'custom_compatible' parameter to s/This patch// > fitimage_emit_section_dtb(). When provided, this value is used instead > of extracting from the DTB. The parameter accepts either a space- > separated string or a list of strings, which are split into the Can't you seetle on one format? Whitespace-separated string should be fine, it's the format that is commonly accepted by other routines. > compatible array for the ITS node. > > This patch also updates test_get_compatible_from_dtb() to check that the > FIT_DTB_COMPATIBLE_OVERRIDE_<dtb>.dtb variable is applied correctly. > > Suggested-By: Alexander Kanavin <alex.kanavin@gmail.com> > Signed-off-by: Kavinaya S <kavinaya@qti.qualcomm.com> > --- > meta/classes-recipe/kernel-fit-image.bbclass | 3 ++- > meta/conf/image-fitimage.conf | 6 ++++++ > meta/lib/oe/fitimage.py | 12 +++++++++--- > meta/lib/oeqa/selftest/cases/fitimage.py | 8 ++++++++ > 4 files changed, 25 insertions(+), 4 deletions(-) > > diff --git a/meta/classes-recipe/kernel-fit-image.bbclass b/meta/classes-recipe/kernel-fit-image.bbclass > index f04aee1807..de0f3c332e 100644 > --- a/meta/classes-recipe/kernel-fit-image.bbclass > +++ b/meta/classes-recipe/kernel-fit-image.bbclass > @@ -84,8 +84,9 @@ python do_compile() { > > # Copy the dtb or dtbo file into the FIT image assembly directory > shutil.copyfile(os.path.join(kernel_deploydir, dtb_name), dtb_name) > + custom_compatible_str = d.getVar(f"FIT_DTB_COMPATIBLE_OVERRIDE_{dtb_name}") or None Would it be better to use VarFlags instead of a var? Also I think you need to declare dependency on the corresponding variable. > root_node.fitimage_emit_section_dtb(dtb_name, dtb_name, > - d.getVar("UBOOT_DTB_LOADADDRESS"), d.getVar("UBOOT_DTBO_LOADADDRESS")) > + d.getVar("UBOOT_DTB_LOADADDRESS"), d.getVar("UBOOT_DTBO_LOADADDRESS"), True, custom_compatible=custom_compatible_str) The string is too long, split it. > > if external_kernel_devicetree: > # iterate over all .dtb and .dtbo files in the external kernel devicetree directory > diff --git a/meta/conf/image-fitimage.conf b/meta/conf/image-fitimage.conf > index 090ee148f4..f685948c3b 100644 > --- a/meta/conf/image-fitimage.conf > +++ b/meta/conf/image-fitimage.conf > @@ -65,3 +65,9 @@ FIT_ADDRESS_CELLS ?= "1" > # Machine configurations needing such a script file should include it in the > # SRC_URI of the kernel recipe and set the FIT_UBOOT_ENV parameter. > FIT_UBOOT_ENV ?= "" > + > + > +# To override the DTB 'compatible' string in the FIT image, add in your > +# machine.conf or local.conf: > +# > +# FIT_DTB_COMPATIBLE_OVERRIDE_qcs6490-rb3gen2-vision-mezzanine.dtb = "qcom,qcs6490-rb-subtype2" Also no need for .dtb here. What about: FIT_DTB_COMPATIBLE_OVERRIDE[qcs6490-rb3gen2-vision-mezzanine] > diff --git a/meta/lib/oe/fitimage.py b/meta/lib/oe/fitimage.py > index f303799155..54baba28bc 100644 > --- a/meta/lib/oe/fitimage.py > +++ b/meta/lib/oe/fitimage.py > @@ -289,7 +289,7 @@ class ItsNodeRootKernel(ItsNode): > self._kernel = kernel_node > > def fitimage_emit_section_dtb(self, dtb_id, dtb_path, dtb_loadaddress=None, > - dtbo_loadaddress=None, add_compatible=False): > + dtbo_loadaddress=None, add_compatible=False, custom_compatible=None): Also too long > """Emit the fitImage ITS DTB section""" > load=None > dtb_ext = os.path.splitext(dtb_path)[1] > @@ -309,7 +309,10 @@ class ItsNodeRootKernel(ItsNode): > # Preserve the DTB's compatible string to be added to the configuration node > compatible = None > if add_compatible: > - compatible = get_compatible_from_dtb(dtb_path) > + if custom_compatible: > + compatible = str(custom_compatible).split() > + else: > + compatible = get_compatible_from_dtb(dtb_path) > > dtb_node = self.its_add_node_dtb( > "fdt-" + dtb_id, > @@ -326,7 +329,10 @@ class ItsNodeRootKernel(ItsNode): > # Preserve the DTB's compatible string to be added to the configuration node > compatible = None > if add_compatible: > - compatible = get_compatible_from_dtb(dtb_path) > + if custom_compatible: > + compatible = str(custom_compatible).split() > + else: > + compatible = get_compatible_from_dtb(dtb_path) > > dtb_id = os.path.basename(dtb_path) > dtb_alias_node = ItsNodeDtbAlias("fdt-" + dtb_id, dtb_alias_id, compatible) > diff --git a/meta/lib/oeqa/selftest/cases/fitimage.py b/meta/lib/oeqa/selftest/cases/fitimage.py > index 3c40857747..1ca55a7706 100644 > --- a/meta/lib/oeqa/selftest/cases/fitimage.py > +++ b/meta/lib/oeqa/selftest/cases/fitimage.py > @@ -778,6 +778,8 @@ FIT_CONF_PREFIX = "foo-" > 1. bitbake bbb-dtbs-as-ext > 2. Check if symlink_points_below returns the path to the DTB > 3. Check if the expected compatible string is found by get_compatible_from_dtb() > + 4. Verify that a custom compatible string can be passed > + > """ > DTB_RECIPE = "bbb-dtbs-as-ext" > DTB_FILE = "am335x-bonegreen-ext.dtb" > @@ -788,6 +790,7 @@ FIT_CONF_PREFIX = "foo-" > config = """ > DISTRO = "poky" > MACHINE = "beaglebone-yocto" > +FIT_DTB_COMPATIBLE_OVERRIDE_am335x-bonegreen-ext.dtb = "custom,board custom,variant" > """ > self.write_config(config) > > @@ -819,6 +822,11 @@ MACHINE = "beaglebone-yocto" > # The alias is a symlink, therefore the compatible string is equal > self.assertEqual(comp_alias, comp) > > + # Test custom compatible string override via FIT_DTB_COMPATIBLE_OVERRIDE variable > + custom_override = get_bb_var("FIT_DTB_COMPATIBLE_OVERRIDE_am335x-bonegreen-ext.dtb", DTB_RECIPE) > + self.assertTrue(custom_override) > + self.assertEqual(str(custom_override).split(), ["custom,board", "custom,variant"]) > + > def test_fit_image_ext_dtb_dtbo(self): > """ > Summary: Check if FIT image and Image Tree Source (its) are created correctly. > -- > 2.34.1 > >
On Tue, Sep 30, 2025 at 01:01:45PM +0200, Alexander Kanavin wrote: > On Tue, 30 Sept 2025 at 08:51, Kavinaya S <kavinaya@qti.qualcomm.com> wrote: > > > --- a/meta/lib/oeqa/selftest/cases/fitimage.py > > +++ b/meta/lib/oeqa/selftest/cases/fitimage.py > > @@ -778,6 +778,8 @@ FIT_CONF_PREFIX = "foo-" > > 1. bitbake bbb-dtbs-as-ext > > 2. Check if symlink_points_below returns the path to the DTB > > 3. Check if the expected compatible string is found by get_compatible_from_dtb() > > + 4. Verify that a custom compatible string can be passed > > + > > """ > > DTB_RECIPE = "bbb-dtbs-as-ext" > > DTB_FILE = "am335x-bonegreen-ext.dtb" > > @@ -788,6 +790,7 @@ FIT_CONF_PREFIX = "foo-" > > config = """ > > DISTRO = "poky" > > MACHINE = "beaglebone-yocto" > > +FIT_DTB_COMPATIBLE_OVERRIDE_am335x-bonegreen-ext.dtb = "custom,board custom,variant" > > """ > > self.write_config(config) > > > > @@ -819,6 +822,11 @@ MACHINE = "beaglebone-yocto" > > # The alias is a symlink, therefore the compatible string is equal > > self.assertEqual(comp_alias, comp) > > > > + # Test custom compatible string override via FIT_DTB_COMPATIBLE_OVERRIDE variable > > + custom_override = get_bb_var("FIT_DTB_COMPATIBLE_OVERRIDE_am335x-bonegreen-ext.dtb", DTB_RECIPE) > > + self.assertTrue(custom_override) > > + self.assertEqual(str(custom_override).split(), ["custom,board", "custom,variant"]) > > + > > I took a closer look at the selftest, and actually this is not right. > This modifies a test that is intended specifically for testing > get_compatible_from_dtb() (so it's not the right test to modify), and > it doesn't check that passing in a custom compatible will result in a > correct .its output, it only checks that getting a bitbake variable > (after it's been set) works ok - not a useful check. Yes. I would suggest starting from the test, making sure that it documents the expected behaviour (and fails without your changes) and then implementing the python changes on top to make the test pass. > Rather, I think you should take a look at test_fitimage_py_default() > and test_fitimage_py_default_dtb(), and add one more test that sets > the custom compatible. Adrian could probably give more authoritative > advice.
On Mon, Oct 6, 2025 at 04:04 AM, Dmitry Baryshkov wrote: > > In which cases? Could you please be more specific here? > One case in Qualcomm DTBs is, both 'qcs6490-rb3gen2-vision-mezzanine.dtb' & 'qcs6490-rb3gen2-industrial-mezzanine.dtb' are going to have same compatible string even though the overlays applied are different. When they are packed into a single FIT Image, it is not possible to distinguish between them just by reading compatible string. Same is the case with 'apq8016-sbc-d3-camera-mezzanine.dtb' & 'apq8016-sbc-usb-host.dtb' as well.
On Mon, Oct 6, 2025 at 04:04 AM, Dmitry Baryshkov wrote: > > Of course you can. > Couldn't find any precedence in kernel device tree project for dtbos performing platform overlays. All I could see are performing only driver overlays. Since these are already accepted in linux kernel, assuming updating compatible string is not necessary always.
On Mon, Oct 6, 2025 at 04:04 AM, Dmitry Baryshkov wrote: > > Can't you seetle on one format? Whitespace-separated string should be > fine, it's the format that is commonly accepted by other routines. > Sure, will settle to whitespace-separated format.
On Mon, Oct 6, 2025 at 04:04 AM, Dmitry Baryshkov wrote: > > Also no need for .dtb here. What about: > > FIT_DTB_COMPATIBLE_OVERRIDE[qcs6490-rb3gen2-vision-mezzanine] > > > > > diff --git a/meta/lib/oe/fitimage.py b/meta/lib/oe/fitimage.py > > index f303799155..54baba28bc 100644 > > --- a/meta/lib/oe/fitimage.py > > +++ b/meta/lib/oe/fitimage.py > > @@ -289,7 +289,7 @@ class ItsNodeRootKernel(ItsNode): > > self._kernel = kernel_node > > > > def fitimage_emit_section_dtb(self, dtb_id, dtb_path, > > dtb_loadaddress=None, > > - dtbo_loadaddress=None, add_compatible=False): > > + dtbo_loadaddress=None, add_compatible=False, custom_compatible=None): > > Also too long > I'll refine the code as suggested in next patch. I will also update the test cases as required.
I will update the test case and upload a new patch. Thanks, Kavinaya
diff --git a/meta/classes-recipe/kernel-fit-image.bbclass b/meta/classes-recipe/kernel-fit-image.bbclass index f04aee1807..de0f3c332e 100644 --- a/meta/classes-recipe/kernel-fit-image.bbclass +++ b/meta/classes-recipe/kernel-fit-image.bbclass @@ -84,8 +84,9 @@ python do_compile() { # Copy the dtb or dtbo file into the FIT image assembly directory shutil.copyfile(os.path.join(kernel_deploydir, dtb_name), dtb_name) + custom_compatible_str = d.getVar(f"FIT_DTB_COMPATIBLE_OVERRIDE_{dtb_name}") or None root_node.fitimage_emit_section_dtb(dtb_name, dtb_name, - d.getVar("UBOOT_DTB_LOADADDRESS"), d.getVar("UBOOT_DTBO_LOADADDRESS")) + d.getVar("UBOOT_DTB_LOADADDRESS"), d.getVar("UBOOT_DTBO_LOADADDRESS"), True, custom_compatible=custom_compatible_str) if external_kernel_devicetree: # iterate over all .dtb and .dtbo files in the external kernel devicetree directory diff --git a/meta/conf/image-fitimage.conf b/meta/conf/image-fitimage.conf index 090ee148f4..f685948c3b 100644 --- a/meta/conf/image-fitimage.conf +++ b/meta/conf/image-fitimage.conf @@ -65,3 +65,9 @@ FIT_ADDRESS_CELLS ?= "1" # Machine configurations needing such a script file should include it in the # SRC_URI of the kernel recipe and set the FIT_UBOOT_ENV parameter. FIT_UBOOT_ENV ?= "" + + +# To override the DTB 'compatible' string in the FIT image, add in your +# machine.conf or local.conf: +# +# FIT_DTB_COMPATIBLE_OVERRIDE_qcs6490-rb3gen2-vision-mezzanine.dtb = "qcom,qcs6490-rb-subtype2" diff --git a/meta/lib/oe/fitimage.py b/meta/lib/oe/fitimage.py index f303799155..54baba28bc 100644 --- a/meta/lib/oe/fitimage.py +++ b/meta/lib/oe/fitimage.py @@ -289,7 +289,7 @@ class ItsNodeRootKernel(ItsNode): self._kernel = kernel_node def fitimage_emit_section_dtb(self, dtb_id, dtb_path, dtb_loadaddress=None, - dtbo_loadaddress=None, add_compatible=False): + dtbo_loadaddress=None, add_compatible=False, custom_compatible=None): """Emit the fitImage ITS DTB section""" load=None dtb_ext = os.path.splitext(dtb_path)[1] @@ -309,7 +309,10 @@ class ItsNodeRootKernel(ItsNode): # Preserve the DTB's compatible string to be added to the configuration node compatible = None if add_compatible: - compatible = get_compatible_from_dtb(dtb_path) + if custom_compatible: + compatible = str(custom_compatible).split() + else: + compatible = get_compatible_from_dtb(dtb_path) dtb_node = self.its_add_node_dtb( "fdt-" + dtb_id, @@ -326,7 +329,10 @@ class ItsNodeRootKernel(ItsNode): # Preserve the DTB's compatible string to be added to the configuration node compatible = None if add_compatible: - compatible = get_compatible_from_dtb(dtb_path) + if custom_compatible: + compatible = str(custom_compatible).split() + else: + compatible = get_compatible_from_dtb(dtb_path) dtb_id = os.path.basename(dtb_path) dtb_alias_node = ItsNodeDtbAlias("fdt-" + dtb_id, dtb_alias_id, compatible) diff --git a/meta/lib/oeqa/selftest/cases/fitimage.py b/meta/lib/oeqa/selftest/cases/fitimage.py index 3c40857747..1ca55a7706 100644 --- a/meta/lib/oeqa/selftest/cases/fitimage.py +++ b/meta/lib/oeqa/selftest/cases/fitimage.py @@ -778,6 +778,8 @@ FIT_CONF_PREFIX = "foo-" 1. bitbake bbb-dtbs-as-ext 2. Check if symlink_points_below returns the path to the DTB 3. Check if the expected compatible string is found by get_compatible_from_dtb() + 4. Verify that a custom compatible string can be passed + """ DTB_RECIPE = "bbb-dtbs-as-ext" DTB_FILE = "am335x-bonegreen-ext.dtb" @@ -788,6 +790,7 @@ FIT_CONF_PREFIX = "foo-" config = """ DISTRO = "poky" MACHINE = "beaglebone-yocto" +FIT_DTB_COMPATIBLE_OVERRIDE_am335x-bonegreen-ext.dtb = "custom,board custom,variant" """ self.write_config(config) @@ -819,6 +822,11 @@ MACHINE = "beaglebone-yocto" # The alias is a symlink, therefore the compatible string is equal self.assertEqual(comp_alias, comp) + # Test custom compatible string override via FIT_DTB_COMPATIBLE_OVERRIDE variable + custom_override = get_bb_var("FIT_DTB_COMPATIBLE_OVERRIDE_am335x-bonegreen-ext.dtb", DTB_RECIPE) + self.assertTrue(custom_override) + self.assertEqual(str(custom_override).split(), ["custom,board", "custom,variant"]) + def test_fit_image_ext_dtb_dtbo(self): """ Summary: Check if FIT image and Image Tree Source (its) are created correctly.
Currently, fitimage_emit_section_dtb() always derives the 'compatible' property from the DTB using fdtget when add_compatible=True. In some cases, it is desirable to override this with a custom compatible string defined in the build metadata. 1.The compatible string format that we require is different from what dynamic generation allows. The format that we rely on is: compatible = "qcom,<SoC>[-<soc_version>][-<foundry_id>]-<board> [/<subtype>][-<pmic>][-<board_version>]" This structure enables precise identification of the appropriate DTB for each board variant. 2.As in the upstream kernel Makefile for QCOM platforms (https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/arch/arm64/boot/dts/qcom/Makefile ), overlays are used to generate composite DTBs: dtb-$(CONFIG_ARCH_QCOM) += qcs6490-rb3gen2.dtb qcs6490-rb3gen2-vision-mezzanine-dtbs := qcs6490-rb3gen2.dtb qcs6490-rb3gen2-vision-mezzanine.dtbo qcs6490-rb3gen2-industrial-mezzanine-dtbs := qcs6490-rb3gen2.dtb qcs6490-rb3gen2-industrial-mezzanine.dtbo In the above cases, the base DTB remains the same, but the overlays differ. In such cases,we cannot assign unique compatible strings to these variants. This patch introduces an optional 'custom_compatible' parameter to fitimage_emit_section_dtb(). When provided, this value is used instead of extracting from the DTB. The parameter accepts either a space- separated string or a list of strings, which are split into the compatible array for the ITS node. This patch also updates test_get_compatible_from_dtb() to check that the FIT_DTB_COMPATIBLE_OVERRIDE_<dtb>.dtb variable is applied correctly. Suggested-By: Alexander Kanavin <alex.kanavin@gmail.com> Signed-off-by: Kavinaya S <kavinaya@qti.qualcomm.com> --- meta/classes-recipe/kernel-fit-image.bbclass | 3 ++- meta/conf/image-fitimage.conf | 6 ++++++ meta/lib/oe/fitimage.py | 12 +++++++++--- meta/lib/oeqa/selftest/cases/fitimage.py | 8 ++++++++ 4 files changed, 25 insertions(+), 4 deletions(-)