binman: Tidy up setting of entry contents
authorSimon Glass <sjg@chromium.org>
Fri, 6 Jul 2018 16:27:19 +0000 (10:27 -0600)
committerSimon Glass <sjg@chromium.org>
Mon, 9 Jul 2018 15:11:00 +0000 (09:11 -0600)
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 <sjg@chromium.org>
tools/binman/entry.py
tools/binman/etype/_testing.py
tools/binman/etype/blob.py
tools/binman/etype/u_boot_spl_bss_pad.py
tools/binman/etype/u_boot_with_ucode_ptr.py
tools/binman/ftest.py
tools/binman/test/59_change_size.dts [new file with mode: 0644]

index e4d688c91f9aa54c27331b80dccb5f2074edd6de..303c992e3758777387a0807dac5554473c24364a 100644 (file)
@@ -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.
 
index c075c3ff0d91aa8a652ea709de5856d2181839e6..04bdc6c532b213b98259ffe0a58564137e10037b 100644 (file)
@@ -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')
index 16b1e5f64d97933a95fbdd6acfcf70a64094e318..28e6651a935e4c171b2e26c7ada812128919b031 100644 (file)
@@ -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):
index 6c397957e305b1b750bf599c387b4a83e899ded1..65f631d3c5e4d6080ade38ec877252b161a12002 100644 (file)
@@ -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
index 41c2ded2fe8bf461ab994e73df1e87c6102a2e98..86945f331844b155aa243654221794b74166074d 100644 (file)
@@ -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:])
index ca9d158eef33029dd4ca9b6743dedd1d3ce06dd1..af3b4dc3e56c7972275717105d6e0d01b5c8fb7c 100644 (file)
@@ -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 (file)
index 0000000..1a69026
--- /dev/null
@@ -0,0 +1,14 @@
+// SPDX-License-Identifier: GPL-2.0+
+
+/dts-v1/;
+
+/ {
+       #address-cells = <1>;
+       #size-cells = <1>;
+
+       binman {
+               _testing {
+                       bad-update-contents;
+               };
+       };
+};