import os import io from pyfdt.pyfdt import FdtBlobParse from .matcher import SignatureMatcher, Match class FlattenDeviceTree(SignatureMatcher): """ https://devicetree-specification.readthedocs.io/en/stable/flattened-format.html header -> space -> memory reservation block -> space -> structure block -> space -> strings block -> space """ def __init__(self, file): self.name = "Flatten Device Tree" self.signature = b'\xd0\x0d\xfe\xed' super().__init__(file) def is_valid(self): for match in self.search(): """ All the header fields ... stored in big-endian format """ start = match header = io.BytesIO(self.file[start:start+4*10]) magic = header.read(4) totalsize = header.read(4) off_dt_struct = header.read(4) off_dt_strings = header.read(4) off_mem_rsvmap = header.read(4) version = header.read(4) last_comp_version = header.read(4) boot_cpuid_phys = header.read(4) size_dt_strings = header.read(4) size_dt_struct = header.read(4) as_num = lambda f: int.from_bytes(f, 'big') totalsize = as_num(totalsize) data = { 'off_dt_struct': as_num(off_dt_struct), 'off_dt_strings': as_num(off_dt_strings), 'off_mem_rsvmap': as_num(off_mem_rsvmap), 'version': as_num(version), 'last_comp_version': as_num(last_comp_version), 'boot_cpuid_phys': as_num(boot_cpuid_phys), 'size_dt_strings': as_num(size_dt_strings), 'size_dt_struct': as_num(size_dt_struct), } self.matches += [Match(start, totalsize, data)] return len(self.matches) != 0 def view(self, match): as_num = lambda n: int.from_bytes(n, 'big') data = match.data region = io.BytesIO(self.file[match.offset : match.offset + match.length]) dtb = FdtBlobParse(region) s = dtb.to_fdt() for name, node in s.rootnode.walk(): print(name) if "kernel" in name: if len(list(filter(lambda f: f in name, ["arch", "os", "description"]))) != 0: print("> ", node)