binman: Support writing symbols inside a mkimage image

Add support for writing symbols and determining the assumed position of
binaries inside a mkimage image. This is useful as an example for other
entry types which might want to do the same thing.

Signed-off-by: Simon Glass <sjg@chromium.org>
This commit is contained in:
Simon Glass 2023-07-18 07:24:08 -06:00
parent 696f2b73d6
commit 23b96e920b
4 changed files with 127 additions and 2 deletions

View File

@ -1314,8 +1314,6 @@ features to produce new behaviours.
"""
data = b''
for entry in entries:
# First get the input data and put it in a file
entry.ObtainContents(fake_size=fake_size)
data += entry.GetData()
uniq = self.GetUniqueName()
fname = tools.get_output_filename(f'{prefix}.{uniq}')

View File

@ -218,3 +218,39 @@ class Entry_mkimage(Entry_section):
def CheckEntries(self):
pass
def ProcessContents(self):
# The blob may have changed due to WriteSymbols()
ok = super().ProcessContents()
data = self.BuildSectionData(True)
ok2 = self.ProcessContentsUpdate(data)
return ok and ok2
def SetImagePos(self, image_pos):
"""Set the position in the image
This sets each subentry's offsets, sizes and positions-in-image
according to where they ended up in the packed mkimage file.
NOTE: This assumes a legacy mkimage and assumes that the images are
written to the output in order. SoC-specific mkimage handling may not
conform to this, in which case these values may be wrong.
Args:
image_pos (int): Position of this entry in the image
"""
# The mkimage header consists of 0x40 bytes, following by a table of
# offsets for each file
upto = 0x40
# Skip the 0-terminated list of offsets (assume a single image)
upto += 4 + 4
for entry in self.GetEntries().values():
entry.SetOffsetSize(upto, None)
# Give up if any entries lack a size
if entry.size is None:
return
upto += entry.size
super().SetImagePos(image_pos)

View File

@ -6820,6 +6820,70 @@ fdt fdtmap Extract the devicetree blob from the fdtmap
second = U_BOOT_DATA + b'#' + VGA_DATA + U_BOOT_DTB_DATA
self.assertEqual(U_BOOT_IMG_DATA + first + second + first, data)
def testMkimageSymbols(self):
"""Test using mkimage to build an image with symbols in it"""
self._SetupSplElf('u_boot_binman_syms')
data = self._DoReadFile('290_mkimage_sym.dts')
image = control.images['image']
entries = image.GetEntries()
self.assertIn('u-boot', entries)
u_boot = entries['u-boot']
mkim = entries['mkimage']
mkim_entries = mkim.GetEntries()
self.assertIn('u-boot-spl', mkim_entries)
spl = mkim_entries['u-boot-spl']
self.assertIn('u-boot-spl2', mkim_entries)
spl2 = mkim_entries['u-boot-spl2']
# skip the mkimage header and the area sizes
mk_data = data[mkim.offset + 0x40:]
size, term = struct.unpack('>LL', mk_data[:8])
# There should be only one image, so check that the zero terminator is
# present
self.assertEqual(0, term)
content = mk_data[8:8 + size]
# 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
spl_data = content[:0x18]
content = content[0x1b:]
# After the header is a table of offsets for each image. There should
# only be one image, then a 0 terminator, so figure out the real start
# of the image data
base = 0x40 + 8
# Check symbols in both u-boot-spl and u-boot-spl2
for i in range(2):
vals = struct.unpack('<LLQLL', spl_data)
# 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 'u_boot_binman_syms' test image
self.assertEqual(elf.BINMAN_SYM_MAGIC_VALUE, vals[0])
self.assertEqual(base, vals[1])
self.assertEqual(spl2.offset, vals[2])
# figure out the internal positions of its components
self.assertEqual(0x10 + u_boot.image_pos, vals[3])
# Check that spl and spl2 are actually at the indicated positions
self.assertEqual(
elf.BINMAN_SYM_MAGIC_VALUE,
struct.unpack('<I', data[spl.image_pos:spl.image_pos + 4])[0])
self.assertEqual(
elf.BINMAN_SYM_MAGIC_VALUE,
struct.unpack('<I', data[spl2.image_pos:spl2.image_pos + 4])[0])
self.assertEqual(len(U_BOOT_DATA), vals[4])
# Move to next
spl_data = content[:0x18]
if __name__ == "__main__":
unittest.main()

View File

@ -0,0 +1,27 @@
// SPDX-License-Identifier: GPL-2.0+
/dts-v1/;
/ {
#address-cells = <1>;
#size-cells = <1>;
binman {
u-boot-dtb {
};
mkimage {
args = "-n test -T script";
u-boot-spl {
};
u-boot-spl2 {
type = "u-boot-spl";
};
};
u-boot {
};
};
};