binman: Support multithreading for building images
[platform/kernel/u-boot.git] / tools / binman / image.py
index 523b274..cdc58b3 100644 (file)
@@ -36,6 +36,8 @@ class Image(section.Entry_section):
         fdtmap_data: Contents of the fdtmap when loading from a file
         allow_repack: True to add properties to allow the image to be safely
             repacked later
+        test_section_timeout: Use a zero timeout for section multi-threading
+            (for testing)
 
     Args:
         copy_to_orig: Copy offset/size to orig_offset/orig_size after reading
@@ -43,9 +45,28 @@ class Image(section.Entry_section):
         test: True if this is being called from a test of Images. This this case
             there is no device tree defining the structure of the section, so
             we create a section manually.
+        ignore_missing: Ignore any missing entry arguments (i.e. don't raise an
+            exception). This should be used if the Image is being loaded from
+            a file rather than generated. In that case we obviously don't need
+            the entry arguments since the contents already exists.
+        use_expanded: True if we are updating the FDT wth entry offsets, etc.
+            and should use the expanded versions of the U-Boot entries.
+            Any entry type that includes a devicetree must put it in a
+            separate entry so that it will be updated. For example. 'u-boot'
+            normally just picks up 'u-boot.bin' which includes the
+            devicetree, but this is not updateable, since it comes into
+            binman as one piece and binman doesn't know that it is actually
+            an executable followed by a devicetree. Of course it could be
+            taught this, but then when reading an image (e.g. 'binman ls')
+            it may need to be able to split the devicetree out of the image
+            in order to determine the location of things. Instead we choose
+            to ignore 'u-boot-bin' in this case, and build it ourselves in
+            binman with 'u-boot-dtb.bin' and 'u-boot.dtb'. See
+            Entry_u_boot_expanded and Entry_blob_phase for details.
     """
-    def __init__(self, name, node, copy_to_orig=True, test=False):
-        section.Entry_section.__init__(self, None, 'section', node, test=test)
+    def __init__(self, name, node, copy_to_orig=True, test=False,
+                 ignore_missing=False, use_expanded=False):
+        super().__init__(None, 'section', node, test=test)
         self.copy_to_orig = copy_to_orig
         self.name = 'main-section'
         self.image_name = name
@@ -53,11 +74,14 @@ class Image(section.Entry_section):
         self.fdtmap_dtb = None
         self.fdtmap_data = None
         self.allow_repack = False
+        self._ignore_missing = ignore_missing
+        self.use_expanded = use_expanded
+        self.test_section_timeout = False
         if not test:
             self.ReadNode()
 
     def ReadNode(self):
-        section.Entry_section.ReadNode(self)
+        super().ReadNode()
         filename = fdt_util.GetString(self._node, 'filename')
         if filename:
             self._filename = filename
@@ -100,7 +124,7 @@ class Image(section.Entry_section):
 
         # Return an Image with the associated nodes
         root = dtb.GetRoot()
-        image = Image('image', root, copy_to_orig=False)
+        image = Image('image', root, copy_to_orig=False, ignore_missing=True)
 
         image.image_node = fdt_util.GetString(root, 'image-node', 'image')
         image.fdtmap_dtb = dtb
@@ -116,11 +140,11 @@ class Image(section.Entry_section):
 
     def PackEntries(self):
         """Pack all entries into the image"""
-        section.Entry_section.Pack(self, 0)
+        super().Pack(0)
 
     def SetImagePos(self):
         # This first section in the image so it starts at 0
-        section.Entry_section.SetImagePos(self, 0)
+        super().SetImagePos(0)
 
     def ProcessEntryContents(self):
         """Call the ProcessContents() method for each entry
@@ -130,23 +154,18 @@ class Image(section.Entry_section):
         Returns:
             True if the new data size is OK, False if expansion is needed
         """
-        sizes_ok = True
-        for entry in self._entries.values():
-            if not entry.ProcessContents():
-                sizes_ok = False
-                tout.Debug("Entry '%s' size change" % self._node.path)
-        return sizes_ok
+        return super().ProcessContents()
 
     def WriteSymbols(self):
         """Write symbol values into binary files for access at run time"""
-        section.Entry_section.WriteSymbols(self, self)
+        super().WriteSymbols(self)
 
     def BuildImage(self):
         """Write the image to a file"""
         fname = tools.GetOutputFilename(self._filename)
         tout.Info("Writing image to '%s'" % fname)
         with open(fname, 'wb') as fd:
-            data = self.GetData()
+            data = self.GetPaddedData()
             fd.write(data)
         tout.Info("Wrote %#x bytes" % len(data))
 
@@ -161,7 +180,7 @@ class Image(section.Entry_section):
         with open(fname, 'w') as fd:
             print('%8s  %8s  %8s  %s' % ('ImagePos', 'Offset', 'Size', 'Name'),
                   file=fd)
-            section.Entry_section.WriteMap(self, fd, 0)
+            super().WriteMap(fd, 0)
         return fname
 
     def BuildEntryList(self):
@@ -324,3 +343,48 @@ class Image(section.Entry_section):
             _DoLine(lines, _EntryToStrings(entry))
             selected_entries.append(entry)
         return selected_entries, lines, widths
+
+    def LookupImageSymbol(self, sym_name, optional, msg, base_addr):
+        """Look up a symbol in an ELF file
+
+        Looks up a symbol in an ELF file. Only entry types which come from an
+        ELF image can be used by this function.
+
+        This searches through this image including all of its subsections.
+
+        At present the only entry properties supported are:
+            offset
+            image_pos - 'base_addr' is added if this is not an end-at-4gb image
+            size
+
+        Args:
+            sym_name: Symbol name in the ELF file to look up in the format
+                _binman_<entry>_prop_<property> where <entry> is the name of
+                the entry and <property> is the property to find (e.g.
+                _binman_u_boot_prop_offset). As a special case, you can append
+                _any to <entry> to have it search for any matching entry. E.g.
+                _binman_u_boot_any_prop_offset will match entries called u-boot,
+                u-boot-img and u-boot-nodtb)
+            optional: True if the symbol is optional. If False this function
+                will raise if the symbol is not found
+            msg: Message to display if an error occurs
+            base_addr: Base address of image. This is added to the returned
+                image_pos in most cases so that the returned position indicates
+                where the targeted entry/binary has actually been loaded. But
+                if end-at-4gb is used, this is not done, since the binary is
+                already assumed to be linked to the ROM position and using
+                execute-in-place (XIP).
+
+        Returns:
+            Value that should be assigned to that symbol, or None if it was
+                optional and not found
+
+        Raises:
+            ValueError if the symbol is invalid or not found, or references a
+                property which is not supported
+        """
+        entries = OrderedDict()
+        entries_by_name = {}
+        self._CollectEntries(entries, entries_by_name, self)
+        return self.LookupSymbol(sym_name, optional, msg, base_addr,
+                                 entries_by_name)