summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--tools/binman/elf.py3
-rw-r--r--tools/binman/elf_test.py4
-rw-r--r--tools/binman/etype/section.py41
-rw-r--r--tools/binman/ftest.py15
-rw-r--r--tools/binman/image.py45
-rw-r--r--tools/binman/test/187_symbols_sub.dts22
6 files changed, 123 insertions, 7 deletions
diff --git a/tools/binman/elf.py b/tools/binman/elf.py
index 249074a334..03b49d7163 100644
--- a/tools/binman/elf.py
+++ b/tools/binman/elf.py
@@ -132,7 +132,8 @@ def LookupAndWriteSymbols(elf_fname, entry, section):
(msg, sym.size))
# Look up the symbol in our entry tables.
- value = section.LookupSymbol(name, sym.weak, msg, base.address)
+ value = section.GetImage().LookupImageSymbol(name, sym.weak, msg,
+ base.address)
if value is None:
value = -1
pack_string = pack_string.lower()
diff --git a/tools/binman/elf_test.py b/tools/binman/elf_test.py
index e3d218a89e..7a128018d9 100644
--- a/tools/binman/elf_test.py
+++ b/tools/binman/elf_test.py
@@ -45,10 +45,12 @@ class FakeSection:
def GetPath(self):
return 'section_path'
- def LookupSymbol(self, name, weak, msg, base_addr):
+ def LookupImageSymbol(self, name, weak, msg, base_addr):
"""Fake implementation which returns the same value for all symbols"""
return self.sym_value
+ def GetImage(self):
+ return self
def BuildElfTestFiles(target_dir):
"""Build ELF files used for testing in binman
diff --git a/tools/binman/etype/section.py b/tools/binman/etype/section.py
index 3dd5f58c4c..9c6334c450 100644
--- a/tools/binman/etype/section.py
+++ b/tools/binman/etype/section.py
@@ -385,7 +385,7 @@ class Entry_section(Entry):
return entry.GetData()
source_entry.Raise("Cannot find entry for node '%s'" % node.name)
- def LookupSymbol(self, sym_name, optional, msg, base_addr):
+ def LookupSymbol(self, sym_name, optional, msg, base_addr, entries=None):
"""Look up a symbol in an ELF file
Looks up a symbol in an ELF file. Only entry types which come from an
@@ -428,18 +428,20 @@ class Entry_section(Entry):
(msg, sym_name))
entry_name, prop_name = m.groups()
entry_name = entry_name.replace('_', '-')
- entry = self._entries.get(entry_name)
+ if not entries:
+ entries = self._entries
+ entry = entries.get(entry_name)
if not entry:
if entry_name.endswith('-any'):
root = entry_name[:-4]
- for name in self._entries:
+ for name in entries:
if name.startswith(root):
rest = name[len(root):]
if rest in ['', '-img', '-nodtb']:
- entry = self._entries[name]
+ entry = entries[name]
if not entry:
err = ("%s: Entry '%s' not found in list (%s)" %
- (msg, entry_name, ','.join(self._entries.keys())))
+ (msg, entry_name, ','.join(entries.keys())))
if optional:
print('Warning: %s' % err, file=sys.stderr)
return None
@@ -648,3 +650,32 @@ class Entry_section(Entry):
"""
for entry in self._entries.values():
entry.CheckMissing(missing_list)
+
+ def _CollectEntries(self, entries, entries_by_name, add_entry):
+ """Collect all the entries in an section
+
+ This builds up a dict of entries in this section and all subsections.
+ Entries are indexed by path and by name.
+
+ Since all paths are unique, entries will not have any conflicts. However
+ entries_by_name make have conflicts if two entries have the same name
+ (e.g. with different parent sections). In this case, an entry at a
+ higher level in the hierarchy will win over a lower-level entry.
+
+ Args:
+ entries: dict to put entries:
+ key: entry path
+ value: Entry object
+ entries_by_name: dict to put entries
+ key: entry name
+ value: Entry object
+ add_entry: Entry to add
+ """
+ entries[add_entry.GetPath()] = add_entry
+ to_add = add_entry.GetEntries()
+ if to_add:
+ for entry in to_add.values():
+ entries[entry.GetPath()] = entry
+ for entry in to_add.values():
+ self._CollectEntries(entries, entries_by_name, entry)
+ entries_by_name[add_entry.name] = add_entry
diff --git a/tools/binman/ftest.py b/tools/binman/ftest.py
index e753a342c8..5016060ea6 100644
--- a/tools/binman/ftest.py
+++ b/tools/binman/ftest.py
@@ -4139,6 +4139,21 @@ class TestFunctional(unittest.TestCase):
}
self.assertEqual(expected, props)
+ def testSymbolsSubsection(self):
+ """Test binman can assign symbols from a subsection"""
+ elf_fname = self.ElfTestFile('u_boot_binman_syms')
+ syms = elf.GetSymbols(elf_fname, ['binman', 'image'])
+ addr = elf.GetSymbolAddress(elf_fname, '__image_copy_start')
+ self.assertEqual(syms['_binman_u_boot_spl_prop_offset'].address, addr)
+
+ self._SetupSplElf('u_boot_binman_syms')
+ data = self._DoReadFile('187_symbols_sub.dts')
+ sym_values = struct.pack('<LQLL', 0x00, 0x1c, 0x28, 0x04)
+ expected = (sym_values + U_BOOT_SPL_DATA[20:] +
+ tools.GetBytes(0xff, 1) + U_BOOT_DATA + sym_values +
+ U_BOOT_SPL_DATA[20:])
+ self.assertEqual(expected, data)
+
if __name__ == "__main__":
unittest.main()
diff --git a/tools/binman/image.py b/tools/binman/image.py
index d65ab887b8..3622efc686 100644
--- a/tools/binman/image.py
+++ b/tools/binman/image.py
@@ -324,3 +324,48 @@ class Image(section.Entry_section):
_DoLine(lines, _EntryToStrings(entry))
selected_entries.append(entry)
return selected_entries, lines, widths
+
+ def LookupImageSymbol(self, sym_name, optional, msg, base_addr):
+ """Look up a symbol in an ELF file
+
+ Looks up a symbol in an ELF file. Only entry types which come from an
+ ELF image can be used by this function.
+
+ This searches through this image including all of its subsections.
+
+ At present the only entry properties supported are:
+ offset
+ image_pos - 'base_addr' is added if this is not an end-at-4gb image
+ size
+
+ Args:
+ sym_name: Symbol name in the ELF file to look up in the format
+ _binman_<entry>_prop_<property> where <entry> is the name of
+ the entry and <property> is the property to find (e.g.
+ _binman_u_boot_prop_offset). As a special case, you can append
+ _any to <entry> to have it search for any matching entry. E.g.
+ _binman_u_boot_any_prop_offset will match entries called u-boot,
+ u-boot-img and u-boot-nodtb)
+ optional: True if the symbol is optional. If False this function
+ will raise if the symbol is not found
+ msg: Message to display if an error occurs
+ base_addr: Base address of image. This is added to the returned
+ image_pos in most cases so that the returned position indicates
+ where the targeted entry/binary has actually been loaded. But
+ if end-at-4gb is used, this is not done, since the binary is
+ already assumed to be linked to the ROM position and using
+ execute-in-place (XIP).
+
+ Returns:
+ Value that should be assigned to that symbol, or None if it was
+ optional and not found
+
+ Raises:
+ ValueError if the symbol is invalid or not found, or references a
+ property which is not supported
+ """
+ entries = OrderedDict()
+ entries_by_name = {}
+ self._CollectEntries(entries, entries_by_name, self)
+ return self.LookupSymbol(sym_name, optional, msg, base_addr,
+ entries_by_name)
diff --git a/tools/binman/test/187_symbols_sub.dts b/tools/binman/test/187_symbols_sub.dts
new file mode 100644
index 0000000000..54511a7371
--- /dev/null
+++ b/tools/binman/test/187_symbols_sub.dts
@@ -0,0 +1,22 @@
+/dts-v1/;
+
+/ {
+ #address-cells = <1>;
+ #size-cells = <1>;
+
+ binman {
+ section {
+ pad-byte = <0xff>;
+ u-boot-spl {
+ };
+
+ u-boot {
+ offset = <24>;
+ };
+ };
+
+ u-boot-spl2 {
+ type = "u-boot-spl";
+ };
+ };
+};