@@ -509,6 +509,7 @@ class KernelFitImageBase(FitImageTestCase):
'UBOOT_SIGN_IMG_KEYNAME',
'UBOOT_SIGN_KEYDIR',
'UBOOT_SIGN_KEYNAME',
+ 'UBOOT_DTB_IMAGE',
}
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))
@@ -571,9 +572,21 @@ class KernelFitImageBase(FitImageTestCase):
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))
+ setup_bin_dir = os.path.join(deploy_dir_image, kernel_deploysubdir)
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))
+ setup_bin_dir = deploy_dir_image
+ # x86 kernel builds produce setup.bin which is packed into the FIT image.
+ # Detect this and inject KERNEL_SETUP_BIN into bb_vars so that the
+ # downstream helpers (_get_req_its_paths, _get_req_sections, etc.) can
+ # use it instead of checking MACHINE == "qemux86-64" directly.
+ if bb_vars['MACHINE'] == "qemux86-64":
+ setup_bin_path = os.path.join(setup_bin_dir, "setup.bin")
+ self.assertExists(setup_bin_path, "Expected setup.bin artifact not found: %s" % setup_bin_path)
+ bb_vars['KERNEL_SETUP_BIN'] = "setup.bin"
+ else:
+ bb_vars['KERNEL_SETUP_BIN'] = ""
return (fitimage_its_path, fitimage_path)
def _get_req_its_paths(self, bb_vars):
@@ -605,7 +618,10 @@ class KernelFitImageBase(FitImageTestCase):
else:
not_images.append('bootscr-boot.cmd')
- if bb_vars['MACHINE'] == "qemux86-64": # Not really the right if
+ # setup-1 is an x86-only section present when the kernel build emits
+ # setup.bin. KERNEL_SETUP_BIN is either injected by _bitbake_fit_image
+ # after the build, or set explicitly in unit tests.
+ if bb_vars.get('KERNEL_SETUP_BIN'):
images.append('setup-1')
else:
not_images.append('setup-1')
@@ -737,11 +753,16 @@ class KernelFitImageBase(FitImageTestCase):
"""Generate a dictionary of expected configuration signature nodes"""
if bb_vars.get('UBOOT_SIGN_ENABLE') != "1":
return {}
- sign_images = '"kernel", "fdt"'
+ sign_images = '"kernel"'
+ dtb_files, _ = FitImageTestCase._get_dtb_files(bb_vars)
+ if dtb_files:
+ sign_images += ', "fdt"'
if bb_vars['INITRAMFS_IMAGE'] and bb_vars['INITRAMFS_IMAGE_BUNDLE'] != "1":
sign_images += ', "ramdisk"'
if bb_vars['FIT_UBOOT_ENV']:
sign_images += ', "bootscr"'
+ if bb_vars.get('KERNEL_SETUP_BIN'):
+ sign_images += ', "setup"'
req_sigvalues_config = {
'algo': '"%s,%s"' % (bb_vars['FIT_HASH_ALG'], bb_vars['FIT_SIGN_ALG']),
'key-name-hint': '"%s"' % bb_vars['UBOOT_SIGN_KEYNAME'],
@@ -789,6 +810,9 @@ class KernelFitImageBase(FitImageTestCase):
# Add a script section if there is a script
if fit_uboot_env:
req_sections['bootscr-' + fit_uboot_env] = { "Type": "Script" }
+ # Add the x86 setup section if present
+ if bb_vars.get('KERNEL_SETUP_BIN'):
+ req_sections['setup-1'] = { "Type": "x86 setup.bin" }
# Add the initramfs
if initramfs_image and initramfs_image_bundle != "1":
req_sections['ramdisk-1'] = {
@@ -864,6 +888,15 @@ class KernelFitImageBase(FitImageTestCase):
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]
+ dtb_files, dtb_symlinks = FitImageTestCase._get_dtb_files(bb_vars)
+ all_dtb_names = set(dtb_files + dtb_symlinks)
+ # The public key is always injected into UBOOT_DTB_IMAGE (-K flag in
+ # uboot-sign.bbclass concat_dtb). For DTB-based configurations the same
+ # key is also injected into each per-configuration DTB, so either file
+ # works. For configurations without a matching DTB (e.g. conf-1 on x86)
+ # UBOOT_DTB_IMAGE is the only option.
+ uboot_dtb_image = bb_vars.get('UBOOT_DTB_IMAGE')
+ uboot_dtb_path_default = os.path.join(deploy_dir_image, uboot_dtb_image) if uboot_dtb_image else None
for section, values in sections.items():
# Configuration nodes are always signed with UBOOT_SIGN_KEYNAME (if UBOOT_SIGN_ENABLE = "1")
if section.startswith(bb_vars['FIT_CONF_PREFIX']):
@@ -873,13 +906,29 @@ class KernelFitImageBase(FitImageTestCase):
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_file_name = section.replace(bb_vars['FIT_CONF_PREFIX'], '')
- 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):
- dtb_path = dtb_path_ext
+ if dtb_file_name in all_dtb_names:
+ # Use the per-configuration DTB (public key is also injected there)
+ 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):
+ dtb_path = dtb_path_ext
+ elif uboot_dtb_path_default:
+ # No per-config DTB (e.g. conf-1 on x86): use the U-Boot DTB
+ # which always gets the public key injected via -K in concat_dtb
+ dtb_path = uboot_dtb_path_default
+ else:
+ # No key-holding DTB available (e.g. qemux86-64 without
+ # UBOOT_DTB_BINARY). The algo/key-name/value checks above
+ # already ran; the cryptographic fit_check_sign step is not
+ # possible without a DTB containing the public key.
+ self.logger.debug(
+ "Skipping fit_check_sign for section %s: no UBOOT_DTB_IMAGE "
+ "available to carry the public key on MACHINE=%s"
+ % (section, bb_vars.get('MACHINE', '?')))
+ continue
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
@@ -1247,7 +1296,10 @@ class FitImagePyTests(KernelFitImageBase):
# others
'MACHINE': "qemux86-64",
'UBOOT_ARCH': "x86",
- 'HOST_PREFIX': "x86_64-poky-linux-"
+ 'HOST_PREFIX': "x86_64-poky-linux-",
+ # x86 kernels produce a setup.bin section; set to the file name to
+ # enable it, or to "" / omit the key to suppress it.
+ 'KERNEL_SETUP_BIN': 'setup1.bin',
}
if bb_vars_overrides:
bb_vars.update(bb_vars_overrides)
@@ -1286,8 +1338,8 @@ class FitImagePyTests(KernelFitImageBase):
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('KERNEL_SETUP_BIN'):
+ root_node.fitimage_emit_section_setup("setup-1", bb_vars['KERNEL_SETUP_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",