@@ -8,6 +8,7 @@ LIC_FILES_CHKSUM = "file://${COMMON_LICENSE_DIR}/MIT;md5=0835ade698e0bcf8506ecda
inherit devicetree
+TEST_EXTRA_DTB ?= ""
COMPATIBLE_MACHINE = ".*"
SRC_URI = "\
@@ -18,8 +19,18 @@ SRC_URI = "\
# Sym-links are handled as extra configuration nodes in FIT images.
do_install:append() {
ln -sf test-ext.dtb "${D}/boot/devicetree/test-ext-alias.dtb"
+
+ if [ -n "${TEST_EXTRA_DTB}" ]; then
+ cp "${D}/boot/devicetree/test-ext.dtb" \
+ "${D}/boot/devicetree/${TEST_EXTRA_DTB}"
+ fi
}
do_deploy:append() {
ln -sf test-ext.dtb "${DEPLOYDIR}/devicetree/test-ext-alias.dtb"
+
+ if [ -n "${TEST_EXTRA_DTB}" ]; then
+ cp "${DEPLOYDIR}/devicetree/test-ext.dtb" \
+ "${DEPLOYDIR}/devicetree/${TEST_EXTRA_DTB}"
+ fi
}
@@ -192,6 +192,7 @@ python do_compile() {
# Prepare a DTB image section
kernel_devicetree = d.getVar('KERNEL_DEVICETREE')
external_kernel_devicetree = d.getVar("EXTERNAL_KERNEL_DEVICETREE")
+ external_dtb_aliases = {}
if kernel_devicetree:
for dtb in kernel_devicetree.split():
# In deploy_dir the DTBs are without sub-directories also with KERNEL_DTBVENDORED = "1"
@@ -205,6 +206,8 @@ python do_compile() {
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:
+ if conf_name != dtb_name:
+ external_dtb_aliases[conf_name] = ext_dtb_path
continue
# Copy the dtb or dtbo file into the FIT image assembly directory
@@ -229,6 +232,10 @@ python do_compile() {
root_node.fitimage_emit_section_dtb(dtb_name, dtb_name,
d.getVar("UBOOT_DTB_LOADADDRESS"), d.getVar("UBOOT_DTBO_LOADADDRESS"), True)
+ for alias, dtb_path in external_dtb_aliases.items():
+ symlink_target = oe.fitimage.symlink_points_below(os.path.basename(dtb_path), external_kernel_devicetree)
+ root_node.fitimage_emit_section_dtb_alias(alias, symlink_target or dtb_path)
+
# Prepare a u-boot script section
fit_uboot_env = d.getVar("FIT_UBOOT_ENV")
if fit_uboot_env:
@@ -467,10 +467,9 @@ class FitImageTestCase(OESelftestTestCase):
kernel_devicetree = bb_vars.get('KERNEL_DEVICETREE')
all_dtbs = []
dtb_aliases = {}
+ external_aliases = {}
+ kernel_dtbs = kernel_devicetree.split() if kernel_devicetree else []
- if kernel_devicetree:
- all_dtbs += [FitImageTestCase._apply_dtbvendored(bb_vars, dtb) for dtb in kernel_devicetree.split()]
-
if bb_vars.get("PREFERRED_PROVIDER_virtual/dtb") == "test-dtbs-as-ext":
if bb_vars.get("_python_only_test"):
external_dtbs, external_aliases = FitImageTestCase._get_test_dtb_files()
@@ -481,6 +480,23 @@ class FitImageTestCase(OESelftestTestCase):
all_dtbs.extend(external_dtbs)
dtb_aliases.update(external_aliases)
+ for dtb in kernel_dtbs:
+ dtb_name = os.path.basename(dtb)
+ mapped_name = FitImageTestCase._apply_dtbvendored(bb_vars, dtb)
+
+ if dtb_name in all_dtbs:
+ target = dtb_name
+ elif dtb_name in external_aliases:
+ target = external_aliases[dtb_name]
+ else:
+ target = None
+
+ if target:
+ if mapped_name != target:
+ dtb_aliases[mapped_name] = target
+ else:
+ all_dtbs.append(mapped_name)
+
return all_dtbs, dtb_aliases
@staticmethod
@@ -508,10 +524,10 @@ class FitImageTestCase(OESelftestTestCase):
extra_configs = []
for conf in configs:
dtb = dtbs[conf]
- if dtb in dtb_aliases:
- dtb = dtb_aliases[dtb]
- elif dtb:
+ if dtb:
dtb = FitImageTestCase._apply_dtbvendored(bb_vars, dtb)
+ dtb = dtb_aliases.get(dtb, dtb)
+
extra_configs.append((conf, kernels[conf] or "kernel-1", dtb))
return extra_configs
@@ -1379,6 +1395,58 @@ PREFERRED_PROVIDER_virtual/dtb = "test-dtbs-as-ext"
self._gen_atf_tee_dummy_images(bb_vars)
self._test_fitimage(bb_vars)
+ def test_fit_image_ext_dtb_vendored_override(self):
+ """Check that an external DTB overrides a vendored kernel DTB."""
+ machine = self._get_machine_or_skip()
+
+ if machine != "qemuarm64":
+ self.skipTest("This test requires the qemuarm64 foundation-v8.dtb")
+
+ config = """
+KERNEL_DTBVENDORED = "1"
+PREFERRED_PROVIDER_virtual/dtb = "test-dtbs-as-ext"
+TEST_EXTRA_DTB = "foundation-v8.dtb"
+FIT_CONF_DEFAULT_DTB = "arm/foundation-v8.dtb"
+FIT_CONFIGS = "external-override"
+FIT_CONFIG_DTB[external-override] = "arm/foundation-v8.dtb"
+"""
+ config = self._config_add_machine_settings(config, machine, keys=["KERNEL_DEVICETREE"])
+ 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._gen_atf_tee_dummy_images(bb_vars)
+
+ its_path, fit_path = self._bitbake_fit_image(bb_vars)
+
+ self.assertExists(its_path)
+ self.assertExists(fit_path)
+
+ self.logger.info("Regression test ITS: %s", its_path)
+
+ with open(its_path, encoding="utf-8") as f:
+ its = f.read()
+
+ self.assertIn("fdt-foundation-v8.dtb", its)
+ self.assertIn("conf-arm_foundation-v8.dtb", its)
+ self.assertIn("conf-external-override", its)
+ self.assertNotIn("fdt-arm_foundation-v8.dtb {", its)
+ # The vendored configuration must be the default.
+ self.assertIn('default = "conf-arm_foundation-v8.dtb";', its)
+
+ # Both the vendored and custom configurations must reference
+ # the external DTB image.
+ for conf in ("conf-arm_foundation-v8.dtb", "conf-external-override"):
+ match = re.search(r'\b' + re.escape(conf) + r'\s*\{([^{}]*)', its)
+ self.assertIsNotNone(match, "Missing configuration: %s" % conf)
+ self.assertIn('fdt = "fdt-foundation-v8.dtb";', match.group(1))
+
+ self._check_its_file(bb_vars, its_path)
+
+ uboot_tools_bindir = self._setup_native('u-boot-tools-native')
+ self._check_fitimage(bb_vars, fit_path, uboot_tools_bindir)
def test_sign_fit_image_configurations(self):
"""
@@ -1616,17 +1684,17 @@ class FitImagePyTests(KernelFitImageBase):
root.fitimage_emit_section_dtb(
"test-overlay.dtbo", "a-dir/test-overlay.dtbo"
)
-
+
with self.assertRaises(bb.BBHandledException):
root.fitimage_emit_section_config_custom(
"invalid", "kernel-1", "test-overlay.dtbo"
)
-
+
# A regular DTB may explicitly select a kernel.
root.fitimage_emit_section_dtb(
"test-board.dtb", "a-dir/test-board.dtb"
)
-
+
root.fitimage_emit_section_config_custom(
"regular", "kernel-1", "test-board.dtb"
)
@@ -1639,7 +1707,7 @@ class FitImagePyTests(KernelFitImageBase):
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
@@ -1764,6 +1832,23 @@ class FitImagePyTests(KernelFitImageBase):
self.logger.debug("Checking its: %s" % fitimage_its_path)
self._check_its_file(bb_vars, fitimage_its_path)
+ def test_fitimage_py_vendored_external_dtb_symlink_override(self):
+ bb_vars = {
+ "KERNEL_DEVICETREE": "arm/test-ext-alias.dtb",
+ "KERNEL_DTBVENDORED": "1",
+ "PREFERRED_PROVIDER_virtual/dtb": "test-dtbs-as-ext",
+ "_python_only_test": True,
+ }
+
+ dtbs, aliases = FitImageTestCase._get_dtb_files(bb_vars)
+
+ self.assertIn("test-ext.dtb", dtbs)
+ self.assertNotIn("arm_test-ext-alias.dtb", dtbs)
+ self.assertEqual(aliases["arm_test-ext-alias.dtb"],"test-ext.dtb")
+
+ # Verify that the original external symlink alias is preserved
+ self.assertEqual(aliases["test-ext-alias.dtb"], "test-ext.dtb")
+
def test_fitimage_py_default(self):
self._test_fitimage_py()