binman: Support FDT update for CBFS

It is useful to add the CBFS file information (offset, size, etc.) into
the FDT so that the layout is complete. Add support for this.

Signed-off-by: Simon Glass <sjg@chromium.org>
diff --git a/tools/binman/etype/cbfs.py b/tools/binman/etype/cbfs.py
index 49baa6a..a46bb98 100644
--- a/tools/binman/etype/cbfs.py
+++ b/tools/binman/etype/cbfs.py
@@ -11,6 +11,7 @@
 from cbfs_util import CbfsWriter
 from entry import Entry
 import fdt_util
+import state
 
 class Entry_cbfs(Entry):
     """Entry containing a Coreboot Filesystem (CBFS)
@@ -181,11 +182,17 @@
             if not entry.ObtainContents():
                 return False
             data = entry.GetData()
+            cfile = None
             if entry._type == 'raw':
-                cbfs.add_file_raw(entry._cbfs_name, data, entry._cbfs_offset,
-                                  entry._cbfs_compress)
+                cfile = cbfs.add_file_raw(entry._cbfs_name, data,
+                                          entry._cbfs_offset,
+                                          entry._cbfs_compress)
             elif entry._type == 'stage':
-                cbfs.add_file_stage(entry._cbfs_name, data, entry._cbfs_offset)
+                cfile = cbfs.add_file_stage(entry._cbfs_name, data,
+                                            entry._cbfs_offset)
+            if cfile:
+                entry._cbfs_file = cfile
+                entry.size = cfile.data_len
         data = cbfs.get_data()
         self.SetContents(data)
         return True
@@ -203,3 +210,39 @@
                 self.Raise("Invalid compression in '%s': '%s'" %
                            (node.name, compress))
             self._cbfs_entries[entry._cbfs_name] = entry
+
+    def SetImagePos(self, image_pos):
+        """Override this function to set all the entry properties from CBFS
+
+        We can only do this once image_pos is known
+
+        Args:
+            image_pos: Position of this entry in the image
+        """
+        Entry.SetImagePos(self, image_pos)
+
+        # Now update the entries with info from the CBFS entries
+        for entry in self._cbfs_entries.values():
+            cfile = entry._cbfs_file
+            entry.size = cfile.data_len
+            entry.offset = cfile.calced_cbfs_offset
+            entry.image_pos = self.image_pos + entry.offset
+            if entry._cbfs_compress:
+                entry.uncomp_size = cfile.memlen
+
+    def AddMissingProperties(self):
+        Entry.AddMissingProperties(self)
+        for entry in self._cbfs_entries.values():
+            entry.AddMissingProperties()
+            if entry._cbfs_compress:
+                state.AddZeroProp(entry._node, 'uncomp-size')
+
+    def SetCalculatedProperties(self):
+        """Set the value of device-tree properties calculated by binman"""
+        Entry.SetCalculatedProperties(self)
+        for entry in self._cbfs_entries.values():
+            state.SetInt(entry._node, 'offset', entry.offset)
+            state.SetInt(entry._node, 'size', entry.size)
+            state.SetInt(entry._node, 'image-pos', entry.image_pos)
+            if entry.uncomp_size is not None:
+                state.SetInt(entry._node, 'uncomp-size', entry.uncomp_size)
diff --git a/tools/binman/ftest.py b/tools/binman/ftest.py
index 89e732f..999d888 100644
--- a/tools/binman/ftest.py
+++ b/tools/binman/ftest.py
@@ -2160,6 +2160,31 @@
             }
         self.assertEqual(expected, props)
 
+    def testCbfsUpdateFdt(self):
+        """Test that we can update the device tree with CBFS offset/size info"""
+        self._CheckLz4()
+        data, _, _, out_dtb_fname = self._DoReadFileDtb('125_cbfs_update.dts',
+                                                        update_dtb=True)
+        dtb = fdt.Fdt(out_dtb_fname)
+        dtb.Scan()
+        props = self._GetPropTree(dtb, ['offset', 'size', 'image-pos',
+                                        'uncomp-size'])
+        del props['cbfs/u-boot:size']
+        self.assertEqual({
+            'offset': 0,
+            'size': len(data),
+            'image-pos': 0,
+            'cbfs:offset': 0,
+            'cbfs:size': len(data),
+            'cbfs:image-pos': 0,
+            'cbfs/u-boot:offset': 0x38,
+            'cbfs/u-boot:uncomp-size': len(U_BOOT_DATA),
+            'cbfs/u-boot:image-pos': 0x38,
+            'cbfs/u-boot-dtb:offset': 0xb8,
+            'cbfs/u-boot-dtb:size': len(U_BOOT_DATA),
+            'cbfs/u-boot-dtb:image-pos': 0xb8,
+            }, props)
+
 
 if __name__ == "__main__":
     unittest.main()
diff --git a/tools/binman/test/125_cbfs_update.dts b/tools/binman/test/125_cbfs_update.dts
new file mode 100644
index 0000000..6d2e8a0
--- /dev/null
+++ b/tools/binman/test/125_cbfs_update.dts
@@ -0,0 +1,21 @@
+// SPDX-License-Identifier: GPL-2.0+
+
+/dts-v1/;
+
+/ {
+	#address-cells = <1>;
+	#size-cells = <1>;
+
+	binman {
+		cbfs {
+			size = <0x100>;
+			u-boot {
+				cbfs-type = "raw";
+				cbfs-compress = "lz4";
+			};
+			u-boot-dtb {
+				cbfs-type = "raw";
+			};
+		};
+	};
+};