From 4649beae3e3e256d65ceb5d69572327792de495a Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Tue, 18 Jul 2023 07:23:54 -0600 Subject: binman: Allow disabling symbol writing Some boards don't use symbol writing but do access the symbols in SPL. Provide an option to work around this. Signed-off-by: Simon Glass --- tools/binman/ftest.py | 28 ++++++++++++++++++++++++---- 1 file changed, 24 insertions(+), 4 deletions(-) (limited to 'tools/binman/ftest.py') diff --git a/tools/binman/ftest.py b/tools/binman/ftest.py index 43b4f850a69..dabb3f689fd 100644 --- a/tools/binman/ftest.py +++ b/tools/binman/ftest.py @@ -1452,7 +1452,7 @@ class TestFunctional(unittest.TestCase): self.assertEqual(U_BOOT_SPL_NODTB_DATA, data[:len(U_BOOT_SPL_NODTB_DATA)]) def checkSymbols(self, dts, base_data, u_boot_offset, entry_args=None, - use_expanded=False): + use_expanded=False, no_write_symbols=False): """Check the image contains the expected symbol values Args: @@ -1481,9 +1481,14 @@ class TestFunctional(unittest.TestCase): sym_values = struct.pack(' Date: Tue, 18 Jul 2023 07:23:58 -0600 Subject: binman: Convert mkimage to Entry_section This is needed to handle mkimage with inner section located itself in a section. Signed-off-by: Marek Vasut Use BuildSectionData() instead of ObtainContents(), add tests and a few other minor fixes: Signed-off-by: Simon Glass --- tools/binman/ftest.py | 67 ++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 66 insertions(+), 1 deletion(-) (limited to 'tools/binman/ftest.py') diff --git a/tools/binman/ftest.py b/tools/binman/ftest.py index dabb3f689fd..db348de7222 100644 --- a/tools/binman/ftest.py +++ b/tools/binman/ftest.py @@ -1103,6 +1103,7 @@ class TestFunctional(unittest.TestCase): def testPackZeroOffset(self): """Test that an entry at offset 0 is not given a new offset""" + self._SetupSplElf() with self.assertRaises(ValueError) as e: self._DoTestFile('025_pack_zero_size.dts') self.assertIn("Node '/binman/u-boot-spl': Offset 0x0 (0) overlaps " @@ -1116,6 +1117,7 @@ class TestFunctional(unittest.TestCase): def testPackX86RomNoSize(self): """Test that the end-at-4gb property requires a size property""" + self._SetupSplElf() with self.assertRaises(ValueError) as e: self._DoTestFile('027_pack_4gb_no_size.dts') self.assertIn("Image '/binman': Section size must be provided when " @@ -1124,6 +1126,7 @@ class TestFunctional(unittest.TestCase): def test4gbAndSkipAtStartTogether(self): """Test that the end-at-4gb and skip-at-size property can't be used together""" + self._SetupSplElf() with self.assertRaises(ValueError) as e: self._DoTestFile('098_4gb_and_skip_at_start_together.dts') self.assertIn("Image '/binman': Provide either 'end-at-4gb' or " @@ -1131,6 +1134,7 @@ class TestFunctional(unittest.TestCase): def testPackX86RomOutside(self): """Test that the end-at-4gb property checks for offset boundaries""" + self._SetupSplElf() with self.assertRaises(ValueError) as e: self._DoTestFile('028_pack_4gb_outside.dts') self.assertIn("Node '/binman/u-boot': Offset 0x0 (0) size 0x4 (4) " @@ -1423,6 +1427,7 @@ class TestFunctional(unittest.TestCase): def testPackUbootSplMicrocode(self): """Test that x86 microcode can be handled correctly in SPL""" + self._SetupSplElf() self._PackUbootSplMicrocode('049_x86_ucode_spl.dts') def testPackUbootSplMicrocodeReorder(self): @@ -1442,6 +1447,7 @@ class TestFunctional(unittest.TestCase): def testSplDtb(self): """Test that an image with spl/u-boot-spl.dtb can be created""" + self._SetupSplElf() data = self._DoReadFile('051_u_boot_spl_dtb.dts') self.assertEqual(U_BOOT_SPL_DTB_DATA, data[:len(U_BOOT_SPL_DTB_DATA)]) @@ -1962,6 +1968,8 @@ class TestFunctional(unittest.TestCase): def testUpdateFdtAll(self): """Test that all device trees are updated with offset/size info""" + self._SetupSplElf() + self._SetupTplElf() data = self._DoReadFileRealDtb('082_fdt_update_all.dts') base_expected = { @@ -3284,6 +3292,8 @@ class TestFunctional(unittest.TestCase): def testUpdateFdtAllRepack(self): """Test that all device trees are updated with offset/size info""" + self._SetupSplElf() + self._SetupTplElf() data = self._DoReadFileRealDtb('134_fdt_update_all_repack.dts') SECTION_SIZE = 0x300 DTB_SIZE = 602 @@ -3737,6 +3747,7 @@ class TestFunctional(unittest.TestCase): def testMkimage(self): """Test using mkimage to build an image""" + self._SetupSplElf() data = self._DoReadFile('156_mkimage.dts') # Just check that the data appears in the file somewhere @@ -3744,6 +3755,7 @@ class TestFunctional(unittest.TestCase): def testMkimageMissing(self): """Test that binman still produces an image if mkimage is missing""" + self._SetupSplElf() with test_util.capture_sys_output() as (_, stderr): self._DoTestFile('156_mkimage.dts', force_missing_bintools='mkimage') @@ -3856,6 +3868,7 @@ class TestFunctional(unittest.TestCase): def testSimpleFit(self): """Test an image with a FIT inside""" + self._SetupSplElf() data = self._DoReadFile('161_fit.dts') self.assertEqual(U_BOOT_DATA, data[:len(U_BOOT_DATA)]) self.assertEqual(U_BOOT_NODTB_DATA, data[-len(U_BOOT_NODTB_DATA):]) @@ -5375,6 +5388,7 @@ fdt fdtmap Extract the devicetree blob from the fdtmap def testFitSubentryHashSubnode(self): """Test an image with a FIT inside""" + self._SetupSplElf() data, _, _, out_dtb_name = self._DoReadFileDtb( '221_fit_subentry_hash.dts', use_real_dtb=True, update_dtb=True) @@ -5893,6 +5907,7 @@ fdt fdtmap Extract the devicetree blob from the fdtmap def testMkimageImagename(self): """Test using mkimage with -n holding the data too""" + self._SetupSplElf() data = self._DoReadFile('242_mkimage_name.dts') # Check that the data appears in the file somewhere @@ -5910,6 +5925,7 @@ fdt fdtmap Extract the devicetree blob from the fdtmap def testMkimageImage(self): """Test using mkimage with -n holding the data too""" + self._SetupSplElf() data = self._DoReadFile('243_mkimage_image.dts') # Check that the data appears in the file somewhere @@ -5930,6 +5946,7 @@ fdt fdtmap Extract the devicetree blob from the fdtmap def testMkimageImageNoContent(self): """Test using mkimage with -n and no data""" + self._SetupSplElf() with self.assertRaises(ValueError) as exc: self._DoReadFile('244_mkimage_image_no_content.dts') self.assertIn('Could not complete processing of contents', @@ -5937,6 +5954,7 @@ fdt fdtmap Extract the devicetree blob from the fdtmap def testMkimageImageBad(self): """Test using mkimage with imagename node and data-to-imagename""" + self._SetupSplElf() with self.assertRaises(ValueError) as exc: self._DoReadFile('245_mkimage_image_bad.dts') self.assertIn('Cannot use both imagename node and data-to-imagename', @@ -5952,6 +5970,7 @@ fdt fdtmap Extract the devicetree blob from the fdtmap def testMkimageCollection(self): """Test using a collection referring to an entry in a mkimage entry""" + self._SetupSplElf() data = self._DoReadFile('247_mkimage_coll.dts') expect = U_BOOT_SPL_DATA + U_BOOT_DATA self.assertEqual(expect, data[:len(expect)]) @@ -6037,6 +6056,8 @@ fdt fdtmap Extract the devicetree blob from the fdtmap def testMkimageMultipleDataFiles(self): """Test passing multiple files to mkimage in a mkimage entry""" + self._SetupSplElf() + self._SetupTplElf() data = self._DoReadFile('252_mkimage_mult_data.dts') # Size of files are packed in their 4B big-endian format expect = struct.pack('>I', len(U_BOOT_TPL_DATA)) @@ -6051,8 +6072,42 @@ fdt fdtmap Extract the devicetree blob from the fdtmap expect += U_BOOT_SPL_DATA self.assertEqual(expect, data[-len(expect):]) + def testMkimageMultipleExpanded(self): + """Test passing multiple files to mkimage in a mkimage entry""" + self._SetupSplElf() + self._SetupTplElf() + entry_args = { + 'spl-bss-pad': 'y', + 'spl-dtb': 'y', + } + data = self._DoReadFileDtb('252_mkimage_mult_data.dts', + use_expanded=True, entry_args=entry_args)[0] + pad_len = 10 + tpl_expect = U_BOOT_TPL_DATA + spl_expect = U_BOOT_SPL_NODTB_DATA + tools.get_bytes(0, pad_len) + spl_expect += U_BOOT_SPL_DTB_DATA + + content = data[0x40:] + lens = struct.unpack('>III', content[:12]) + + # Size of files are packed in their 4B big-endian format + # Size info is always followed by a 4B zero value. + self.assertEqual(len(tpl_expect), lens[0]) + self.assertEqual(len(spl_expect), lens[1]) + self.assertEqual(0, lens[2]) + + rest = content[12:] + self.assertEqual(tpl_expect, rest[:len(tpl_expect)]) + + rest = rest[len(tpl_expect):] + align_pad = len(tpl_expect) % 4 + self.assertEqual(tools.get_bytes(0, align_pad), rest[:align_pad]) + rest = rest[align_pad:] + self.assertEqual(spl_expect, rest) + def testMkimageMultipleNoContent(self): """Test passing multiple data files to mkimage with one data file having no content""" + self._SetupSplElf() with self.assertRaises(ValueError) as exc: self._DoReadFile('253_mkimage_mult_no_content.dts') self.assertIn('Could not complete processing of contents', @@ -6060,6 +6115,7 @@ fdt fdtmap Extract the devicetree blob from the fdtmap def testMkimageFilename(self): """Test using mkimage to build a binary with a filename""" + self._SetupSplElf() retcode = self._DoTestFile('254_mkimage_filename.dts') self.assertEqual(0, retcode) fname = tools.get_output_filename('mkimage-test.bin') @@ -6534,6 +6590,7 @@ fdt fdtmap Extract the devicetree blob from the fdtmap def testReplaceFitSibling(self): """Test an image with a FIT inside where we replace its sibling""" + self._SetupSplElf() fname = TestFunctional._MakeInputFile('once', b'available once') self._DoReadFileRealDtb('277_replace_fit_sibling.dts') os.remove(fname) @@ -6608,7 +6665,7 @@ fdt fdtmap Extract the devicetree blob from the fdtmap Private key DTB """ - + self._SetupSplElf() data = self._DoReadFileRealDtb(dts) updated_fname = tools.get_output_filename('image-updated.bin') tools.write_file(updated_fname, data) @@ -6683,6 +6740,7 @@ fdt fdtmap Extract the devicetree blob from the fdtmap def testSymbolNoWrite(self): """Test disabling of symbol writing""" + self._SetupSplElf() self.checkSymbols('282_symbols_disable.dts', U_BOOT_SPL_DATA, 0x1c, no_write_symbols=True) @@ -6696,6 +6754,13 @@ fdt fdtmap Extract the devicetree blob from the fdtmap entry_args=entry_args, use_expanded=True, no_write_symbols=True) + def testMkimageSpecial(self): + """Test mkimage ignores special hash-1 node""" + data = self._DoReadFile('283_mkimage_special.dts') + + # Just check that the data appears in the file somewhere + self.assertIn(U_BOOT_DATA, data) + if __name__ == "__main__": unittest.main() -- cgit v1.2.3 From b1e40ee73421018a42000e3d462708625c73a48f Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Tue, 18 Jul 2023 07:23:59 -0600 Subject: binman: Provide a way to specify the fdt-list directly Sometimes multiple boards are built with binman and it is useful to specify a different FDT list for each. At present this is not possible without providing multiple values of the of-list entryarg (which is not supported in the U-Boot build system). Allow a fit,fdt-list-val string-list property to be used instead. Signed-off-by: Simon Glass --- tools/binman/ftest.py | 12 ++++++++++++ 1 file changed, 12 insertions(+) (limited to 'tools/binman/ftest.py') diff --git a/tools/binman/ftest.py b/tools/binman/ftest.py index db348de7222..ed1940ed9f7 100644 --- a/tools/binman/ftest.py +++ b/tools/binman/ftest.py @@ -6761,6 +6761,18 @@ fdt fdtmap Extract the devicetree blob from the fdtmap # Just check that the data appears in the file somewhere self.assertIn(U_BOOT_DATA, data) + def testFitFdtList(self): + """Test an image with an FIT with the fit,fdt-list-val option""" + entry_args = { + 'default-dt': 'test-fdt2', + } + data = self._DoReadFileDtb( + '284_fit_fdt_list.dts', + entry_args=entry_args, + extra_indirs=[os.path.join(self._indir, TEST_FDT_SUBDIR)])[0] + self.assertEqual(U_BOOT_NODTB_DATA, data[-len(U_BOOT_NODTB_DATA):]) + fit_data = data[len(U_BOOT_DATA):-len(U_BOOT_NODTB_DATA)] + if __name__ == "__main__": unittest.main() -- cgit v1.2.3 From e1ad57e7ef6e17fb6f55bf70fff61bfd93703b78 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Tue, 18 Jul 2023 07:24:01 -0600 Subject: binman: Correct handling of zero bss size Fix the check for the __bss_size symbol, since it may be 0. Unfortunately there was no test coverage for this. Signed-off-by: Simon Glass --- tools/binman/ftest.py | 12 ++++++++++++ 1 file changed, 12 insertions(+) (limited to 'tools/binman/ftest.py') diff --git a/tools/binman/ftest.py b/tools/binman/ftest.py index ed1940ed9f7..dc9a95d341e 100644 --- a/tools/binman/ftest.py +++ b/tools/binman/ftest.py @@ -6773,6 +6773,18 @@ fdt fdtmap Extract the devicetree blob from the fdtmap self.assertEqual(U_BOOT_NODTB_DATA, data[-len(U_BOOT_NODTB_DATA):]) fit_data = data[len(U_BOOT_DATA):-len(U_BOOT_NODTB_DATA)] + def testSplEmptyBss(self): + """Test an expanded SPL with a zero-size BSS""" + # ELF file with a '__bss_size' symbol + self._SetupSplElf(src_fname='bss_data_zero') + + entry_args = { + 'spl-bss-pad': 'y', + 'spl-dtb': 'y', + } + data = self._DoReadFileDtb('285_spl_expand.dts', + use_expanded=True, entry_args=entry_args)[0] + if __name__ == "__main__": unittest.main() -- cgit v1.2.3 From f6abd5227a13e652c6a6c25173403ae19ac9e0f0 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Tue, 18 Jul 2023 07:24:04 -0600 Subject: binman: Support simple templates Collections can used to collect the contents of other entries into a single entry, but they result in a single entry, with the original entries 'left behind' in their old place. It is useful to be able to specific a set of entries ones and have it used in multiple images, or parts of an image. Implement this mechanism. Signed-off-by: Simon Glass --- tools/binman/ftest.py | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'tools/binman/ftest.py') diff --git a/tools/binman/ftest.py b/tools/binman/ftest.py index dc9a95d341e..fc5d8a839e6 100644 --- a/tools/binman/ftest.py +++ b/tools/binman/ftest.py @@ -6785,6 +6785,14 @@ fdt fdtmap Extract the devicetree blob from the fdtmap data = self._DoReadFileDtb('285_spl_expand.dts', use_expanded=True, entry_args=entry_args)[0] + def testTemplate(self): + """Test using a template""" + TestFunctional._MakeInputFile('vga2.bin', b'#' + VGA_DATA) + data = self._DoReadFile('286_template.dts') + first = U_BOOT_DATA + VGA_DATA + U_BOOT_DTB_DATA + second = U_BOOT_DATA + b'#' + VGA_DATA + U_BOOT_DTB_DATA + self.assertEqual(U_BOOT_IMG_DATA + first + second, data) + if __name__ == "__main__": unittest.main() -- cgit v1.2.3 From 35f72fb55a05ccf2a372566005f60c340924d1cc Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Tue, 18 Jul 2023 07:24:05 -0600 Subject: binman: Support templating with multiple images Allow a template to appear in the top level description when using multiple images. Signed-off-by: Simon Glass --- tools/binman/ftest.py | 12 ++++++++++++ 1 file changed, 12 insertions(+) (limited to 'tools/binman/ftest.py') diff --git a/tools/binman/ftest.py b/tools/binman/ftest.py index fc5d8a839e6..dd6075b871d 100644 --- a/tools/binman/ftest.py +++ b/tools/binman/ftest.py @@ -6793,6 +6793,18 @@ fdt fdtmap Extract the devicetree blob from the fdtmap second = U_BOOT_DATA + b'#' + VGA_DATA + U_BOOT_DTB_DATA self.assertEqual(U_BOOT_IMG_DATA + first + second, data) + def testTemplateBlobMulti(self): + """Test using a template with 'multiple-images' enabled""" + TestFunctional._MakeInputFile('my-blob.bin', b'blob') + TestFunctional._MakeInputFile('my-blob2.bin', b'other') + retcode = self._DoTestFile('287_template_multi.dts') + + self.assertEqual(0, retcode) + image = control.images['image'] + image_fname = tools.get_output_filename('my-image.bin') + data = tools.read_file(image_fname) + self.assertEqual(b'blob@@@@other', data) + if __name__ == "__main__": unittest.main() -- cgit v1.2.3 From db0e3f13b481cabd8f203a4ac742bb1afde6c67e Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Tue, 18 Jul 2023 07:24:06 -0600 Subject: binman: Add a test for templating in a FIT Add this as a separate test case. Signed-off-by: Simon Glass --- tools/binman/ftest.py | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'tools/binman/ftest.py') diff --git a/tools/binman/ftest.py b/tools/binman/ftest.py index dd6075b871d..dfca6316624 100644 --- a/tools/binman/ftest.py +++ b/tools/binman/ftest.py @@ -6805,6 +6805,13 @@ fdt fdtmap Extract the devicetree blob from the fdtmap data = tools.read_file(image_fname) self.assertEqual(b'blob@@@@other', data) + def testTemplateFit(self): + """Test using a template in a FIT""" + fit_data = self._DoReadFile('288_template_fit.dts') + fname = os.path.join(self._indir, 'fit_data.fit') + tools.write_file(fname, fit_data) + out = tools.run('dumpimage', '-l', fname) + if __name__ == "__main__": unittest.main() -- cgit v1.2.3 From 696f2b73d6ccffe23d5c295308817ca8d2bebc92 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Tue, 18 Jul 2023 07:24:07 -0600 Subject: binman: Support templates at any level Allow templates to be used inside a section, not just in the top-level /binman node. Signed-off-by: Simon Glass --- tools/binman/ftest.py | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'tools/binman/ftest.py') diff --git a/tools/binman/ftest.py b/tools/binman/ftest.py index dfca6316624..e96223cbd89 100644 --- a/tools/binman/ftest.py +++ b/tools/binman/ftest.py @@ -6812,6 +6812,14 @@ fdt fdtmap Extract the devicetree blob from the fdtmap tools.write_file(fname, fit_data) out = tools.run('dumpimage', '-l', fname) + def testTemplateSection(self): + """Test using a template in a section (not at top level)""" + TestFunctional._MakeInputFile('vga2.bin', b'#' + VGA_DATA) + data = self._DoReadFile('289_template_section.dts') + first = U_BOOT_DATA + VGA_DATA + U_BOOT_DTB_DATA + second = U_BOOT_DATA + b'#' + VGA_DATA + U_BOOT_DTB_DATA + self.assertEqual(U_BOOT_IMG_DATA + first + second + first, data) + if __name__ == "__main__": unittest.main() -- cgit v1.2.3 From 23b96e920b95428c55c0659ab4e1576c83a4b366 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Tue, 18 Jul 2023 07:24:08 -0600 Subject: binman: Support writing symbols inside a mkimage image Add support for writing symbols and determining the assumed position of binaries inside a mkimage image. This is useful as an example for other entry types which might want to do the same thing. Signed-off-by: Simon Glass --- tools/binman/ftest.py | 64 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 64 insertions(+) (limited to 'tools/binman/ftest.py') diff --git a/tools/binman/ftest.py b/tools/binman/ftest.py index e96223cbd89..e53181afb78 100644 --- a/tools/binman/ftest.py +++ b/tools/binman/ftest.py @@ -6820,6 +6820,70 @@ fdt fdtmap Extract the devicetree blob from the fdtmap second = U_BOOT_DATA + b'#' + VGA_DATA + U_BOOT_DTB_DATA self.assertEqual(U_BOOT_IMG_DATA + first + second + first, data) + def testMkimageSymbols(self): + """Test using mkimage to build an image with symbols in it""" + self._SetupSplElf('u_boot_binman_syms') + data = self._DoReadFile('290_mkimage_sym.dts') + + image = control.images['image'] + entries = image.GetEntries() + self.assertIn('u-boot', entries) + u_boot = entries['u-boot'] + + mkim = entries['mkimage'] + mkim_entries = mkim.GetEntries() + self.assertIn('u-boot-spl', mkim_entries) + spl = mkim_entries['u-boot-spl'] + self.assertIn('u-boot-spl2', mkim_entries) + spl2 = mkim_entries['u-boot-spl2'] + + # skip the mkimage header and the area sizes + mk_data = data[mkim.offset + 0x40:] + size, term = struct.unpack('>LL', mk_data[:8]) + + # There should be only one image, so check that the zero terminator is + # present + self.assertEqual(0, term) + + content = mk_data[8:8 + size] + + # The image should contain the symbols from u_boot_binman_syms.c + # Note that image_pos is adjusted by the base address of the image, + # which is 0x10 in our test image + spl_data = content[:0x18] + content = content[0x1b:] + + # After the header is a table of offsets for each image. There should + # only be one image, then a 0 terminator, so figure out the real start + # of the image data + base = 0x40 + 8 + + # Check symbols in both u-boot-spl and u-boot-spl2 + for i in range(2): + vals = struct.unpack('