mirror of
https://github.com/u-boot/u-boot.git
synced 2025-05-08 19:11:53 +00:00
binman: tegra: Adjust symbol calculation depending on end-at-4gb
A recent change adjusted the symbol calculation to work on x86 but broke
it for Tegra. In fact this is because they have different needs.
On x86 devices the code is linked to a ROM address and the end-at-4gb
property is used for the image. In this case there is no need to add the
base address of the image, since the base address is already built into
the offset and image-pos properties.
On other devices we must add the base address since the offsets start at
zero.
In addition the base address is currently added to the 'offset' and 'size'
values. It should in fact only be added to 'image-pos', since 'offset' is
relative to its parent and 'size' is not actually an address. This code
should have been adjusted when support for 'image-pos' and 'size' was
added, but it was not.
To correct these problems:
- move the code that handles adding the base address to section.py, which
can check the end-at-4gb property and which property
(offset/size/image-pos) is being read
- add the base address only when needed (only for image-pos and not if the
image uses end-at-4gb)
- add a note to the documentation
- add a separate test to cover x86 behaviour
Fixes: 15c981cc
(binman: Correct symbol calculation with non-zero image base)
Signed-off-by: Simon Glass <sjg@chromium.org>
Tested-by: Stephen Warren <swarren@nvidia.com>
This commit is contained in:
parent
086e391bc4
commit
7c15013639
10 changed files with 134 additions and 26 deletions
|
@ -766,20 +766,38 @@ when SPL is finished.
|
||||||
Binman allows you to declare symbols in the SPL image which are filled in
|
Binman allows you to declare symbols in the SPL image which are filled in
|
||||||
with their correct values during the build. For example:
|
with their correct values during the build. For example:
|
||||||
|
|
||||||
binman_sym_declare(ulong, u_boot_any, offset);
|
binman_sym_declare(ulong, u_boot_any, image_pos);
|
||||||
|
|
||||||
declares a ulong value which will be assigned to the offset of any U-Boot
|
declares a ulong value which will be assigned to the image-pos of any U-Boot
|
||||||
image (u-boot.bin, u-boot.img, u-boot-nodtb.bin) that is present in the image.
|
image (u-boot.bin, u-boot.img, u-boot-nodtb.bin) that is present in the image.
|
||||||
You can access this value with something like:
|
You can access this value with something like:
|
||||||
|
|
||||||
ulong u_boot_offset = binman_sym(ulong, u_boot_any, offset);
|
ulong u_boot_offset = binman_sym(ulong, u_boot_any, image_pos);
|
||||||
|
|
||||||
Thus u_boot_offset will be set to the offset of U-Boot in memory, assuming that
|
Thus u_boot_offset will be set to the image-pos of U-Boot in memory, assuming
|
||||||
the whole image has been loaded, or is available in flash. You can then jump to
|
that the whole image has been loaded, or is available in flash. You can then
|
||||||
that address to start U-Boot.
|
jump to that address to start U-Boot.
|
||||||
|
|
||||||
At present this feature is only supported in SPL. In principle it is possible
|
At present this feature is only supported in SPL and TPL. In principle it is
|
||||||
to fill in such symbols in U-Boot proper, as well.
|
possible to fill in such symbols in U-Boot proper, as well, but a future C
|
||||||
|
library is planned for this instead, to read from the device tree.
|
||||||
|
|
||||||
|
As well as image-pos, it is possible to read the size of an entry and its
|
||||||
|
offset (which is the start position of the entry within its parent).
|
||||||
|
|
||||||
|
A small technical note: Binman automatically adds the base address of the image
|
||||||
|
(i.e. __image_copy_start) to the value of the image-pos symbol, so that when the
|
||||||
|
image is loaded to its linked address, the value will be correct and actually
|
||||||
|
point into the image.
|
||||||
|
|
||||||
|
For example, say SPL is at the start of the image and linked to start at address
|
||||||
|
80108000. If U-Boot's image-pos is 0x8000 then binman will write an image-pos
|
||||||
|
for U-Boot of 80110000 into the SPL binary, since it assumes the image is loaded
|
||||||
|
to 80108000, with SPL at 80108000 and U-Boot at 80110000.
|
||||||
|
|
||||||
|
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.
|
||||||
|
|
||||||
|
|
||||||
Access to binman entry offsets at run time (fdt)
|
Access to binman entry offsets at run time (fdt)
|
||||||
|
|
|
@ -134,7 +134,7 @@ def LookupAndWriteSymbols(elf_fname, entry, section):
|
||||||
(msg, sym.size))
|
(msg, sym.size))
|
||||||
|
|
||||||
# Look up the symbol in our entry tables.
|
# Look up the symbol in our entry tables.
|
||||||
value = section.LookupSymbol(name, sym.weak, msg)
|
value = section.LookupSymbol(name, sym.weak, msg, base.address)
|
||||||
if value is None:
|
if value is None:
|
||||||
value = -1
|
value = -1
|
||||||
pack_string = pack_string.lower()
|
pack_string = pack_string.lower()
|
||||||
|
|
|
@ -45,7 +45,7 @@ class FakeSection:
|
||||||
def GetPath(self):
|
def GetPath(self):
|
||||||
return 'section_path'
|
return 'section_path'
|
||||||
|
|
||||||
def LookupSymbol(self, name, weak, msg):
|
def LookupSymbol(self, name, weak, msg, base_addr):
|
||||||
"""Fake implementation which returns the same value for all symbols"""
|
"""Fake implementation which returns the same value for all symbols"""
|
||||||
return self.sym_value
|
return self.sym_value
|
||||||
|
|
||||||
|
|
|
@ -290,13 +290,16 @@ class Entry_section(Entry):
|
||||||
return entry.GetData()
|
return entry.GetData()
|
||||||
source_entry.Raise("Cannot find entry for node '%s'" % node.name)
|
source_entry.Raise("Cannot find entry for node '%s'" % node.name)
|
||||||
|
|
||||||
def LookupSymbol(self, sym_name, optional, msg):
|
def LookupSymbol(self, sym_name, optional, msg, base_addr):
|
||||||
"""Look up a symbol in an ELF file
|
"""Look up a symbol in an ELF file
|
||||||
|
|
||||||
Looks up a symbol in an ELF file. Only entry types which come from an
|
Looks up a symbol in an ELF file. Only entry types which come from an
|
||||||
ELF image can be used by this function.
|
ELF image can be used by this function.
|
||||||
|
|
||||||
At present the only entry property supported is offset.
|
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:
|
Args:
|
||||||
sym_name: Symbol name in the ELF file to look up in the format
|
sym_name: Symbol name in the ELF file to look up in the format
|
||||||
|
@ -309,6 +312,12 @@ class Entry_section(Entry):
|
||||||
optional: True if the symbol is optional. If False this function
|
optional: True if the symbol is optional. If False this function
|
||||||
will raise if the symbol is not found
|
will raise if the symbol is not found
|
||||||
msg: Message to display if an error occurs
|
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 targetted 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:
|
Returns:
|
||||||
Value that should be assigned to that symbol, or None if it was
|
Value that should be assigned to that symbol, or None if it was
|
||||||
|
@ -343,7 +352,10 @@ class Entry_section(Entry):
|
||||||
if prop_name == 'offset':
|
if prop_name == 'offset':
|
||||||
return entry.offset
|
return entry.offset
|
||||||
elif prop_name == 'image_pos':
|
elif prop_name == 'image_pos':
|
||||||
return entry.image_pos
|
value = entry.image_pos
|
||||||
|
if not self.GetImage()._end_4gb:
|
||||||
|
value += base_addr
|
||||||
|
return value
|
||||||
if prop_name == 'size':
|
if prop_name == 'size':
|
||||||
return entry.size
|
return entry.size
|
||||||
else:
|
else:
|
||||||
|
|
|
@ -1242,7 +1242,7 @@ class TestFunctional(unittest.TestCase):
|
||||||
|
|
||||||
self._SetupSplElf('u_boot_binman_syms')
|
self._SetupSplElf('u_boot_binman_syms')
|
||||||
data = self._DoReadFile('053_symbols.dts')
|
data = self._DoReadFile('053_symbols.dts')
|
||||||
sym_values = struct.pack('<LQLL', 0, 28, 24, 4)
|
sym_values = struct.pack('<LQLL', 0x00, 0x1c, 0x28, 0x04)
|
||||||
expected = (sym_values + U_BOOT_SPL_DATA[20:] +
|
expected = (sym_values + U_BOOT_SPL_DATA[20:] +
|
||||||
tools.GetBytes(0xff, 1) + U_BOOT_DATA + sym_values +
|
tools.GetBytes(0xff, 1) + U_BOOT_DATA + sym_values +
|
||||||
U_BOOT_SPL_DATA[20:])
|
U_BOOT_SPL_DATA[20:])
|
||||||
|
@ -3304,12 +3304,9 @@ class TestFunctional(unittest.TestCase):
|
||||||
self.assertIn("'intel-fit-ptr' section must have an 'intel-fit' sibling",
|
self.assertIn("'intel-fit-ptr' section must have an 'intel-fit' sibling",
|
||||||
str(e.exception))
|
str(e.exception))
|
||||||
|
|
||||||
def testSymbolsTplSection(self):
|
def _CheckSymbolsTplSection(self, dts, expected_vals):
|
||||||
"""Test binman can assign symbols embedded in U-Boot TPL in a section"""
|
data = self._DoReadFile(dts)
|
||||||
self._SetupSplElf('u_boot_binman_syms')
|
sym_values = struct.pack('<LQLL', *expected_vals)
|
||||||
self._SetupTplElf('u_boot_binman_syms')
|
|
||||||
data = self._DoReadFile('149_symbols_tpl.dts')
|
|
||||||
sym_values = struct.pack('<LQLL', 4, 0x1c, 0x34, 4)
|
|
||||||
upto1 = 4 + len(U_BOOT_SPL_DATA)
|
upto1 = 4 + len(U_BOOT_SPL_DATA)
|
||||||
expected1 = tools.GetBytes(0xff, 4) + sym_values + U_BOOT_SPL_DATA[20:]
|
expected1 = tools.GetBytes(0xff, 4) + sym_values + U_BOOT_SPL_DATA[20:]
|
||||||
self.assertEqual(expected1, data[:upto1])
|
self.assertEqual(expected1, data[:upto1])
|
||||||
|
@ -3323,7 +3320,22 @@ class TestFunctional(unittest.TestCase):
|
||||||
self.assertEqual(expected3, data[upto2:upto3])
|
self.assertEqual(expected3, data[upto2:upto3])
|
||||||
|
|
||||||
expected4 = sym_values + U_BOOT_TPL_DATA[20:]
|
expected4 = sym_values + U_BOOT_TPL_DATA[20:]
|
||||||
self.assertEqual(expected4, data[upto3:])
|
self.assertEqual(expected4, data[upto3:upto3 + len(U_BOOT_TPL_DATA)])
|
||||||
|
|
||||||
|
def testSymbolsTplSection(self):
|
||||||
|
"""Test binman can assign symbols embedded in U-Boot TPL in a section"""
|
||||||
|
self._SetupSplElf('u_boot_binman_syms')
|
||||||
|
self._SetupTplElf('u_boot_binman_syms')
|
||||||
|
self._CheckSymbolsTplSection('149_symbols_tpl.dts',
|
||||||
|
[0x04, 0x1c, 0x10 + 0x34, 0x04])
|
||||||
|
|
||||||
|
def testSymbolsTplSectionX86(self):
|
||||||
|
"""Test binman can assign symbols in a section with end-at-4gb"""
|
||||||
|
self._SetupSplElf('u_boot_binman_syms_x86')
|
||||||
|
self._SetupTplElf('u_boot_binman_syms_x86')
|
||||||
|
self._CheckSymbolsTplSection('155_symbols_tpl_x86.dts',
|
||||||
|
[0xffffff04, 0xffffff1c, 0xffffff34,
|
||||||
|
0x04])
|
||||||
|
|
||||||
def testPackX86RomIfwiSectiom(self):
|
def testPackX86RomIfwiSectiom(self):
|
||||||
"""Test that a section can be placed in an IFWI region"""
|
"""Test that a section can be placed in an IFWI region"""
|
||||||
|
|
|
@ -13,7 +13,7 @@ class TestImage(unittest.TestCase):
|
||||||
def testInvalidFormat(self):
|
def testInvalidFormat(self):
|
||||||
image = Image('name', 'node', test=True)
|
image = Image('name', 'node', test=True)
|
||||||
with self.assertRaises(ValueError) as e:
|
with self.assertRaises(ValueError) as e:
|
||||||
image.LookupSymbol('_binman_something_prop_', False, 'msg')
|
image.LookupSymbol('_binman_something_prop_', False, 'msg', 0)
|
||||||
self.assertIn(
|
self.assertIn(
|
||||||
"msg: Symbol '_binman_something_prop_' has invalid format",
|
"msg: Symbol '_binman_something_prop_' has invalid format",
|
||||||
str(e.exception))
|
str(e.exception))
|
||||||
|
@ -22,7 +22,7 @@ class TestImage(unittest.TestCase):
|
||||||
image = Image('name', 'node', test=True)
|
image = Image('name', 'node', test=True)
|
||||||
image._entries = {}
|
image._entries = {}
|
||||||
with self.assertRaises(ValueError) as e:
|
with self.assertRaises(ValueError) as e:
|
||||||
image.LookupSymbol('_binman_type_prop_pname', False, 'msg')
|
image.LookupSymbol('_binman_type_prop_pname', False, 'msg', 0)
|
||||||
self.assertIn("msg: Entry 'type' not found in list ()",
|
self.assertIn("msg: Entry 'type' not found in list ()",
|
||||||
str(e.exception))
|
str(e.exception))
|
||||||
|
|
||||||
|
@ -30,7 +30,7 @@ class TestImage(unittest.TestCase):
|
||||||
image = Image('name', 'node', test=True)
|
image = Image('name', 'node', test=True)
|
||||||
image._entries = {}
|
image._entries = {}
|
||||||
with capture_sys_output() as (stdout, stderr):
|
with capture_sys_output() as (stdout, stderr):
|
||||||
val = image.LookupSymbol('_binman_type_prop_pname', True, 'msg')
|
val = image.LookupSymbol('_binman_type_prop_pname', True, 'msg', 0)
|
||||||
self.assertEqual(val, None)
|
self.assertEqual(val, None)
|
||||||
self.assertEqual("Warning: msg: Entry 'type' not found in list ()\n",
|
self.assertEqual("Warning: msg: Entry 'type' not found in list ()\n",
|
||||||
stderr.getvalue())
|
stderr.getvalue())
|
||||||
|
@ -40,5 +40,5 @@ class TestImage(unittest.TestCase):
|
||||||
image = Image('name', 'node', test=True)
|
image = Image('name', 'node', test=True)
|
||||||
image._entries = {'u-boot': 1}
|
image._entries = {'u-boot': 1}
|
||||||
with self.assertRaises(ValueError) as e:
|
with self.assertRaises(ValueError) as e:
|
||||||
image.LookupSymbol('_binman_u_boot_prop_bad', False, 'msg')
|
image.LookupSymbol('_binman_u_boot_prop_bad', False, 'msg', 0)
|
||||||
self.assertIn("msg: No such property 'bad", str(e.exception))
|
self.assertIn("msg: No such property 'bad", str(e.exception))
|
||||||
|
|
31
tools/binman/test/155_symbols_tpl_x86.dts
Normal file
31
tools/binman/test/155_symbols_tpl_x86.dts
Normal file
|
@ -0,0 +1,31 @@
|
||||||
|
/* SPDX-License-Identifier: GPL-2.0+ */
|
||||||
|
/dts-v1/;
|
||||||
|
|
||||||
|
/ {
|
||||||
|
#address-cells = <1>;
|
||||||
|
#size-cells = <1>;
|
||||||
|
|
||||||
|
binman {
|
||||||
|
pad-byte = <0xff>;
|
||||||
|
end-at-4gb;
|
||||||
|
size = <0x100>;
|
||||||
|
u-boot-spl {
|
||||||
|
offset = <0xffffff04>;
|
||||||
|
};
|
||||||
|
|
||||||
|
u-boot-spl2 {
|
||||||
|
offset = <0xffffff1c>;
|
||||||
|
type = "u-boot-spl";
|
||||||
|
};
|
||||||
|
|
||||||
|
u-boot {
|
||||||
|
offset = <0xffffff34>;
|
||||||
|
};
|
||||||
|
|
||||||
|
section {
|
||||||
|
u-boot-tpl {
|
||||||
|
type = "u-boot-tpl";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
|
@ -14,10 +14,11 @@ CFLAGS := -march=i386 -m32 -nostdlib -I $(SRC)../../../include \
|
||||||
LDS_UCODE := -T $(SRC)u_boot_ucode_ptr.lds
|
LDS_UCODE := -T $(SRC)u_boot_ucode_ptr.lds
|
||||||
LDS_BINMAN := -T $(SRC)u_boot_binman_syms.lds
|
LDS_BINMAN := -T $(SRC)u_boot_binman_syms.lds
|
||||||
LDS_BINMAN_BAD := -T $(SRC)u_boot_binman_syms_bad.lds
|
LDS_BINMAN_BAD := -T $(SRC)u_boot_binman_syms_bad.lds
|
||||||
|
LDS_BINMAN_X86 := -T $(SRC)u_boot_binman_syms_x86.lds
|
||||||
|
|
||||||
TARGETS = u_boot_ucode_ptr u_boot_no_ucode_ptr bss_data \
|
TARGETS = u_boot_ucode_ptr u_boot_no_ucode_ptr bss_data \
|
||||||
u_boot_binman_syms u_boot_binman_syms.bin u_boot_binman_syms_bad \
|
u_boot_binman_syms u_boot_binman_syms.bin u_boot_binman_syms_bad \
|
||||||
u_boot_binman_syms_size
|
u_boot_binman_syms_size u_boot_binman_syms_x86
|
||||||
|
|
||||||
all: $(TARGETS)
|
all: $(TARGETS)
|
||||||
|
|
||||||
|
@ -36,6 +37,9 @@ u_boot_binman_syms.bin: u_boot_binman_syms
|
||||||
u_boot_binman_syms: CFLAGS += $(LDS_BINMAN)
|
u_boot_binman_syms: CFLAGS += $(LDS_BINMAN)
|
||||||
u_boot_binman_syms: u_boot_binman_syms.c
|
u_boot_binman_syms: u_boot_binman_syms.c
|
||||||
|
|
||||||
|
u_boot_binman_syms_x86: CFLAGS += $(LDS_BINMAN_X86)
|
||||||
|
u_boot_binman_syms_x86: u_boot_binman_syms_x86.c
|
||||||
|
|
||||||
u_boot_binman_syms_bad: CFLAGS += $(LDS_BINMAN_BAD)
|
u_boot_binman_syms_bad: CFLAGS += $(LDS_BINMAN_BAD)
|
||||||
u_boot_binman_syms_bad: u_boot_binman_syms_bad.c
|
u_boot_binman_syms_bad: u_boot_binman_syms_bad.c
|
||||||
|
|
||||||
|
|
1
tools/binman/test/u_boot_binman_syms_x86.c
Symbolic link
1
tools/binman/test/u_boot_binman_syms_x86.c
Symbolic link
|
@ -0,0 +1 @@
|
||||||
|
u_boot_binman_syms.c
|
30
tools/binman/test/u_boot_binman_syms_x86.lds
Normal file
30
tools/binman/test/u_boot_binman_syms_x86.lds
Normal file
|
@ -0,0 +1,30 @@
|
||||||
|
/* SPDX-License-Identifier: GPL-2.0+ */
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2016 Google, Inc
|
||||||
|
*/
|
||||||
|
|
||||||
|
OUTPUT_FORMAT("elf32-i386", "elf32-i386", "elf32-i386")
|
||||||
|
OUTPUT_ARCH(i386)
|
||||||
|
ENTRY(_start)
|
||||||
|
|
||||||
|
SECTIONS
|
||||||
|
{
|
||||||
|
. = 0xffffff00;
|
||||||
|
_start = .;
|
||||||
|
|
||||||
|
. = ALIGN(4);
|
||||||
|
.text :
|
||||||
|
{
|
||||||
|
__image_copy_start = .;
|
||||||
|
*(.text*)
|
||||||
|
}
|
||||||
|
|
||||||
|
. = ALIGN(4);
|
||||||
|
.binman_sym_table : {
|
||||||
|
__binman_sym_start = .;
|
||||||
|
KEEP(*(SORT(.binman_sym*)));
|
||||||
|
__binman_sym_end = .;
|
||||||
|
}
|
||||||
|
.interp : { *(.interp*) }
|
||||||
|
|
||||||
|
}
|
Loading…
Add table
Add a link
Reference in a new issue