[U-Boot] [PATCH 25/26] binman: Support reading an image into an Image object

Simon Glass sjg at chromium.org
Tue Jul 2 00:24:54 UTC 2019


It is possible to read an Image, locate its FDT map and then read it into
the binman data structures. This allows full access to the entries that
were written to the image. Add support for this.

Signed-off-by: Simon Glass <sjg at chromium.org>
---

 tools/binman/entry.py                         |  6 ++++
 tools/binman/ftest.py                         | 33 +++++++++++++++++
 tools/binman/image.py                         | 36 +++++++++++++++++++
 tools/binman/test/128_decode_image_no_hdr.dts | 33 +++++++++++++++++
 tools/binman/test/129_list_fdtmap.dts         | 36 +++++++++++++++++++
 5 files changed, 144 insertions(+)
 create mode 100644 tools/binman/test/128_decode_image_no_hdr.dts
 create mode 100644 tools/binman/test/129_list_fdtmap.dts

diff --git a/tools/binman/entry.py b/tools/binman/entry.py
index a39b316b3eb..1fe905ae904 100644
--- a/tools/binman/entry.py
+++ b/tools/binman/entry.py
@@ -159,6 +159,12 @@ class Entry(object):
         self.offset = fdt_util.GetInt(self._node, 'offset')
         self.size = fdt_util.GetInt(self._node, 'size')
         self.orig_offset, self.orig_size = self.offset, self.size
+
+        # These should not be set in input files, but are set in an FDT map,
+        # which is also read by this code.
+        self.image_pos = fdt_util.GetInt(self._node, 'image-pos')
+        self.uncomp_size = fdt_util.GetInt(self._node, 'uncomp-size')
+
         self.align = fdt_util.GetInt(self._node, 'align')
         if tools.NotPowerOfTwo(self.align):
             raise ValueError("Node '%s': Alignment %s must be a power of two" %
diff --git a/tools/binman/ftest.py b/tools/binman/ftest.py
index 15cf5cea457..88c3d847f82 100644
--- a/tools/binman/ftest.py
+++ b/tools/binman/ftest.py
@@ -30,6 +30,7 @@ import fdt_util
 import fmap_util
 import test_util
 import gzip
+from image import Image
 import state
 import tools
 import tout
@@ -2302,6 +2303,38 @@ class TestFunctional(unittest.TestCase):
         data = self._DoReadFile('005_simple.dts')
         self.assertEqual(None, image_header.LocateHeaderOffset(data))
 
+    def testReadImage(self):
+        """Test reading an image and accessing its FDT map"""
+        data = self._DoReadFileDtb('128_decode_image.dts',
+                                   use_real_dtb=True, update_dtb=True)[0]
+        image_fname = tools.GetOutputFilename('image.bin')
+        orig_image = control.images['image']
+        image = Image.FromFile(image_fname)
+        self.assertEqual(orig_image.GetEntries().keys(),
+                         image.GetEntries().keys())
+
+        orig_entry = orig_image.GetEntries()['fdtmap']
+        entry = image.GetEntries()['fdtmap']
+        self.assertEquals(orig_entry.offset, entry.offset)
+        self.assertEquals(orig_entry.size, entry.size)
+        self.assertEquals(orig_entry.image_pos, entry.image_pos)
+
+    def testReadImageNoHeader(self):
+        """Test accessing an image's FDT map without an image header"""
+        data = self._DoReadFileDtb('128_decode_image_no_hdr.dts',
+                                   use_real_dtb=True, update_dtb=True)[0]
+        image_fname = tools.GetOutputFilename('image.bin')
+        image = Image.FromFile(image_fname)
+        self.assertTrue(isinstance(image, Image))
+        self.assertEqual('image', image._name)
+
+    def testReadImageFail(self):
+        """Test failing to read an image image's FDT map"""
+        self._DoReadFile('005_simple.dts')
+        image_fname = tools.GetOutputFilename('image.bin')
+        image = Image.FromFile(image_fname)
+        self.assertTrue(isinstance(image, str))
+        self.assertEqual('Cannot find FDT map in image', image)
 
 if __name__ == "__main__":
     unittest.main()
diff --git a/tools/binman/image.py b/tools/binman/image.py
index d4145685972..d918b5a7194 100644
--- a/tools/binman/image.py
+++ b/tools/binman/image.py
@@ -12,6 +12,9 @@ from operator import attrgetter
 import re
 import sys
 
+from etype import fdtmap
+from etype import image_header
+import fdt
 import fdt_util
 import bsection
 import tools
@@ -47,6 +50,39 @@ class Image:
         else:
             self._ReadNode()
 
+    @classmethod
+    def FromFile(cls, fname):
+        """Convert an image file into an Image for use in binman
+
+        Args:
+            fname: Filename of image file to read
+
+        Returns:
+            Image object on success, or string error message on failure
+        """
+        data = tools.ReadFile(fname)
+        size = len(data)
+
+        # First look for an image header
+        pos = image_header.LocateHeaderOffset(data)
+        if pos is None:
+            # Look for the FDT map
+            pos = fdtmap.LocateFdtmap(data)
+        else:
+            # Move past the header to the FDT
+            pos += fdtmap.FDTMAP_HDR_LEN
+        if pos is None:
+            return 'Cannot find FDT map in image'
+
+        # We don't knowe the FDT size, so check its header first
+        probe_dtb = fdt.Fdt.FromData(data[pos:pos + 256])
+        dtb_size = probe_dtb.GetFdtObj().totalsize()
+        dtb = fdt.Fdt.FromData(data[pos:pos + dtb_size])
+        dtb.Scan()
+
+        # Return an Image with the associated nodes
+        return Image('image', dtb.GetRoot())
+
     def _ReadNode(self):
         """Read properties from the image node"""
         self._size = fdt_util.GetInt(self._node, 'size')
diff --git a/tools/binman/test/128_decode_image_no_hdr.dts b/tools/binman/test/128_decode_image_no_hdr.dts
new file mode 100644
index 00000000000..90fdd8820ca
--- /dev/null
+++ b/tools/binman/test/128_decode_image_no_hdr.dts
@@ -0,0 +1,33 @@
+// SPDX-License-Identifier: GPL-2.0+
+
+/dts-v1/;
+
+/ {
+	#address-cells = <1>;
+	#size-cells = <1>;
+
+	binman {
+		size = <0xc00>;
+		u-boot {
+		};
+		section {
+			align = <0x100>;
+			cbfs {
+				size = <0x400>;
+				u-boot {
+					cbfs-type = "raw";
+				};
+				u-boot-dtb {
+					cbfs-type = "raw";
+					cbfs-compress = "lzma";
+					cbfs-offset = <0x80>;
+				};
+			};
+			u-boot-dtb {
+				compress = "lz4";
+			};
+		};
+		fdtmap {
+		};
+	};
+};
diff --git a/tools/binman/test/129_list_fdtmap.dts b/tools/binman/test/129_list_fdtmap.dts
new file mode 100644
index 00000000000..449fccc41df
--- /dev/null
+++ b/tools/binman/test/129_list_fdtmap.dts
@@ -0,0 +1,36 @@
+// SPDX-License-Identifier: GPL-2.0+
+
+/dts-v1/;
+
+/ {
+	#address-cells = <1>;
+	#size-cells = <1>;
+
+	binman {
+		size = <0xc00>;
+		u-boot {
+		};
+		section {
+			align = <0x100>;
+			cbfs {
+				size = <0x400>;
+				u-boot {
+					cbfs-type = "raw";
+				};
+				u-boot-dtb {
+					cbfs-type = "raw";
+					cbfs-compress = "lzma";
+					cbfs-offset = <0x80>;
+				};
+			};
+			u-boot-dtb {
+				compress = "lz4";
+			};
+		};
+		fdtmap {
+		};
+		image-header {
+			location = "end";
+		};
+	};
+};
-- 
2.22.0.410.gd8fdbe21b5-goog



More information about the U-Boot mailing list