binman: Provide a way to set the symbol base address
The base address of the ELF containing symbols is normally added to
any symbols written, so that the value points to the correct address in
memory when everything is loaded. When the binary resides on disk, a
different offset may be needed, typically 0. Provide a way to specify
this.
Signed-off-by: Simon Glass <sjg@chromium.org>
diff --git a/tools/binman/binman.rst b/tools/binman/binman.rst
index 04564f4..f9a3a42 100644
--- a/tools/binman/binman.rst
+++ b/tools/binman/binman.rst
@@ -502,6 +502,10 @@
since it is assumed that images are XIP and the offsets already include the
address.
+For non-x86 cases where the symbol is used as a flash offset, the symbols-base
+property can be set to that offset (e.g. 0), so that the unadjusted image-pos
+is written into the image.
+
While U-Boot's symbol updating is handled automatically by the u-boot-spl
entry type (and others), it is possible to use this feature with any blob. To
do this, add a `write-symbols` (boolean) property to the node, set the ELF
@@ -743,6 +747,17 @@
properties are brought into the target node. See Templates_ below for
more information.
+symbols-base:
+ When writing symbols into a binary, the value of that symbol is assumed to
+ be relative to the base address of the binary. This allow the binary to be
+ loaded in memory at its base address, so that symbols point into the binary
+ correctly. In some cases the binary is in fact not yet in memory, but must
+ be read from storage. In this case there is no base address for the symbols.
+ This property can be set to 0 to indicate this. Other values for
+ symbols-base are allowed, but care must be taken that the code which uses
+ the symbol is aware of the base being used. If omitted, the binary's base
+ address is used.
+
The attributes supported for images and sections are described below. Several
are similar to those for entries.
diff --git a/tools/binman/elf.py b/tools/binman/elf.py
index 7339483..c75f447 100644
--- a/tools/binman/elf.py
+++ b/tools/binman/elf.py
@@ -234,7 +234,7 @@
return val - base
def LookupAndWriteSymbols(elf_fname, entry, section, is_elf=False,
- base_sym=None):
+ base_sym=None, base_addr=None):
"""Replace all symbols in an entry with their correct values
The entry contents is updated so that values for referenced symbols will be
@@ -249,6 +249,8 @@
section: Section which can be used to lookup symbol values
base_sym: Base symbol marking the start of the image (__image_copy_start
by default)
+ base_addr (int): Base address to use for the entry being written. If
+ None then the value of base_sym is used
Returns:
int: Number of symbols written
@@ -278,7 +280,8 @@
if not base and not is_elf:
tout.debug(f'LookupAndWriteSymbols: no base: elf_fname={elf_fname}, base_sym={base_sym}, is_elf={is_elf}')
return 0
- base_addr = 0 if is_elf else base.address
+ if base_addr is None:
+ base_addr = 0 if is_elf else base.address
count = 0
for name, sym in syms.items():
if name.startswith('_binman'):
diff --git a/tools/binman/entry.py b/tools/binman/entry.py
index 7d4d469..8ad9fe8 100644
--- a/tools/binman/entry.py
+++ b/tools/binman/entry.py
@@ -108,6 +108,9 @@
not need to be done again. This is only used with 'binman replace',
to stop sections from being rebuilt if their entries have not been
replaced
+ symbols_base (int): Use this value as the assumed load address of the
+ target entry, when calculating the symbol value. If None, this is
+ 0 for blobs and the image-start address for ELF files
"""
fake_dir = None
@@ -159,6 +162,7 @@
self.preserve = False
self.build_done = False
self.no_write_symbols = False
+ self.symbols_base = None
@staticmethod
def FindEntryClass(etype, expanded):
@@ -324,6 +328,7 @@
self.preserve = fdt_util.GetBool(self._node, 'preserve')
self.no_write_symbols = fdt_util.GetBool(self._node, 'no-write-symbols')
+ self.symbols_base = fdt_util.GetInt(self._node, 'symbols-base')
def GetDefaultFilename(self):
return None
@@ -713,7 +718,8 @@
# Check if we are writing symbols into an ELF file
is_elf = self.GetDefaultFilename() == self.elf_fname
elf.LookupAndWriteSymbols(self.elf_fname, self, section.GetImage(),
- is_elf, self.elf_base_sym)
+ is_elf, self.elf_base_sym,
+ self.symbols_base)
def CheckEntries(self):
"""Check that the entry offsets are correct
diff --git a/tools/binman/etype/blob_phase.py b/tools/binman/etype/blob_phase.py
index 951d993..09bb89b 100644
--- a/tools/binman/etype/blob_phase.py
+++ b/tools/binman/etype/blob_phase.py
@@ -57,3 +57,8 @@
if self.no_write_symbols:
for entry in self._entries.values():
entry.no_write_symbols = True
+
+ # Propagate the symbols-base property
+ if self.symbols_base is not None:
+ for entry in self._entries.values():
+ entry.symbols_base = self.symbols_base
diff --git a/tools/binman/ftest.py b/tools/binman/ftest.py
index 7b4454b..ecfcd6b 100644
--- a/tools/binman/ftest.py
+++ b/tools/binman/ftest.py
@@ -1500,7 +1500,8 @@
self.assertEqual(U_BOOT_SPL_NODTB_DATA, data[:len(U_BOOT_SPL_NODTB_DATA)])
def checkSymbols(self, dts, base_data, u_boot_offset, entry_args=None,
- use_expanded=False, no_write_symbols=False):
+ use_expanded=False, no_write_symbols=False,
+ symbols_base=None):
"""Check the image contains the expected symbol values
Args:
@@ -1512,6 +1513,8 @@
value: value of that arg
use_expanded: True to use expanded entries where available, e.g.
'u-boot-expanded' instead of 'u-boot'
+ symbols_base (int): Value to expect for symbols-base in u-boot-spl,
+ None if none
"""
elf_fname = self.ElfTestFile('u_boot_binman_syms')
syms = elf.GetSymbols(elf_fname, ['binman', 'image'])
@@ -1526,10 +1529,19 @@
# The image should contain the symbols from u_boot_binman_syms.c
# Note that image_pos is adjusted by the base address of the image,
# which is 0x10 in our test image
- vals = (elf.BINMAN_SYM_MAGIC_VALUE, 0x00,
+ vals2 = (elf.BINMAN_SYM_MAGIC_VALUE, 0x00,
u_boot_offset + len(U_BOOT_DATA),
0x10 + u_boot_offset, 0x04)
+
+ # u-boot-spl has a symbols-base property, so take that into account if
+ # required. The caller must supply the value
+ vals = list(vals2)
+ if symbols_base is not None:
+ vals[3] = symbols_base + u_boot_offset
+ vals = tuple(vals)
+
sym_values = struct.pack('<LLQLL', *vals)
+ sym_values2 = struct.pack('<LLQLL', *vals2)
if no_write_symbols:
self.assertEqual(
base_data +
@@ -1552,12 +1564,12 @@
ofs = blen + 1 + len(U_BOOT_DATA)
self.assertEqual(U_BOOT_DATA, data[blen + 1:ofs])
- self.assertEqual(sym_values, data[ofs:ofs + 24])
+ self.assertEqual(sym_values2, data[ofs:ofs + 24])
self.assertEqual(base_data[24:], data[ofs + 24:])
# Just repeating the above asserts all at once, for clarity
expected = (sym_values + base_data[24:] +
- tools.get_bytes(0xff, 1) + U_BOOT_DATA + sym_values +
+ tools.get_bytes(0xff, 1) + U_BOOT_DATA + sym_values2 +
base_data[24:])
self.assertEqual(expected, data)
@@ -7750,6 +7762,21 @@
err = stderr.getvalue()
self.assertRegex(err, "Image 'image'.*missing bintools.*: mkeficapsule")
+ def testSymbolsBase(self):
+ """Test handling of symbols-base"""
+ self.checkSymbols('336_symbols_base.dts', U_BOOT_SPL_DATA, 0x1c,
+ symbols_base=0)
+
+ def testSymbolsBaseExpanded(self):
+ """Test handling of symbols-base with expanded entries"""
+ entry_args = {
+ 'spl-dtb': '1',
+ }
+ self.checkSymbols('337_symbols_base_expand.dts', U_BOOT_SPL_NODTB_DATA +
+ U_BOOT_SPL_DTB_DATA, 0x38,
+ entry_args=entry_args, use_expanded=True,
+ symbols_base=0)
+
if __name__ == "__main__":
unittest.main()
diff --git a/tools/binman/test/336_symbols_base.dts b/tools/binman/test/336_symbols_base.dts
new file mode 100644
index 0000000..e4dccd3
--- /dev/null
+++ b/tools/binman/test/336_symbols_base.dts
@@ -0,0 +1,23 @@
+// SPDX-License-Identifier: GPL-2.0+
+
+/dts-v1/;
+
+/ {
+ #address-cells = <1>;
+ #size-cells = <1>;
+
+ binman {
+ pad-byte = <0xff>;
+ u-boot-spl {
+ symbols-base = <0>;
+ };
+
+ u-boot {
+ offset = <0x1c>;
+ };
+
+ u-boot-spl2 {
+ type = "u-boot-spl";
+ };
+ };
+};
diff --git a/tools/binman/test/337_symbols_base_expand.dts b/tools/binman/test/337_symbols_base_expand.dts
new file mode 100644
index 0000000..5a777ae
--- /dev/null
+++ b/tools/binman/test/337_symbols_base_expand.dts
@@ -0,0 +1,24 @@
+// SPDX-License-Identifier: GPL-2.0+
+
+/dts-v1/;
+
+/ {
+ #address-cells = <1>;
+ #size-cells = <1>;
+
+ binman {
+ pad-byte = <0xff>;
+ u-boot-spl {
+ symbols-base = <0>;
+ };
+
+ u-boot {
+ offset = <0x38>;
+ no-expanded;
+ };
+
+ u-boot-spl2 {
+ type = "u-boot-spl";
+ };
+ };
+};