]> git.dujemihanovic.xyz Git - u-boot.git/commitdiff
binman: add support for creating dummy files for external blobs
authorHeiko Thiery <heiko.thiery@gmail.com>
Thu, 6 Jan 2022 10:49:41 +0000 (11:49 +0100)
committerTom Rini <trini@konsulko.com>
Fri, 7 Jan 2022 17:10:55 +0000 (12:10 -0500)
While converting to binman for an imx8mq board, it has been found that
building in the u-boot CI fails. This is because an imx8mq requires an
external binary (signed_hdmi_imx8m.bin). If this file cannot be found
mkimage fails.
To be able to build this board in the u-boot CI a binman option
(--fake-ext-blobs) is introduced that can be switched on via the u-boot
makefile option BINMAN_FAKE_EXT_BLOBS. With that the needed dummy files are
created.

Signed-off-by: Heiko Thiery <heiko.thiery@gmail.com>
Reviewed-by: Simon Glass <sjg@chromium.org>
Makefile
tools/binman/cmdline.py
tools/binman/control.py
tools/binman/entry.py
tools/binman/etype/blob.py
tools/binman/etype/blob_ext.py
tools/binman/etype/mkimage.py
tools/binman/etype/section.py
tools/binman/ftest.py
tools/binman/test/203_fake_blob.dts [new file with mode: 0644]

index ae9bfab91acfc4c1863a75ad2e88a687dd920acc..63d286a4c15e1363b9b97dcfc87c03aecc6d9a6b 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -1315,6 +1315,7 @@ cmd_binman = $(srctree)/tools/binman/binman $(if $(BINMAN_DEBUG),-D) \
                -a tpl-bss-pad=$(if $(CONFIG_TPL_SEPARATE_BSS),,1) \
                -a spl-dtb=$(CONFIG_SPL_OF_REAL) \
                -a tpl-dtb=$(CONFIG_TPL_OF_REAL) \
+               $(if $(BINMAN_FAKE_EXT_BLOBS),--fake-ext-blobs) \
                $(BINMAN_$(@F))
 
 OBJCOPYFLAGS_u-boot.ldr.hex := -I binary -O ihex
index e73ff78095628d4ea53602981a59aa0d33d1057a..700e5a29a530a58af4c7403672766bdb166d3fa7 100644 (file)
@@ -52,6 +52,8 @@ controlled by a description in the board device tree.'''
             help='Configuration file (.dtb) to use')
     build_parser.add_argument('--fake-dtb', action='store_true',
             help='Use fake device tree contents (for testing only)')
+    build_parser.add_argument('--fake-ext-blobs', action='store_true',
+            help='Create fake ext blobs with dummy content (for testing only)')
     build_parser.add_argument('-i', '--image', type=str, action='append',
             help='Image filename to build (if not specified, build all)')
     build_parser.add_argument('-I', '--indir', action='append',
index 304fc70f56f638be9f3b75d8567a0855fa9d3817..47aac207b4662f1ec4436d3b10eb06d8611c8c2f 100644 (file)
@@ -479,7 +479,8 @@ def PrepareImagesAndDtbs(dtb_fname, select_images, update_fdt, use_expanded):
 
 
 def ProcessImage(image, update_fdt, write_map, get_contents=True,
-                 allow_resize=True, allow_missing=False):
+                 allow_resize=True, allow_missing=False,
+                 allow_fake_blobs=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
@@ -495,12 +496,15 @@ def ProcessImage(image, update_fdt, write_map, get_contents=True,
         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
+        allow_fake_blobs: Allow blob_ext objects to be faked with dummy files
 
     Returns:
-        True if one or more external blobs are missing, False if all are present
+        True if one or more external blobs are missing or faked,
+        False if all are present
     """
     if get_contents:
         image.SetAllowMissing(allow_missing)
+        image.SetAllowFakeBlob(allow_fake_blobs)
         image.GetEntryContents()
     image.GetEntryOffsets()
 
@@ -549,7 +553,13 @@ def ProcessImage(image, update_fdt, write_map, get_contents=True,
         tout.Warning("Image '%s' is missing external blobs and is non-functional: %s" %
                      (image.name, ' '.join([e.name for e in missing_list])))
         _ShowHelpForMissingBlobs(missing_list)
-    return bool(missing_list)
+    faked_list = []
+    image.CheckFakedBlobs(faked_list)
+    if faked_list:
+        tout.Warning("Image '%s:%s' has faked external blobs and is non-functional: %s" %
+                     (image.name, image.image_name,
+                      ' '.join([e.GetDefaultFilename() for e in faked_list])))
+    return bool(missing_list) or bool(faked_list)
 
 
 def Binman(args):
@@ -636,13 +646,15 @@ def Binman(args):
 
             images = PrepareImagesAndDtbs(dtb_fname, args.image,
                                           args.update_fdt, use_expanded)
+
             if args.test_section_timeout:
                 # Set the first image to timeout, used in testThreadTimeout()
                 images[list(images.keys())[0]].test_section_timeout = True
-            missing = False
+            invalid = False
             for image in images.values():
-                missing |= ProcessImage(image, args.update_fdt, args.map,
-                                        allow_missing=args.allow_missing)
+                invalid |= ProcessImage(image, args.update_fdt, args.map,
+                                       allow_missing=args.allow_missing,
+                                       allow_fake_blobs=args.fake_ext_blobs)
 
             # Write the updated FDTs to our output files
             for dtb_item in state.GetAllFdts():
@@ -652,7 +664,7 @@ def Binman(args):
                 data = state.GetFdtForEtype('u-boot-dtb').GetContents()
                 elf.UpdateFile(*elf_params, data)
 
-            if missing:
+            if invalid:
                 tout.Warning("\nSome images are invalid")
 
             # Use this to debug the time take to pack the image
index 70222718ea9303760eff69665e297454c9dc7bdd..401476fe760387f79c5eac83cfa5b80626d61a9f 100644 (file)
@@ -70,6 +70,8 @@ class Entry(object):
         missing: True if this entry is missing its contents
         allow_missing: Allow children of this entry to be missing (used by
             subclasses such as Entry_section)
+        allow_fake: Allow creating a dummy fake file if the blob file is not
+            available. This is mainly used for testing.
         external: True if this entry contains an external binary blob
     """
     def __init__(self, section, etype, node, name_prefix=''):
@@ -98,8 +100,10 @@ class Entry(object):
         self._expand_size = False
         self.compress = 'none'
         self.missing = False
+        self.faked = False
         self.external = False
         self.allow_missing = False
+        self.allow_fake = False
 
     @staticmethod
     def Lookup(node_path, etype, expanded):
@@ -898,6 +902,14 @@ features to produce new behaviours.
         # This is meaningless for anything other than sections
         pass
 
+    def SetAllowFakeBlob(self, allow_fake):
+        """Set whether a section allows to create a fake blob
+
+        Args:
+            allow_fake: True if allowed, False if not allowed
+        """
+        pass
+
     def CheckMissing(self, missing_list):
         """Check if any entries in this section have missing external blobs
 
@@ -909,6 +921,17 @@ features to produce new behaviours.
         if self.missing:
             missing_list.append(self)
 
+    def CheckFakedBlobs(self, faked_blobs_list):
+        """Check if any entries in this section have faked external blobs
+
+        If there are faked blobs, the entries are added to the list
+
+        Args:
+            fake_blobs_list: List of Entry objects to be added to
+        """
+        # This is meaningless for anything other than blobs
+        pass
+
     def GetAllowMissing(self):
         """Get whether a section allows missing external blobs
 
index fae86ca3ec02275c201ecec5ec378d798c671956..6e63d777eb08247d31767f5af9745a3ca5012796 100644 (file)
@@ -5,6 +5,8 @@
 # Entry-type module for blobs, which are binary objects read from files
 #
 
+import pathlib
+
 from binman.entry import Entry
 from binman import state
 from dtoc import fdt_util
@@ -36,6 +38,11 @@ class Entry_blob(Entry):
         self._filename = fdt_util.GetString(self._node, 'filename', self.etype)
 
     def ObtainContents(self):
+        if self.allow_fake and not pathlib.Path(self._filename).is_file():
+            with open(self._filename, "wb") as out:
+                out.truncate(1024)
+            self.faked = True
+
         self._filename = self.GetDefaultFilename()
         self._pathname = tools.GetInputFilename(self._filename,
             self.external and self.section.GetAllowMissing())
@@ -75,3 +82,14 @@ class Entry_blob(Entry):
     def ProcessContents(self):
         # The blob may have changed due to WriteSymbols()
         return self.ProcessContentsUpdate(self.data)
+
+    def CheckFakedBlobs(self, faked_blobs_list):
+        """Check if any entries in this section have faked external blobs
+
+        If there are faked blobs, the entries are added to the list
+
+        Args:
+            fake_blobs_list: List of Entry objects to be added to
+        """
+        if self.faked:
+            faked_blobs_list.append(self)
index d6b0ca17c3f31ba1c00ebff0650676bd65362e9e..fba6271de2bb355fd1cdbbed154bad3a3bc3d024 100644 (file)
@@ -26,3 +26,11 @@ class Entry_blob_ext(Entry_blob):
     def __init__(self, section, etype, node):
         Entry_blob.__init__(self, section, etype, node)
         self.external = True
+
+    def SetAllowFakeBlob(self, allow_fake):
+        """Set whether the entry allows to create a fake blob
+
+        Args:
+            allow_fake_blob: True if allowed, False if not allowed
+        """
+        self.allow_fake = allow_fake
index e49977522e30f73565abc18ae1e4ddd65a65f35c..80fdce0b1446aa948646b54d24648d60b6d37fcf 100644 (file)
@@ -61,3 +61,23 @@ class Entry_mkimage(Entry):
             entry = Entry.Create(self, node)
             entry.ReadNode()
             self._mkimage_entries[entry.name] = entry
+
+    def SetAllowFakeBlob(self, allow_fake):
+        """Set whether the sub nodes allows to create a fake blob
+
+        Args:
+            allow_fake: True if allowed, False if not allowed
+        """
+        for entry in self._mkimage_entries.values():
+            entry.SetAllowFakeBlob(allow_fake)
+
+    def CheckFakedBlobs(self, faked_blobs_list):
+        """Check if any entries in this section have faked external blobs
+
+        If there are faked blobs, the entries are added to the list
+
+        Args:
+            faked_blobs_list: List of Entry objects to be added to
+        """
+        for entry in self._mkimage_entries.values():
+            entry.CheckFakedBlobs(faked_blobs_list)
index e2949fc9163fe4b89dc38e44f31b6a24871d38a9..4e423855d919be4d3c14ab9af0b36e68e57b9b20 100644 (file)
@@ -689,6 +689,15 @@ class Entry_section(Entry):
         for entry in self._entries.values():
             entry.SetAllowMissing(allow_missing)
 
+    def SetAllowFakeBlob(self, allow_fake):
+        """Set whether a section allows to create a fake blob
+
+        Args:
+            allow_fake_blob: True if allowed, False if not allowed
+        """
+        for entry in self._entries.values():
+            entry.SetAllowFakeBlob(allow_fake)
+
     def CheckMissing(self, missing_list):
         """Check if any entries in this section have missing external blobs
 
@@ -700,6 +709,17 @@ class Entry_section(Entry):
         for entry in self._entries.values():
             entry.CheckMissing(missing_list)
 
+    def CheckFakedBlobs(self, faked_blobs_list):
+        """Check if any entries in this section have faked external blobs
+
+        If there are faked blobs, the entries are added to the list
+
+        Args:
+            fake_blobs_list: List of Entry objects to be added to
+        """
+        for entry in self._entries.values():
+            entry.CheckFakedBlobs(faked_blobs_list)
+
     def _CollectEntries(self, entries, entries_by_name, add_entry):
         """Collect all the entries in an section
 
index 6be003786e8e58e6837284dda0cb2f378f564f5c..2a98d810288451699f88e9f50df585e746474c80 100644 (file)
@@ -308,7 +308,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,
                     use_expanded=False, verbosity=None, allow_missing=False,
-                    extra_indirs=None, threads=None,
+                    allow_fake_blobs=False, extra_indirs=None, threads=None,
                     test_section_timeout=False, update_fdt_in_elf=None):
         """Run binman with a given test file
 
@@ -331,6 +331,7 @@ class TestFunctional(unittest.TestCase):
             verbosity: Verbosity level to use (0-3, None=don't set it)
             allow_missing: Set the '--allow-missing' flag so that missing
                 external binaries just produce a warning instead of an error
+            allow_fake_blobs: Set the '--fake-ext-blobs' flag
             extra_indirs: Extra input directories to add using -I
             threads: Number of threads to use (None for default, 0 for
                 single-threaded)
@@ -369,6 +370,8 @@ class TestFunctional(unittest.TestCase):
                 args.append('-a%s=%s' % (arg, value))
         if allow_missing:
             args.append('-M')
+        if allow_fake_blobs:
+            args.append('--fake-ext-blobs')
         if update_fdt_in_elf:
             args += ['--update-fdt-in-elf', update_fdt_in_elf]
         if images:
@@ -4661,6 +4664,16 @@ class TestFunctional(unittest.TestCase):
             str(e.exception),
             "Not enough space in '.*u_boot_binman_embed_sm' for data length.*")
 
+    def testFakeBlob(self):
+        """Test handling of faking an external blob"""
+        with test_util.capture_sys_output() as (stdout, stderr):
+            self._DoTestFile('203_fake_blob.dts', allow_missing=True,
+                             allow_fake_blobs=True)
+        err = stderr.getvalue()
+        self.assertRegex(err,
+                         "Image '.*' has faked external blobs and is non-functional: .*")
+        os.remove('binman_faking_test_blob')
+
 
 if __name__ == "__main__":
     unittest.main()
diff --git a/tools/binman/test/203_fake_blob.dts b/tools/binman/test/203_fake_blob.dts
new file mode 100644 (file)
index 0000000..22cf67f
--- /dev/null
@@ -0,0 +1,14 @@
+// SPDX-License-Identifier: GPL-2.0+
+
+/dts-v1/;
+
+/ {
+       #address-cells = <1>;
+       #size-cells = <1>;
+
+       binman {
+               blob-ext {
+                       filename = "binman_faking_test_blob";
+               };
+       };
+};