]> git.dujemihanovic.xyz Git - u-boot.git/commitdiff
binman: Provide a way to set the symbol base address
authorSimon Glass <sjg@chromium.org>
Mon, 26 Aug 2024 19:11:40 +0000 (13:11 -0600)
committerSimon Glass <sjg@chromium.org>
Thu, 26 Sep 2024 10:40:30 +0000 (12:40 +0200)
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>
tools/binman/binman.rst
tools/binman/elf.py
tools/binman/entry.py
tools/binman/etype/blob_phase.py
tools/binman/ftest.py
tools/binman/test/336_symbols_base.dts [new file with mode: 0644]
tools/binman/test/337_symbols_base_expand.dts [new file with mode: 0644]

index 04564f4f66fe1568966c69983519a1dea18de27d..f9a3a42183b43b63175df1d8398a240847283e11 100644 (file)
@@ -502,6 +502,10 @@ For x86 devices (with the end-at-4gb property) this base address is not added
 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 @@ insert-template:
     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.
 
index 73394830ebe2ed2abb0bb97eed4fe9eeaa7bed04..c75f44788136a03f851a46b20be009cea395ee1b 100644 (file)
@@ -234,7 +234,7 @@ def GetSymbolOffset(elf_fname, sym_name, base_sym=None):
     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 @@ def LookupAndWriteSymbols(elf_fname, entry, section, is_elf=False,
         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 @@ def LookupAndWriteSymbols(elf_fname, entry, section, is_elf=False,
     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'):
index 7d4d4692776eee6f5065edf25f0f70513a2e264d..8ad9fe89e0c3a6d170faa789182095c29a095dd2 100644 (file)
@@ -108,6 +108,9 @@ class Entry(object):
             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 @@ class Entry(object):
         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 @@ class Entry(object):
 
         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 @@ class Entry(object):
             # 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
index 951d9934050e123fdbed3cdaff4dc5ed79c73cf3..09bb89b3b7849834c3572f4c8080ce0fdcca1dc2 100644 (file)
@@ -57,3 +57,8 @@ class Entry_blob_phase(Entry_section):
         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
index 7b4454bd342f40a095eb654522ed3983f2dda59a..ecfcd6bd915eb445052447707e431a984005f2cb 100644 (file)
@@ -1500,7 +1500,8 @@ class TestFunctional(unittest.TestCase):
         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 @@ class TestFunctional(unittest.TestCase):
                 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 @@ class TestFunctional(unittest.TestCase):
         # 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 @@ class TestFunctional(unittest.TestCase):
             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 @@ fdt         fdtmap                Extract the devicetree blob from the fdtmap
         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 (file)
index 0000000..e4dccd3
--- /dev/null
@@ -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 (file)
index 0000000..5a777ae
--- /dev/null
@@ -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";
+               };
+       };
+};