binman: add support for skipping file concatenation for mkimage

Some image types handled by mkimage require the datafiles to be passed
independently (-d data1:data2) for specific handling of each. A
concatenation of datafiles prior to passing them to mkimage wouldn't
work.

That is the case for rkspi for example which requires page alignment
and only writing 2KB every 4KB.

This adds the ability to tell binman to pass the datafiles without
prior concatenation to mkimage, by adding the multiple-data-files
boolean property to the mkimage node.

Cc: Quentin Schulz <foss+uboot@0leil.net>
Signed-off-by: Quentin Schulz <quentin.schulz@theobroma-systems.com>
Reviewed-by: Simon Glass <sjg@chromium.org>
This commit is contained in:
Quentin Schulz 2022-09-02 15:10:48 +02:00 committed by Kever Yang
parent 7a81a44caf
commit 4d91df0548
5 changed files with 125 additions and 4 deletions

View File

@ -1175,6 +1175,9 @@ Properties / Entry arguments:
- args: Arguments to pass
- data-to-imagename: Indicates that the -d data should be passed in as
the image name also (-n)
- multiple-data-files: boolean to tell binman to pass all files as
datafiles to mkimage instead of creating a temporary file the result
of datafiles concatenation
The data passed to mkimage via the -d flag is collected from subnodes of the
mkimage node, e.g.::
@ -1205,6 +1208,25 @@ a section, or just multiple subnodes like this::
};
};
To pass all datafiles untouched to mkimage::
mkimage {
args = "-n rk3399 -T rkspi";
multiple-data-files;
u-boot-tpl {
};
u-boot-spl {
};
};
This calls mkimage to create a Rockchip RK3399-specific first stage
bootloader, made of TPL+SPL. Since this first stage bootloader requires to
align the TPL and SPL but also some weird hacks that is handled by mkimage
directly, binman is told to not perform the concatenation of datafiles prior
to passing the data to mkimage.
To use CONFIG options in the arguments, use a string list instead, as in
this example which also produces four arguments::

View File

@ -18,6 +18,9 @@ class Entry_mkimage(Entry):
- args: Arguments to pass
- data-to-imagename: Indicates that the -d data should be passed in as
the image name also (-n)
- multiple-data-files: boolean to tell binman to pass all files as
datafiles to mkimage instead of creating a temporary file the result
of datafiles concatenation
The data passed to mkimage via the -d flag is collected from subnodes of the
mkimage node, e.g.::
@ -51,6 +54,25 @@ class Entry_mkimage(Entry):
Note that binman places the contents (here SPL and TPL) into a single file
and passes that to mkimage using the -d option.
To pass all datafiles untouched to mkimage::
mkimage {
args = "-n rk3399 -T rkspi";
multiple-data-files;
u-boot-tpl {
};
u-boot-spl {
};
};
This calls mkimage to create a Rockchip RK3399-specific first stage
bootloader, made of TPL+SPL. Since this first stage bootloader requires to
align the TPL and SPL but also some weird hacks that is handled by mkimage
directly, binman is told to not perform the concatenation of datafiles prior
to passing the data to mkimage.
To use CONFIG options in the arguments, use a string list instead, as in
this example which also produces four arguments::
@ -96,6 +118,7 @@ class Entry_mkimage(Entry):
"""
def __init__(self, section, etype, node):
super().__init__(section, etype, node)
self._multiple_data_files = fdt_util.GetBool(self._node, 'multiple-data-files')
self._mkimage_entries = OrderedDict()
self._imagename = None
self.align_default = None
@ -122,10 +145,20 @@ class Entry_mkimage(Entry):
def ObtainContents(self):
# Use a non-zero size for any fake files to keep mkimage happy
# Note that testMkimageImagename() relies on this 'mkimage' parameter
data, input_fname, uniq = self.collect_contents_to_file(
self._mkimage_entries.values(), 'mkimage', 1024)
if data is None:
return False
fake_size = 1024
if self._multiple_data_files:
fnames = []
uniq = self.GetUniqueName()
for entry in self._mkimage_entries.values():
if not entry.ObtainContents(fake_size=fake_size):
return False
fnames.append(tools.get_input_filename(entry.GetDefaultFilename()))
input_fname = ":".join(fnames)
else:
data, input_fname, uniq = self.collect_contents_to_file(
self._mkimage_entries.values(), 'mkimage', fake_size)
if data is None:
return False
if self._imagename:
image_data, imagename_fname, _ = self.collect_contents_to_file(
[self._imagename], 'mkimage-n', 1024)

View File

@ -5898,6 +5898,29 @@ fdt fdtmap Extract the devicetree blob from the fdtmap
self.assertIn("Node '/binman/u-boot-dtb': The zstd compression "
"requires a length header", str(e.exception))
def testMkimageMultipleDataFiles(self):
"""Test passing multiple files to mkimage in a mkimage entry"""
data = self._DoReadFile('252_mkimage_mult_data.dts')
# Size of files are packed in their 4B big-endian format
expect = struct.pack('>I', len(U_BOOT_TPL_DATA))
expect += struct.pack('>I', len(U_BOOT_SPL_DATA))
# Size info is always followed by a 4B zero value.
expect += tools.get_bytes(0, 4)
expect += U_BOOT_TPL_DATA
# All but last files are 4B-aligned
align_pad = len(U_BOOT_TPL_DATA) % 4
if align_pad:
expect += tools.get_bytes(0, align_pad)
expect += U_BOOT_SPL_DATA
self.assertEqual(expect, data[-len(expect):])
def testMkimageMultipleNoContent(self):
"""Test passing multiple data files to mkimage with one data file having no content"""
with self.assertRaises(ValueError) as exc:
self._DoReadFile('253_mkimage_mult_no_content.dts')
self.assertIn('Could not complete processing of contents',
str(exc.exception))
if __name__ == "__main__":
unittest.main()

View File

@ -0,0 +1,21 @@
// SPDX-License-Identifier: GPL-2.0+
/dts-v1/;
/ {
#address-cells = <1>;
#size-cells = <1>;
binman {
mkimage {
args = "-T script";
multiple-data-files;
u-boot-tpl {
};
u-boot-spl {
};
};
};
};

View File

@ -0,0 +1,22 @@
// SPDX-License-Identifier: GPL-2.0+
/dts-v1/;
/ {
#address-cells = <1>;
#size-cells = <1>;
binman {
mkimage {
args = "-T script";
multiple-data-files;
_testing {
return-unknown-contents;
};
u-boot-spl {
};
};
};
};