From a4dfe3e473ea53c44db50d07c34815e24069d39d Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Mon, 26 Oct 2020 17:40:00 -0600 Subject: binman: Drop unused return variable for _DoTestFile() This function returns the exit code from binman, not any data. Fix up a few callers in the tests. Signed-off-by: Simon Glass --- tools/binman/ftest.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'tools/binman/ftest.py') diff --git a/tools/binman/ftest.py b/tools/binman/ftest.py index 75f6ca3a895..d23967e603d 100644 --- a/tools/binman/ftest.py +++ b/tools/binman/ftest.py @@ -3737,14 +3737,14 @@ class TestFunctional(unittest.TestCase): def testEnvironmentNoSize(self): """Test that a missing 'size' property is detected""" with self.assertRaises(ValueError) as e: - data = self._DoTestFile('175_env_no_size.dts') + self._DoTestFile('175_env_no_size.dts') self.assertIn("'u-boot-env' entry must have a size property", str(e.exception)) def testEnvironmentTooSmall(self): """Test handling of an environment that does not fit""" with self.assertRaises(ValueError) as e: - data = self._DoTestFile('176_env_too_small.dts') + self._DoTestFile('176_env_too_small.dts') # checksum, start byte, environment with \0 terminator, final \0 need = 4 + 1 + len(ENV_DATA) + 1 + 1 -- cgit v1.2.3 From f2c0dd85ad6cbf8b53ad5fc423a0177a0eb7fe6f Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Mon, 26 Oct 2020 17:40:01 -0600 Subject: binman: Add tests for skip-at-start sections At present this feature is tested view the end-at-4gb feature. Add some tests of its own, including the operation of padding. The third test here shows binman's current, inconsistent approach to padding in the top-level section. Future patches in this series will address this. Signed-off-by: Simon Glass --- tools/binman/ftest.py | 59 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 59 insertions(+) (limited to 'tools/binman/ftest.py') diff --git a/tools/binman/ftest.py b/tools/binman/ftest.py index d23967e603d..adc16038d99 100644 --- a/tools/binman/ftest.py +++ b/tools/binman/ftest.py @@ -3752,6 +3752,65 @@ class TestFunctional(unittest.TestCase): self.assertIn("too small to hold data (need %#x more bytes)" % short, str(e.exception)) + def testSkipAtStart(self): + """Test handling of skip-at-start section""" + data = self._DoReadFile('177_skip_at_start.dts') + self.assertEqual(U_BOOT_DATA, data) + + image = control.images['image'] + entries = image.GetEntries() + section = entries['section'] + self.assertEqual(0, section.offset) + self.assertEqual(len(U_BOOT_DATA), section.size) + self.assertEqual(U_BOOT_DATA, section.GetData()) + + entry = section.GetEntries()['u-boot'] + self.assertEqual(16, entry.offset) + self.assertEqual(len(U_BOOT_DATA), entry.size) + self.assertEqual(U_BOOT_DATA, entry.data) + + def testSkipAtStartPad(self): + """Test handling of skip-at-start section with padded entry""" + data = self._DoReadFile('178_skip_at_start_pad.dts') + before = tools.GetBytes(0, 8) + after = tools.GetBytes(0, 4) + all = before + U_BOOT_DATA + after + self.assertEqual(all, data) + + image = control.images['image'] + entries = image.GetEntries() + section = entries['section'] + self.assertEqual(0, section.offset) + self.assertEqual(len(all), section.size) + self.assertEqual(all, section.GetData()) + + entry = section.GetEntries()['u-boot'] + self.assertEqual(16, entry.offset) + self.assertEqual(len(all), entry.size) + self.assertEqual(U_BOOT_DATA, entry.data) + + def testSkipAtStartSectionPad(self): + """Test handling of skip-at-start section with padding""" + data = self._DoReadFile('179_skip_at_start_section_pad.dts') + before = tools.GetBytes(0, 8) + after = tools.GetBytes(0, 4) + all = before + U_BOOT_DATA + after + + # This is not correct, but it is what binman currently produces + self.assertEqual(tools.GetBytes(0, 16) + U_BOOT_DATA + after, data) + + image = control.images['image'] + entries = image.GetEntries() + section = entries['section'] + self.assertEqual(0, section.offset) + self.assertEqual(len(all), section.size) + self.assertIsNone(section.data) + self.assertEqual(all, section.GetData()) + + entry = section.GetEntries()['u-boot'] + self.assertEqual(16, entry.offset) + self.assertEqual(len(U_BOOT_DATA), entry.size) + self.assertEqual(U_BOOT_DATA, entry.data) if __name__ == "__main__": unittest.main() -- cgit v1.2.3 From e6bed4f1812c1666eeab794694c4b3765f41c143 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Mon, 26 Oct 2020 17:40:05 -0600 Subject: binman: Expand the error message for breaching a section Add in a few more details to this error message to make it easier to see what is going on. Signed-off-by: Simon Glass --- tools/binman/ftest.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'tools/binman/ftest.py') diff --git a/tools/binman/ftest.py b/tools/binman/ftest.py index adc16038d99..4f7e22612cc 100644 --- a/tools/binman/ftest.py +++ b/tools/binman/ftest.py @@ -970,8 +970,9 @@ class TestFunctional(unittest.TestCase): """Test that the end-at-4gb property checks for offset boundaries""" with self.assertRaises(ValueError) as e: self._DoTestFile('028_pack_4gb_outside.dts') - self.assertIn("Node '/binman/u-boot': Offset 0x0 (0) is outside " - "the section starting at 0xffffffe0 (4294967264)", + self.assertIn("Node '/binman/u-boot': Offset 0x0 (0) size 0x4 (4) " + "is outside the section '/binman' starting at " + '0xffffffe0 (4294967264) of size 0x20 (32)', str(e.exception)) def testPackX86Rom(self): -- cgit v1.2.3 From ef439ed191a0655a86f5b4035cec9cc57e97d8b1 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Mon, 26 Oct 2020 17:40:08 -0600 Subject: binman: Update testPackExtra with more checks Check the contents of each section to make sure it is actually in the right place. Also fix a whitespace error in the .dts file. Signed-off-by: Simon Glass --- tools/binman/ftest.py | 27 ++++++++++++++++++++++----- 1 file changed, 22 insertions(+), 5 deletions(-) (limited to 'tools/binman/ftest.py') diff --git a/tools/binman/ftest.py b/tools/binman/ftest.py index 4f7e22612cc..481b8fd03c1 100644 --- a/tools/binman/ftest.py +++ b/tools/binman/ftest.py @@ -785,9 +785,8 @@ class TestFunctional(unittest.TestCase): def testPackExtra(self): """Test that extra packing feature works as expected""" - retcode = self._DoTestFile('009_pack_extra.dts') + data = self._DoReadFile('009_pack_extra.dts') - self.assertEqual(0, retcode) self.assertIn('image', control.images) image = control.images['image'] entries = image.GetEntries() @@ -799,30 +798,48 @@ class TestFunctional(unittest.TestCase): self.assertEqual(0, entry.offset) self.assertEqual(3, entry.pad_before) self.assertEqual(3 + 5 + len(U_BOOT_DATA), entry.size) + self.assertEqual(U_BOOT_DATA, entry.data) + self.assertEqual(tools.GetBytes(0, 3) + U_BOOT_DATA + + tools.GetBytes(0, 5), data[:entry.size]) + pos = entry.size # Second u-boot has an aligned size, but it has no effect self.assertIn('u-boot-align-size-nop', entries) entry = entries['u-boot-align-size-nop'] - self.assertEqual(12, entry.offset) - self.assertEqual(4, entry.size) + self.assertEqual(pos, entry.offset) + self.assertEqual(len(U_BOOT_DATA), entry.size) + self.assertEqual(U_BOOT_DATA, entry.data) + self.assertEqual(U_BOOT_DATA, data[pos:pos + entry.size]) + pos += entry.size # Third u-boot has an aligned size too self.assertIn('u-boot-align-size', entries) entry = entries['u-boot-align-size'] - self.assertEqual(16, entry.offset) + self.assertEqual(pos, entry.offset) self.assertEqual(32, entry.size) + self.assertEqual(U_BOOT_DATA, entry.data) + self.assertEqual(U_BOOT_DATA + tools.GetBytes(0, 32 - len(U_BOOT_DATA)), + data[pos:pos + entry.size]) + pos += entry.size # Fourth u-boot has an aligned end self.assertIn('u-boot-align-end', entries) entry = entries['u-boot-align-end'] self.assertEqual(48, entry.offset) self.assertEqual(16, entry.size) + self.assertEqual(U_BOOT_DATA, entry.data[:len(U_BOOT_DATA)]) + self.assertEqual(U_BOOT_DATA + tools.GetBytes(0, 16 - len(U_BOOT_DATA)), + data[pos:pos + entry.size]) + pos += entry.size # Fifth u-boot immediately afterwards self.assertIn('u-boot-align-both', entries) entry = entries['u-boot-align-both'] self.assertEqual(64, entry.offset) self.assertEqual(64, entry.size) + self.assertEqual(U_BOOT_DATA, entry.data[:len(U_BOOT_DATA)]) + self.assertEqual(U_BOOT_DATA + tools.GetBytes(0, 64 - len(U_BOOT_DATA)), + data[pos:pos + entry.size]) self.CheckNoGaps(entries) self.assertEqual(128, image.size) -- cgit v1.2.3 From f90d906a275f85e7077d9a30ab82b20676b54645 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Mon, 26 Oct 2020 17:40:09 -0600 Subject: binman: Expand docs and test for padding Padding becomes part of the entry once the image is written out, but within binman the entry contents does not include the padding. Add documentation to make this clear, as well as a test. Signed-off-by: Simon Glass --- tools/binman/ftest.py | 29 ++++++++++++++++++++++++++++- 1 file changed, 28 insertions(+), 1 deletion(-) (limited to 'tools/binman/ftest.py') diff --git a/tools/binman/ftest.py b/tools/binman/ftest.py index 481b8fd03c1..35c14206818 100644 --- a/tools/binman/ftest.py +++ b/tools/binman/ftest.py @@ -3548,12 +3548,39 @@ class TestFunctional(unittest.TestCase): def testPadInSections(self): """Test pad-before, pad-after for entries in sections""" - data = self._DoReadFile('166_pad_in_sections.dts') + data, _, _, out_dtb_fname = self._DoReadFileDtb( + '166_pad_in_sections.dts', update_dtb=True) expected = (U_BOOT_DATA + tools.GetBytes(ord('!'), 12) + U_BOOT_DATA + tools.GetBytes(ord('!'), 6) + U_BOOT_DATA) self.assertEqual(expected, data) + dtb = fdt.Fdt(out_dtb_fname) + dtb.Scan() + props = self._GetPropTree(dtb, ['size', 'image-pos', 'offset']) + expected = { + 'image-pos': 0, + 'offset': 0, + 'size': 12 + 6 + 3 * len(U_BOOT_DATA), + + 'section:image-pos': 0, + 'section:offset': 0, + 'section:size': 12 + 6 + 3 * len(U_BOOT_DATA), + + 'section/before:image-pos': 0, + 'section/before:offset': 0, + 'section/before:size': len(U_BOOT_DATA), + + 'section/u-boot:image-pos': 4, + 'section/u-boot:offset': 4, + 'section/u-boot:size': 12 + len(U_BOOT_DATA) + 6, + + 'section/after:image-pos': 26, + 'section/after:offset': 26, + 'section/after:size': len(U_BOOT_DATA), + } + self.assertEqual(expected, props) + def testFitImageSubentryAlignment(self): """Test relative alignability of FIT image subentries""" entry_args = { -- cgit v1.2.3 From 4eec34c91f84d6c3915b300f0688f9b055e04dda Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Mon, 26 Oct 2020 17:40:10 -0600 Subject: binman: Expand docs and test for alignment Alignment does form part of the entry once the image is written out, but within binman the entry contents does not include the padding. Add documentation to make this clear, as well as a test. Signed-off-by: Simon Glass --- tools/binman/ftest.py | 33 ++++++++++++++++++++++++++++++++- 1 file changed, 32 insertions(+), 1 deletion(-) (limited to 'tools/binman/ftest.py') diff --git a/tools/binman/ftest.py b/tools/binman/ftest.py index 35c14206818..c99852d5814 100644 --- a/tools/binman/ftest.py +++ b/tools/binman/ftest.py @@ -785,7 +785,8 @@ class TestFunctional(unittest.TestCase): def testPackExtra(self): """Test that extra packing feature works as expected""" - data = self._DoReadFile('009_pack_extra.dts') + data, _, _, out_dtb_fname = self._DoReadFileDtb('009_pack_extra.dts', + update_dtb=True) self.assertIn('image', control.images) image = control.images['image'] @@ -844,6 +845,36 @@ class TestFunctional(unittest.TestCase): self.CheckNoGaps(entries) self.assertEqual(128, image.size) + dtb = fdt.Fdt(out_dtb_fname) + dtb.Scan() + props = self._GetPropTree(dtb, ['size', 'offset', 'image-pos']) + expected = { + 'image-pos': 0, + 'offset': 0, + 'size': 128, + + 'u-boot:image-pos': 0, + 'u-boot:offset': 0, + 'u-boot:size': 3 + 5 + len(U_BOOT_DATA), + + 'u-boot-align-size-nop:image-pos': 12, + 'u-boot-align-size-nop:offset': 12, + 'u-boot-align-size-nop:size': 4, + + 'u-boot-align-size:image-pos': 16, + 'u-boot-align-size:offset': 16, + 'u-boot-align-size:size': 32, + + 'u-boot-align-end:image-pos': 48, + 'u-boot-align-end:offset': 48, + 'u-boot-align-end:size': 16, + + 'u-boot-align-both:image-pos': 64, + 'u-boot-align-both:offset': 64, + 'u-boot-align-both:size': 64, + } + self.assertEqual(expected, props) + def testPackAlignPowerOf2(self): """Test that invalid entry alignment is detected""" with self.assertRaises(ValueError) as e: -- cgit v1.2.3 From 17ea9f35e780d073820a770b8e65641761a31d1f Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Mon, 26 Oct 2020 17:40:11 -0600 Subject: binman: Move section-building code into a function Create a new _BuildSectionData() to hold the code that is now in GetData(), so that it is clearly separated from entry.GetData() base function. Separate out the 'pad-before' processing to make this easier to understand. Unfortunately this breaks the testDual test. Rather than squash several patches into an un-reviewable glob, disable the test for now. This also affects testSkipAtStartSectionPad(), although it still not quite what it should be. Update that temporarily for now. Signed-off-by: Simon Glass --- tools/binman/ftest.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'tools/binman/ftest.py') diff --git a/tools/binman/ftest.py b/tools/binman/ftest.py index c99852d5814..82be9976c32 100644 --- a/tools/binman/ftest.py +++ b/tools/binman/ftest.py @@ -708,6 +708,7 @@ class TestFunctional(unittest.TestCase): """Test a simple binman run with debugging enabled""" self._DoTestFile('005_simple.dts', debug=True) + @unittest.skip('Disable for now until padding of images is supported') def testDual(self): """Test that we can handle creating two images @@ -3873,7 +3874,7 @@ class TestFunctional(unittest.TestCase): all = before + U_BOOT_DATA + after # This is not correct, but it is what binman currently produces - self.assertEqual(tools.GetBytes(0, 16) + U_BOOT_DATA + after, data) + self.assertEqual(before + U_BOOT_DATA + tools.GetBytes(0, 16), data) image = control.images['image'] entries = image.GetEntries() @@ -3881,7 +3882,6 @@ class TestFunctional(unittest.TestCase): self.assertEqual(0, section.offset) self.assertEqual(len(all), section.size) self.assertIsNone(section.data) - self.assertEqual(all, section.GetData()) entry = section.GetEntries()['u-boot'] self.assertEqual(16, entry.offset) -- cgit v1.2.3 From d1d3ad7d1fea137a6fe0709458947ca84ffb124c Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Mon, 26 Oct 2020 17:40:13 -0600 Subject: binman: Move section padding to the parent Each section is padded up to its size, if the contents are not large enough. Move this logic from _BuildSectionData() to GetPaddedDataForEntry() so that all the padding is in one place. With this, the testDual test is working again, so enable it. Signed-off-by: Simon Glass --- tools/binman/ftest.py | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) (limited to 'tools/binman/ftest.py') diff --git a/tools/binman/ftest.py b/tools/binman/ftest.py index 82be9976c32..31e93c647fe 100644 --- a/tools/binman/ftest.py +++ b/tools/binman/ftest.py @@ -708,7 +708,6 @@ class TestFunctional(unittest.TestCase): """Test a simple binman run with debugging enabled""" self._DoTestFile('005_simple.dts', debug=True) - @unittest.skip('Disable for now until padding of images is supported') def testDual(self): """Test that we can handle creating two images @@ -3872,9 +3871,7 @@ class TestFunctional(unittest.TestCase): before = tools.GetBytes(0, 8) after = tools.GetBytes(0, 4) all = before + U_BOOT_DATA + after - - # This is not correct, but it is what binman currently produces - self.assertEqual(before + U_BOOT_DATA + tools.GetBytes(0, 16), data) + self.assertEqual(all, data) image = control.images['image'] entries = image.GetEntries() @@ -3882,6 +3879,7 @@ class TestFunctional(unittest.TestCase): self.assertEqual(0, section.offset) self.assertEqual(len(all), section.size) self.assertIsNone(section.data) + self.assertEqual(all, section.GetPaddedData()) entry = section.GetEntries()['u-boot'] self.assertEqual(16, entry.offset) -- cgit v1.2.3 From 7d398bb1c71580da2182f0b820d91950bf4b3d24 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Mon, 26 Oct 2020 17:40:14 -0600 Subject: binman: Make section padding consistent with other entries At present padding of sections is inconsistent with other entry types, in that different pad bytes are used. When a normal entry is padded by its parent, the parent's pad byte is used. But for sections, the section's pad byte is used. Adjust logic to always do this the same way. Note there is still a special case in entry_Section.GetPaddedData() where an image is padded with the pad byte of the top-level section. This is necessary since otherwise there would be no way to set the pad byte of the image, without adding a top-level section to every image. Signed-off-by: Simon Glass --- tools/binman/ftest.py | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) (limited to 'tools/binman/ftest.py') diff --git a/tools/binman/ftest.py b/tools/binman/ftest.py index 31e93c647fe..830b610890f 100644 --- a/tools/binman/ftest.py +++ b/tools/binman/ftest.py @@ -3886,5 +3886,28 @@ class TestFunctional(unittest.TestCase): self.assertEqual(len(U_BOOT_DATA), entry.size) self.assertEqual(U_BOOT_DATA, entry.data) + def testSectionPad(self): + """Testing padding with sections""" + data = self._DoReadFile('180_section_pad.dts') + expected = (tools.GetBytes(ord('&'), 3) + + tools.GetBytes(ord('!'), 5) + + U_BOOT_DATA + + tools.GetBytes(ord('!'), 1) + + tools.GetBytes(ord('&'), 2)) + self.assertEqual(expected, data) + + def testSectionAlign(self): + """Testing alignment with sections""" + data = self._DoReadFileDtb('181_section_align.dts', map=True)[0] + expected = (b'\0' + # fill section + tools.GetBytes(ord('&'), 1) + # padding to section align + b'\0' + # fill section + tools.GetBytes(ord('!'), 3) + # padding to u-boot align + U_BOOT_DATA + + tools.GetBytes(ord('!'), 4) + # padding to u-boot size + tools.GetBytes(ord('!'), 4)) # padding to section size + self.assertEqual(expected, data) + + if __name__ == "__main__": unittest.main() -- cgit v1.2.3 From 97c3e9a6faa4483a700b26988bc48c2f9efe8dd6 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Mon, 26 Oct 2020 17:40:15 -0600 Subject: binman: Store the original data before compression When compressing an entry, the original uncompressed data is overwritten. Store it so it is available if needed. 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 830b610890f..4c94bea6f00 100644 --- a/tools/binman/ftest.py +++ b/tools/binman/ftest.py @@ -1810,6 +1810,18 @@ class TestFunctional(unittest.TestCase): props = self._GetPropTree(dtb, ['size', 'uncomp-size']) orig = self._decompress(data) self.assertEquals(COMPRESS_DATA, orig) + + # Do a sanity check on various fields + image = control.images['image'] + entries = image.GetEntries() + self.assertEqual(1, len(entries)) + + entry = entries['blob'] + self.assertEqual(COMPRESS_DATA, entry.uncomp_data) + self.assertEqual(len(COMPRESS_DATA), entry.uncomp_size) + orig = self._decompress(entry.data) + self.assertEqual(orig, entry.uncomp_data) + expected = { 'blob:uncomp-size': len(COMPRESS_DATA), 'blob:size': len(data), -- cgit v1.2.3 From 63e7ba6c1820def06e7ba88ce357cb605285e70c Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Mon, 26 Oct 2020 17:40:16 -0600 Subject: binman: Set section contents in GetData() Section contents is not set up when ObtainContents() is called, since packing often changes the layout of the contents. Ensure that the contents are correctly recorded by making this function regenerate the section. It is normally only called by the parent section (when packing) or by the top-level image code, when writing out the image. So the performance impact is fairly small. Now that sections have their contents in their 'data' property, update testSkipAtStartSectionPad() to check it. Signed-off-by: Simon Glass --- tools/binman/ftest.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'tools/binman/ftest.py') diff --git a/tools/binman/ftest.py b/tools/binman/ftest.py index 4c94bea6f00..6f47deac3b6 100644 --- a/tools/binman/ftest.py +++ b/tools/binman/ftest.py @@ -1822,6 +1822,8 @@ class TestFunctional(unittest.TestCase): orig = self._decompress(entry.data) self.assertEqual(orig, entry.uncomp_data) + self.assertEqual(image.data, entry.data) + expected = { 'blob:uncomp-size': len(COMPRESS_DATA), 'blob:size': len(data), @@ -3890,7 +3892,7 @@ class TestFunctional(unittest.TestCase): section = entries['section'] self.assertEqual(0, section.offset) self.assertEqual(len(all), section.size) - self.assertIsNone(section.data) + self.assertEqual(U_BOOT_DATA, section.data) self.assertEqual(all, section.GetPaddedData()) entry = section.GetEntries()['u-boot'] -- cgit v1.2.3 From 0ff83da634c4e4a8e510c5b2434cab88cb33c164 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Mon, 26 Oct 2020 17:40:24 -0600 Subject: binman: Use the actual contents in CheckSize() At present this function adds up the total size of entries to work out the size of a section's contents. With compression this is no-longer enough. We may as well bite the bullet and build the section contents instead. Call _BuildSectionData() to get the (possibly compressed) contents and GetPaddedData() to get the same but with padding added. Note that this is inefficient since the section contents is calculated twice. Future work will improve this. This affects testPackOverlapMap() since the error is reported with a different section size now (enough to hold the contents). Update that at the same time. Signed-off-by: Simon Glass --- tools/binman/ftest.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'tools/binman/ftest.py') diff --git a/tools/binman/ftest.py b/tools/binman/ftest.py index 6f47deac3b6..5bcdb70c41a 100644 --- a/tools/binman/ftest.py +++ b/tools/binman/ftest.py @@ -2024,7 +2024,7 @@ class TestFunctional(unittest.TestCase): self.assertTrue(os.path.exists(map_fname)) map_data = tools.ReadFile(map_fname, binary=False) self.assertEqual('''ImagePos Offset Size Name - 00000000 00000007 main-section + 00000000 00000008 main-section 00000000 00000004 u-boot 00000003 00000004 u-boot-align ''', map_data) -- cgit v1.2.3 From 8f5ef89f00133df6381e60f0415269ded39647c1 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Mon, 26 Oct 2020 17:40:25 -0600 Subject: binman: Support compression of sections With the previous changes, it is now possible to compress entire sections. Add some tests to check that compression works correctly, including updating the metadata. Also update the documentation. Signed-off-by: Simon Glass --- tools/binman/ftest.py | 217 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 217 insertions(+) (limited to 'tools/binman/ftest.py') diff --git a/tools/binman/ftest.py b/tools/binman/ftest.py index 5bcdb70c41a..e753a342c8f 100644 --- a/tools/binman/ftest.py +++ b/tools/binman/ftest.py @@ -70,6 +70,7 @@ VBLOCK_DATA = b'vblk' FILES_DATA = (b"sorry I'm late\nOh, don't bother apologising, I'm " + b"sorry you're alive\n") COMPRESS_DATA = b'compress xxxxxxxxxxxxxxxxxxxxxx data' +COMPRESS_DATA_BIG = COMPRESS_DATA * 2 REFCODE_DATA = b'refcode' FSP_M_DATA = b'fsp_m' FSP_S_DATA = b'fsp_s' @@ -175,6 +176,7 @@ class TestFunctional(unittest.TestCase): os.path.join(cls._indir, 'files')) TestFunctional._MakeInputFile('compress', COMPRESS_DATA) + TestFunctional._MakeInputFile('compress_big', COMPRESS_DATA_BIG) TestFunctional._MakeInputFile('bl31.bin', ATF_BL31_DATA) TestFunctional._MakeInputFile('scp.bin', SCP_DATA) @@ -3922,6 +3924,221 @@ class TestFunctional(unittest.TestCase): tools.GetBytes(ord('!'), 4)) # padding to section size self.assertEqual(expected, data) + def testCompressImage(self): + """Test compression of the entire image""" + self._CheckLz4() + data, _, _, out_dtb_fname = self._DoReadFileDtb( + '182_compress_image.dts', use_real_dtb=True, update_dtb=True) + dtb = fdt.Fdt(out_dtb_fname) + dtb.Scan() + props = self._GetPropTree(dtb, ['offset', 'image-pos', 'size', + 'uncomp-size']) + orig = self._decompress(data) + self.assertEquals(COMPRESS_DATA + U_BOOT_DATA, orig) + + # Do a sanity check on various fields + image = control.images['image'] + entries = image.GetEntries() + self.assertEqual(2, len(entries)) + + entry = entries['blob'] + self.assertEqual(COMPRESS_DATA, entry.data) + self.assertEqual(len(COMPRESS_DATA), entry.size) + + entry = entries['u-boot'] + self.assertEqual(U_BOOT_DATA, entry.data) + self.assertEqual(len(U_BOOT_DATA), entry.size) + + self.assertEqual(len(data), image.size) + self.assertEqual(COMPRESS_DATA + U_BOOT_DATA, image.uncomp_data) + self.assertEqual(len(COMPRESS_DATA + U_BOOT_DATA), image.uncomp_size) + orig = self._decompress(image.data) + self.assertEqual(orig, image.uncomp_data) + + expected = { + 'blob:offset': 0, + 'blob:size': len(COMPRESS_DATA), + 'u-boot:offset': len(COMPRESS_DATA), + 'u-boot:size': len(U_BOOT_DATA), + 'uncomp-size': len(COMPRESS_DATA + U_BOOT_DATA), + 'offset': 0, + 'image-pos': 0, + 'size': len(data), + } + self.assertEqual(expected, props) + + def testCompressImageLess(self): + """Test compression where compression reduces the image size""" + self._CheckLz4() + data, _, _, out_dtb_fname = self._DoReadFileDtb( + '183_compress_image_less.dts', use_real_dtb=True, update_dtb=True) + dtb = fdt.Fdt(out_dtb_fname) + dtb.Scan() + props = self._GetPropTree(dtb, ['offset', 'image-pos', 'size', + 'uncomp-size']) + orig = self._decompress(data) + + self.assertEquals(COMPRESS_DATA + COMPRESS_DATA + U_BOOT_DATA, orig) + + # Do a sanity check on various fields + image = control.images['image'] + entries = image.GetEntries() + self.assertEqual(2, len(entries)) + + entry = entries['blob'] + self.assertEqual(COMPRESS_DATA_BIG, entry.data) + self.assertEqual(len(COMPRESS_DATA_BIG), entry.size) + + entry = entries['u-boot'] + self.assertEqual(U_BOOT_DATA, entry.data) + self.assertEqual(len(U_BOOT_DATA), entry.size) + + self.assertEqual(len(data), image.size) + self.assertEqual(COMPRESS_DATA_BIG + U_BOOT_DATA, image.uncomp_data) + self.assertEqual(len(COMPRESS_DATA_BIG + U_BOOT_DATA), + image.uncomp_size) + orig = self._decompress(image.data) + self.assertEqual(orig, image.uncomp_data) + + expected = { + 'blob:offset': 0, + 'blob:size': len(COMPRESS_DATA_BIG), + 'u-boot:offset': len(COMPRESS_DATA_BIG), + 'u-boot:size': len(U_BOOT_DATA), + 'uncomp-size': len(COMPRESS_DATA_BIG + U_BOOT_DATA), + 'offset': 0, + 'image-pos': 0, + 'size': len(data), + } + self.assertEqual(expected, props) + + def testCompressSectionSize(self): + """Test compression of a section with a fixed size""" + self._CheckLz4() + data, _, _, out_dtb_fname = self._DoReadFileDtb( + '184_compress_section_size.dts', use_real_dtb=True, update_dtb=True) + dtb = fdt.Fdt(out_dtb_fname) + dtb.Scan() + props = self._GetPropTree(dtb, ['offset', 'image-pos', 'size', + 'uncomp-size']) + orig = self._decompress(data) + self.assertEquals(COMPRESS_DATA + U_BOOT_DATA, orig) + expected = { + 'section/blob:offset': 0, + 'section/blob:size': len(COMPRESS_DATA), + 'section/u-boot:offset': len(COMPRESS_DATA), + 'section/u-boot:size': len(U_BOOT_DATA), + 'section:offset': 0, + 'section:image-pos': 0, + 'section:uncomp-size': len(COMPRESS_DATA + U_BOOT_DATA), + 'section:size': 0x30, + 'offset': 0, + 'image-pos': 0, + 'size': 0x30, + } + self.assertEqual(expected, props) + + def testCompressSection(self): + """Test compression of a section with no fixed size""" + self._CheckLz4() + data, _, _, out_dtb_fname = self._DoReadFileDtb( + '185_compress_section.dts', use_real_dtb=True, update_dtb=True) + dtb = fdt.Fdt(out_dtb_fname) + dtb.Scan() + props = self._GetPropTree(dtb, ['offset', 'image-pos', 'size', + 'uncomp-size']) + orig = self._decompress(data) + self.assertEquals(COMPRESS_DATA + U_BOOT_DATA, orig) + expected = { + 'section/blob:offset': 0, + 'section/blob:size': len(COMPRESS_DATA), + 'section/u-boot:offset': len(COMPRESS_DATA), + 'section/u-boot:size': len(U_BOOT_DATA), + 'section:offset': 0, + 'section:image-pos': 0, + 'section:uncomp-size': len(COMPRESS_DATA + U_BOOT_DATA), + 'section:size': len(data), + 'offset': 0, + 'image-pos': 0, + 'size': len(data), + } + self.assertEqual(expected, props) + + def testCompressExtra(self): + """Test compression of a section with no fixed size""" + self._CheckLz4() + data, _, _, out_dtb_fname = self._DoReadFileDtb( + '186_compress_extra.dts', use_real_dtb=True, update_dtb=True) + dtb = fdt.Fdt(out_dtb_fname) + dtb.Scan() + props = self._GetPropTree(dtb, ['offset', 'image-pos', 'size', + 'uncomp-size']) + + base = data[len(U_BOOT_DATA):] + self.assertEquals(U_BOOT_DATA, base[:len(U_BOOT_DATA)]) + rest = base[len(U_BOOT_DATA):] + + # Check compressed data + section1 = self._decompress(rest) + expect1 = tools.Compress(COMPRESS_DATA + U_BOOT_DATA, 'lz4') + self.assertEquals(expect1, rest[:len(expect1)]) + self.assertEquals(COMPRESS_DATA + U_BOOT_DATA, section1) + rest1 = rest[len(expect1):] + + section2 = self._decompress(rest1) + expect2 = tools.Compress(COMPRESS_DATA + COMPRESS_DATA, 'lz4') + self.assertEquals(expect2, rest1[:len(expect2)]) + self.assertEquals(COMPRESS_DATA + COMPRESS_DATA, section2) + rest2 = rest1[len(expect2):] + + expect_size = (len(U_BOOT_DATA) + len(U_BOOT_DATA) + len(expect1) + + len(expect2) + len(U_BOOT_DATA)) + #self.assertEquals(expect_size, len(data)) + + #self.assertEquals(U_BOOT_DATA, rest2) + + self.maxDiff = None + expected = { + 'u-boot:offset': 0, + 'u-boot:image-pos': 0, + 'u-boot:size': len(U_BOOT_DATA), + + 'base:offset': len(U_BOOT_DATA), + 'base:image-pos': len(U_BOOT_DATA), + 'base:size': len(data) - len(U_BOOT_DATA), + 'base/u-boot:offset': 0, + 'base/u-boot:image-pos': len(U_BOOT_DATA), + 'base/u-boot:size': len(U_BOOT_DATA), + 'base/u-boot2:offset': len(U_BOOT_DATA) + len(expect1) + + len(expect2), + 'base/u-boot2:image-pos': len(U_BOOT_DATA) * 2 + len(expect1) + + len(expect2), + 'base/u-boot2:size': len(U_BOOT_DATA), + + 'base/section:offset': len(U_BOOT_DATA), + 'base/section:image-pos': len(U_BOOT_DATA) * 2, + 'base/section:size': len(expect1), + 'base/section:uncomp-size': len(COMPRESS_DATA + U_BOOT_DATA), + 'base/section/blob:offset': 0, + 'base/section/blob:size': len(COMPRESS_DATA), + 'base/section/u-boot:offset': len(COMPRESS_DATA), + 'base/section/u-boot:size': len(U_BOOT_DATA), + + 'base/section2:offset': len(U_BOOT_DATA) + len(expect1), + 'base/section2:image-pos': len(U_BOOT_DATA) * 2 + len(expect1), + 'base/section2:size': len(expect2), + 'base/section2:uncomp-size': len(COMPRESS_DATA + COMPRESS_DATA), + 'base/section2/blob:offset': 0, + 'base/section2/blob:size': len(COMPRESS_DATA), + 'base/section2/blob2:offset': len(COMPRESS_DATA), + 'base/section2/blob2:size': len(COMPRESS_DATA), + + 'offset': 0, + 'image-pos': 0, + 'size': len(data), + } + self.assertEqual(expected, props) + if __name__ == "__main__": unittest.main() -- cgit v1.2.3