summaryrefslogtreecommitdiff
path: root/tools
diff options
context:
space:
mode:
authorTom Rini <trini@konsulko.com>2022-10-31 14:43:04 -0400
committerTom Rini <trini@konsulko.com>2022-10-31 14:43:04 -0400
commita90afc6730e6c67ad37f4c98a02891a93b4ff971 (patch)
tree724c085433631e142a56c052d667139cba29b4a6 /tools
parent6f38d91158e7e4199753b79e0a25c1a65175aba4 (diff)
parent77bec9e3d8bd2dc307447b92a3d5cefd693a62ad (diff)
Merge branch '2022-10-31-vbe-implement-the-full-firmware-flow'
To quote Simon: This series provides an implementation of VBE from TPL through to U-Boot proper, using VBE to load the relevant firmware stages. It buils a single image.bin file containing all the phases: TPL - initial phase, loads VPL using binman symbols VPL - main firmware phase, loads SPL using VBE parameters SPL - loads U-Boot proper using VBE parameters U-Boot - final firmware phase, where OS booting is processed This series does not include the OS-booting phase. That will be the subject of a future series. The implementation is entirely handled by sandbox. It should be possible to enable this on a real board without much effort, but that is also the subject of a future series.
Diffstat (limited to 'tools')
-rw-r--r--tools/binman/binman.rst4
-rw-r--r--tools/binman/elf.py92
-rw-r--r--tools/binman/entries.rst2
-rw-r--r--tools/binman/entry.py16
-rw-r--r--tools/binman/etype/blob.py5
-rw-r--r--tools/binman/etype/fit.py2
-rw-r--r--tools/binman/etype/section.py60
-rw-r--r--tools/binman/etype/u_boot_spl.py7
-rw-r--r--tools/binman/etype/u_boot_spl_elf.py3
-rw-r--r--tools/binman/etype/u_boot_spl_nodtb.py6
-rw-r--r--tools/binman/etype/u_boot_tpl.py6
-rw-r--r--tools/binman/etype/u_boot_tpl_elf.py3
-rw-r--r--tools/binman/etype/u_boot_tpl_nodtb.py6
-rw-r--r--tools/binman/etype/u_boot_vpl.py6
-rw-r--r--tools/binman/etype/u_boot_vpl_elf.py25
-rw-r--r--tools/binman/etype/u_boot_vpl_nodtb.py6
-rw-r--r--tools/binman/etype/u_boot_with_ucode_ptr.py2
-rw-r--r--tools/binman/ftest.py57
-rw-r--r--tools/binman/test/260_symbols_elf.dts27
19 files changed, 264 insertions, 71 deletions
diff --git a/tools/binman/binman.rst b/tools/binman/binman.rst
index d8a3d776f46..fda16f1992d 100644
--- a/tools/binman/binman.rst
+++ b/tools/binman/binman.rst
@@ -766,11 +766,11 @@ end-at-4gb:
skip-at-start:
This property specifies the entry offset of the first entry.
- For PowerPC mpc85xx based CPU, CONFIG_SYS_TEXT_BASE is the entry
+ For PowerPC mpc85xx based CPU, CONFIG_TEXT_BASE is the entry
offset of the first entry. It can be 0xeff40000 or 0xfff40000 for
nor flash boot, 0x201000 for sd boot etc.
- 'end-at-4gb' property is not applicable where CONFIG_SYS_TEXT_BASE +
+ 'end-at-4gb' property is not applicable where CONFIG_TEXT_BASE +
Image size != 4gb.
align-default:
diff --git a/tools/binman/elf.py b/tools/binman/elf.py
index 6d440ddf21d..fe50bf542c3 100644
--- a/tools/binman/elf.py
+++ b/tools/binman/elf.py
@@ -188,7 +188,29 @@ def GetSymbolAddress(fname, sym_name):
return None
return sym.address
-def LookupAndWriteSymbols(elf_fname, entry, section):
+def GetPackString(sym, msg):
+ """Get the struct.pack/unpack string to use with a given symbol
+
+ Args:
+ sym (Symbol): Symbol to check. Only the size member is checked
+ @msg (str): String which indicates the entry being processed, used for
+ errors
+
+ Returns:
+ str: struct string to use, .e.g. '<I'
+
+ Raises:
+ ValueError: Symbol has an unexpected size
+ """
+ if sym.size == 4:
+ return '<I'
+ elif sym.size == 8:
+ return '<Q'
+ else:
+ raise ValueError('%s has size %d: only 4 and 8 are supported' %
+ (msg, sym.size))
+
+def LookupAndWriteSymbols(elf_fname, entry, section, is_elf=False):
"""Replace all symbols in an entry with their correct values
The entry contents is updated so that values for referenced symbols will be
@@ -204,34 +226,52 @@ def LookupAndWriteSymbols(elf_fname, entry, section):
"""
fname = tools.get_input_filename(elf_fname)
syms = GetSymbols(fname, ['image', 'binman'])
+ if is_elf:
+ if not ELF_TOOLS:
+ msg = ("Section '%s': entry '%s'" %
+ (section.GetPath(), entry.GetPath()))
+ raise ValueError(f'{msg}: Cannot write symbols to an ELF file without Python elftools')
+ new_syms = {}
+ with open(fname, 'rb') as fd:
+ elf = ELFFile(fd)
+ for name, sym in syms.items():
+ offset = _GetFileOffset(elf, sym.address)
+ new_syms[name] = Symbol(sym.section, sym.address, sym.size,
+ sym.weak, offset)
+ syms = new_syms
+
if not syms:
+ tout.debug('LookupAndWriteSymbols: no syms')
return
base = syms.get('__image_copy_start')
- if not base:
+ if not base and not is_elf:
+ tout.debug('LookupAndWriteSymbols: no base')
return
+ base_addr = 0 if is_elf else base.address
for name, sym in syms.items():
if name.startswith('_binman'):
msg = ("Section '%s': Symbol '%s'\n in entry '%s'" %
(section.GetPath(), name, entry.GetPath()))
- offset = sym.address - base.address
- if offset < 0 or offset + sym.size > entry.contents_size:
- raise ValueError('%s has offset %x (size %x) but the contents '
- 'size is %x' % (entry.GetPath(), offset,
- sym.size, entry.contents_size))
- if sym.size == 4:
- pack_string = '<I'
- elif sym.size == 8:
- pack_string = '<Q'
+ if is_elf:
+ # For ELF files, use the file offset
+ offset = sym.offset
else:
- raise ValueError('%s has size %d: only 4 and 8 are supported' %
- (msg, sym.size))
-
+ # For blobs use the offset of the symbol, calculated by
+ # subtracting the base address which by definition is at the
+ # start
+ offset = sym.address - base.address
+ if offset < 0 or offset + sym.size > entry.contents_size:
+ raise ValueError('%s has offset %x (size %x) but the contents '
+ 'size is %x' % (entry.GetPath(), offset,
+ sym.size,
+ entry.contents_size))
+ pack_string = GetPackString(sym, msg)
if name == '_binman_sym_magic':
value = BINMAN_SYM_MAGIC_VALUE
else:
# Look up the symbol in our entry tables.
value = section.GetImage().LookupImageSymbol(name, sym.weak,
- msg, base.address)
+ msg, base_addr)
if value is None:
value = -1
pack_string = pack_string.lower()
@@ -241,6 +281,28 @@ def LookupAndWriteSymbols(elf_fname, entry, section):
entry.data = (entry.data[:offset] + value_bytes +
entry.data[offset + sym.size:])
+def GetSymbolValue(sym, data, msg):
+ """Get the value of a symbol
+
+ This can only be used on symbols with an integer value.
+
+ Args:
+ sym (Symbol): Symbol to check
+ data (butes): Data for the ELF file - the symbol data appears at offset
+ sym.offset
+ @msg (str): String which indicates the entry being processed, used for
+ errors
+
+ Returns:
+ int: Value of the symbol
+
+ Raises:
+ ValueError: Symbol has an unexpected size
+ """
+ pack_string = GetPackString(sym, msg)
+ value = struct.unpack(pack_string, data[sym.offset:sym.offset + sym.size])
+ return value[0]
+
def MakeElf(elf_fname, text, data):
"""Make an elf file with the given data in a single section
diff --git a/tools/binman/entries.rst b/tools/binman/entries.rst
index 18bd328c5cd..3dc32db8a54 100644
--- a/tools/binman/entries.rst
+++ b/tools/binman/entries.rst
@@ -735,7 +735,7 @@ Here is an example showing ATF, TEE and a device tree all combined::
os = "U-Boot";
arch = "arm64";
compression = "none";
- load = <CONFIG_SYS_TEXT_BASE>;
+ load = <CONFIG_TEXT_BASE>;
u-boot-nodtb {
};
};
diff --git a/tools/binman/entry.py b/tools/binman/entry.py
index 63ec5cea3b2..1be31a05e00 100644
--- a/tools/binman/entry.py
+++ b/tools/binman/entry.py
@@ -12,6 +12,7 @@ import sys
import time
from binman import bintool
+from binman import elf
from dtoc import fdt_util
from patman import tools
from patman.tools import to_hex, to_hex_size
@@ -86,10 +87,15 @@ class Entry(object):
fake_fname: Fake filename, if one was created, else None
required_props (dict of str): Properties which must be present. This can
be added to by subclasses
+ elf_fname (str): Filename of the ELF file, if this entry holds an ELF
+ file, or is a binary file produced from an ELF file
+ auto_write_symbols (bool): True to write ELF symbols into this entry's
+ contents
"""
fake_dir = None
- def __init__(self, section, etype, node, name_prefix=''):
+ def __init__(self, section, etype, node, name_prefix='',
+ auto_write_symbols=False):
# Put this here to allow entry-docs and help to work without libfdt
global state
from binman import state
@@ -125,6 +131,8 @@ class Entry(object):
self.fake_fname = None
self.required_props = []
self.comp_bintool = None
+ self.elf_fname = None
+ self.auto_write_symbols = auto_write_symbols
@staticmethod
def FindEntryClass(etype, expanded):
@@ -647,7 +655,11 @@ class Entry(object):
Args:
section: Section containing the entry
"""
- pass
+ if self.auto_write_symbols:
+ # 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)
def CheckEntries(self):
"""Check that the entry offsets are correct
diff --git a/tools/binman/etype/blob.py b/tools/binman/etype/blob.py
index ceaefb07b73..a50a8068901 100644
--- a/tools/binman/etype/blob.py
+++ b/tools/binman/etype/blob.py
@@ -31,8 +31,9 @@ class Entry_blob(Entry):
the node (if enabled with -u) which provides the uncompressed size of the
data.
"""
- def __init__(self, section, etype, node):
- super().__init__(section, etype, node)
+ def __init__(self, section, etype, node, auto_write_symbols=False):
+ super().__init__(section, etype, node,
+ auto_write_symbols=auto_write_symbols)
self._filename = fdt_util.GetString(self._node, 'filename', self.etype)
def ObtainContents(self, fake_size=0):
diff --git a/tools/binman/etype/fit.py b/tools/binman/etype/fit.py
index ad43fce18ec..7860e2aeea3 100644
--- a/tools/binman/etype/fit.py
+++ b/tools/binman/etype/fit.py
@@ -201,7 +201,7 @@ class Entry_fit(Entry_section):
os = "U-Boot";
arch = "arm64";
compression = "none";
- load = <CONFIG_SYS_TEXT_BASE>;
+ load = <CONFIG_TEXT_BASE>;
u-boot-nodtb {
};
};
diff --git a/tools/binman/etype/section.py b/tools/binman/etype/section.py
index 621950893f3..da561e2bcc7 100644
--- a/tools/binman/etype/section.py
+++ b/tools/binman/etype/section.py
@@ -510,6 +510,50 @@ class Entry_section(Entry):
source_entry.Raise("Cannot find entry for node '%s'" % node.name)
return entry.GetData(required)
+ def LookupEntry(self, entries, sym_name, msg):
+ """Look up the entry for an ENF symbol
+
+ Args:
+ entries (dict): entries to search:
+ key: entry name
+ value: Entry object
+ 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)
+ msg: Message to display if an error occurs
+
+ Returns:
+ tuple:
+ Entry: entry object that was found
+ str: name used to search for entries (uses '-' instead of the
+ '_' used by the symbol name)
+ str: property name the symbol refers to, e.g. 'image_pos'
+
+ Raises:
+ ValueError:the symbol name cannot be decoded, e.g. does not have
+ a '_binman_' prefix
+ """
+ m = re.match(r'^_binman_(\w+)_prop_(\w+)$', sym_name)
+ if not m:
+ raise ValueError("%s: Symbol '%s' has invalid format" %
+ (msg, sym_name))
+ entry_name, prop_name = m.groups()
+ entry_name = entry_name.replace('_', '-')
+ entry = entries.get(entry_name)
+ if not entry:
+ if entry_name.endswith('-any'):
+ root = entry_name[:-4]
+ for name in entries:
+ if name.startswith(root):
+ rest = name[len(root):]
+ if rest in ['', '-elf', '-img', '-nodtb']:
+ entry = entries[name]
+ return entry, entry_name, prop_name
+
def LookupSymbol(self, sym_name, optional, msg, base_addr, entries=None):
"""Look up a symbol in an ELF file
@@ -547,23 +591,9 @@ class Entry_section(Entry):
ValueError if the symbol is invalid or not found, or references a
property which is not supported
"""
- m = re.match(r'^_binman_(\w+)_prop_(\w+)$', sym_name)
- if not m:
- raise ValueError("%s: Symbol '%s' has invalid format" %
- (msg, sym_name))
- entry_name, prop_name = m.groups()
- entry_name = entry_name.replace('_', '-')
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 entries:
- if name.startswith(root):
- rest = name[len(root):]
- if rest in ['', '-img', '-nodtb']:
- entry = entries[name]
+ entry, entry_name, prop_name = self.LookupEntry(entries, sym_name, msg)
if not entry:
err = ("%s: Entry '%s' not found in list (%s)" %
(msg, entry_name, ','.join(entries.keys())))
diff --git a/tools/binman/etype/u_boot_spl.py b/tools/binman/etype/u_boot_spl.py
index 6f79bf59f9f..d1aa3b4fdad 100644
--- a/tools/binman/etype/u_boot_spl.py
+++ b/tools/binman/etype/u_boot_spl.py
@@ -5,7 +5,6 @@
# Entry-type module for spl/u-boot-spl.bin
#
-from binman import elf
from binman.entry import Entry
from binman.etype.blob import Entry_blob
@@ -35,11 +34,9 @@ class Entry_u_boot_spl(Entry_blob):
unless --no-expanded is used or the node has a 'no-expanded' property.
"""
def __init__(self, section, etype, node):
- super().__init__(section, etype, node)
+ super().__init__(section, etype, node, auto_write_symbols=True)
self.elf_fname = 'spl/u-boot-spl'
+ self.auto_write_symbols = True
def GetDefaultFilename(self):
return 'spl/u-boot-spl.bin'
-
- def WriteSymbols(self, section):
- elf.LookupAndWriteSymbols(self.elf_fname, self, section.GetImage())
diff --git a/tools/binman/etype/u_boot_spl_elf.py b/tools/binman/etype/u_boot_spl_elf.py
index 7f1236bcbb3..7b7b4e01495 100644
--- a/tools/binman/etype/u_boot_spl_elf.py
+++ b/tools/binman/etype/u_boot_spl_elf.py
@@ -18,7 +18,8 @@ class Entry_u_boot_spl_elf(Entry_blob):
be relocated to any address for execution.
"""
def __init__(self, section, etype, node):
- super().__init__(section, etype, node)
+ super().__init__(section, etype, node, auto_write_symbols=True)
+ self.elf_fname = 'spl/u-boot-spl'
def GetDefaultFilename(self):
return 'spl/u-boot-spl'
diff --git a/tools/binman/etype/u_boot_spl_nodtb.py b/tools/binman/etype/u_boot_spl_nodtb.py
index 316b38172ef..50a126dc7ef 100644
--- a/tools/binman/etype/u_boot_spl_nodtb.py
+++ b/tools/binman/etype/u_boot_spl_nodtb.py
@@ -5,7 +5,6 @@
# Entry-type module for 'u-boot-spl-nodtb.bin'
#
-from binman import elf
from binman.entry import Entry
from binman.etype.blob import Entry_blob
@@ -32,11 +31,8 @@ class Entry_u_boot_spl_nodtb(Entry_blob):
binman uses that to look up symbols to write into the SPL binary.
"""
def __init__(self, section, etype, node):
- super().__init__(section, etype, node)
+ super().__init__(section, etype, node, auto_write_symbols=True)
self.elf_fname = 'spl/u-boot-spl'
def GetDefaultFilename(self):
return 'spl/u-boot-spl-nodtb.bin'
-
- def WriteSymbols(self, section):
- elf.LookupAndWriteSymbols(self.elf_fname, self, section.GetImage())
diff --git a/tools/binman/etype/u_boot_tpl.py b/tools/binman/etype/u_boot_tpl.py
index 0c575df8cdc..1883a2bd5f1 100644
--- a/tools/binman/etype/u_boot_tpl.py
+++ b/tools/binman/etype/u_boot_tpl.py
@@ -5,7 +5,6 @@
# Entry-type module for tpl/u-boot-tpl.bin
#
-from binman import elf
from binman.entry import Entry
from binman.etype.blob import Entry_blob
@@ -35,11 +34,8 @@ class Entry_u_boot_tpl(Entry_blob):
unless --no-expanded is used or the node has a 'no-expanded' property.
"""
def __init__(self, section, etype, node):
- super().__init__(section, etype, node)
+ super().__init__(section, etype, node, auto_write_symbols=True)
self.elf_fname = 'tpl/u-boot-tpl'
def GetDefaultFilename(self):
return 'tpl/u-boot-tpl.bin'
-
- def WriteSymbols(self, section):
- elf.LookupAndWriteSymbols(self.elf_fname, self, section.GetImage())
diff --git a/tools/binman/etype/u_boot_tpl_elf.py b/tools/binman/etype/u_boot_tpl_elf.py
index 3f24d3aa7bc..fd100019b39 100644
--- a/tools/binman/etype/u_boot_tpl_elf.py
+++ b/tools/binman/etype/u_boot_tpl_elf.py
@@ -18,7 +18,8 @@ class Entry_u_boot_tpl_elf(Entry_blob):
be relocated to any address for execution.
"""
def __init__(self, section, etype, node):
- super().__init__(section, etype, node)
+ super().__init__(section, etype, node, auto_write_symbols=True)
+ self.elf_fname = 'tpl/u-boot-tpl'
def GetDefaultFilename(self):
return 'tpl/u-boot-tpl'
diff --git a/tools/binman/etype/u_boot_tpl_nodtb.py b/tools/binman/etype/u_boot_tpl_nodtb.py
index 98f3853f457..7e08e58f1e5 100644
--- a/tools/binman/etype/u_boot_tpl_nodtb.py
+++ b/tools/binman/etype/u_boot_tpl_nodtb.py
@@ -5,7 +5,6 @@
# Entry-type module for 'u-boot-tpl-nodtb.bin'
#
-from binman import elf
from binman.entry import Entry
from binman.etype.blob import Entry_blob
@@ -32,11 +31,8 @@ class Entry_u_boot_tpl_nodtb(Entry_blob):
binman uses that to look up symbols to write into the TPL binary.
"""
def __init__(self, section, etype, node):
- super().__init__(section, etype, node)
+ super().__init__(section, etype, node, auto_write_symbols=True)
self.elf_fname = 'tpl/u-boot-tpl'
def GetDefaultFilename(self):
return 'tpl/u-boot-tpl-nodtb.bin'
-
- def WriteSymbols(self, section):
- elf.LookupAndWriteSymbols(self.elf_fname, self, section.GetImage())
diff --git a/tools/binman/etype/u_boot_vpl.py b/tools/binman/etype/u_boot_vpl.py
index 9daaca4f6fd..62e5969c6ec 100644
--- a/tools/binman/etype/u_boot_vpl.py
+++ b/tools/binman/etype/u_boot_vpl.py
@@ -5,7 +5,6 @@
# Entry-type module for vpl/u-boot-vpl.bin
#
-from binman import elf
from binman.entry import Entry
from binman.etype.blob import Entry_blob
@@ -32,11 +31,8 @@ class Entry_u_boot_vpl(Entry_blob):
binman uses that to look up symbols to write into the VPL binary.
"""
def __init__(self, section, etype, node):
- super().__init__(section, etype, node)
+ super().__init__(section, etype, node, auto_write_symbols=True)
self.elf_fname = 'vpl/u-boot-vpl'
def GetDefaultFilename(self):
return 'vpl/u-boot-vpl.bin'
-
- def WriteSymbols(self, section):
- elf.LookupAndWriteSymbols(self.elf_fname, self, section.GetImage())
diff --git a/tools/binman/etype/u_boot_vpl_elf.py b/tools/binman/etype/u_boot_vpl_elf.py
new file mode 100644
index 00000000000..2c686790194
--- /dev/null
+++ b/tools/binman/etype/u_boot_vpl_elf.py
@@ -0,0 +1,25 @@
+# SPDX-License-Identifier: GPL-2.0+
+# Copyright 2022 Google LLC
+# Written by Simon Glass <sjg@chromium.org>
+#
+# Entry-type module for U-Boot VPL ELF image
+#
+
+from binman.entry import Entry
+from binman.etype.blob import Entry_blob
+
+class Entry_u_boot_vpl_elf(Entry_blob):
+ """U-Boot VPL ELF image
+
+ Properties / Entry arguments:
+ - filename: Filename of VPL u-boot (default 'vpl/u-boot-vpl')
+
+ This is the U-Boot VPL ELF image. It does not include a device tree but can
+ be relocated to any address for execution.
+ """
+ def __init__(self, section, etype, node):
+ super().__init__(section, etype, node, auto_write_symbols=True)
+ self.elf_fname = 'vpl/u-boot-vpl'
+
+ def GetDefaultFilename(self):
+ return 'vpl/u-boot-vpl'
diff --git a/tools/binman/etype/u_boot_vpl_nodtb.py b/tools/binman/etype/u_boot_vpl_nodtb.py
index 25c966cf342..db3d8a91c9b 100644
--- a/tools/binman/etype/u_boot_vpl_nodtb.py
+++ b/tools/binman/etype/u_boot_vpl_nodtb.py
@@ -5,7 +5,6 @@
# Entry-type module for 'u-boot-vpl-nodtb.bin'
#
-from binman import elf
from binman.entry import Entry
from binman.etype.blob import Entry_blob
@@ -32,11 +31,8 @@ class Entry_u_boot_vpl_nodtb(Entry_blob):
binman uses that to look up symbols to write into the VPL binary.
"""
def __init__(self, section, etype, node):
- super().__init__(section, etype, node)
+ super().__init__(section, etype, node, auto_write_symbols=True)
self.elf_fname = 'vpl/u-boot-vpl'
def GetDefaultFilename(self):
return 'vpl/u-boot-vpl-nodtb.bin'
-
- def WriteSymbols(self, section):
- elf.LookupAndWriteSymbols(self.elf_fname, self, section.GetImage())
diff --git a/tools/binman/etype/u_boot_with_ucode_ptr.py b/tools/binman/etype/u_boot_with_ucode_ptr.py
index a5fd2d1ca5e..e275698cebe 100644
--- a/tools/binman/etype/u_boot_with_ucode_ptr.py
+++ b/tools/binman/etype/u_boot_with_ucode_ptr.py
@@ -62,7 +62,7 @@ class Entry_u_boot_with_ucode_ptr(Entry_blob):
#
# The section must be set up so that U-Boot is placed at the
# flash address to which it is linked. For example, if
- # CONFIG_SYS_TEXT_BASE is 0xfff00000, and the ROM is 8MB, then
+ # CONFIG_TEXT_BASE is 0xfff00000, and the ROM is 8MB, then
# the U-Boot region must start at offset 7MB in the section. In this
# case the ROM starts at 0xff800000, so the offset of the first
# entry in the section corresponds to that.
diff --git a/tools/binman/ftest.py b/tools/binman/ftest.py
index 232ac2cf185..e849d96587c 100644
--- a/tools/binman/ftest.py
+++ b/tools/binman/ftest.py
@@ -6005,5 +6005,62 @@ fdt fdtmap Extract the devicetree blob from the fdtmap
self.assertTrue(os.path.islink(sname))
self.assertEqual(os.readlink(sname), fname)
+ def testSymbolsElf(self):
+ """Test binman can assign symbols embedded in an ELF file"""
+ if not elf.ELF_TOOLS:
+ self.skipTest('Python elftools not available')
+ self._SetupTplElf('u_boot_binman_syms')
+ self._SetupVplElf('u_boot_binman_syms')
+ self._SetupSplElf('u_boot_binman_syms')
+ data = self._DoReadFileDtb('260_symbols_elf.dts')[0]
+ image_fname = tools.get_output_filename('image.bin')
+
+ image = control.images['image']
+ entries = image.GetEntries()
+
+ for entry in entries.values():
+ # No symbols in u-boot and it has faked contents anyway
+ if entry.name == 'u-boot':
+ continue
+ edata = data[entry.image_pos:entry.image_pos + entry.size]
+ efname = tools.get_output_filename(f'edata-{entry.name}')
+ tools.write_file(efname, edata)
+
+ syms = elf.GetSymbolFileOffset(efname, ['_binman_u_boot'])
+ re_name = re.compile('_binman_(u_boot_(.*))_prop_(.*)')
+ for name, sym in syms.items():
+ msg = 'test'
+ val = elf.GetSymbolValue(sym, edata, msg)
+ entry_m = re_name.match(name)
+ if entry_m:
+ ename, prop = entry_m.group(1), entry_m.group(3)
+ entry, entry_name, prop_name = image.LookupEntry(entries,
+ name, msg)
+ if prop_name == 'offset':
+ expect_val = entry.offset
+ elif prop_name == 'image_pos':
+ expect_val = entry.image_pos
+ elif prop_name == 'size':
+ expect_val = entry.size
+ self.assertEqual(expect_val, val)
+
+ def testSymbolsElfBad(self):
+ """Check error when trying to write symbols without the elftools lib"""
+ if not elf.ELF_TOOLS:
+ self.skipTest('Python elftools not available')
+ self._SetupTplElf('u_boot_binman_syms')
+ self._SetupVplElf('u_boot_binman_syms')
+ self._SetupSplElf('u_boot_binman_syms')
+ try:
+ elf.ELF_TOOLS = False
+ with self.assertRaises(ValueError) as exc:
+ self._DoReadFileDtb('260_symbols_elf.dts')
+ finally:
+ elf.ELF_TOOLS = True
+ self.assertIn(
+ "Section '/binman': entry '/binman/u-boot-spl-elf': "
+ 'Cannot write symbols to an ELF file without Python elftools',
+ str(exc.exception))
+
if __name__ == "__main__":
unittest.main()
diff --git a/tools/binman/test/260_symbols_elf.dts b/tools/binman/test/260_symbols_elf.dts
new file mode 100644
index 00000000000..0fae118fc12
--- /dev/null
+++ b/tools/binman/test/260_symbols_elf.dts
@@ -0,0 +1,27 @@
+// SPDX-License-Identifier: GPL-2.0+
+
+/dts-v1/;
+
+/ {
+ #address-cells = <1>;
+ #size-cells = <1>;
+
+ binman {
+ pad-byte = <0xff>;
+ u-boot-spl-elf {
+ };
+
+ u-boot {
+ };
+
+ u-boot-spl2 {
+ type = "u-boot-spl-elf";
+ };
+
+ u-boot-tpl-elf {
+ };
+
+ u-boot-vpl-elf {
+ };
+ };
+};