binman: Keep a separate list of entries for fit
The current implementation sets up the FIT entries but then deletes the 'generator' ones so they don't appear in the final image. This is a bit clumsy. We cannot build the image more than once, since the generator entries are lost during the first build. Binman requires that calling BuildSectionData() multiple times returns a valid result each time. Keep a separate, private list which includes the generator nodes and use that where needed, to correct this problem. Ensure that the missing list includes removed generator entries too. Signed-off-by: Simon Glass <sjg@chromium.org> Reviewed-by: Alper Nebi Yasak <alpernebiyasak@gmail.com>
This commit is contained in:
@@ -163,12 +163,17 @@ class Entry_fit(Entry_section):
|
|||||||
key: relative path to entry Node (from the base of the FIT)
|
key: relative path to entry Node (from the base of the FIT)
|
||||||
value: Entry_section object comprising the contents of this
|
value: Entry_section object comprising the contents of this
|
||||||
node
|
node
|
||||||
|
_priv_entries: Internal copy of _entries which includes 'generator'
|
||||||
|
entries which are used to create the FIT, but should not be
|
||||||
|
processed as real entries. This is set up once we have the
|
||||||
|
entries
|
||||||
"""
|
"""
|
||||||
super().__init__(section, etype, node)
|
super().__init__(section, etype, node)
|
||||||
self._fit = None
|
self._fit = None
|
||||||
self._fit_props = {}
|
self._fit_props = {}
|
||||||
self._fdts = None
|
self._fdts = None
|
||||||
self.mkimage = None
|
self.mkimage = None
|
||||||
|
self._priv_entries = {}
|
||||||
|
|
||||||
def ReadNode(self):
|
def ReadNode(self):
|
||||||
super().ReadNode()
|
super().ReadNode()
|
||||||
@@ -236,6 +241,10 @@ class Entry_fit(Entry_section):
|
|||||||
|
|
||||||
_add_entries(self._node, 0, self._node)
|
_add_entries(self._node, 0, self._node)
|
||||||
|
|
||||||
|
# Keep a copy of all entries, including generator entries, since these
|
||||||
|
# removed from self._entries later.
|
||||||
|
self._priv_entries = dict(self._entries)
|
||||||
|
|
||||||
def BuildSectionData(self, required):
|
def BuildSectionData(self, required):
|
||||||
"""Build FIT entry contents
|
"""Build FIT entry contents
|
||||||
|
|
||||||
@@ -415,11 +424,12 @@ class Entry_fit(Entry_section):
|
|||||||
|
|
||||||
has_images = depth == 2 and in_images
|
has_images = depth == 2 and in_images
|
||||||
if has_images:
|
if has_images:
|
||||||
entry = self._entries[rel_path]
|
entry = self._priv_entries[rel_path]
|
||||||
data = entry.GetData()
|
data = entry.GetData()
|
||||||
fsw.property('data', bytes(data))
|
fsw.property('data', bytes(data))
|
||||||
|
|
||||||
for subnode in node.subnodes:
|
for subnode in node.subnodes:
|
||||||
|
subnode_path = f'{rel_path}/{subnode.name}'
|
||||||
if has_images and not (subnode.name.startswith('hash') or
|
if has_images and not (subnode.name.startswith('hash') or
|
||||||
subnode.name.startswith('signature')):
|
subnode.name.startswith('signature')):
|
||||||
# This subnode is a content node not meant to appear in
|
# This subnode is a content node not meant to appear in
|
||||||
@@ -427,11 +437,11 @@ class Entry_fit(Entry_section):
|
|||||||
# fsw.add_node() or _add_node() for it.
|
# fsw.add_node() or _add_node() for it.
|
||||||
pass
|
pass
|
||||||
elif self.GetImage().generate and subnode.name.startswith('@'):
|
elif self.GetImage().generate and subnode.name.startswith('@'):
|
||||||
subnode_path = f'{rel_path}/{subnode.name}'
|
|
||||||
entry = self._entries.get(subnode_path)
|
|
||||||
_gen_node(base_node, subnode, depth, in_images)
|
_gen_node(base_node, subnode, depth, in_images)
|
||||||
if entry:
|
# This is a generator (template) entry, so remove it from
|
||||||
del self._entries[subnode_path]
|
# the list of entries used by PackEntries(), etc. Otherwise
|
||||||
|
# it will appear in the binman output
|
||||||
|
to_remove.append(subnode_path)
|
||||||
else:
|
else:
|
||||||
with fsw.add_node(subnode.name):
|
with fsw.add_node(subnode.name):
|
||||||
_add_node(base_node, depth + 1, subnode)
|
_add_node(base_node, depth + 1, subnode)
|
||||||
@@ -440,10 +450,16 @@ class Entry_fit(Entry_section):
|
|||||||
# entry node
|
# entry node
|
||||||
fsw = libfdt.FdtSw()
|
fsw = libfdt.FdtSw()
|
||||||
fsw.finish_reservemap()
|
fsw.finish_reservemap()
|
||||||
|
to_remove = []
|
||||||
with fsw.add_node(''):
|
with fsw.add_node(''):
|
||||||
_add_node(self._node, 0, self._node)
|
_add_node(self._node, 0, self._node)
|
||||||
fdt = fsw.as_fdt()
|
fdt = fsw.as_fdt()
|
||||||
|
|
||||||
|
# Remove generator entries from the main list
|
||||||
|
for path in to_remove:
|
||||||
|
if path in self._entries:
|
||||||
|
del self._entries[path]
|
||||||
|
|
||||||
# Pack this new FDT and scan it so we can add the data later
|
# Pack this new FDT and scan it so we can add the data later
|
||||||
fdt.pack()
|
fdt.pack()
|
||||||
data = fdt.as_bytearray()
|
data = fdt.as_bytearray()
|
||||||
@@ -503,3 +519,10 @@ class Entry_fit(Entry_section):
|
|||||||
def AddBintools(self, btools):
|
def AddBintools(self, btools):
|
||||||
super().AddBintools(btools)
|
super().AddBintools(btools)
|
||||||
self.mkimage = self.AddBintool(btools, 'mkimage')
|
self.mkimage = self.AddBintool(btools, 'mkimage')
|
||||||
|
|
||||||
|
def CheckMissing(self, missing_list):
|
||||||
|
# We must use our private entry list for this since generator notes
|
||||||
|
# which are removed from self._entries will otherwise not show up as
|
||||||
|
# missing
|
||||||
|
for entry in self._priv_entries.values():
|
||||||
|
entry.CheckMissing(missing_list)
|
||||||
|
Reference in New Issue
Block a user