diff options
Diffstat (limited to 'tools/binman/entry.py')
-rw-r--r-- | tools/binman/entry.py | 122 |
1 files changed, 111 insertions, 11 deletions
diff --git a/tools/binman/entry.py b/tools/binman/entry.py index e3767aefa7..63ec5cea3b 100644 --- a/tools/binman/entry.py +++ b/tools/binman/entry.py @@ -9,9 +9,9 @@ import importlib import os import pathlib import sys +import time from binman import bintool -from binman import comp_util from dtoc import fdt_util from patman import tools from patman.tools import to_hex, to_hex_size @@ -82,7 +82,13 @@ 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 + comp_bintool: Bintools used for compress and decompress data + fake_fname: Fake filename, if one was created, else None + required_props (dict of str): Properties which must be present. This can + be added to by subclasses """ + 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 +122,9 @@ class Entry(object): self.bintools = {} self.missing_bintools = [] self.update_hash = True + self.fake_fname = None + self.required_props = [] + self.comp_bintool = None @staticmethod def FindEntryClass(etype, expanded): @@ -233,6 +242,7 @@ class Entry(object): This reads all the fields we recognise from the node, ready for use. """ + self.ensure_props() if 'pos' in self._node.props: self.Raise("Please use 'offset' instead of 'pos'") if 'expand-size' in self._node.props: @@ -670,6 +680,7 @@ class Entry(object): self.WriteMapLine(fd, indent, self.name, self.offset, self.size, self.image_pos) + # pylint: disable=assignment-from-none def GetEntries(self): """Return a list of entries contained by this entry @@ -679,6 +690,28 @@ class Entry(object): """ return None + def FindEntryByNode(self, find_node): + """Find a node in an entry, searching all subentries + + This does a recursive search. + + Args: + find_node (fdt.Node): Node to find + + Returns: + Entry: entry, if found, else None + """ + entries = self.GetEntries() + if entries: + for entry in entries.values(): + if entry._node == find_node: + return entry + found = entry.FindEntryByNode(find_node) + if found: + return found + + return None + def GetArg(self, name, datatype=str): """Get the value of an entry argument or device-tree-node property @@ -1014,12 +1047,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): @@ -1047,7 +1082,8 @@ features to produce new behaviours. Args: bintool (Bintool): Bintool that was missing """ - self.missing_bintools.append(bintool) + if bintool not in self.missing_bintools: + self.missing_bintools.append(bintool) def check_missing_bintools(self, missing_list): """Check if any entries in this section have missing bintools @@ -1057,7 +1093,10 @@ features to produce new behaviours. Args: missing_list: List of Bintool objects to be added to """ - missing_list += self.missing_bintools + for bintool in self.missing_bintools: + if bintool not in missing_list: + missing_list.append(bintool) + def GetHelpTags(self): """Get the tags use for missing-blob help @@ -1074,12 +1113,39 @@ features to produce new behaviours. indata: Data to compress Returns: - Compressed data (first word is the compressed size) + Compressed data """ self.uncomp_data = indata if self.compress != 'none': self.uncomp_size = len(indata) - data = comp_util.compress(indata, self.compress) + if self.comp_bintool.is_present(): + data = self.comp_bintool.compress(indata) + else: + self.record_missing_bintool(self.comp_bintool) + data = tools.get_bytes(0, 1024) + else: + data = indata + return data + + def DecompressData(self, indata): + """Decompress data according to the entry's compression method + + Args: + indata: Data to decompress + + Returns: + Decompressed data + """ + if self.compress != 'none': + if self.comp_bintool.is_present(): + data = self.comp_bintool.decompress(indata) + self.uncomp_size = len(data) + else: + self.record_missing_bintool(self.comp_bintool) + data = tools.get_bytes(0, 1024) + else: + data = indata + self.uncomp_data = data return data @classmethod @@ -1119,8 +1185,18 @@ features to produce new behaviours. Args: btools (dict of Bintool): + + Raise: + ValueError if compression algorithm is not supported """ - pass + algo = self.compress + if algo != 'none': + algos = ['bzip2', 'gzip', 'lz4', 'lzma', 'lzo', 'xz', 'zstd'] + if algo not in algos: + raise ValueError("Unknown algorithm '%s'" % algo) + names = {'lzma': 'lzma_alone', 'lzo': 'lzop'} + name = names.get(self.compress, self.compress) + self.comp_bintool = self.AddBintool(btools, name) @classmethod def AddBintool(self, tools, name): @@ -1169,3 +1245,27 @@ 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}'") + + def ensure_props(self): + """Raise an exception if properties are missing + + Args: + prop_list (list of str): List of properties to check for + + Raises: + ValueError: Any property is missing + """ + not_present = [] + for prop in self.required_props: + if not prop in self._node.props: + not_present.append(prop) + if not_present: + self.Raise(f"'{self.etype}' entry is missing properties: {' '.join(not_present)}") |