]> git.dujemihanovic.xyz Git - u-boot.git/commitdiff
binman: Add length header attribute to dtb entry
authorStefan Herbrechtsmeier <stefan.herbrechtsmeier@weidmueller.com>
Fri, 19 Aug 2022 14:25:25 +0000 (16:25 +0200)
committerSimon Glass <sjg@chromium.org>
Sun, 21 Aug 2022 00:07:33 +0000 (18:07 -0600)
Add an optional length header attribute to the device tree blob entry
class based on the compressed data header from the utilities to compress
and decompress data.

If needed the header could be enabled with the following
attribute beside the compress attribute:
  prepend = "length";

The header was introduced as part of commit eb0f4a4cb402 ("binman:
Support replacing data in a cbfs") to allow device tree entries to be
larger than the compressed contents. Regarding the commit "this is
necessary to cope with a compressed device tree being updated in such a
way that it shrinks after the entry size is already set (an obscure
case)". This case need to be fixed without influence any compressed data
by itself.

Signed-off-by: Stefan Herbrechtsmeier <stefan.herbrechtsmeier@weidmueller.com>
Reviewed-by: Simon Glass <sjg@chromium.org>
tools/binman/entries.rst
tools/binman/etype/blob_dtb.py
tools/binman/ftest.py
tools/binman/test/235_compress_dtb_prepend_invalid.dts [new file with mode: 0644]
tools/binman/test/236_compress_dtb_prepend_length.dts [new file with mode: 0644]

index 4dda34ca01f3f70a51f7ef9dc8664bdddbe2413b..b3613d7cbd0d34dcdf63148190f81b7817701ac0 100644 (file)
@@ -216,6 +216,9 @@ This is a blob containing a device tree. The contents of the blob are
 obtained from the list of available device-tree files, managed by the
 'state' module.
 
+Additional Properties / Entry arguments:
+    - prepend: Header type to use:
+        length: 32-bit length header
 
 
 .. _etype_blob_ext:
index 4159e3032a1e7b0d29b07703817abd354642b273..5a6a45474851ae4621ae9f315e29d1914cba4607 100644 (file)
@@ -7,6 +7,8 @@
 
 from binman.entry import Entry
 from binman.etype.blob import Entry_blob
+from dtoc import fdt_util
+import struct
 
 # This is imported if needed
 state = None
@@ -17,6 +19,9 @@ class Entry_blob_dtb(Entry_blob):
     This is a blob containing a device tree. The contents of the blob are
     obtained from the list of available device-tree files, managed by the
     'state' module.
+
+    Additional attributes:
+        prepend: Header used (e.g. 'length')
     """
     def __init__(self, section, etype, node):
         # Put this here to allow entry-docs and help to work without libfdt
@@ -24,6 +29,14 @@ class Entry_blob_dtb(Entry_blob):
         from binman import state
 
         super().__init__(section, etype, node)
+        self.prepend = None
+
+    def ReadNode(self):
+        super().ReadNode()
+        self.prepend = fdt_util.GetString(self._node, 'prepend')
+        if self.prepend and self.prepend not in ['length']:
+            self.Raise("Invalid prepend in '%s': '%s'" %
+                       (self._node.name, self.prepend))
 
     def ObtainContents(self):
         """Get the device-tree from the list held by the 'state' module"""
@@ -58,3 +71,17 @@ class Entry_blob_dtb(Entry_blob):
         # will still return the old contents
         state.UpdateFdtContents(self.GetFdtEtype(), data)
         return ok
+
+    def CompressData(self, indata):
+        data = super().CompressData(indata)
+        if self.prepend == 'length':
+            hdr = struct.pack('<I', len(data))
+            data = hdr + data
+        return data
+
+    def DecompressData(self, indata):
+        if self.prepend == 'length':
+            data_len = struct.unpack('<I', indata[:4])[0]
+            indata = indata[4:4 + data_len]
+        data = super().DecompressData(indata)
+        return data
index 9bce102e77bcbd2cbafea945f4264afc2d8f0d40..7a3e4f8ae0b89f7c8e0ec17e4bfed7254f50454f 100644 (file)
@@ -5807,6 +5807,45 @@ fdt         fdtmap                Extract the devicetree blob from the fdtmap
         expect = U_BOOT_SPL_DATA + U_BOOT_DATA
         self.assertEqual(expect, data[:len(expect)])
 
+    def testCompressDtbPrependInvalid(self):
+        """Test that invalid header is detected"""
+        with self.assertRaises(ValueError) as e:
+            self._DoReadFileDtb('235_compress_dtb_prepend_invalid.dts')
+        self.assertIn("Node '/binman/u-boot-dtb': Invalid prepend in "
+                      "'u-boot-dtb': 'invalid'", str(e.exception))
+
+    def testCompressDtbPrependLength(self):
+        """Test that compress with length header works as expected"""
+        data = self._DoReadFileRealDtb('236_compress_dtb_prepend_length.dts')
+        image = control.images['image']
+        entries = image.GetEntries()
+        self.assertIn('u-boot-dtb', entries)
+        u_boot_dtb = entries['u-boot-dtb']
+        self.assertIn('fdtmap', entries)
+        fdtmap = entries['fdtmap']
+
+        image_fname = tools.get_output_filename('image.bin')
+        orig = control.ReadEntry(image_fname, 'u-boot-dtb')
+        dtb = fdt.Fdt.FromData(orig)
+        dtb.Scan()
+        props = self._GetPropTree(dtb, ['size', 'uncomp-size'])
+        expected = {
+            'u-boot:size': len(U_BOOT_DATA),
+            'u-boot-dtb:uncomp-size': len(orig),
+            'u-boot-dtb:size': u_boot_dtb.size,
+            'fdtmap:size': fdtmap.size,
+            'size': len(data),
+            }
+        self.assertEqual(expected, props)
+
+        # Check implementation
+        self.assertEqual(U_BOOT_DATA, data[:len(U_BOOT_DATA)])
+        rest = data[len(U_BOOT_DATA):]
+        comp_data_len = struct.unpack('<I', rest[:4])[0]
+        comp_data = rest[4:4 + comp_data_len]
+        orig2 = self._decompress(comp_data)
+        self.assertEqual(orig, orig2)
+
 
 if __name__ == "__main__":
     unittest.main()
diff --git a/tools/binman/test/235_compress_dtb_prepend_invalid.dts b/tools/binman/test/235_compress_dtb_prepend_invalid.dts
new file mode 100644 (file)
index 0000000..ee32670
--- /dev/null
@@ -0,0 +1,17 @@
+// SPDX-License-Identifier: GPL-2.0+
+
+/dts-v1/;
+
+/ {
+       #address-cells = <1>;
+       #size-cells = <1>;
+
+       binman {
+               u-boot {
+               };
+               u-boot-dtb {
+                       compress = "lz4";
+                       prepend = "invalid";
+               };
+       };
+};
diff --git a/tools/binman/test/236_compress_dtb_prepend_length.dts b/tools/binman/test/236_compress_dtb_prepend_length.dts
new file mode 100644 (file)
index 0000000..1570233
--- /dev/null
@@ -0,0 +1,19 @@
+// SPDX-License-Identifier: GPL-2.0+
+
+/dts-v1/;
+
+/ {
+       #address-cells = <1>;
+       #size-cells = <1>;
+
+       binman {
+               u-boot {
+               };
+               u-boot-dtb {
+                       compress = "lz4";
+                       prepend = "length";
+               };
+               fdtmap {
+               };
+       };
+};