@@ -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.
@@ -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')
@@ -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():
@@ -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
@@ -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()
@@ -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
@@ -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()
@@ -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()))