]> git.dujemihanovic.xyz Git - u-boot.git/commitdiff
binman: Allow external binaries to be missing
authorSimon Glass <sjg@chromium.org>
Fri, 10 Jul 2020 00:39:38 +0000 (18:39 -0600)
committerSimon Glass <sjg@chromium.org>
Mon, 20 Jul 2020 17:37:47 +0000 (11:37 -0600)
Sometimes it is useful to build an image even though external binaries are
not present. This allows the build system to continue to function without
these files, albeit not producing valid images.

U-Boot does with with ATF (ARM Trusted Firmware) today.

Add a new flag to binman to request this behaviour.

Signed-off-by: Simon Glass <sjg@chromium.org>
Reviewed-by: Bin Meng <bmeng.cn@gmail.com>
tools/binman/README.entries
tools/binman/cmdline.py
tools/binman/control.py
tools/binman/entry.py
tools/binman/etype/blob_ext.py
tools/binman/etype/section.py
tools/binman/ftest.py
tools/patman/tools.py

index 46f6ab189980fffce87d5efff326e21d0a84e128..f45f51428ada6aaf182dd1eaf1785824ca27c158 100644 (file)
@@ -48,6 +48,9 @@ Entry: blob-ext: Entry containing an externally built binary blob
 Note: This should not be used by itself. It is normally used as a parent
 class by other entry types.
 
+If the file providing this blob is missing, binman can optionally ignore it
+and produce a broken image with a warning.
+
 See 'blob' for Properties / Entry arguments.
 
 
index 1e385935797cec0a337a978868185b0cfe612966..bb4d9d1288bc4591cced1a6d1a85aee0c844c33d 100644 (file)
@@ -53,6 +53,8 @@ controlled by a description in the board device tree.'''
             help='Add a path to the list of directories to use for input files')
     build_parser.add_argument('-m', '--map', action='store_true',
         default=False, help='Output a map file for each image')
+    build_parser.add_argument('-M', '--allow-missing', action='store_true',
+        default=False, help='Allow external blobs to be missing')
     build_parser.add_argument('-O', '--outdir', type=str,
         action='store', help='Path to directory to use for intermediate and '
         'output files')
index dc1dd2a7dcff85dd58187bd6409bf22074caf0c9..8c6eae83f158367f6f626bf2f3443d479c250390 100644 (file)
@@ -387,7 +387,7 @@ def PrepareImagesAndDtbs(dtb_fname, select_images, update_fdt):
 
 
 def ProcessImage(image, update_fdt, write_map, get_contents=True,
-                 allow_resize=True):
+                 allow_resize=True, allow_missing=False):
     """Perform all steps for this image, including checking and # writing it.
 
     This means that errors found with a later image will be reported after
@@ -402,8 +402,10 @@ def ProcessImage(image, update_fdt, write_map, get_contents=True,
             the contents is already present
         allow_resize: True to allow entries to change size (this does a re-pack
             of the entries), False to raise an exception
+        allow_missing: Allow blob_ext objects to be missing
     """
     if get_contents:
+        image.SetAllowMissing(allow_missing)
         image.GetEntryContents()
     image.GetEntryOffsets()
 
@@ -523,7 +525,8 @@ def Binman(args):
             images = PrepareImagesAndDtbs(dtb_fname, args.image,
                                           args.update_fdt)
             for image in images.values():
-                ProcessImage(image, args.update_fdt, args.map)
+                ProcessImage(image, args.update_fdt, args.map,
+                             allow_missing=args.allow_missing)
 
             # Write the updated FDTs to our output files
             for dtb_item in state.GetAllFdts():
index 90ffd276177d5921e1819843b1e8bda2fc36ec13..9388586e7cbf9b4976cf329ea780f642908aae10 100644 (file)
@@ -794,3 +794,12 @@ features to produce new behaviours.
             elif self == entries[-1]:
                 return 'end'
         return 'middle'
+
+    def SetAllowMissing(self, allow_missing):
+        """Set whether a section allows missing external blobs
+
+        Args:
+            allow_missing: True if allowed, False if not allowed
+        """
+        # This is meaningless for anything other than sections
+        pass
index cc8d91bb599101f5eb69502cb566332dd61998f3..51779c88c900c5dacf2f248b6ed6c5036ae93414 100644 (file)
@@ -18,6 +18,9 @@ class Entry_blob_ext(Entry_blob):
     Note: This should not be used by itself. It is normally used as a parent
     class by other entry types.
 
+    If the file providing this blob is missing, binman can optionally ignore it
+    and produce a broken image with a warning.
+
     See 'blob' for Properties / Entry arguments.
     """
     def __init__(self, section, etype, node):
@@ -26,6 +29,10 @@ class Entry_blob_ext(Entry_blob):
 
     def ObtainContents(self):
         self._filename = self.GetDefaultFilename()
-        self._pathname = tools.GetInputFilename(self._filename)
-        self.ReadBlobContents()
-        return True
+        self._pathname = tools.GetInputFilename(self._filename,
+                                                self.section.GetAllowMissing())
+        # Allow the file to be missing
+        if not self._pathname:
+            self.SetContents(b'')
+            return True
+        return super().ObtainContents()
index f108121c3a2eee0192e82bf3092270590d5b6ca9..9b718f1fa77a6e424a3721f578d5a803f99dfae6 100644 (file)
@@ -34,6 +34,11 @@ class Entry_section(Entry):
         name-prefix: Adds a prefix to the name of every entry in the section
             when writing out the map
 
+    Properties:
+        _allow_missing: True if this section permits external blobs to be
+            missing their contents. The second will produce an image but of
+            course it will not work.
+
     Since a section is also an entry, it inherits all the properies of entries
     too.
 
@@ -49,6 +54,7 @@ class Entry_section(Entry):
         self._sort = False
         self._skip_at_start = None
         self._end_4gb = False
+        self._allow_missing = False
 
     def ReadNode(self):
         """Read properties from the image node"""
@@ -535,3 +541,21 @@ class Entry_section(Entry):
 
     def WriteChildData(self, child):
         return True
+
+    def SetAllowMissing(self, allow_missing):
+        """Set whether a section allows missing external blobs
+
+        Args:
+            allow_missing: True if allowed, False if not allowed
+        """
+        self._allow_missing = allow_missing
+        for entry in self._entries.values():
+            entry.SetAllowMissing(allow_missing)
+
+    def GetAllowMissing(self):
+        """Get whether a section allows missing external blobs
+
+        Returns:
+            True if allowed, False if not allowed
+        """
+        return self._allow_missing
index f8d51916723e78ac4a278edc4d91ca9548aae3b3..7c8b3eb3a093e216e9a68f43f847e53b06d79f5d 100644 (file)
@@ -285,7 +285,7 @@ class TestFunctional(unittest.TestCase):
 
     def _DoTestFile(self, fname, debug=False, map=False, update_dtb=False,
                     entry_args=None, images=None, use_real_dtb=False,
-                    verbosity=None):
+                    verbosity=None, allow_missing=False):
         """Run binman with a given test file
 
         Args:
@@ -319,6 +319,8 @@ class TestFunctional(unittest.TestCase):
         if entry_args:
             for arg, value in entry_args.items():
                 args.append('-a%s=%s' % (arg, value))
+        if allow_missing:
+            args.append('-M')
         if images:
             for image in images:
                 args += ['-i', image]
@@ -3376,6 +3378,10 @@ class TestFunctional(unittest.TestCase):
         self.assertIn("Filename 'missing-file' not found in input path",
                       str(e.exception))
 
+    def testExtblobMissingOk(self):
+        """Test an image with an missing external blob that is allowed"""
+        self._DoTestFile('158_blob_ext_missing.dts', allow_missing=True)
+
 
 if __name__ == "__main__":
     unittest.main()
index f402b9aab8ba54d5abe1fca25ecf25bc3868d6d1..d41115a22c4615d330de394c917fd63076bc98ad 100644 (file)
@@ -114,14 +114,16 @@ def SetInputDirs(dirname):
     indir = dirname
     tout.Debug("Using input directories %s" % indir)
 
-def GetInputFilename(fname):
+def GetInputFilename(fname, allow_missing=False):
     """Return a filename for use as input.
 
     Args:
         fname: Filename to use for new file
+        allow_missing: True if the filename can be missing
 
     Returns:
-        The full path of the filename, within the input directory
+        The full path of the filename, within the input directory, or
+        None on error
     """
     if not indir or fname[:1] == '/':
         return fname
@@ -130,6 +132,8 @@ def GetInputFilename(fname):
         if os.path.exists(pathname):
             return pathname
 
+    if allow_missing:
+        return None
     raise ValueError("Filename '%s' not found in input path (%s) (cwd='%s')" %
                      (fname, ','.join(indir), os.getcwd()))