In some cases it is useful to position an entry over the top of a symbol in an ELF file. For example, if the symbol holds a version string then it allows the string to be accessed from the fdtmap.
Add support for this. Suggested-by: Pali Rohár <p...@kernel.org> Suggested-by: Keith Short <keithsh...@chromium.org> Signed-off-by: Simon Glass <s...@chromium.org> --- tools/binman/binman.rst | 7 ++++++ tools/binman/elf.py | 23 +++++++++++++++++ tools/binman/entry.py | 19 +++++++++++++- tools/binman/ftest.py | 28 +++++++++++++++++++++ tools/binman/test/274_offset_from_elf.dts | 30 +++++++++++++++++++++++ 5 files changed, 106 insertions(+), 1 deletion(-) create mode 100644 tools/binman/test/274_offset_from_elf.dts diff --git a/tools/binman/binman.rst b/tools/binman/binman.rst index 980a1ac5bde..fa8abdcd86a 100644 --- a/tools/binman/binman.rst +++ b/tools/binman/binman.rst @@ -823,6 +823,13 @@ elf-base-sym: needed. Add this symbol to the properties for the blob so that symbols can be read correctly. See binman_syms_ for more information. +offset-from-elf: + Sets the offset of an entry based on a symbol value in an another entry. + The format is <&phandle>, "sym_name", <offset> where phandle is the entry + containing the blob (with associated ELF file providing symbols), <sym_name> + is the symbol to lookup (relative to elf-base-sym) and <offset> is an offset + to add to that value. + Examples of the above options can be found in the tests. See the tools/binman/test directory. diff --git a/tools/binman/elf.py b/tools/binman/elf.py index 9ac00ed9ccf..3cc8a384495 100644 --- a/tools/binman/elf.py +++ b/tools/binman/elf.py @@ -210,6 +210,29 @@ def GetPackString(sym, msg): raise ValueError('%s has size %d: only 4 and 8 are supported' % (msg, sym.size)) +def GetSymbolOffset(elf_fname, sym_name, base_sym=None): + """Read the offset of a symbol compared to base symbol + + This is useful for obtaining the value of a single symbol relative to the + base of a binary blob. + + Args: + elf_fname: Filename of the ELF file to read + sym_name (str): Name of symbol to read + base_sym (str): Base symbol to sue to calculate the offset (or None to + use '__image_copy_start' + + Returns: + int: Offset of the symbol relative to the base symbol + """ + if not base_sym: + base_sym = '__image_copy_start' + fname = tools.get_input_filename(elf_fname) + syms = GetSymbols(fname, [base_sym, sym_name]) + base = syms[base_sym].address + val = syms[sym_name].address + return val - base + def LookupAndWriteSymbols(elf_fname, entry, section, is_elf=False, base_sym=None): """Replace all symbols in an entry with their correct values diff --git a/tools/binman/entry.py b/tools/binman/entry.py index aca08e62d3a..5d8696e32a5 100644 --- a/tools/binman/entry.py +++ b/tools/binman/entry.py @@ -145,6 +145,7 @@ class Entry(object): self.optional = False self.overlap = False self.elf_base_sym = None + self.offset_from_elf = None @staticmethod def FindEntryClass(etype, expanded): @@ -303,6 +304,8 @@ class Entry(object): # This is only supported by blobs and sections at present self.compress = fdt_util.GetString(self._node, 'compress', 'none') + self.offset_from_elf = fdt_util.GetPhandleNameOffset(self._node, + 'offset-from-elf') def GetDefaultFilename(self): return None @@ -499,7 +502,10 @@ class Entry(object): if self.offset_unset: self.Raise('No offset set with offset-unset: should another ' 'entry provide this correct offset?') - self.offset = tools.align(offset, self.align) + elif self.offset_from_elf: + self.offset = self.lookup_offset() + else: + self.offset = tools.align(offset, self.align) needed = self.pad_before + self.contents_size + self.pad_after needed = tools.align(needed, self.align_size) size = self.size @@ -1328,3 +1334,14 @@ features to produce new behaviours. int: entry address of ELF file """ return None + + def lookup_offset(self): + node, sym_name, offset = self.offset_from_elf + entry = self.section.FindEntryByNode(node) + if not entry: + self.Raise("Cannot find entry for node '%s'" % node.name) + if not entry.elf_fname: + entry.Raise("Need elf-fname property '%s'" % node.name) + val = elf.GetSymbolOffset(entry.elf_fname, sym_name, + entry.elf_base_sym) + return val + offset diff --git a/tools/binman/ftest.py b/tools/binman/ftest.py index 17b0431d4f3..be0aea49ce9 100644 --- a/tools/binman/ftest.py +++ b/tools/binman/ftest.py @@ -6281,6 +6281,34 @@ fdt fdtmap Extract the devicetree blob from the fdtmap expected = sym_values self.assertEqual(expected, data[:len(expected)]) + def testOffsetFromElf(self): + """Test a blob with symbols read from an ELF file""" + elf_fname = self.ElfTestFile('blob_syms') + TestFunctional._MakeInputFile('blob_syms', tools.read_file(elf_fname)) + TestFunctional._MakeInputFile('blob_syms.bin', + tools.read_file(self.ElfTestFile('blob_syms.bin'))) + + data = self._DoReadFile('274_offset_from_elf.dts') + + syms = elf.GetSymbols(elf_fname, ['binman', 'image']) + base = elf.GetSymbolAddress(elf_fname, '__my_start_sym') + + image = control.images['image'] + entries = image.GetEntries() + + self.assertIn('inset', entries) + inset = entries['inset'] + + self.assertEqual(base + 4, inset.offset); + self.assertEqual(base + 4, inset.image_pos); + self.assertEqual(4, inset.size); + + self.assertIn('inset2', entries) + inset = entries['inset2'] + self.assertEqual(base + 8, inset.offset); + self.assertEqual(base + 8, inset.image_pos); + self.assertEqual(4, inset.size); + if __name__ == "__main__": unittest.main() diff --git a/tools/binman/test/274_offset_from_elf.dts b/tools/binman/test/274_offset_from_elf.dts new file mode 100644 index 00000000000..e3372fc7c3d --- /dev/null +++ b/tools/binman/test/274_offset_from_elf.dts @@ -0,0 +1,30 @@ +// SPDX-License-Identifier: GPL-2.0+ + +/dts-v1/; + +/ { + #address-cells = <1>; + #size-cells = <1>; + + binman { + blob: blob { + filename = "blob_syms.bin"; + elf-filename = "blob_syms"; + elf-base-sym = "__my_start_sym"; + }; + + inset { + type = "null"; + offset-from-elf = <&blob>, "val3", <0>; + size = <4>; + overlap; + }; + + inset2 { + type = "null"; + offset-from-elf = <&blob>, "val3", <4>; + size = <4>; + overlap; + }; + }; +}; -- 2.39.0.314.g84b9a713c41-goog