From patchwork Sun Jun 14 02:56:53 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Simon Glass X-Patchwork-Id: 242284 List-Id: U-Boot discussion From: sjg at chromium.org (Simon Glass) Date: Sat, 13 Jun 2020 20:56:53 -0600 Subject: [PATCH v2 14/49] binman: Allow external binaries to be missing In-Reply-To: <20200614025728.41065-1-sjg@chromium.org> References: <20200614025728.41065-1-sjg@chromium.org> Message-ID: <20200613205717.v2.14.I3e5845b42b7658be3002d9313d5e8e10a38e6c87@changeid> 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 Reviewed-by: Bin Meng --- (no changes since v1) tools/binman/README.entries | 3 +++ tools/binman/cmdline.py | 2 ++ tools/binman/control.py | 7 +++++-- tools/binman/etype/blob_ext.py | 13 ++++++++++--- tools/binman/etype/section.py | 17 +++++++++++++++++ tools/binman/ftest.py | 8 +++++++- tools/patman/tools.py | 8 ++++++-- 7 files changed, 50 insertions(+), 8 deletions(-) diff --git a/tools/binman/README.entries b/tools/binman/README.entries index ec0d47f8e3..e88fd846db 100644 --- a/tools/binman/README.entries +++ b/tools/binman/README.entries @@ -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. diff --git a/tools/binman/cmdline.py b/tools/binman/cmdline.py index 1e38593579..bb4d9d1288 100644 --- a/tools/binman/cmdline.py +++ b/tools/binman/cmdline.py @@ -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') diff --git a/tools/binman/control.py b/tools/binman/control.py index dc1dd2a7dc..8c6eae83f1 100644 --- a/tools/binman/control.py +++ b/tools/binman/control.py @@ -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(): diff --git a/tools/binman/etype/blob_ext.py b/tools/binman/etype/blob_ext.py index cc8d91bb59..51779c88c9 100644 --- a/tools/binman/etype/blob_ext.py +++ b/tools/binman/etype/blob_ext.py @@ -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() diff --git a/tools/binman/etype/section.py b/tools/binman/etype/section.py index f108121c3a..44b13b2575 100644 --- a/tools/binman/etype/section.py +++ b/tools/binman/etype/section.py @@ -49,6 +49,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 +536,19 @@ 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 + + def GetAllowMissing(self): + """Get whether a section allows missing external blobs + + Returns: + True if allowed, False if not allowed + """ + return self._allow_missing diff --git a/tools/binman/ftest.py b/tools/binman/ftest.py index f8d5191672..7c8b3eb3a0 100644 --- a/tools/binman/ftest.py +++ b/tools/binman/ftest.py @@ -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() diff --git a/tools/patman/tools.py b/tools/patman/tools.py index b50370dfe8..7d92e20afa 100644 --- a/tools/patman/tools.py +++ b/tools/patman/tools.py @@ -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()))