binman: Put fake files in a subdirectory

At present fake files from a previous build appear to be real files for
a subsequent build, since they sit in the output directory.

This can cause problems, since binman may need to parse the file, e.g.
with the Intel description.bin files.

Fix this by putting them in a 'binman-fake' subdirectory. Keep a track
of the fake filename so we only create it once. Subsequent builds will
still see that the file is missing and mark it as fake.

Update a few tests to check the behaviour.

Signed-off-by: Simon Glass <sjg@chromium.org>
This commit is contained in:
Simon Glass
2022-08-07 09:46:46 -06:00
parent 3212be5e24
commit 7960a0a289
4 changed files with 53 additions and 14 deletions

View File

@@ -1684,8 +1684,6 @@ Some ideas:
- Figure out how to make Fdt support changing the node order, so that
Node.AddSubnode() can support adding a node before another, existing node.
Perhaps it should completely regenerate the flat tree?
- Put faked files into a separate subdir and remove them on start-up, to avoid
seeing them as 'real' files on a subsequent run
--
Simon Glass <sjg@chromium.org>

View File

@@ -16,8 +16,9 @@ from patman import tools
from binman import bintool
from binman import cbfs_util
from binman import elf
from patman import command
from binman import elf
from binman import entry
from patman import tout
# These are imported if needed since they import libfdt
@@ -717,6 +718,13 @@ def Binman(args):
bintool.Bintool.set_missing_list(
args.force_missing_bintools.split(',') if
args.force_missing_bintools else None)
# Create the directory here instead of Entry.check_fake_fname()
# since that is called from a threaded context so different threads
# may race to create the directory
if args.fake_ext_blobs:
entry.Entry.create_fake_dir()
for image in images.values():
invalid |= ProcessImage(image, args.update_fdt, args.map,
allow_missing=args.allow_missing,

View File

@@ -9,6 +9,7 @@ import importlib
import os
import pathlib
import sys
import time
from binman import bintool
from binman import comp_util
@@ -82,7 +83,10 @@ class Entry(object):
missing_bintools: List of missing bintools for this entry
update_hash: True if this entry's "hash" subnode should be
updated with a hash of the entry contents
fake_fname: Fake filename, if one was created, else None
"""
fake_dir = None
def __init__(self, section, etype, node, name_prefix=''):
# Put this here to allow entry-docs and help to work without libfdt
global state
@@ -116,6 +120,7 @@ class Entry(object):
self.bintools = {}
self.missing_bintools = []
self.update_hash = True
self.fake_fname = None
@staticmethod
def FindEntryClass(etype, expanded):
@@ -1014,12 +1019,14 @@ features to produce new behaviours.
bool: True if the blob was faked, False if not
"""
if self.allow_fake and not pathlib.Path(fname).is_file():
outfname = tools.get_output_filename(os.path.basename(fname))
with open(outfname, "wb") as out:
out.truncate(size)
if not self.fake_fname:
outfname = os.path.join(self.fake_dir, os.path.basename(fname))
with open(outfname, "wb") as out:
out.truncate(size)
tout.info(f"Entry '{self._node.path}': Faked blob '{outfname}'")
self.fake_fname = outfname
self.faked = True
tout.info(f"Entry '{self._node.path}': Faked file '{outfname}'")
return outfname, True
return self.fake_fname, True
return fname, False
def CheckFakedBlobs(self, faked_blobs_list):
@@ -1169,3 +1176,11 @@ features to produce new behaviours.
fname = tools.get_output_filename(f'{prefix}.{uniq}')
tools.write_file(fname, data)
return data, fname, uniq
@classmethod
def create_fake_dir(cls):
"""Create the directory for fake files"""
cls.fake_dir = tools.get_output_filename('binman-fake')
if not os.path.exists(cls.fake_dir):
os.mkdir(cls.fake_dir)
tout.notice(f"Fake-blob dir is '{cls.fake_dir}'")

View File

@@ -5453,7 +5453,16 @@ fdt fdtmap Extract the devicetree blob from the fdtmap
err)
def checkFitSplitElf(self, **kwargs):
"""Test an split-elf FIT with a missing ELF file"""
"""Test an split-elf FIT with a missing ELF file
Args:
kwargs (dict of str): Arguments to pass to _DoTestFile()
Returns:
tuple:
str: stdout result
str: stderr result
"""
entry_args = {
'of-list': 'test-fdt1 test-fdt2',
'default-dt': 'test-fdt2',
@@ -5464,23 +5473,32 @@ fdt fdtmap Extract the devicetree blob from the fdtmap
with test_util.capture_sys_output() as (stdout, stderr):
self._DoTestFile(
'226_fit_split_elf.dts', entry_args=entry_args,
extra_indirs=[test_subdir], **kwargs)
err = stderr.getvalue()
return err
extra_indirs=[test_subdir], verbosity=3, **kwargs)
out = stdout.getvalue()
err = stderr.getvalue()
return out, err
def testFitSplitElfMissing(self):
"""Test an split-elf FIT with a missing ELF file"""
err = self.checkFitSplitElf(allow_missing=True)
out, err = self.checkFitSplitElf(allow_missing=True)
self.assertRegex(
err,
"Image '.*' is missing external blobs and is non-functional: .*")
self.assertNotRegex(out, '.*Faked blob.*')
fname = tools.get_output_filename('binman-fake/missing.elf')
self.assertFalse(os.path.exists(fname))
def testFitSplitElfFaked(self):
"""Test an split-elf FIT with faked ELF file"""
err = self.checkFitSplitElf(allow_missing=True, allow_fake_blobs=True)
out, err = self.checkFitSplitElf(allow_missing=True, allow_fake_blobs=True)
self.assertRegex(
err,
"Image '.*' is missing external blobs and is non-functional: .*")
self.assertRegex(
out,
"Entry '/binman/fit/images/@tee-SEQ/tee-os': Faked blob '.*binman-fake/missing.elf")
fname = tools.get_output_filename('binman-fake/missing.elf')
self.assertTrue(os.path.exists(fname))
def testPreLoad(self):
"""Test an image with a pre-load header"""