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
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.
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
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
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'):
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
self.preserve = False
self.build_done = False
self.no_write_symbols = False
+ self.symbols_base = None
@staticmethod
def FindEntryClass(etype, expanded):
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
# 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
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
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:
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'])
# 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 +
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)
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()
--- /dev/null
+// 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";
+ };
+ };
+};
--- /dev/null
+// 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";
+ };
+ };
+};