From 1835cd2264ebd8814624b738d6e25ee772682cbe Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Fri, 6 Jul 2018 10:27:15 -0600 Subject: binman: Make the operation of Entry__testing explicit This fake entry is used for testing. At present it only has one behaviour which is to return an invalid set of entry positions, to cause an error. The fake entry will need to be used for other things too. Allow the test .dts file to specify the behaviour of the fake entry, so we can control its behaviour easily. While we are here, drop the ReadContents() method, since this only applies to subclasses of Entry_blob, which Entry__testing is not. Signed-off-by: Simon Glass --- tools/binman/test/41_unknown_pos_size.dts | 1 + 1 file changed, 1 insertion(+) (limited to 'tools/binman/test') diff --git a/tools/binman/test/41_unknown_pos_size.dts b/tools/binman/test/41_unknown_pos_size.dts index a8e7d8aa227..94fe821c470 100644 --- a/tools/binman/test/41_unknown_pos_size.dts +++ b/tools/binman/test/41_unknown_pos_size.dts @@ -6,6 +6,7 @@ binman { _testing { + return-invalid-entry; }; }; }; -- cgit v1.3.1 From 736bb0aec80891891f3f86004e1afa7976585918 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Fri, 6 Jul 2018 10:27:17 -0600 Subject: binman: Correct operation of ObtainContents() This method is supposed to return the contents of an entry. However at present there is no check that it actually does. Also some implementations do not return 'True' to indicate success, as required. Add a check for things working as expected, and correct the implementations. This requires some additional test cases to cover things which were missed originally. Add these at the same time. Signed-off-by: Simon Glass --- tools/binman/bsection.py | 4 ++ tools/binman/etype/_testing.py | 5 ++ tools/binman/etype/section.py | 2 +- tools/binman/etype/u_boot_spl_bss_pad.py | 1 + tools/binman/etype/u_boot_ucode.py | 9 +++- tools/binman/ftest.py | 57 +++++++++++++++++----- tools/binman/test/57_unknown_contents.dts | 14 ++++++ tools/binman/test/58_x86_ucode_spl_needs_retry.dts | 36 ++++++++++++++ 8 files changed, 114 insertions(+), 14 deletions(-) create mode 100644 tools/binman/test/57_unknown_contents.dts create mode 100644 tools/binman/test/58_x86_ucode_spl_needs_retry.dts (limited to 'tools/binman/test') diff --git a/tools/binman/bsection.py b/tools/binman/bsection.py index 3f30f6e4fe7..06a6711350a 100644 --- a/tools/binman/bsection.py +++ b/tools/binman/bsection.py @@ -162,6 +162,10 @@ class Section(object): todo = next_todo if not todo: break + if todo: + self._Raise('Internal error: Could not complete processing of ' + 'contents: remaining %s' % todo) + return True def _SetEntryPosSize(self, name, pos, size): """Set the position and size of an entry diff --git a/tools/binman/etype/_testing.py b/tools/binman/etype/_testing.py index 0b1eaefc3ce..c075c3ff0d9 100644 --- a/tools/binman/etype/_testing.py +++ b/tools/binman/etype/_testing.py @@ -9,6 +9,7 @@ from entry import Entry import fdt_util import tools + class Entry__testing(Entry): """A fake entry used for testing @@ -19,8 +20,12 @@ class Entry__testing(Entry): Entry.__init__(self, section, etype, node) self.return_invalid_entry = fdt_util.GetBool(self._node, 'return-invalid-entry') + self.return_unknown_contents = fdt_util.GetBool(self._node, + 'return-unknown-contents') def ObtainContents(self): + if self.return_unknown_contents: + return False self.data = 'a' self.contents_size = len(self.data) return True diff --git a/tools/binman/etype/section.py b/tools/binman/etype/section.py index 139fcad51af..36b31a849f8 100644 --- a/tools/binman/etype/section.py +++ b/tools/binman/etype/section.py @@ -18,7 +18,7 @@ class Entry_section(Entry): self._section = bsection.Section(node.name, node) def ObtainContents(self): - self._section.GetEntryContents() + return self._section.GetEntryContents() def GetData(self): return self._section.GetData() diff --git a/tools/binman/etype/u_boot_spl_bss_pad.py b/tools/binman/etype/u_boot_spl_bss_pad.py index 3d2dea2e0d8..6c397957e30 100644 --- a/tools/binman/etype/u_boot_spl_bss_pad.py +++ b/tools/binman/etype/u_boot_spl_bss_pad.py @@ -24,3 +24,4 @@ class Entry_u_boot_spl_bss_pad(Entry_blob): self.Raise('Expected __bss_size symbol in spl/u-boot-spl') self.data = chr(0) * bss_size self.contents_size = bss_size + return True diff --git a/tools/binman/etype/u_boot_ucode.py b/tools/binman/etype/u_boot_ucode.py index 3a0cff7c3a3..8cae7deed3c 100644 --- a/tools/binman/etype/u_boot_ucode.py +++ b/tools/binman/etype/u_boot_ucode.py @@ -64,9 +64,14 @@ class Entry_u_boot_ucode(Entry_blob): self.data = '' return True - # Get the microcode from the device tree entry + # Get the microcode from the device tree entry. If it is not available + # yet, return False so we will be called later. If the section simply + # doesn't exist, then we may as well return True, since we are going to + # get an error anyway. fdt_entry = self.section.FindEntryType('u-boot-dtb-with-ucode') - if not fdt_entry or not fdt_entry.ucode_data: + if not fdt_entry: + return True + if not fdt_entry.ucode_data: return False if not fdt_entry.collate: diff --git a/tools/binman/ftest.py b/tools/binman/ftest.py index 80eadeffab8..ca9d158eef3 100644 --- a/tools/binman/ftest.py +++ b/tools/binman/ftest.py @@ -688,12 +688,14 @@ class TestFunctional(unittest.TestCase): data = self._DoReadFile('33_x86-start16.dts') self.assertEqual(X86_START16_DATA, data[:len(X86_START16_DATA)]) - def _RunMicrocodeTest(self, dts_fname, nodtb_data): + def _RunMicrocodeTest(self, dts_fname, nodtb_data, ucode_second=False): """Handle running a test for insertion of microcode Args: dts_fname: Name of test .dts file nodtb_data: Data that we expect in the first section + ucode_second: True if the microsecond entry is second instead of + third Returns: Tuple: @@ -704,10 +706,16 @@ class TestFunctional(unittest.TestCase): data = self._DoReadFile(dts_fname, True) # Now check the device tree has no microcode - dtb_with_ucode = data[len(nodtb_data):] - fdt_len = self.GetFdtLen(dtb_with_ucode) - ucode_content = dtb_with_ucode[fdt_len:] - ucode_pos = len(nodtb_data) + fdt_len + if ucode_second: + ucode_content = data[len(nodtb_data):] + ucode_pos = len(nodtb_data) + dtb_with_ucode = ucode_content[16:] + fdt_len = self.GetFdtLen(dtb_with_ucode) + else: + dtb_with_ucode = data[len(nodtb_data):] + fdt_len = self.GetFdtLen(dtb_with_ucode) + ucode_content = dtb_with_ucode[fdt_len:] + ucode_pos = len(nodtb_data) + fdt_len fname = tools.GetOutputFilename('test.dtb') with open(fname, 'wb') as fd: fd.write(dtb_with_ucode) @@ -728,8 +736,8 @@ class TestFunctional(unittest.TestCase): # expected position and size pos_and_size = struct.pack('<2L', 0xfffffe00 + ucode_pos, len(ucode_data)) - first = data[:len(nodtb_data)] - return first, pos_and_size + u_boot = data[:len(nodtb_data)] + return u_boot, pos_and_size def testPackUbootMicrocode(self): """Test that x86 microcode can be handled correctly @@ -892,23 +900,42 @@ class TestFunctional(unittest.TestCase): data = self._DoReadFile('48_x86-start16-spl.dts') self.assertEqual(X86_START16_SPL_DATA, data[:len(X86_START16_SPL_DATA)]) - def testPackUbootSplMicrocode(self): - """Test that x86 microcode can be handled correctly in SPL + def _PackUbootSplMicrocode(self, dts, ucode_second=False): + """Helper function for microcode tests We expect to see the following in the image, in order: u-boot-spl-nodtb.bin with a microcode pointer inserted at the correct place u-boot.dtb with the microcode removed the microcode + + Args: + dts: Device tree file to use for test + ucode_second: True if the microsecond entry is second instead of + third """ # ELF file with a '_dt_ucode_base_size' symbol with open(self.TestFile('u_boot_ucode_ptr')) as fd: TestFunctional._MakeInputFile('spl/u-boot-spl', fd.read()) - first, pos_and_size = self._RunMicrocodeTest('49_x86_ucode_spl.dts', - U_BOOT_SPL_NODTB_DATA) + first, pos_and_size = self._RunMicrocodeTest(dts, U_BOOT_SPL_NODTB_DATA, + ucode_second=ucode_second) self.assertEqual('splnodtb with microc' + pos_and_size + 'ter somewhere in here', first) + def testPackUbootSplMicrocode(self): + """Test that x86 microcode can be handled correctly in SPL""" + self._PackUbootSplMicrocode('49_x86_ucode_spl.dts') + + def testPackUbootSplMicrocodeReorder(self): + """Test that order doesn't matter for microcode entries + + This is the same as testPackUbootSplMicrocode but when we process the + u-boot-ucode entry we have not yet seen the u-boot-dtb-with-ucode + entry, so we reply on binman to try later. + """ + self._PackUbootSplMicrocode('58_x86_ucode_spl_needs_retry.dts', + ucode_second=True) + def testPackMrc(self): """Test that an image with an MRC binary can be created""" data = self._DoReadFile('50_intel_mrc.dts') @@ -971,5 +998,13 @@ class TestFunctional(unittest.TestCase): 00000000 00000004 rw-u-boot ''', map_data) + def testUnknownContents(self): + """Test that obtaining the contents works as expected""" + with self.assertRaises(ValueError) as e: + self._DoReadFile('57_unknown_contents.dts', True) + self.assertIn("Section '/binman': Internal error: Could not complete " + "processing of contents: remaining [<_testing.Entry__testing ", + str(e.exception)) + if __name__ == "__main__": unittest.main() diff --git a/tools/binman/test/57_unknown_contents.dts b/tools/binman/test/57_unknown_contents.dts new file mode 100644 index 00000000000..6ea98d7cab6 --- /dev/null +++ b/tools/binman/test/57_unknown_contents.dts @@ -0,0 +1,14 @@ +// SPDX-License-Identifier: GPL-2.0+ + +/dts-v1/; + +/ { + #address-cells = <1>; + #size-cells = <1>; + + binman { + _testing { + return-unknown-contents; + }; + }; +}; diff --git a/tools/binman/test/58_x86_ucode_spl_needs_retry.dts b/tools/binman/test/58_x86_ucode_spl_needs_retry.dts new file mode 100644 index 00000000000..e2cb80cf6e2 --- /dev/null +++ b/tools/binman/test/58_x86_ucode_spl_needs_retry.dts @@ -0,0 +1,36 @@ +// SPDX-License-Identifier: GPL-2.0+ + +/dts-v1/; + +/ { + #address-cells = <1>; + #size-cells = <1>; + + binman { + sort-by-pos; + end-at-4gb; + size = <0x200>; + u-boot-spl-with-ucode-ptr { + }; + + /* + * Microcode goes before the DTB which contains it, so binman + * will need to obtain the contents of the next section before + * obtaining the contents of this one. + */ + u-boot-ucode { + }; + + u-boot-dtb-with-ucode { + }; + }; + + microcode { + update@0 { + data = <0x12345678 0x12345679>; + }; + update@1 { + data = <0xabcd0000 0x78235609>; + }; + }; +}; -- cgit v1.3.1 From 5c890238c480a96d4d0b06c92199e21867170c31 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Fri, 6 Jul 2018 10:27:19 -0600 Subject: binman: Tidy up setting of entry contents At present the contents of an entry are set in subclasses simply by assigning to the data and content_size properties. Add some methods to do this, so that we have more control. In particular, add a method to set the contents without changing its size, so we can validate that case. Add a test case for trying to change the size when this is not allowed. Signed-off-by: Simon Glass --- tools/binman/entry.py | 28 ++++++++++++++++++++++++++++ tools/binman/etype/_testing.py | 8 ++++++++ tools/binman/etype/blob.py | 3 +-- tools/binman/etype/u_boot_spl_bss_pad.py | 3 +-- tools/binman/etype/u_boot_with_ucode_ptr.py | 4 ++-- tools/binman/ftest.py | 8 ++++++++ tools/binman/test/59_change_size.dts | 14 ++++++++++++++ 7 files changed, 62 insertions(+), 6 deletions(-) create mode 100644 tools/binman/test/59_change_size.dts (limited to 'tools/binman/test') diff --git a/tools/binman/entry.py b/tools/binman/entry.py index e4d688c91f9..303c992e375 100644 --- a/tools/binman/entry.py +++ b/tools/binman/entry.py @@ -55,6 +55,7 @@ class Entry(object): self.name = node and (name_prefix + node.name) or 'none' self.pos = None self.size = None + self.data = '' self.contents_size = 0 self.align = None self.align_size = None @@ -138,6 +139,33 @@ class Entry(object): if prefix: self.name = prefix + self.name + def SetContents(self, data): + """Set the contents of an entry + + This sets both the data and content_size properties + + Args: + data: Data to set to the contents (string) + """ + self.data = data + self.contents_size = len(self.data) + + def ProcessContentsUpdate(self, data): + """Update the contens of an entry, after the size is fixed + + This checks that the new data is the same size as the old. + + Args: + data: Data to set to the contents (string) + + Raises: + ValueError if the new data size is not the same as the old + """ + if len(data) != self.contents_size: + self.Raise('Cannot update entry size from %d to %d' % + (len(data), self.contents_size)) + self.SetContents(data) + def ObtainContents(self): """Figure out the contents of an entry. diff --git a/tools/binman/etype/_testing.py b/tools/binman/etype/_testing.py index c075c3ff0d9..04bdc6c532b 100644 --- a/tools/binman/etype/_testing.py +++ b/tools/binman/etype/_testing.py @@ -22,6 +22,8 @@ class Entry__testing(Entry): 'return-invalid-entry') self.return_unknown_contents = fdt_util.GetBool(self._node, 'return-unknown-contents') + self.bad_update_contents = fdt_util.GetBool(self._node, + 'bad-update-contents') def ObtainContents(self): if self.return_unknown_contents: @@ -34,3 +36,9 @@ class Entry__testing(Entry): if self.return_invalid_entry : return {'invalid-entry': [1, 2]} return {} + + def ProcessContents(self): + if self.bad_update_contents: + # Request to update the conents with something larger, to cause a + # failure. + self.ProcessContentsUpdate('aa') diff --git a/tools/binman/etype/blob.py b/tools/binman/etype/blob.py index 16b1e5f64d9..28e6651a935 100644 --- a/tools/binman/etype/blob.py +++ b/tools/binman/etype/blob.py @@ -28,8 +28,7 @@ class Entry_blob(Entry): # new Entry method which can read in chunks. Then we could copy # the data in chunks and avoid reading it all at once. For now # this seems like an unnecessary complication. - self.data = fd.read() - self.contents_size = len(self.data) + self.SetContents(fd.read()) return True def GetDefaultFilename(self): diff --git a/tools/binman/etype/u_boot_spl_bss_pad.py b/tools/binman/etype/u_boot_spl_bss_pad.py index 6c397957e30..65f631d3c5e 100644 --- a/tools/binman/etype/u_boot_spl_bss_pad.py +++ b/tools/binman/etype/u_boot_spl_bss_pad.py @@ -22,6 +22,5 @@ class Entry_u_boot_spl_bss_pad(Entry_blob): bss_size = elf.GetSymbolAddress(fname, '__bss_size') if not bss_size: self.Raise('Expected __bss_size symbol in spl/u-boot-spl') - self.data = chr(0) * bss_size - self.contents_size = bss_size + self.SetContents(chr(0) * bss_size) return True diff --git a/tools/binman/etype/u_boot_with_ucode_ptr.py b/tools/binman/etype/u_boot_with_ucode_ptr.py index 41c2ded2fe8..86945f33184 100644 --- a/tools/binman/etype/u_boot_with_ucode_ptr.py +++ b/tools/binman/etype/u_boot_with_ucode_ptr.py @@ -81,5 +81,5 @@ class Entry_u_boot_with_ucode_ptr(Entry_blob): # Write the microcode position and size into the entry pos_and_size = struct.pack('<2L', pos, size) self.target_pos -= self.pos - self.data = (self.data[:self.target_pos] + pos_and_size + - self.data[self.target_pos + 8:]) + self.ProcessContentsUpdate(self.data[:self.target_pos] + pos_and_size + + self.data[self.target_pos + 8:]) diff --git a/tools/binman/ftest.py b/tools/binman/ftest.py index ca9d158eef3..af3b4dc3e56 100644 --- a/tools/binman/ftest.py +++ b/tools/binman/ftest.py @@ -1006,5 +1006,13 @@ class TestFunctional(unittest.TestCase): "processing of contents: remaining [<_testing.Entry__testing ", str(e.exception)) + def testBadChangeSize(self): + """Test that trying to change the size of an entry fails""" + with self.assertRaises(ValueError) as e: + self._DoReadFile('59_change_size.dts', True) + self.assertIn("Node '/binman/_testing': Cannot update entry size from " + '2 to 1', str(e.exception)) + + if __name__ == "__main__": unittest.main() diff --git a/tools/binman/test/59_change_size.dts b/tools/binman/test/59_change_size.dts new file mode 100644 index 00000000000..1a69026a64c --- /dev/null +++ b/tools/binman/test/59_change_size.dts @@ -0,0 +1,14 @@ +// SPDX-License-Identifier: GPL-2.0+ + +/dts-v1/; + +/ { + #address-cells = <1>; + #size-cells = <1>; + + binman { + _testing { + bad-update-contents; + }; + }; +}; -- cgit v1.3.1 From 16b8d6b76992690c65c58dc8b0591496cc5e46ef Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Fri, 6 Jul 2018 10:27:42 -0600 Subject: binman: Support updating the device tree with calc'd info It is useful to write the position and size of each entry back to the device tree so that U-Boot can access this at runtime. Add a feature to support this, along with associated tests. Signed-off-by: Simon Glass --- tools/binman/README | 6 +-- tools/binman/control.py | 2 + tools/binman/etype/_testing.py | 10 +++++ tools/binman/ftest.py | 77 ++++++++++++++++++++++++++++----- tools/binman/test/60_fdt_update.dts | 31 +++++++++++++ tools/binman/test/61_fdt_update_bad.dts | 32 ++++++++++++++ 6 files changed, 144 insertions(+), 14 deletions(-) create mode 100644 tools/binman/test/60_fdt_update.dts create mode 100644 tools/binman/test/61_fdt_update_bad.dts (limited to 'tools/binman/test') diff --git a/tools/binman/README b/tools/binman/README index 8b598a75c80..207928aa955 100644 --- a/tools/binman/README +++ b/tools/binman/README @@ -669,13 +669,11 @@ To do ----- Some ideas: -- Fill out the device tree to include the final position and size of each - entry (since the input file may not always specify these). See also - 'Access to binman entry positions at run time' above - Use of-platdata to make the information available to code that is unable to use device tree (such as a very small SPL image) - Allow easy building of images by specifying just the board name -- Produce a full Python binding for libfdt (for upstream) +- Produce a full Python binding for libfdt (for upstream). This is nearing + completion but some work remains - Add an option to decode an image into the constituent binaries - Support building an image for a board (-b) more completely, with a configurable build directory diff --git a/tools/binman/control.py b/tools/binman/control.py index eafabf05c7c..a40b300fdac 100644 --- a/tools/binman/control.py +++ b/tools/binman/control.py @@ -168,6 +168,8 @@ def Binman(options, args): image.BuildImage() if options.map: image.WriteMap() + with open(fname, 'wb') as outfd: + outfd.write(dtb.GetContents()) finally: tools.FinaliseOutputDir() finally: diff --git a/tools/binman/etype/_testing.py b/tools/binman/etype/_testing.py index 04bdc6c532b..6a1af577988 100644 --- a/tools/binman/etype/_testing.py +++ b/tools/binman/etype/_testing.py @@ -24,6 +24,9 @@ class Entry__testing(Entry): 'return-unknown-contents') self.bad_update_contents = fdt_util.GetBool(self._node, 'bad-update-contents') + self.process_fdt_ready = False + self.never_complete_process_fdt = fdt_util.GetBool(self._node, + 'never-complete-process-fdt') def ObtainContents(self): if self.return_unknown_contents: @@ -42,3 +45,10 @@ class Entry__testing(Entry): # Request to update the conents with something larger, to cause a # failure. self.ProcessContentsUpdate('aa') + + def ProcessFdt(self, fdt): + """Force reprocessing the first time""" + ready = self.process_fdt_ready + if not self.never_complete_process_fdt: + self.process_fdt_ready = True + return ready diff --git a/tools/binman/ftest.py b/tools/binman/ftest.py index af3b4dc3e56..12164a85b4d 100644 --- a/tools/binman/ftest.py +++ b/tools/binman/ftest.py @@ -146,19 +146,23 @@ class TestFunctional(unittest.TestCase): # options.verbosity = tout.DEBUG return control.Binman(options, args) - def _DoTestFile(self, fname, debug=False, map=False): + def _DoTestFile(self, fname, debug=False, map=False, update_dtb=False): """Run binman with a given test file Args: fname: Device-tree source filename to use (e.g. 05_simple.dts) debug: True to enable debugging output map: True to output map files for the images + update_dtb: Update the position and size of each entry in the device + tree before packing it into the image """ args = ['-p', '-I', self._indir, '-d', self.TestFile(fname)] if debug: args.append('-D') if map: args.append('-m') + if update_dtb: + args.append('-up') return self._DoBinman(*args) def _SetupDtb(self, fname, outfile='u-boot.dtb'): @@ -183,7 +187,8 @@ class TestFunctional(unittest.TestCase): TestFunctional._MakeInputFile(outfile, data) return data - def _DoReadFileDtb(self, fname, use_real_dtb=False, map=False): + def _DoReadFileDtb(self, fname, use_real_dtb=False, map=False, + update_dtb=False): """Run binman and return the resulting image This runs binman with a given test file and then reads the resulting @@ -199,6 +204,8 @@ class TestFunctional(unittest.TestCase): test contents (the U_BOOT_DTB_DATA string) can be used. But in some test we need the real contents. map: True to output map files for the images + update_dtb: Update the position and size of each entry in the device + tree before packing it into the image Returns: Tuple: @@ -212,21 +219,22 @@ class TestFunctional(unittest.TestCase): dtb_data = self._SetupDtb(fname) try: - retcode = self._DoTestFile(fname, map=map) + retcode = self._DoTestFile(fname, map=map, update_dtb=update_dtb) self.assertEqual(0, retcode) + out_dtb_fname = control.GetFdtPath('u-boot.dtb') # Find the (only) image, read it and return its contents image = control.images['image'] - fname = tools.GetOutputFilename('image.bin') - self.assertTrue(os.path.exists(fname)) + image_fname = tools.GetOutputFilename('image.bin') + self.assertTrue(os.path.exists(image_fname)) if map: map_fname = tools.GetOutputFilename('image.map') with open(map_fname) as fd: map_data = fd.read() else: map_data = None - with open(fname) as fd: - return fd.read(), dtb_data, map_data + with open(image_fname) as fd: + return fd.read(), dtb_data, map_data, out_dtb_fname finally: # Put the test file back if use_real_dtb: @@ -300,6 +308,26 @@ class TestFunctional(unittest.TestCase): """ return struct.unpack('>L', dtb[4:8])[0] + def _GetPropTree(self, dtb_data, node_names): + def AddNode(node, path): + if node.name != '/': + path += '/' + node.name + #print 'path', path + for subnode in node.subnodes: + for prop in subnode.props.values(): + if prop.name in node_names: + prop_path = path + '/' + subnode.name + ':' + prop.name + tree[prop_path[len('/binman/'):]] = fdt_util.fdt32_to_cpu( + prop.value) + #print ' ', prop.name + AddNode(subnode, path) + + tree = {} + dtb = fdt.Fdt(dtb_data) + dtb.Scan() + AddNode(dtb.GetRoot(), '') + return tree + def testRun(self): """Test a basic run with valid args""" result = self._RunBinman('-h') @@ -845,7 +873,7 @@ class TestFunctional(unittest.TestCase): """Test that we can cope with an image without microcode (e.g. qemu)""" with open(self.TestFile('u_boot_no_ucode_ptr')) as fd: TestFunctional._MakeInputFile('u-boot', fd.read()) - data, dtb, _ = self._DoReadFileDtb('44_x86_optional_ucode.dts', True) + data, dtb, _, _ = self._DoReadFileDtb('44_x86_optional_ucode.dts', True) # Now check the device tree has no microcode self.assertEqual(U_BOOT_NODTB_DATA, data[:len(U_BOOT_NODTB_DATA)]) @@ -980,7 +1008,7 @@ class TestFunctional(unittest.TestCase): def testMap(self): """Tests outputting a map of the images""" - _, _, map_data = self._DoReadFileDtb('55_sections.dts', map=True) + _, _, map_data, _ = self._DoReadFileDtb('55_sections.dts', map=True) self.assertEqual('''Position Size Name 00000000 00000010 section@0 00000000 00000004 u-boot @@ -990,7 +1018,7 @@ class TestFunctional(unittest.TestCase): def testNamePrefix(self): """Tests that name prefixes are used""" - _, _, map_data = self._DoReadFileDtb('56_name_prefix.dts', map=True) + _, _, map_data, _ = self._DoReadFileDtb('56_name_prefix.dts', map=True) self.assertEqual('''Position Size Name 00000000 00000010 section@0 00000000 00000004 ro-u-boot @@ -1013,6 +1041,35 @@ class TestFunctional(unittest.TestCase): self.assertIn("Node '/binman/_testing': Cannot update entry size from " '2 to 1', str(e.exception)) + def testUpdateFdt(self): + """Test that we can update the device tree with pos/size info""" + _, _, _, out_dtb_fname = self._DoReadFileDtb('60_fdt_update.dts', + update_dtb=True) + props = self._GetPropTree(out_dtb_fname, ['pos', 'size']) + with open('/tmp/x.dtb', 'wb') as outf: + with open(out_dtb_fname) as inf: + outf.write(inf.read()) + self.assertEqual({ + '_testing:pos': 32, + '_testing:size': 1, + 'section@0/u-boot:pos': 0, + 'section@0/u-boot:size': len(U_BOOT_DATA), + 'section@0:pos': 0, + 'section@0:size': 16, + + 'section@1/u-boot:pos': 0, + 'section@1/u-boot:size': len(U_BOOT_DATA), + 'section@1:pos': 16, + 'section@1:size': 16, + 'size': 40 + }, props) + + def testUpdateFdtBad(self): + """Test that we detect when ProcessFdt never completes""" + with self.assertRaises(ValueError) as e: + self._DoReadFileDtb('61_fdt_update_bad.dts', update_dtb=True) + self.assertIn('Could not complete processing of Fdt: remaining ' + '[<_testing.Entry__testing', str(e.exception)) if __name__ == "__main__": unittest.main() diff --git a/tools/binman/test/60_fdt_update.dts b/tools/binman/test/60_fdt_update.dts new file mode 100644 index 00000000000..f53c8a5053e --- /dev/null +++ b/tools/binman/test/60_fdt_update.dts @@ -0,0 +1,31 @@ +// SPDX-License-Identifier: GPL-2.0+ +/dts-v1/; + +/ { + #address-cells = <1>; + #size-cells = <1>; + + binman { + pad-byte = <0x26>; + size = <0x28>; + section@0 { + read-only; + name-prefix = "ro-"; + size = <0x10>; + pad-byte = <0x21>; + + u-boot { + }; + }; + section@1 { + name-prefix = "rw-"; + size = <0x10>; + pad-byte = <0x61>; + + u-boot { + }; + }; + _testing { + }; + }; +}; diff --git a/tools/binman/test/61_fdt_update_bad.dts b/tools/binman/test/61_fdt_update_bad.dts new file mode 100644 index 00000000000..e5abf31699c --- /dev/null +++ b/tools/binman/test/61_fdt_update_bad.dts @@ -0,0 +1,32 @@ +// SPDX-License-Identifier: GPL-2.0+ +/dts-v1/; + +/ { + #address-cells = <1>; + #size-cells = <1>; + + binman { + pad-byte = <0x26>; + size = <0x28>; + section@0 { + read-only; + name-prefix = "ro-"; + size = <0x10>; + pad-byte = <0x21>; + + u-boot { + }; + }; + section@1 { + name-prefix = "rw-"; + size = <0x10>; + pad-byte = <0x61>; + + u-boot { + }; + }; + _testing { + never-complete-process-fdt; + }; + }; +}; -- cgit v1.3.1