binman: add support for creating dummy files for external blobs
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>
diff --git a/tools/binman/cmdline.py b/tools/binman/cmdline.py
index e73ff78..700e5a2 100644
--- a/tools/binman/cmdline.py
+++ b/tools/binman/cmdline.py
@@ -52,6 +52,8 @@
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',
diff --git a/tools/binman/control.py b/tools/binman/control.py
index 304fc70..47aac20 100644
--- a/tools/binman/control.py
+++ b/tools/binman/control.py
@@ -479,7 +479,8 @@
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 @@
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 @@
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 @@
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 @@
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
diff --git a/tools/binman/entry.py b/tools/binman/entry.py
index 7022271..401476f 100644
--- a/tools/binman/entry.py
+++ b/tools/binman/entry.py
@@ -70,6 +70,8 @@
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 @@
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 @@
# 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 @@
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
diff --git a/tools/binman/etype/blob.py b/tools/binman/etype/blob.py
index fae86ca..6e63d77 100644
--- a/tools/binman/etype/blob.py
+++ b/tools/binman/etype/blob.py
@@ -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 @@
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 @@
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)
diff --git a/tools/binman/etype/blob_ext.py b/tools/binman/etype/blob_ext.py
index d6b0ca1..fba6271 100644
--- a/tools/binman/etype/blob_ext.py
+++ b/tools/binman/etype/blob_ext.py
@@ -26,3 +26,11 @@
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
diff --git a/tools/binman/etype/mkimage.py b/tools/binman/etype/mkimage.py
index e499775..80fdce0 100644
--- a/tools/binman/etype/mkimage.py
+++ b/tools/binman/etype/mkimage.py
@@ -61,3 +61,23 @@
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)
diff --git a/tools/binman/etype/section.py b/tools/binman/etype/section.py
index e2949fc..4e42385 100644
--- a/tools/binman/etype/section.py
+++ b/tools/binman/etype/section.py
@@ -689,6 +689,15 @@
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 @@
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
diff --git a/tools/binman/ftest.py b/tools/binman/ftest.py
index 6be0037..2a98d81 100644
--- a/tools/binman/ftest.py
+++ b/tools/binman/ftest.py
@@ -308,7 +308,7 @@
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 @@
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 @@
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 @@
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
index 0000000..22cf67f
--- /dev/null
+++ b/tools/binman/test/203_fake_blob.dts
@@ -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";
+ };
+ };
+};