binman: Allow using an an 'expanded' entry type

As the first step in supporting expanded entries, add a way for binman to
automatically select an 'expanded' version of an entry type, if requested.
This is controlled by a class method.

Signed-off-by: Simon Glass <sjg@chromium.org>
This commit is contained in:
Simon Glass 2021-03-18 20:25:04 +13:00
parent 5187b80617
commit b35fb17936
2 changed files with 63 additions and 9 deletions

View File

@ -102,22 +102,30 @@ class Entry(object):
self.allow_missing = False
@staticmethod
def Lookup(node_path, etype):
def Lookup(node_path, etype, expanded):
"""Look up the entry class for a node.
Args:
node_node: Path name of Node object containing information about
the entry to create (used for errors)
etype: Entry type to use
expanded: Use the expanded version of etype
Returns:
The entry class object if found, else None
The entry class object if found, else None if not found and expanded
is True
Raise:
ValueError if expanded is False and the class is not found
"""
# Convert something like 'u-boot@0' to 'u_boot' since we are only
# interested in the type.
module_name = etype.replace('-', '_')
if '@' in module_name:
module_name = module_name.split('@')[0]
if expanded:
module_name += '_expanded'
module = modules.get(module_name)
# Also allow entry-type modules to be brought in from the etype directory.
@ -127,6 +135,8 @@ class Entry(object):
try:
module = importlib.import_module('binman.etype.' + module_name)
except ImportError as e:
if expanded:
return None
raise ValueError("Unknown entry type '%s' in node '%s' (expected etype/%s.py, error '%s'" %
(etype, node_path, module_name, e))
modules[module_name] = module
@ -135,21 +145,31 @@ class Entry(object):
return getattr(module, 'Entry_%s' % module_name)
@staticmethod
def Create(section, node, etype=None):
def Create(section, node, etype=None, expanded=False):
"""Create a new entry for a node.
Args:
section: Section object containing this node
node: Node object containing information about the entry to
create
etype: Entry type to use, or None to work it out (used for tests)
section: Section object containing this node
node: Node object containing information about the entry to
create
etype: Entry type to use, or None to work it out (used for tests)
expanded: True to use expanded versions of entries, where available
Returns:
A new Entry object of the correct type (a subclass of Entry)
"""
if not etype:
etype = fdt_util.GetString(node, 'type', node.name)
obj = Entry.Lookup(node.path, etype)
obj = Entry.Lookup(node.path, etype, expanded)
if obj and expanded:
# Check whether to use the expanded entry
new_etype = etype + '-expanded'
if obj.UseExpanded(node, etype, new_etype):
etype = new_etype
else:
obj = None
if not obj:
obj = Entry.Lookup(node.path, etype, False)
# Call its constructor to get the object we want.
return obj(section, etype, node)
@ -648,7 +668,7 @@ features to produce new behaviours.
modules.remove('_testing')
missing = []
for name in modules:
module = Entry.Lookup('WriteDocs', name)
module = Entry.Lookup('WriteDocs', name, False)
docs = getattr(module, '__doc__')
if test_missing == name:
docs = None
@ -907,3 +927,25 @@ features to produce new behaviours.
self.uncomp_size = len(indata)
data = tools.Compress(indata, self.compress)
return data
@classmethod
def UseExpanded(cls, node, etype, new_etype):
"""Check whether to use an expanded entry type
This is called by Entry.Create() when it finds an expanded version of
an entry type (e.g. 'u-boot-expanded'). If this method returns True then
it will be used (e.g. in place of 'u-boot'). If it returns False, it is
ignored.
Args:
node: Node object containing information about the entry to
create
etype: Original entry type being used
new_etype: New entry type proposed
Returns:
True to use this entry type, False to use the original one
"""
tout.Info("Node '%s': etype '%s': %s selected" %
(node.path, etype, new_etype))
return True

View File

@ -87,6 +87,18 @@ class TestEntry(unittest.TestCase):
base = entry.Entry.Create(None, self.GetNode(), 'blob-dtb')
self.assertIsNone(base.ReadChildData(base))
def testExpandedEntry(self):
"""Test use of an expanded entry when available"""
base = entry.Entry.Create(None, self.GetNode())
self.assertEqual('u-boot', base.etype)
expanded = entry.Entry.Create(None, self.GetNode(), expanded=True)
self.assertEqual('u-boot-expanded', expanded.etype)
with self.assertRaises(ValueError) as e:
entry.Entry.Create(None, self.GetNode(), 'missing', expanded=True)
self.assertIn("Unknown entry type 'missing' in node '/binman/u-boot'",
str(e.exception))
if __name__ == "__main__":
unittest.main()