diff options
| author | Adrian Freihofer <adrian.freihofer@siemens.com> | 2025-06-03 10:23:24 +0200 |
|---|---|---|
| committer | Richard Purdie <richard.purdie@linuxfoundation.org> | 2025-06-05 11:02:21 +0100 |
| commit | 87fc5911504e6dea6e60819250ed8c6db82c9465 (patch) | |
| tree | 517ad42dd5d403d3a9e46d93ca62726da2e32e8a | |
| parent | 2dbbeb1d98daa3334c36dc5c15a8c3157ffc7988 (diff) | |
| download | poky-87fc5911504e6dea6e60819250ed8c6db82c9465.tar.gz | |
oe-selftest: fitimage: add tests for fitimage.py
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.
(From OE-Core rev: f990d95007a616bdafbe80c30877d3bdfd954c05)
Signed-off-by: Adrian Freihofer <adrian.freihofer@siemens.com>
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
| -rw-r--r-- | meta/lib/oeqa/selftest/cases/fitimage.py | 179 |
1 files changed, 175 insertions, 4 deletions
diff --git a/meta/lib/oeqa/selftest/cases/fitimage.py b/meta/lib/oeqa/selftest/cases/fitimage.py index 9c353b6ed1..3d6a5a582f 100644 --- a/meta/lib/oeqa/selftest/cases/fitimage.py +++ b/meta/lib/oeqa/selftest/cases/fitimage.py | |||
| @@ -4,13 +4,36 @@ | |||
| 4 | # SPDX-License-Identifier: MIT | 4 | # SPDX-License-Identifier: MIT |
| 5 | # | 5 | # |
| 6 | 6 | ||
| 7 | from oeqa.selftest.case import OESelftestTestCase | ||
| 8 | from oeqa.utils.commands import runCmd, bitbake, get_bb_vars | ||
| 9 | import os | 7 | import os |
| 10 | import re | 8 | import re |
| 11 | import shlex | 9 | import shlex |
| 12 | import logging | 10 | import logging |
| 13 | import pprint | 11 | import pprint |
| 12 | import tempfile | ||
| 13 | |||
| 14 | import oe.fitimage | ||
| 15 | |||
| 16 | from oeqa.selftest.case import OESelftestTestCase | ||
| 17 | from oeqa.utils.commands import runCmd, bitbake, get_bb_vars, get_bb_var | ||
| 18 | |||
| 19 | |||
| 20 | class BbVarsMockGenKeys: | ||
| 21 | def __init__(self, keydir, gen_keys="0", sign_enabled="0", keyname="", sign_ind="0", img_keyname=""): | ||
| 22 | self.bb_vars = { | ||
| 23 | 'FIT_GENERATE_KEYS': gen_keys, | ||
| 24 | 'FIT_KEY_GENRSA_ARGS': "-F4", | ||
| 25 | 'FIT_KEY_REQ_ARGS': "-batch -new", | ||
| 26 | 'FIT_KEY_SIGN_PKCS': "-x509", | ||
| 27 | 'FIT_SIGN_INDIVIDUAL': sign_ind, | ||
| 28 | 'FIT_SIGN_NUMBITS': "2048", | ||
| 29 | 'UBOOT_SIGN_ENABLE': sign_enabled, | ||
| 30 | 'UBOOT_SIGN_IMG_KEYNAME': img_keyname, | ||
| 31 | 'UBOOT_SIGN_KEYDIR': keydir, | ||
| 32 | 'UBOOT_SIGN_KEYNAME': keyname, | ||
| 33 | } | ||
| 34 | |||
| 35 | def getVar(self, var): | ||
| 36 | return self.bb_vars[var] | ||
| 14 | 37 | ||
| 15 | class FitImageTestCase(OESelftestTestCase): | 38 | class FitImageTestCase(OESelftestTestCase): |
| 16 | """Test functions usable for testing kernel-fitimage.bbclass and uboot-sign.bbclass | 39 | """Test functions usable for testing kernel-fitimage.bbclass and uboot-sign.bbclass |
| @@ -369,8 +392,7 @@ class FitImageTestCase(OESelftestTestCase): | |||
| 369 | # Verify the FIT image | 392 | # Verify the FIT image |
| 370 | self._check_fitimage(bb_vars, fitimage_path, uboot_tools_bindir) | 393 | self._check_fitimage(bb_vars, fitimage_path, uboot_tools_bindir) |
| 371 | 394 | ||
| 372 | 395 | class KernelFitImageBase(FitImageTestCase): | |
| 373 | class KernelFitImageTests(FitImageTestCase): | ||
| 374 | """Test cases for the kernel-fitimage bbclass""" | 396 | """Test cases for the kernel-fitimage bbclass""" |
| 375 | 397 | ||
| 376 | def _fit_get_bb_vars(self, additional_vars=[]): | 398 | def _fit_get_bb_vars(self, additional_vars=[]): |
| @@ -696,6 +718,8 @@ class KernelFitImageTests(FitImageTestCase): | |||
| 696 | self.assertEqual(found_comments, num_signatures, "Expected %d signed and commented (%s) sections in the fitImage." % | 718 | self.assertEqual(found_comments, num_signatures, "Expected %d signed and commented (%s) sections in the fitImage." % |
| 697 | (num_signatures, a_comment)) | 719 | (num_signatures, a_comment)) |
| 698 | 720 | ||
| 721 | class KernelFitImageTests(KernelFitImageBase): | ||
| 722 | """Test cases for the kernel-fitimage bbclass""" | ||
| 699 | 723 | ||
| 700 | def test_fit_image(self): | 724 | def test_fit_image(self): |
| 701 | """ | 725 | """ |
| @@ -732,6 +756,52 @@ FIT_CONF_PREFIX = "foo-" | |||
| 732 | bb_vars = self._fit_get_bb_vars() | 756 | bb_vars = self._fit_get_bb_vars() |
| 733 | self._test_fitimage(bb_vars) | 757 | self._test_fitimage(bb_vars) |
| 734 | 758 | ||
| 759 | def test_get_compatible_from_dtb(self): | ||
| 760 | """Test the oe.fitimage.get_compatible_from_dtb function | ||
| 761 | |||
| 762 | 1. bitbake bbb-dtbs-as-ext | ||
| 763 | 2. Check if symlink_points_below returns the path to the DTB | ||
| 764 | 3. Check if the expected compatible string is found by get_compatible_from_dtb() | ||
| 765 | """ | ||
| 766 | DTB_RECIPE = "bbb-dtbs-as-ext" | ||
| 767 | DTB_FILE = "am335x-bonegreen-ext.dtb" | ||
| 768 | DTB_SYMLINK = "am335x-bonegreen-ext-alias.dtb" | ||
| 769 | DTBO_FILE = "BBORG_RELAY-00A2.dtbo" | ||
| 770 | EXPECTED_COMP = ["ti,am335x-bone-green", "ti,am335x-bone-black", "ti,am335x-bone", "ti,am33xx"] | ||
| 771 | |||
| 772 | config = """ | ||
| 773 | DISTRO="poky" | ||
| 774 | MACHINE = "beaglebone-yocto" | ||
| 775 | """ | ||
| 776 | self.write_config(config) | ||
| 777 | |||
| 778 | # Provide the fdtget command called by get_compatible_from_dtb | ||
| 779 | dtc_bindir = FitImageTestCase._setup_native('dtc-native') | ||
| 780 | fdtget_path = os.path.join(dtc_bindir, "fdtget") | ||
| 781 | self.assertExists(fdtget_path) | ||
| 782 | |||
| 783 | # bitbake an external DTB with a symlink to it and a DTB overlay | ||
| 784 | bitbake(DTB_RECIPE) | ||
| 785 | deploy_dir_image = get_bb_var("DEPLOY_DIR_IMAGE", DTB_RECIPE) | ||
| 786 | devicetree_dir = os.path.join(deploy_dir_image, "devicetree") | ||
| 787 | dtb_path = os.path.join(devicetree_dir, DTB_FILE) | ||
| 788 | dtb_alias_path = os.path.join(devicetree_dir, DTB_SYMLINK) | ||
| 789 | dtbo_file = os.path.join(devicetree_dir, DTBO_FILE) | ||
| 790 | self.assertExists(dtb_path) | ||
| 791 | self.assertExists(dtb_alias_path) | ||
| 792 | self.assertExists(dtbo_file) | ||
| 793 | |||
| 794 | # Test symlink_points_below | ||
| 795 | linked_dtb = oe.fitimage.symlink_points_below(dtb_alias_path, devicetree_dir) | ||
| 796 | self.assertEqual(linked_dtb, DTB_FILE) | ||
| 797 | |||
| 798 | # Check if get_compatible_from_dtb finds the expected compatible string in the DTBs | ||
| 799 | comp = oe.fitimage.get_compatible_from_dtb(dtb_path, fdtget_path) | ||
| 800 | self.assertEqual(comp, EXPECTED_COMP) | ||
| 801 | comp_alias = oe.fitimage.get_compatible_from_dtb(dtb_alias_path, fdtget_path) | ||
| 802 | self.assertEqual(comp_alias, EXPECTED_COMP) | ||
| 803 | # The alias is a symlink, therefore the compatible string is equal | ||
| 804 | self.assertEqual(comp_alias, comp) | ||
| 735 | 805 | ||
| 736 | def test_fit_image_ext_dtb_dtbo(self): | 806 | def test_fit_image_ext_dtb_dtbo(self): |
| 737 | """ | 807 | """ |
| @@ -939,6 +1009,107 @@ FIT_HASH_ALG = "sha256" | |||
| 939 | self._gen_signing_key(bb_vars) | 1009 | self._gen_signing_key(bb_vars) |
| 940 | self._test_fitimage(bb_vars) | 1010 | self._test_fitimage(bb_vars) |
| 941 | 1011 | ||
| 1012 | class FitImagePyTests(KernelFitImageBase): | ||
| 1013 | """Test cases for the fitimage.py module without calling bitbake""" | ||
| 1014 | |||
| 1015 | def _test_fitimage_py(self, bb_vars_overrides=None): | ||
| 1016 | topdir = os.path.join(os.environ['BUILDDIR']) | ||
| 1017 | fitimage_its_path = os.path.join(topdir, self._testMethodName + '.its') | ||
| 1018 | |||
| 1019 | # Provide variables without calling bitbake | ||
| 1020 | bb_vars = { | ||
| 1021 | # image-fitimage.conf | ||
| 1022 | 'FIT_DESC': "Kernel fitImage for a dummy distro", | ||
| 1023 | 'FIT_HASH_ALG': "sha256", | ||
| 1024 | 'FIT_SIGN_ALG': "rsa2048", | ||
| 1025 | 'FIT_PAD_ALG': "pkcs-1.5", | ||
| 1026 | 'FIT_GENERATE_KEYS': "0", | ||
| 1027 | 'FIT_SIGN_NUMBITS': "2048", | ||
| 1028 | 'FIT_KEY_GENRSA_ARGS': "-F4", | ||
| 1029 | 'FIT_KEY_REQ_ARGS': "-batch -new", | ||
| 1030 | 'FIT_KEY_SIGN_PKCS': "-x509", | ||
| 1031 | 'FIT_SIGN_INDIVIDUAL': "0", | ||
| 1032 | 'FIT_CONF_PREFIX': "conf-", | ||
| 1033 | 'FIT_SUPPORTED_INITRAMFS_FSTYPES': "cpio.lz4 cpio.lzo cpio.lzma cpio.xz cpio.zst cpio.gz ext2.gz cpio", | ||
| 1034 | 'FIT_CONF_DEFAULT_DTB': "", | ||
| 1035 | 'FIT_ADDRESS_CELLS': "1", | ||
| 1036 | 'FIT_UBOOT_ENV': "", | ||
| 1037 | # kernel.bbclass | ||
| 1038 | 'UBOOT_ENTRYPOINT': "0x20008000", | ||
| 1039 | 'UBOOT_LOADADDRESS': "0x20008000", | ||
| 1040 | 'INITRAMFS_IMAGE': "", | ||
| 1041 | 'INITRAMFS_IMAGE_BUNDLE': "", | ||
| 1042 | # kernel-uboot.bbclass | ||
| 1043 | 'FIT_KERNEL_COMP_ALG': "gzip", | ||
| 1044 | 'FIT_KERNEL_COMP_ALG_EXTENSION': ".gz", | ||
| 1045 | 'UBOOT_MKIMAGE_KERNEL_TYPE': "kernel", | ||
| 1046 | # uboot-config.bbclass | ||
| 1047 | 'UBOOT_MKIMAGE_DTCOPTS': "", | ||
| 1048 | 'UBOOT_MKIMAGE': "uboot-mkimage", | ||
| 1049 | 'UBOOT_MKIMAGE_SIGN': "uboot-mkimage", | ||
| 1050 | 'UBOOT_MKIMAGE_SIGN_ARGS': "", | ||
| 1051 | 'UBOOT_SIGN_ENABLE': "0", | ||
| 1052 | 'UBOOT_SIGN_KEYDIR': None, | ||
| 1053 | 'UBOOT_SIGN_KEYNAME': None, | ||
| 1054 | 'UBOOT_SIGN_IMG_KEYNAME': None, | ||
| 1055 | # others | ||
| 1056 | 'MACHINE': "qemux86-64", | ||
| 1057 | 'UBOOT_ARCH': "x86", | ||
| 1058 | 'HOST_PREFIX': "x86_64-poky-linux-" | ||
| 1059 | } | ||
| 1060 | if bb_vars_overrides: | ||
| 1061 | bb_vars.update(bb_vars_overrides) | ||
| 1062 | |||
| 1063 | root_node = oe.fitimage.ItsNodeRootKernel( | ||
| 1064 | bb_vars["FIT_DESC"], bb_vars["FIT_ADDRESS_CELLS"], | ||
| 1065 | bb_vars['HOST_PREFIX'], bb_vars['UBOOT_ARCH'], bb_vars["FIT_CONF_PREFIX"], | ||
| 1066 | oe.types.boolean(bb_vars['UBOOT_SIGN_ENABLE']), bb_vars["UBOOT_SIGN_KEYDIR"], | ||
| 1067 | bb_vars["UBOOT_MKIMAGE"], bb_vars["UBOOT_MKIMAGE_DTCOPTS"], | ||
| 1068 | bb_vars["UBOOT_MKIMAGE_SIGN"], bb_vars["UBOOT_MKIMAGE_SIGN_ARGS"], | ||
| 1069 | bb_vars['FIT_HASH_ALG'], bb_vars['FIT_SIGN_ALG'], bb_vars['FIT_PAD_ALG'], | ||
| 1070 | bb_vars['UBOOT_SIGN_KEYNAME'], | ||
| 1071 | oe.types.boolean(bb_vars['FIT_SIGN_INDIVIDUAL']), bb_vars['UBOOT_SIGN_IMG_KEYNAME'] | ||
| 1072 | ) | ||
| 1073 | |||
| 1074 | root_node.fitimage_emit_section_kernel("kernel-1", "linux.bin", "none", | ||
| 1075 | bb_vars.get('UBOOT_LOADADDRESS'), bb_vars.get('UBOOT_ENTRYPOINT'), | ||
| 1076 | bb_vars.get('UBOOT_MKIMAGE_KERNEL_TYPE'), bb_vars.get("UBOOT_ENTRYSYMBOL") | ||
| 1077 | ) | ||
| 1078 | |||
| 1079 | dtb_files, _ = FitImageTestCase._get_dtb_files(bb_vars) | ||
| 1080 | for dtb in dtb_files: | ||
| 1081 | root_node.fitimage_emit_section_dtb(dtb, os.path.join("a-dir", dtb), | ||
| 1082 | bb_vars.get("UBOOT_DTB_LOADADDRESS"), bb_vars.get("UBOOT_DTBO_LOADADDRESS")) | ||
| 1083 | |||
| 1084 | if bb_vars.get('FIT_UBOOT_ENV'): | ||
| 1085 | root_node.fitimage_emit_section_boot_script( | ||
| 1086 | "bootscr-" + bb_vars['FIT_UBOOT_ENV'], bb_vars['FIT_UBOOT_ENV']) | ||
| 1087 | |||
| 1088 | if bb_vars['MACHINE'] == "qemux86-64": # Not really the right if | ||
| 1089 | root_node.fitimage_emit_section_setup("setup-1", "setup1.bin") | ||
| 1090 | |||
| 1091 | if bb_vars.get('INITRAMFS_IMAGE') and bb_vars.get("INITRAMFS_IMAGE_BUNDLE") != "1": | ||
| 1092 | root_node.fitimage_emit_section_ramdisk("ramdisk-1", "a-dir/a-initramfs-1", | ||
| 1093 | "core-image-minimal-initramfs", | ||
| 1094 | bb_vars.get("UBOOT_RD_LOADADDRESS"), bb_vars.get("UBOOT_RD_ENTRYPOINT")) | ||
| 1095 | |||
| 1096 | root_node.fitimage_emit_section_config(bb_vars['FIT_CONF_DEFAULT_DTB']) | ||
| 1097 | root_node.write_its_file(fitimage_its_path) | ||
| 1098 | |||
| 1099 | self.assertExists(fitimage_its_path, "%s image tree source doesn't exist" % (fitimage_its_path)) | ||
| 1100 | self.logger.debug("Checking its: %s" % fitimage_its_path) | ||
| 1101 | self._check_its_file(bb_vars, fitimage_its_path) | ||
| 1102 | |||
| 1103 | def test_fitimage_py_default(self): | ||
| 1104 | self._test_fitimage_py() | ||
| 1105 | |||
| 1106 | def test_fitimage_py_default_dtb(self): | ||
| 1107 | bb_vars_overrides = { | ||
| 1108 | 'KERNEL_DEVICETREE': "one.dtb two.dtb three.dtb", | ||
| 1109 | 'FIT_CONF_DEFAULT_DTB': "two.dtb" | ||
| 1110 | } | ||
| 1111 | self._test_fitimage_py(bb_vars_overrides) | ||
| 1112 | |||
| 942 | 1113 | ||
| 943 | class UBootFitImageTests(FitImageTestCase): | 1114 | class UBootFitImageTests(FitImageTestCase): |
| 944 | """Test cases for the uboot-sign bbclass""" | 1115 | """Test cases for the uboot-sign bbclass""" |
