diff options
author | Tom Rini <trini@konsulko.com> | 2023-10-02 10:55:44 -0400 |
---|---|---|
committer | Tom Rini <trini@konsulko.com> | 2023-10-02 10:55:44 -0400 |
commit | ac897385bbfa30cfdfb62ccf24acfcd4b274b2ff (patch) | |
tree | ae567980737beb24ca24e2ee8cfeaf6eb9e26e3f /tools | |
parent | 4459ed60cb1e0562bc5b40405e2b4b9bbf766d57 (diff) | |
parent | e29b932aa07fa0226d325b35d96cd4eea0370129 (diff) | |
download | u-boot-ac897385bbfa30cfdfb62ccf24acfcd4b274b2ff.tar.gz u-boot-ac897385bbfa30cfdfb62ccf24acfcd4b274b2ff.tar.bz2 u-boot-ac897385bbfa30cfdfb62ccf24acfcd4b274b2ff.zip |
Merge branch 'next'
Signed-off-by: Tom Rini <trini@konsulko.com>
Diffstat (limited to 'tools')
27 files changed, 1064 insertions, 188 deletions
diff --git a/tools/Makefile b/tools/Makefile index 3d0c4b0dd6..1aa1e36137 100644 --- a/tools/Makefile +++ b/tools/Makefile @@ -123,6 +123,7 @@ dumpimage-mkimage-objs := aisimage.o \ pblimage.o \ pbl_crc32.o \ renesas_spkgimage.o \ + sfspl.o \ vybridimage.o \ stm32image.o \ $(ROCKCHIP_OBS) \ diff --git a/tools/binman/bintool.py b/tools/binman/bintool.py index 0b0f56dbbb..3c4ad1adbb 100644 --- a/tools/binman/bintool.py +++ b/tools/binman/bintool.py @@ -328,7 +328,7 @@ class Bintool: return result.stdout @classmethod - def build_from_git(cls, git_repo, make_target, bintool_path, flags=None): + def build_from_git(cls, git_repo, make_targets, bintool_path, flags=None): """Build a bintool from a git repo This clones the repo in a temporary directory, builds it with 'make', @@ -336,7 +336,8 @@ class Bintool: Args: git_repo (str): URL of git repo - make_target (str): Target to pass to 'make' to build the tool + make_targets (list of str): List of targets to pass to 'make' to build + the tool bintool_path (str): Relative path of the tool in the repo, after build is complete flags (list of str): Flags or variables to pass to make, or None @@ -350,12 +351,14 @@ class Bintool: tmpdir = tempfile.mkdtemp(prefix='binmanf.') print(f"- clone git repo '{git_repo}' to '{tmpdir}'") tools.run('git', 'clone', '--depth', '1', git_repo, tmpdir) - print(f"- build target '{make_target}'") - cmd = ['make', '-C', tmpdir, '-j', f'{multiprocessing.cpu_count()}', - make_target] - if flags: - cmd += flags - tools.run(*cmd) + for target in make_targets: + print(f"- build target '{target}'") + cmd = ['make', '-C', tmpdir, '-j', f'{multiprocessing.cpu_count()}', + target] + if flags: + cmd += flags + tools.run(*cmd) + fname = os.path.join(tmpdir, bintool_path) if not os.path.exists(fname): print(f"- File '{fname}' was not produced") diff --git a/tools/binman/btool/mkeficapsule.py b/tools/binman/btool/mkeficapsule.py new file mode 100644 index 0000000000..61179747ff --- /dev/null +++ b/tools/binman/btool/mkeficapsule.py @@ -0,0 +1,101 @@ +# SPDX-License-Identifier: GPL-2.0+ +# Copyright 2023 Linaro Limited +# +"""Bintool implementation for mkeficapsule tool + +mkeficapsule is a tool used for generating EFI capsules. + +The following are the commandline options to be provided +to the tool +Usage: mkeficapsule [options] <image blob> <output file> +Options: + -g, --guid <guid string> guid for image blob type + -i, --index <index> update image index + -I, --instance <instance> update hardware instance + -v, --fw-version <version> firmware version + -p, --private-key <privkey file> private key file + -c, --certificate <cert file> signer's certificate file + -m, --monotonic-count <count> monotonic count + -d, --dump_sig dump signature (*.p7) + -A, --fw-accept firmware accept capsule, requires GUID, no image blob + -R, --fw-revert firmware revert capsule, takes no GUID, no image blob + -o, --capoemflag Capsule OEM Flag, an integer between 0x0000 and 0xffff + -h, --help print a help message +""" + +from binman import bintool + +class Bintoolmkeficapsule(bintool.Bintool): + """Handles the 'mkeficapsule' tool + + This bintool is used for generating the EFI capsules. The + capsule generation parameters can either be specified through + commandline, or through a config file. + """ + def __init__(self, name): + super().__init__(name, 'mkeficapsule tool for generating capsules') + + def generate_capsule(self, image_index, image_guid, hardware_instance, + payload, output_fname, priv_key, pub_key, + monotonic_count=0, version=0, oemflags=0): + """Generate a capsule through commandline-provided parameters + + Args: + image_index (int): Unique number for identifying payload image + image_guid (str): GUID used for identifying the image + hardware_instance (int): Optional unique hardware instance of + a device in the system. 0 if not being used + payload (str): Path to the input payload image + output_fname (str): Path to the output capsule file + priv_key (str): Path to the private key + pub_key(str): Path to the public key + monotonic_count (int): Count used when signing an image + version (int): Image version (Optional) + oemflags (int): Optional 16 bit OEM flags + + Returns: + str: Tool output + """ + args = [ + f'--index={image_index}', + f'--guid={image_guid}', + f'--instance={hardware_instance}' + ] + + if version: + args += [f'--fw-version={version}'] + if oemflags: + args += [f'--capoemflag={oemflags}'] + if priv_key and pub_key: + args += [ + f'--monotonic-count={monotonic_count}', + f'--private-key={priv_key}', + f'--certificate={pub_key}' + ] + + args += [ + payload, + output_fname + ] + + return self.run_cmd(*args) + + def fetch(self, method): + """Fetch handler for mkeficapsule + + This builds the tool from source + + Returns: + tuple: + str: Filename of fetched file to copy to a suitable directory + str: Name of temp directory to remove, or None + """ + if method != bintool.FETCH_BUILD: + return None + + cmd = ['tools-only_defconfig', 'tools'] + result = self.build_from_git( + 'https://source.denx.de/u-boot/u-boot.git', + cmd, + 'tools/mkeficapsule') + return result diff --git a/tools/binman/entries.rst b/tools/binman/entries.rst index e7dfe6b2a3..801bd94674 100644 --- a/tools/binman/entries.rst +++ b/tools/binman/entries.rst @@ -468,6 +468,70 @@ updating the EC on startup via software sync. +.. _etype_efi_capsule: + +Entry: capsule: Entry for generating EFI Capsule files +------------------------------------------------------ + +The parameters needed for generation of the capsules can be provided +as properties in the entry. + +Properties / Entry arguments: + - image-index: Unique number for identifying corresponding + payload image. Number between 1 and descriptor count, i.e. + the total number of firmware images that can be updated. Mandatory + property. + - image-guid: Image GUID which will be used for identifying the + updatable image on the board. Mandatory property. + - hardware-instance: Optional number for identifying unique + hardware instance of a device in the system. Default value of 0 + for images where value is not to be used. + - fw-version: Value of image version that can be put on the capsule + through the Firmware Management Protocol(FMP) header. + - monotonic-count: Count used when signing an image. + - private-key: Path to PEM formatted .key private key file. Mandatory + property for generating signed capsules. + - public-key-cert: Path to PEM formatted .crt public key certificate + file. Mandatory property for generating signed capsules. + - oem-flags - OEM flags to be passed through capsule header. + + Since this is a subclass of Entry_section, all properties of the parent + class also apply here. Except for the properties stated as mandatory, the + rest of the properties are optional. + +For more details on the description of the capsule format, and the capsule +update functionality, refer Section 8.5 and Chapter 23 in the `UEFI +specification`_. + +The capsule parameters like image index and image GUID are passed as +properties in the entry. The payload to be used in the capsule is to be +provided as a subnode of the capsule entry. + +A typical capsule entry node would then look something like this:: + + capsule { + type = "efi-capsule"; + image-index = <0x1>; + /* Image GUID for testing capsule update */ + image-guid = SANDBOX_UBOOT_IMAGE_GUID; + hardware-instance = <0x0>; + private-key = "path/to/the/private/key"; + public-key-cert = "path/to/the/public-key-cert"; + oem-flags = <0x8000>; + + u-boot { + }; + }; + +In the above example, the capsule payload is the U-Boot image. The +capsule entry would read the contents of the payload and put them +into the capsule. Any external file can also be specified as the +payload using the blob-ext subnode. + +.. _`UEFI specification`: https://uefi.org/sites/default/files/resources/UEFI_Spec_2_10_Aug29.pdf + + + .. _etype_encrypted: Entry: encrypted: Externally built encrypted binary blob diff --git a/tools/binman/etype/efi_capsule.py b/tools/binman/etype/efi_capsule.py new file mode 100644 index 0000000000..006eb630ad --- /dev/null +++ b/tools/binman/etype/efi_capsule.py @@ -0,0 +1,143 @@ +# SPDX-License-Identifier: GPL-2.0+ +# Copyright (c) 2023 Linaro Limited +# +# Entry-type module for producing a EFI capsule +# + +import os + +from binman.entry import Entry +from binman.etype.section import Entry_section +from dtoc import fdt_util +from u_boot_pylib import tools + +class Entry_efi_capsule(Entry_section): + """Generate EFI capsules + + The parameters needed for generation of the capsules can + be provided as properties in the entry. + + Properties / Entry arguments: + - image-index: Unique number for identifying corresponding + payload image. Number between 1 and descriptor count, i.e. + the total number of firmware images that can be updated. Mandatory + property. + - image-guid: Image GUID which will be used for identifying the + updatable image on the board. Mandatory property. + - hardware-instance: Optional number for identifying unique + hardware instance of a device in the system. Default value of 0 + for images where value is not to be used. + - fw-version: Value of image version that can be put on the capsule + through the Firmware Management Protocol(FMP) header. + - monotonic-count: Count used when signing an image. + - private-key: Path to PEM formatted .key private key file. Mandatory + property for generating signed capsules. + - public-key-cert: Path to PEM formatted .crt public key certificate + file. Mandatory property for generating signed capsules. + - oem-flags - OEM flags to be passed through capsule header. + + Since this is a subclass of Entry_section, all properties of the parent + class also apply here. Except for the properties stated as mandatory, the + rest of the properties are optional. + + For more details on the description of the capsule format, and the capsule + update functionality, refer Section 8.5 and Chapter 23 in the `UEFI + specification`_. + + The capsule parameters like image index and image GUID are passed as + properties in the entry. The payload to be used in the capsule is to be + provided as a subnode of the capsule entry. + + A typical capsule entry node would then look something like this + + capsule { + type = "efi-capsule"; + image-index = <0x1>; + /* Image GUID for testing capsule update */ + image-guid = SANDBOX_UBOOT_IMAGE_GUID; + hardware-instance = <0x0>; + private-key = "path/to/the/private/key"; + public-key-cert = "path/to/the/public-key-cert"; + oem-flags = <0x8000>; + + u-boot { + }; + }; + + In the above example, the capsule payload is the U-Boot image. The + capsule entry would read the contents of the payload and put them + into the capsule. Any external file can also be specified as the + payload using the blob-ext subnode. + + .. _`UEFI specification`: https://uefi.org/sites/default/files/resources/UEFI_Spec_2_10_Aug29.pdf + """ + def __init__(self, section, etype, node): + super().__init__(section, etype, node) + self.required_props = ['image-index', 'image-guid'] + self.image_index = 0 + self.image_guid = '' + self.hardware_instance = 0 + self.monotonic_count = 0 + self.fw_version = 0 + self.oem_flags = 0 + self.private_key = '' + self.public_key_cert = '' + self.auth = 0 + + def ReadNode(self): + super().ReadNode() + + self.image_index = fdt_util.GetInt(self._node, 'image-index') + self.image_guid = fdt_util.GetString(self._node, 'image-guid') + self.fw_version = fdt_util.GetInt(self._node, 'fw-version') + self.hardware_instance = fdt_util.GetInt(self._node, 'hardware-instance') + self.monotonic_count = fdt_util.GetInt(self._node, 'monotonic-count') + self.oem_flags = fdt_util.GetInt(self._node, 'oem-flags') + + self.private_key = fdt_util.GetString(self._node, 'private-key') + self.public_key_cert = fdt_util.GetString(self._node, 'public-key-cert') + if ((self.private_key and not self.public_key_cert) or (self.public_key_cert and not self.private_key)): + self.Raise('Both private key and public key certificate need to be provided') + elif not (self.private_key and self.public_key_cert): + self.auth = 0 + else: + self.auth = 1 + + def BuildSectionData(self, required): + def get_binman_test_guid(type_str): + TYPE_TO_GUID = { + 'binman-test' : '09d7cf52-0720-4710-91d1-08469b7fe9c8' + } + return TYPE_TO_GUID[type_str] + + private_key = '' + public_key_cert = '' + if self.auth: + if not os.path.isabs(self.private_key): + private_key = tools.get_input_filename(self.private_key) + if not os.path.isabs(self.public_key_cert): + public_key_cert = tools.get_input_filename(self.public_key_cert) + data, payload, uniq = self.collect_contents_to_file( + self._entries.values(), 'capsule_in') + outfile = self._filename if self._filename else 'capsule.%s' % uniq + capsule_fname = tools.get_output_filename(outfile) + guid = self.image_guid + if self.image_guid == "binman-test": + guid = get_binman_test_guid('binman-test') + + ret = self.mkeficapsule.generate_capsule(self.image_index, + guid, + self.hardware_instance, + payload, + capsule_fname, + private_key, + public_key_cert, + self.monotonic_count, + self.fw_version, + self.oem_flags) + if ret is not None: + os.remove(payload) + return tools.read_file(capsule_fname) + + def AddBintools(self, btools): + self.mkeficapsule = self.AddBintool(btools, 'mkeficapsule') diff --git a/tools/binman/ftest.py b/tools/binman/ftest.py index 1293e9dbf4..8e419645a6 100644 --- a/tools/binman/ftest.py +++ b/tools/binman/ftest.py @@ -48,6 +48,7 @@ U_BOOT_VPL_DATA = b'vpl76543210fedcbazywxyz_' BLOB_DATA = b'89' ME_DATA = b'0abcd' VGA_DATA = b'vga' +EFI_CAPSULE_DATA = b'efi' U_BOOT_DTB_DATA = b'udtb' U_BOOT_SPL_DTB_DATA = b'spldtb' U_BOOT_TPL_DTB_DATA = b'tpldtb' @@ -119,6 +120,11 @@ COMP_BINTOOLS = ['bzip2', 'gzip', 'lz4', 'lzma_alone', 'lzop', 'xz', 'zstd'] TEE_ADDR = 0x5678 +# Firmware Management Protocol(FMP) GUID +FW_MGMT_GUID = 'edd5cb6d2de8444cbda17194199ad92a' +# Image GUID specified in the DTS +CAPSULE_IMAGE_GUID = '52cfd7092007104791d108469b7fe9c8' + class TestFunctional(unittest.TestCase): """Functional tests for binman @@ -215,6 +221,7 @@ class TestFunctional(unittest.TestCase): TestFunctional._MakeInputFile('scp.bin', SCP_DATA) TestFunctional._MakeInputFile('rockchip-tpl.bin', ROCKCHIP_TPL_DATA) TestFunctional._MakeInputFile('ti_unsecure.bin', TI_UNSECURE_DATA) + TestFunctional._MakeInputFile('capsule_input.bin', EFI_CAPSULE_DATA) # Add a few .dtb files for testing TestFunctional._MakeInputFile('%s/test-fdt1.dtb' % TEST_FDT_SUBDIR, @@ -7216,5 +7223,116 @@ fdt fdtmap Extract the devicetree blob from the fdtmap self.assertRegex(err, "Image 'image'.*missing bintools.*: bootgen") + def _CheckCapsule(self, data, signed_capsule=False, version_check=False, + capoemflags=False): + fmp_signature = "4d535331" # 'M', 'S', 'S', '1' + fmp_size = "10" + fmp_fw_version = "02" + oemflag = "0080" + + payload_data = EFI_CAPSULE_DATA + + # TODO - Currently, these offsets for capsule fields are hardcoded. + # There are plans to add support to the mkeficapsule tool to dump + # the capsule contents which can then be used for capsule + # verification. + + # Firmware Management Protocol(FMP) GUID - offset(0 - 32) + self.assertEqual(FW_MGMT_GUID, data.hex()[:32]) + # Image GUID - offset(96 - 128) + self.assertEqual(CAPSULE_IMAGE_GUID, data.hex()[96:128]) + + if capoemflags: + # OEM Flags - offset(40 - 44) + self.assertEqual(oemflag, data.hex()[40:44]) + if signed_capsule and version_check: + # FMP header signature - offset(4770 - 4778) + self.assertEqual(fmp_signature, data.hex()[4770:4778]) + # FMP header size - offset(4778 - 4780) + self.assertEqual(fmp_size, data.hex()[4778:4780]) + # firmware version - offset(4786 - 4788) + self.assertEqual(fmp_fw_version, data.hex()[4786:4788]) + # payload offset signed capsule(4802 - 4808) + self.assertEqual(payload_data.hex(), data.hex()[4802:4808]) + elif signed_capsule: + # payload offset signed capsule(4770 - 4776) + self.assertEqual(payload_data.hex(), data.hex()[4770:4776]) + elif version_check: + # FMP header signature - offset(184 - 192) + self.assertEqual(fmp_signature, data.hex()[184:192]) + # FMP header size - offset(192 - 194) + self.assertEqual(fmp_size, data.hex()[192:194]) + # firmware version - offset(200 - 202) + self.assertEqual(fmp_fw_version, data.hex()[200:202]) + # payload offset for non-signed capsule with version header(216 - 222) + self.assertEqual(payload_data.hex(), data.hex()[216:222]) + else: + # payload offset for non-signed capsule with no version header(184 - 190) + self.assertEqual(payload_data.hex(), data.hex()[184:190]) + + def testCapsuleGen(self): + """Test generation of EFI capsule""" + data = self._DoReadFile('311_capsule.dts') + + self._CheckCapsule(data) + + def testSignedCapsuleGen(self): + """Test generation of EFI capsule""" + data = tools.read_file(self.TestFile("key.key")) + self._MakeInputFile("key.key", data) + data = tools.read_file(self.TestFile("key.pem")) + self._MakeInputFile("key.crt", data) + + data = self._DoReadFile('312_capsule_signed.dts') + + self._CheckCapsule(data, signed_capsule=True) + + def testCapsuleGenVersionSupport(self): + """Test generation of EFI capsule with version support""" + data = self._DoReadFile('313_capsule_version.dts') + + self._CheckCapsule(data, version_check=True) + + def testCapsuleGenSignedVer(self): + """Test generation of signed EFI capsule with version information""" + data = tools.read_file(self.TestFile("key.key")) + self._MakeInputFile("key.key", data) + data = tools.read_file(self.TestFile("key.pem")) + self._MakeInputFile("key.crt", data) + + data = self._DoReadFile('314_capsule_signed_ver.dts') + + self._CheckCapsule(data, signed_capsule=True, version_check=True) + + def testCapsuleGenCapOemFlags(self): + """Test generation of EFI capsule with OEM Flags set""" + data = self._DoReadFile('315_capsule_oemflags.dts') + + self._CheckCapsule(data, capoemflags=True) + + def testCapsuleGenKeyMissing(self): + """Test that binman errors out on missing key""" + with self.assertRaises(ValueError) as e: + self._DoReadFile('316_capsule_missing_key.dts') + + self.assertIn("Both private key and public key certificate need to be provided", + str(e.exception)) + + def testCapsuleGenIndexMissing(self): + """Test that binman errors out on missing image index""" + with self.assertRaises(ValueError) as e: + self._DoReadFile('317_capsule_missing_index.dts') + + self.assertIn("entry is missing properties: image-index", + str(e.exception)) + + def testCapsuleGenGuidMissing(self): + """Test that binman errors out on missing image GUID""" + with self.assertRaises(ValueError) as e: + self._DoReadFile('318_capsule_missing_guid.dts') + + self.assertIn("entry is missing properties: image-guid", + str(e.exception)) + if __name__ == "__main__": unittest.main() diff --git a/tools/binman/test/311_capsule.dts b/tools/binman/test/311_capsule.dts new file mode 100644 index 0000000000..8eb4250b14 --- /dev/null +++ b/tools/binman/test/311_capsule.dts @@ -0,0 +1,21 @@ +// SPDX-License-Identifier: GPL-2.0+ + +/dts-v1/; + +/ { + #address-cells = <1>; + #size-cells = <1>; + + binman { + efi-capsule { + image-index = <0x1>; + /* Image GUID for testing capsule update */ + image-guid = "binman-test"; + hardware-instance = <0x0>; + + blob { + filename = "capsule_input.bin"; + }; + }; + }; +}; diff --git a/tools/binman/test/312_capsule_signed.dts b/tools/binman/test/312_capsule_signed.dts new file mode 100644 index 0000000000..d1c76e269c --- /dev/null +++ b/tools/binman/test/312_capsule_signed.dts @@ -0,0 +1,23 @@ +// SPDX-License-Identifier: GPL-2.0+ + +/dts-v1/; + +/ { + #address-cells = <1>; + #size-cells = <1>; + + binman { + efi-capsule { + image-index = <0x1>; + /* Image GUID for testing capsule update */ + image-guid = "binman-test"; + hardware-instance = <0x0>; + private-key = "key.key"; + public-key-cert = "key.crt"; + + blob { + filename = "capsule_input.bin"; + }; + }; + }; +}; diff --git a/tools/binman/test/313_capsule_version.dts b/tools/binman/test/313_capsule_version.dts new file mode 100644 index 0000000000..bafef3609e --- /dev/null +++ b/tools/binman/test/313_capsule_version.dts @@ -0,0 +1,22 @@ +// SPDX-License-Identifier: GPL-2.0+ + +/dts-v1/; + +/ { + #address-cells = <1>; + #size-cells = <1>; + + binman { + efi-capsule { + image-index = <0x1>; + fw-version = <0x2>; + /* Image GUID for testing capsule update */ + image-guid = "binman-test"; + hardware-instance = <0x0>; + + blob { + filename = "capsule_input.bin"; + }; + }; + }; +}; diff --git a/tools/binman/test/314_capsule_signed_ver.dts b/tools/binman/test/314_capsule_signed_ver.dts new file mode 100644 index 0000000000..85c784bba4 --- /dev/null +++ b/tools/binman/test/314_capsule_signed_ver.dts @@ -0,0 +1,24 @@ +// SPDX-License-Identifier: GPL-2.0+ + +/dts-v1/; + +/ { + #address-cells = <1>; + #size-cells = <1>; + + binman { + efi-capsule { + image-index = <0x1>; + fw-version = <0x2>; + /* Image GUID for testing capsule update */ + image-guid = "binman-test"; + hardware-instance = <0x0>; + private-key = "key.key"; + public-key-cert = "key.crt"; + + blob { + filename = "capsule_input.bin"; + }; + }; + }; +}; diff --git a/tools/binman/test/315_capsule_oemflags.dts b/tools/binman/test/315_capsule_oemflags.dts new file mode 100644 index 0000000000..f736e8758f --- /dev/null +++ b/tools/binman/test/315_capsule_oemflags.dts @@ -0,0 +1,22 @@ +// SPDX-License-Identifier: GPL-2.0+ + +/dts-v1/; + +/ { + #address-cells = <1>; + #size-cells = <1>; + + binman { + efi-capsule { + image-index = <0x1>; + /* Image GUID for testing capsule update */ + image-guid = "binman-test"; + hardware-instance = <0x0>; + oem-flags = <0x8000>; + + blob { + filename = "capsule_input.bin"; + }; + }; + }; +}; diff --git a/tools/binman/test/316_capsule_missing_key.dts b/tools/binman/test/316_capsule_missing_key.dts new file mode 100644 index 0000000000..2080b50e3d --- /dev/null +++ b/tools/binman/test/316_capsule_missing_key.dts @@ -0,0 +1,22 @@ +// SPDX-License-Identifier: GPL-2.0+ + +/dts-v1/; + +/ { + #address-cells = <1>; + #size-cells = <1>; + + binman { + efi-capsule { + image-index = <0x1>; + /* Image GUID for testing capsule update */ + image-guid = "binman-test"; + hardware-instance = <0x0>; + private-key = "tools/binman/test/key.key"; + + blob { + filename = "capsule_input.bin"; + }; + }; + }; +}; diff --git a/tools/binman/test/317_capsule_missing_index.dts b/tools/binman/test/317_capsule_missing_index.dts new file mode 100644 index 0000000000..aadb61f647 --- /dev/null +++ b/tools/binman/test/317_capsule_missing_index.dts @@ -0,0 +1,20 @@ +// SPDX-License-Identifier: GPL-2.0+ + +/dts-v1/; + +/ { + #address-cells = <1>; + #size-cells = <1>; + + binman { + efi-capsule { + /* Image GUID for testing capsule update */ + image-guid = "binman-test"; + hardware-instance = <0x0>; + + blob { + filename = "capsule_input.bin"; + }; + }; + }; +}; diff --git a/tools/binman/test/318_capsule_missing_guid.dts b/tools/binman/test/318_capsule_missing_guid.dts new file mode 100644 index 0000000000..d76afba853 --- /dev/null +++ b/tools/binman/test/318_capsule_missing_guid.dts @@ -0,0 +1,19 @@ +// SPDX-License-Identifier: GPL-2.0+ + +/dts-v1/; + +/ { + #address-cells = <1>; + #size-cells = <1>; + + binman { + efi-capsule { + image-index = <0x1>; + hardware-instance = <0x0>; + + blob { + filename = "capsule_input.bin"; + }; + }; + }; +}; diff --git a/tools/buildman/boards.py b/tools/buildman/boards.py index eef3f19f7a..341a5056df 100644 --- a/tools/buildman/boards.py +++ b/tools/buildman/boards.py @@ -19,6 +19,7 @@ import time from buildman import board from buildman import kconfiglib +from u_boot_pylib.terminal import print_clear, tprint ### constant variables ### OUTPUT_FILE = 'boards.cfg' @@ -863,11 +864,19 @@ class Boards: Returns: bool: True if all is well, False if there were warnings """ - if not force and output_is_new(output, CONFIG_DIR, '.'): + if not force: if not quiet: - print(f'{output} is up to date. Nothing to do.') - return True + tprint('\rChecking for Kconfig changes...', newline=False) + is_new = output_is_new(output, CONFIG_DIR, '.') + print_clear() + if is_new: + if not quiet: + print(f'{output} is up to date. Nothing to do.') + return True + if not quiet: + tprint('\rGenerating board list...', newline=False) params_list, warnings = self.build_board_list(CONFIG_DIR, '.', jobs) + print_clear() for warn in warnings: print(warn, file=sys.stderr) self.format_and_output(params_list, output) diff --git a/tools/buildman/builder.py b/tools/buildman/builder.py index ecbd368c47..5305477c5b 100644 --- a/tools/buildman/builder.py +++ b/tools/buildman/builder.py @@ -328,7 +328,7 @@ class Builder: self._build_period_us = None self._complete_delay = None self._next_delay_update = datetime.now() - self._start_time = datetime.now() + self._start_time = None self._step = step self._error_lines = 0 self.no_subdirs = no_subdirs @@ -1778,6 +1778,7 @@ class Builder: self._prepare_output_space() if not self._ide: tprint('\rStarting build...', newline=False) + self._start_time = datetime.now() self.setup_build(board_selected, commits) self.process_result(None) self.thread_exceptions = [] diff --git a/tools/buildman/builderthread.py b/tools/buildman/builderthread.py index 25f460c207..6a61f64da1 100644 --- a/tools/buildman/builderthread.py +++ b/tools/buildman/builderthread.py @@ -23,6 +23,9 @@ from u_boot_pylib import command RETURN_CODE_RETRY = -1 BASE_ELF_FILENAMES = ['u-boot', 'spl/u-boot-spl', 'tpl/u-boot-tpl'] +# Common extensions for images +COMMON_EXTS = ['.bin', '.rom', '.itb', '.img'] + def mkdir(dirname, parents=False): """Make a directory if it doesn't already exist. @@ -636,10 +639,11 @@ class BuilderThread(threading.Thread): # Now write the actual build output if keep_outputs: - copy_files( - result.out_dir, build_dir, '', - ['u-boot*', '*.bin', '*.map', '*.img', 'MLO', 'SPL', - 'include/autoconf.mk', 'spl/u-boot-spl*']) + to_copy = ['u-boot*', '*.map', 'MLO', 'SPL', + 'include/autoconf.mk', 'spl/u-boot-spl*', + 'tpl/u-boot-tpl*', 'vpl/u-boot-vpl*'] + to_copy += [f'*{ext}' for ext in COMMON_EXTS] + copy_files(result.out_dir, build_dir, '', to_copy) def _send_result(self, result): """Send a result to the builder for processing diff --git a/tools/buildman/control.py b/tools/buildman/control.py index f2ffb7f5b4..8f6850c521 100644 --- a/tools/buildman/control.py +++ b/tools/buildman/control.py @@ -621,7 +621,8 @@ def do_buildman(args, toolchains=None, make_func=None, brds=None, if not brds: brds = get_boards_obj(output_dir, args.regen_board_list, args.maintainer_check, args.full_check, - args.threads, args.verbose) + args.threads, args.verbose and + not args.print_arch and not args.print_prefix) if isinstance(brds, int): return brds diff --git a/tools/buildman/toolchain.py b/tools/buildman/toolchain.py index b05001194e..79c7c11a11 100644 --- a/tools/buildman/toolchain.py +++ b/tools/buildman/toolchain.py @@ -499,7 +499,7 @@ class Toolchains: if arch == 'aarch64': arch = 'arm64' base = 'https://www.kernel.org/pub/tools/crosstool/files/bin' - versions = ['13.1.0', '12.2.0'] + versions = ['13.2.0', '12.2.0'] links = [] for version in versions: url = '%s/%s/%s/' % (base, arch, version) diff --git a/tools/default_image.c b/tools/default_image.c index 0e49ab3301..04bc85bf93 100644 --- a/tools/default_image.c +++ b/tools/default_image.c @@ -15,7 +15,6 @@ #include "imagetool.h" #include "mkimage.h" -#include <u-boot/crc.h> #include <image.h> #include <tee/optee.h> diff --git a/tools/docker/Dockerfile b/tools/docker/Dockerfile index ff16829887..c4a2596b48 100644 --- a/tools/docker/Dockerfile +++ b/tools/docker/Dockerfile @@ -2,7 +2,7 @@ # This Dockerfile is used to build an image containing basic stuff to be used # to build U-Boot and run our test suites. -FROM ubuntu:jammy-20230624 +FROM ubuntu:jammy-20230804 MAINTAINER Tom Rini <trini@konsulko.com> LABEL Description=" This image is for building U-Boot inside a container" @@ -14,19 +14,19 @@ RUN apt-get update && apt-get install -y gnupg2 wget xz-utils && rm -rf /var/lib RUN wget -O - https://apt.llvm.org/llvm-snapshot.gpg.key | apt-key add - RUN echo deb http://apt.llvm.org/jammy/ llvm-toolchain-jammy-16 main | tee /etc/apt/sources.list.d/llvm.list -# Manually install the kernel.org "Crosstool" based toolchains for gcc-13.1.0 -RUN wget -O - https://mirrors.edge.kernel.org/pub/tools/crosstool/files/bin/x86_64/13.1.0/x86_64-gcc-13.1.0-nolibc-aarch64-linux.tar.xz | tar -C /opt -xJ -RUN wget -O - https://mirrors.edge.kernel.org/pub/tools/crosstool/files/bin/x86_64/13.1.0/x86_64-gcc-13.1.0-nolibc-arc-linux.tar.xz | tar -C /opt -xJ -RUN wget -O - https://mirrors.edge.kernel.org/pub/tools/crosstool/files/bin/x86_64/13.1.0/x86_64-gcc-13.1.0-nolibc-arm-linux-gnueabi.tar.xz | tar -C /opt -xJ -RUN wget -O - https://mirrors.edge.kernel.org/pub/tools/crosstool/files/bin/x86_64/13.1.0/x86_64-gcc-13.1.0-nolibc-i386-linux.tar.xz | tar -C /opt -xJ -RUN wget -O - https://mirrors.edge.kernel.org/pub/tools/crosstool/files/bin/x86_64/13.1.0/x86_64-gcc-13.1.0-nolibc-m68k-linux.tar.xz | tar -C /opt -xJ -RUN wget -O - https://mirrors.edge.kernel.org/pub/tools/crosstool/files/bin/x86_64/13.1.0/x86_64-gcc-13.1.0-nolibc-mips-linux.tar.xz | tar -C /opt -xJ -RUN wget -O - https://mirrors.edge.kernel.org/pub/tools/crosstool/files/bin/x86_64/13.1.0/x86_64-gcc-13.1.0-nolibc-microblaze-linux.tar.xz | tar -C /opt -xJ -RUN wget -O - https://mirrors.edge.kernel.org/pub/tools/crosstool/files/bin/x86_64/13.1.0/x86_64-gcc-13.1.0-nolibc-nios2-linux.tar.xz | tar -C /opt -xJ -RUN wget -O - https://mirrors.edge.kernel.org/pub/tools/crosstool/files/bin/x86_64/13.1.0/x86_64-gcc-13.1.0-nolibc-powerpc-linux.tar.xz | tar -C /opt -xJ -RUN wget -O - https://mirrors.edge.kernel.org/pub/tools/crosstool/files/bin/x86_64/13.1.0/x86_64-gcc-13.1.0-nolibc-riscv64-linux.tar.xz | tar -C /opt -xJ -RUN wget -O - https://mirrors.edge.kernel.org/pub/tools/crosstool/files/bin/x86_64/13.1.0/x86_64-gcc-13.1.0-nolibc-riscv32-linux.tar.xz | tar -C /opt -xJ -RUN wget -O - https://mirrors.edge.kernel.org/pub/tools/crosstool/files/bin/x86_64/13.1.0/x86_64-gcc-13.1.0-nolibc-sh2-linux.tar.xz | tar -C /opt -xJ +# Manually install the kernel.org "Crosstool" based toolchains for gcc-13.2.0 +RUN wget -O - https://mirrors.edge.kernel.org/pub/tools/crosstool/files/bin/x86_64/13.2.0/x86_64-gcc-13.2.0-nolibc-aarch64-linux.tar.xz | tar -C /opt -xJ +RUN wget -O - https://mirrors.edge.kernel.org/pub/tools/crosstool/files/bin/x86_64/13.2.0/x86_64-gcc-13.2.0-nolibc-arc-linux.tar.xz | tar -C /opt -xJ +RUN wget -O - https://mirrors.edge.kernel.org/pub/tools/crosstool/files/bin/x86_64/13.2.0/x86_64-gcc-13.2.0-nolibc-arm-linux-gnueabi.tar.xz | tar -C /opt -xJ +RUN wget -O - https://mirrors.edge.kernel.org/pub/tools/crosstool/files/bin/x86_64/13.2.0/x86_64-gcc-13.2.0-nolibc-i386-linux.tar.xz | tar -C /opt -xJ +RUN wget -O - https://mirrors.edge.kernel.org/pub/tools/crosstool/files/bin/x86_64/13.2.0/x86_64-gcc-13.2.0-nolibc-m68k-linux.tar.xz | tar -C /opt -xJ +RUN wget -O - https://mirrors.edge.kernel.org/pub/tools/crosstool/files/bin/x86_64/13.2.0/x86_64-gcc-13.2.0-nolibc-mips-linux.tar.xz | tar -C /opt -xJ +RUN wget -O - https://mirrors.edge.kernel.org/pub/tools/crosstool/files/bin/x86_64/13.2.0/x86_64-gcc-13.2.0-nolibc-microblaze-linux.tar.xz | tar -C /opt -xJ +RUN wget -O - https://mirrors.edge.kernel.org/pub/tools/crosstool/files/bin/x86_64/13.2.0/x86_64-gcc-13.2.0-nolibc-nios2-linux.tar.xz | tar -C /opt -xJ +RUN wget -O - https://mirrors.edge.kernel.org/pub/tools/crosstool/files/bin/x86_64/13.2.0/x86_64-gcc-13.2.0-nolibc-powerpc-linux.tar.xz | tar -C /opt -xJ +RUN wget -O - https://mirrors.edge.kernel.org/pub/tools/crosstool/files/bin/x86_64/13.2.0/x86_64-gcc-13.2.0-nolibc-riscv64-linux.tar.xz | tar -C /opt -xJ +RUN wget -O - https://mirrors.edge.kernel.org/pub/tools/crosstool/files/bin/x86_64/13.2.0/x86_64-gcc-13.2.0-nolibc-riscv32-linux.tar.xz | tar -C /opt -xJ +RUN wget -O - https://mirrors.edge.kernel.org/pub/tools/crosstool/files/bin/x86_64/13.2.0/x86_64-gcc-13.2.0-nolibc-sh2-linux.tar.xz | tar -C /opt -xJ # Manually install other toolchains RUN wget -O - https://github.com/foss-xtensa/toolchain/releases/download/2020.07/x86_64-2020.07-xtensa-dc233c-elf.tar.gz | tar -C /opt -xz @@ -39,10 +39,10 @@ RUN apt-get update && apt-get install -y \ binutils-dev \ bison \ build-essential \ + cgpt \ clang-16 \ coreutils \ cpio \ - cppcheck \ curl \ device-tree-compiler \ dosfstools \ @@ -104,7 +104,6 @@ RUN apt-get update && apt-get install -y \ python3-virtualenv \ rpm2cpio \ sbsigntool \ - sloccount \ socat \ softhsm2 \ sparse \ @@ -115,6 +114,8 @@ RUN apt-get update && apt-get install -y \ util-linux \ uuid-dev \ virtualenv \ + vboot-kernel-utils \ + vboot-utils \ xxd \ zip \ && rm -rf /var/lib/apt/lists/* @@ -134,11 +135,11 @@ RUN git clone git://git.savannah.gnu.org/grub.git /tmp/grub && \ mkdir -p /opt/grub && \ ./configure --target=aarch64 --with-platform=efi \ CC=gcc \ - TARGET_CC=/opt/gcc-13.1.0-nolibc/aarch64-linux/bin/aarch64-linux-gcc \ - TARGET_OBJCOPY=/opt/gcc-13.1.0-nolibc/aarch64-linux/bin/aarch64-linux-objcopy \ - TARGET_STRIP=/opt/gcc-13.1.0-nolibc/aarch64-linux/bin/aarch64-linux-strip \ - TARGET_NM=/opt/gcc-13.1.0-nolibc/aarch64-linux/bin/aarch64-linux-nm \ - TARGET_RANLIB=/opt/gcc-13.1.0-nolibc/aarch64-linux/bin/aarch64-linux-ranlib && \ + TARGET_CC=/opt/gcc-13.2.0-nolibc/aarch64-linux/bin/aarch64-linux-gcc \ + TARGET_OBJCOPY=/opt/gcc-13.2.0-nolibc/aarch64-linux/bin/aarch64-linux-objcopy \ + TARGET_STRIP=/opt/gcc-13.2.0-nolibc/aarch64-linux/bin/aarch64-linux-strip \ + TARGET_NM=/opt/gcc-13.2.0-nolibc/aarch64-linux/bin/aarch64-linux-nm \ + TARGET_RANLIB=/opt/gcc-13.2.0-nolibc/aarch64-linux/bin/aarch64-linux-ranlib && \ make && \ ./grub-mkimage -O arm64-efi -o /opt/grub/grubaa64.efi --prefix= -d \ grub-core cat chain configfile echo efinet ext2 fat halt help linux \ @@ -148,11 +149,11 @@ RUN git clone git://git.savannah.gnu.org/grub.git /tmp/grub && \ make clean && \ ./configure --target=arm --with-platform=efi \ CC=gcc \ - TARGET_CC=/opt/gcc-13.1.0-nolibc/arm-linux-gnueabi/bin/arm-linux-gnueabi-gcc \ - TARGET_OBJCOPY=/opt/gcc-13.1.0-nolibc/arm-linux-gnueabi/bin/arm-linux-gnueabi-objcopy \ - TARGET_STRIP=/opt/gcc-13.1.0-nolibc/arm-linux-gnueabi/bin/arm-linux-gnueabi-strip \ - TARGET_NM=/opt/gcc-13.1.0-nolibc/arm-linux-gnueabi/bin/arm-linux-gnueabi-nm \ - TARGET_RANLIB=/opt/gcc-13.1.0-nolibc/arm-linux-gnueabi/bin/arm-linux-gnueabi-ranlib && \ + TARGET_CC=/opt/gcc-13.2.0-nolibc/arm-linux-gnueabi/bin/arm-linux-gnueabi-gcc \ + TARGET_OBJCOPY=/opt/gcc-13.2.0-nolibc/arm-linux-gnueabi/bin/arm-linux-gnueabi-objcopy \ + TARGET_STRIP=/opt/gcc-13.2.0-nolibc/arm-linux-gnueabi/bin/arm-linux-gnueabi-strip \ + TARGET_NM=/opt/gcc-13.2.0-nolibc/arm-linux-gnueabi/bin/arm-linux-gnueabi-nm \ + TARGET_RANLIB=/opt/gcc-13.2.0-nolibc/arm-linux-gnueabi/bin/arm-linux-gnueabi-ranlib && \ make && \ ./grub-mkimage -O arm-efi -o /opt/grub/grubarm.efi --prefix= -d \ grub-core cat chain configfile echo efinet ext2 fat halt help linux \ @@ -162,11 +163,11 @@ RUN git clone git://git.savannah.gnu.org/grub.git /tmp/grub && \ make clean && \ ./configure --target=riscv64 --with-platform=efi \ CC=gcc \ - TARGET_CC=/opt/gcc-13.1.0-nolibc/riscv64-linux/bin/riscv64-linux-gcc \ - TARGET_OBJCOPY=/opt/gcc-13.1.0-nolibc/riscv64-linux/bin/riscv64-linux-objcopy \ - TARGET_STRIP=/opt/gcc-13.1.0-nolibc/riscv64-linux/bin/riscv64-linux-strip \ - TARGET_NM=/opt/gcc-13.1.0-nolibc/riscv64-linux/bin/riscv64-linux-nm \ - TARGET_RANLIB=/opt/gcc-13.1.0-nolibc/riscv64-linux/bin/riscv64-linux-ranlib && \ + TARGET_CC=/opt/gcc-13.2.0-nolibc/riscv64-linux/bin/riscv64-linux-gcc \ + TARGET_OBJCOPY=/opt/gcc-13.2.0-nolibc/riscv64-linux/bin/riscv64-linux-objcopy \ + TARGET_STRIP=/opt/gcc-13.2.0-nolibc/riscv64-linux/bin/riscv64-linux-strip \ + TARGET_NM=/opt/gcc-13.2.0-nolibc/riscv64-linux/bin/riscv64-linux-nm \ + TARGET_RANLIB=/opt/gcc-13.2.0-nolibc/riscv64-linux/bin/riscv64-linux-ranlib && \ make && \ ./grub-mkimage -O riscv64-efi -o /opt/grub/grubriscv64.efi --prefix= -d \ grub-core cat chain configfile echo efinet ext2 fat halt help linux \ @@ -246,7 +247,7 @@ RUN virtualenv -p /usr/bin/python3 /tmp/venv && \ # Create the buildman config file RUN /bin/echo -e "[toolchain]\nroot = /usr" > ~/.buildman -RUN /bin/echo -e "kernelorg = /opt/gcc-13.1.0-nolibc/*" >> ~/.buildman +RUN /bin/echo -e "kernelorg = /opt/gcc-13.2.0-nolibc/*" >> ~/.buildman RUN /bin/echo -e "\n[toolchain-prefix]\nxtensa = /opt/2020.07/xtensa-dc233c-elf/bin/xtensa-dc233c-elf-" >> ~/.buildman; RUN /bin/echo -e "\n[toolchain-alias]\nsh = sh2" >> ~/.buildman RUN /bin/echo -e "\nsandbox = x86_64" >> ~/.buildman diff --git a/tools/expo.py b/tools/expo.py index c6eb87aec7..ea80c70f04 100755 --- a/tools/expo.py +++ b/tools/expo.py @@ -69,7 +69,10 @@ def calc_ids(fname): def run_expo(args): """Run the expo program""" - ids = calc_ids(args.enum_fname) + fname = args.enum_fname or args.layout + ids = calc_ids(fname) + if not ids: + print(f"Warning: No enum ID values found in file '{fname}'") indata = tools.read_file(args.layout) @@ -88,10 +91,10 @@ def run_expo(args): with open('/tmp/asc', 'wb') as outf: outf.write(data) - proc = subprocess.run('dtc', input=data, capture_output=True, check=True) + proc = subprocess.run('dtc', input=data, capture_output=True) edtb = proc.stdout if proc.stderr: - print(proc.stderr) + print(f"Devicetree compiler error:\n{proc.stderr.decode('utf-8')}") return 1 tools.write_file(args.outfile, edtb) return 0 @@ -109,11 +112,13 @@ def parse_args(argv): args is a list of string arguments """ parser = argparse.ArgumentParser() + parser.add_argument('-D', '--debug', action='store_true', + help='Enable full debug traceback') parser.add_argument('-e', '--enum-fname', type=str, - help='C file containing enum declaration for expo items') - parser.add_argument('-l', '--layout', type=str, - help='Devicetree file source .dts for expo layout') - parser.add_argument('-o', '--outfile', type=str, + help='.dts or C file containing enum declaration for expo items') + parser.add_argument('-l', '--layout', type=str, required=True, + help='Devicetree file source .dts for expo layout (and perhaps enums)') + parser.add_argument('-o', '--outfile', type=str, required=True, help='Filename to write expo layout dtb') return parser.parse_args(argv) @@ -122,6 +127,9 @@ def start_expo(): """Start the expo program""" args = parse_args(sys.argv[1:]) + if not args.debug: + sys.tracebacklimit = 0 + ret_code = run_expo(args) sys.exit(ret_code) diff --git a/tools/image-host.c b/tools/image-host.c index 4a24dee815..ca4950312f 100644 --- a/tools/image-host.c +++ b/tools/image-host.c @@ -38,9 +38,9 @@ static int fit_set_hash_value(void *fit, int noffset, uint8_t *value, ret = fdt_setprop(fit, noffset, FIT_VALUE_PROP, value, value_len); if (ret) { - printf("Can't set hash '%s' property for '%s' node(%s)\n", - FIT_VALUE_PROP, fit_get_name(fit, noffset, NULL), - fdt_strerror(ret)); + fprintf(stderr, "Can't set hash '%s' property for '%s' node(%s)\n", + FIT_VALUE_PROP, fit_get_name(fit, noffset, NULL), + fdt_strerror(ret)); return ret == -FDT_ERR_NOSPACE ? -ENOSPC : -EIO; } @@ -72,21 +72,23 @@ static int fit_image_process_hash(void *fit, const char *image_name, node_name = fit_get_name(fit, noffset, NULL); if (fit_image_hash_get_algo(fit, noffset, &algo)) { - printf("Can't get hash algo property for '%s' hash node in '%s' image node\n", - node_name, image_name); + fprintf(stderr, + "Can't get hash algo property for '%s' hash node in '%s' image node\n", + node_name, image_name); return -ENOENT; } if (calculate_hash(data, size, algo, value, &value_len)) { - printf("Unsupported hash algorithm (%s) for '%s' hash node in '%s' image node\n", - algo, node_name, image_name); + fprintf(stderr, + "Unsupported hash algorithm (%s) for '%s' hash node in '%s' image node\n", + algo, node_name, image_name); return -EPROTONOSUPPORT; } ret = fit_set_hash_value(fit, noffset, value, value_len); if (ret) { - printf("Can't set hash value for '%s' hash node in '%s' image node\n", - node_name, image_name); + fprintf(stderr, "Can't set hash value for '%s' hash node in '%s' image node\n", + node_name, image_name); return ret; } @@ -170,8 +172,9 @@ static int fit_image_setup_sig(struct image_sign_info *info, node_name = fit_get_name(fit, noffset, NULL); if (!algo_name) { if (fit_image_hash_get_algo(fit, noffset, &algo_name)) { - printf("Can't get algo property for '%s' signature node in '%s' image node\n", - node_name, image_name); + fprintf(stderr, + "Can't get algo property for '%s' signature node in '%s' image node\n", + node_name, image_name); return -1; } } @@ -191,8 +194,9 @@ static int fit_image_setup_sig(struct image_sign_info *info, info->require_keys = require_keys; info->engine_id = engine_id; if (!info->checksum || !info->crypto) { - printf("Unsupported signature algorithm (%s) for '%s' signature node in '%s' image node\n", - algo_name, node_name, image_name); + fprintf(stderr, + "Unsupported signature algorithm (%s) for '%s' signature node in '%s' image node\n", + algo_name, node_name, image_name); return -1; } @@ -241,8 +245,8 @@ static int fit_image_process_sig(const char *keydir, const char *keyfile, region.size = size; ret = info.crypto->sign(&info, ®ion, 1, &value, &value_len); if (ret) { - printf("Failed to sign '%s' signature node in '%s' image node: %d\n", - node_name, image_name, ret); + fprintf(stderr, "Failed to sign '%s' signature node in '%s' image node: %d\n", + node_name, image_name, ret); /* We allow keys to be missing */ if (ret == -ENOENT) @@ -255,8 +259,9 @@ static int fit_image_process_sig(const char *keydir, const char *keyfile, if (ret) { if (ret == -FDT_ERR_NOSPACE) return -ENOSPC; - printf("Can't write signature for '%s' signature node in '%s' conf node: %s\n", - node_name, image_name, fdt_strerror(ret)); + fprintf(stderr, + "Can't write signature for '%s' signature node in '%s' conf node: %s\n", + node_name, image_name, fdt_strerror(ret)); return -1; } free(value); @@ -272,8 +277,9 @@ static int fit_image_process_sig(const char *keydir, const char *keyfile, if (keydest) { ret = info.crypto->add_verify_data(&info, keydest); if (ret < 0) { - printf("Failed to add verification data for '%s' signature node in '%s' image node\n", - node_name, image_name); + fprintf(stderr, + "Failed to add verification data for '%s' signature node in '%s' image node\n", + node_name, image_name); return ret; } /* Return the node that was written to */ @@ -293,37 +299,37 @@ static int fit_image_read_data(char *filename, unsigned char *data, /* Open file */ fd = open(filename, O_RDONLY | O_BINARY); if (fd < 0) { - printf("Can't open file %s (err=%d => %s)\n", - filename, errno, strerror(errno)); + fprintf(stderr, "Can't open file %s (err=%d => %s)\n", + filename, errno, strerror(errno)); return -1; } /* Compute file size */ if (fstat(fd, &sbuf) < 0) { - printf("Can't fstat file %s (err=%d => %s)\n", - filename, errno, strerror(errno)); + fprintf(stderr, "Can't fstat file %s (err=%d => %s)\n", + filename, errno, strerror(errno)); goto err; } /* Check file size */ if (sbuf.st_size != expected_size) { - printf("File %s don't have the expected size (size=%lld, expected=%d)\n", - filename, (long long)sbuf.st_size, expected_size); + fprintf(stderr, "File %s don't have the expected size (size=%lld, expected=%d)\n", + filename, (long long)sbuf.st_size, expected_size); goto err; } /* Read data */ n = read(fd, data, sbuf.st_size); if (n < 0) { - printf("Can't read file %s (err=%d => %s)\n", - filename, errno, strerror(errno)); + fprintf(stderr, "Can't read file %s (err=%d => %s)\n", + filename, errno, strerror(errno)); goto err; } /* Check that we have read all the file */ if (n != sbuf.st_size) { - printf("Can't read all file %s (read %zd bytes, expected %lld)\n", - filename, n, (long long)sbuf.st_size); + fprintf(stderr, "Can't read all file %s (read %zd bytes, expected %lld)\n", + filename, n, (long long)sbuf.st_size); goto err; } @@ -341,15 +347,15 @@ static int get_random_data(void *data, int size) int i, ret; if (!tmp) { - printf("%s: pointer data is NULL\n", __func__); + fprintf(stderr, "%s: pointer data is NULL\n", __func__); ret = -1; goto out; } ret = clock_gettime(CLOCK_MONOTONIC, &date); if (ret) { - printf("%s: clock_gettime has failed (%s)\n", __func__, - strerror(errno)); + fprintf(stderr, "%s: clock_gettime has failed (%s)\n", __func__, + strerror(errno)); goto out; } @@ -374,8 +380,8 @@ static int fit_image_setup_cipher(struct image_cipher_info *info, int ret = -1; if (fit_image_cipher_get_algo(fit, noffset, &algo_name)) { - printf("Can't get algo name for cipher in image '%s'\n", - image_name); + fprintf(stderr, "Can't get algo name for cipher in image '%s'\n", + image_name); goto out; } @@ -384,8 +390,8 @@ static int fit_image_setup_cipher(struct image_cipher_info *info, /* Read the key name */ info->keyname = fdt_getprop(fit, noffset, FIT_KEY_HINT, NULL); if (!info->keyname) { - printf("Can't get key name for cipher in image '%s'\n", - image_name); + fprintf(stderr, "Can't get key name for cipher in image '%s'\n", + image_name); goto out; } @@ -403,7 +409,7 @@ static int fit_image_setup_cipher(struct image_cipher_info *info, info->cipher = image_get_cipher_algo(algo_name); if (!info->cipher) { - printf("Can't get algo for cipher '%s'\n", image_name); + fprintf(stderr, "Can't get algo for cipher '%s'\n", image_name); goto out; } @@ -412,7 +418,7 @@ static int fit_image_setup_cipher(struct image_cipher_info *info, info->keydir, info->keyname, ".bin"); info->key = malloc(info->cipher->key_len); if (!info->key) { - printf("Can't allocate memory for key\n"); + fprintf(stderr, "Can't allocate memory for key\n"); ret = -1; goto out; } @@ -423,7 +429,7 @@ static int fit_image_setup_cipher(struct image_cipher_info *info, info->iv = malloc(info->cipher->iv_len); if (!info->iv) { - printf("Can't allocate memory for iv\n"); + fprintf(stderr, "Can't allocate memory for iv\n"); ret = -1; goto out; } @@ -457,7 +463,7 @@ int fit_image_write_cipher(void *fit, int image_noffset, int noffset, goto out; } if (ret) { - printf("Can't replace data with ciphered data (err = %d)\n", ret); + fprintf(stderr, "Can't replace data with ciphered data (err = %d)\n", ret); goto out; } @@ -468,7 +474,7 @@ int fit_image_write_cipher(void *fit, int image_noffset, int noffset, goto out; } if (ret) { - printf("Can't add unciphered data size (err = %d)\n", ret); + fprintf(stderr, "Can't add unciphered data size (err = %d)\n", ret); goto out; } @@ -508,8 +514,9 @@ fit_image_process_cipher(const char *keydir, void *keydest, void *fit, if (keydest) { ret = info.cipher->add_cipher_data(&info, keydest, fit, node_noffset); if (ret) { - printf("Failed to add verification data for cipher '%s' in image '%s'\n", - info.keyname, image_name); + fprintf(stderr, + "Failed to add verification data for cipher '%s' in image '%s'\n", + info.keyname, image_name); goto out; } } @@ -538,13 +545,13 @@ int fit_image_cipher_data(const char *keydir, void *keydest, /* Get image name */ image_name = fit_get_name(fit, image_noffset, NULL); if (!image_name) { - printf("Can't get image name\n"); + fprintf(stderr, "Can't get image name\n"); return -1; } /* Get image data and data length */ if (fit_image_get_data(fit, image_noffset, &data, &size)) { - printf("Can't get image data/size\n"); + fprintf(stderr, "Can't get image data/size\n"); return -1; } @@ -558,7 +565,7 @@ int fit_image_cipher_data(const char *keydir, void *keydest, if (fdt_getprop(fit, image_noffset, "data-size-unciphered", &len)) return 0; if (len != -FDT_ERR_NOTFOUND) { - printf("Failure testing for data-size-unciphered\n"); + fprintf(stderr, "Failure testing for data-size-unciphered\n"); return -1; } @@ -568,7 +575,7 @@ int fit_image_cipher_data(const char *keydir, void *keydest, if (cipher_node_offset == -FDT_ERR_NOTFOUND) return 0; if (cipher_node_offset < 0) { - printf("Failure getting cipher node\n"); + fprintf(stderr, "Failure getting cipher node\n"); return -1; } if (!IMAGE_ENABLE_ENCRYPT || !keydir) @@ -624,7 +631,7 @@ int fit_image_add_verification_data(const char *keydir, const char *keyfile, /* Get image data and data length */ if (fit_image_get_data(fit, image_noffset, &data, &size)) { - printf("Can't get image data/size\n"); + fprintf(stderr, "Can't get image data/size\n"); return -1; } @@ -765,8 +772,9 @@ static int fit_config_add_hash(const void *fit, int image_noffset, } if (!hash_count) { - printf("Failed to find any hash nodes in configuration '%s/%s' image '%s' - without these it is not possible to verify this image\n", - conf_name, sig_name, iname); + fprintf(stderr, + "Failed to find any hash nodes in configuration '%s/%s' image '%s' - without these it is not possible to verify this image\n", + conf_name, sig_name, iname); return -ENOMSG; } @@ -775,9 +783,10 @@ static int fit_config_add_hash(const void *fit, int image_noffset, FIT_CIPHER_NODENAME); if (noffset != -FDT_ERR_NOTFOUND) { if (noffset < 0) { - printf("Failed to get cipher node in configuration '%s/%s' image '%s': %s\n", - conf_name, sig_name, iname, - fdt_strerror(noffset)); + fprintf(stderr, + "Failed to get cipher node in configuration '%s/%s' image '%s': %s\n", + conf_name, sig_name, iname, + fdt_strerror(noffset)); return -EIO; } ret = fdt_get_path(fit, noffset, path, sizeof(path)); @@ -790,13 +799,13 @@ static int fit_config_add_hash(const void *fit, int image_noffset, return 0; err_mem: - printf("Out of memory processing configuration '%s/%s'\n", conf_name, - sig_name); + fprintf(stderr, "Out of memory processing configuration '%s/%s'\n", conf_name, + sig_name); return -ENOMEM; err_path: - printf("Failed to get path for image '%s' in configuration '%s/%s': %s\n", - iname, conf_name, sig_name, fdt_strerror(ret)); + fprintf(stderr, "Failed to get path for image '%s' in configuration '%s/%s': %s\n", + iname, conf_name, sig_name, fdt_strerror(ret)); return -ENOENT; } @@ -857,8 +866,9 @@ static int fit_config_get_hash_list(const void *fit, int conf_noffset, iname, index); if (image_noffset < 0) { - printf("Failed to find image '%s' in configuration '%s/%s'\n", - iname, conf_name, sig_name); + fprintf(stderr, + "Failed to find image '%s' in configuration '%s/%s'\n", + iname, conf_name, sig_name); if (allow_missing) continue; @@ -875,16 +885,16 @@ static int fit_config_get_hash_list(const void *fit, int conf_noffset, } if (!image_count) { - printf("Failed to find any images for configuration '%s/%s'\n", - conf_name, sig_name); + fprintf(stderr, "Failed to find any images for configuration '%s/%s'\n", + conf_name, sig_name); return -ENOMSG; } return 0; err_mem: - printf("Out of memory processing configuration '%s/%s'\n", conf_name, - sig_name); + fprintf(stderr, "Out of memory processing configuration '%s/%s'\n", conf_name, + sig_name); return -ENOMEM; } @@ -946,21 +956,21 @@ static int fit_config_get_regions(const void *fit, int conf_noffset, fdt_regions, ARRAY_SIZE(fdt_regions), path, sizeof(path), 1); if (count < 0) { - printf("Failed to hash configuration '%s/%s': %s\n", conf_name, - sig_name, fdt_strerror(ret)); + fprintf(stderr, "Failed to hash configuration '%s/%s': %s\n", conf_name, + sig_name, fdt_strerror(ret)); return -EIO; } if (count == 0) { - printf("No data to hash for configuration '%s/%s': %s\n", - conf_name, sig_name, fdt_strerror(ret)); + fprintf(stderr, "No data to hash for configuration '%s/%s': %s\n", + conf_name, sig_name, fdt_strerror(ret)); return -EINVAL; } /* Build our list of data blocks */ region = fit_region_make_list(fit, fdt_regions, count, NULL); if (!region) { - printf("Out of memory hashing configuration '%s/%s'\n", - conf_name, sig_name); + fprintf(stderr, "Out of memory hashing configuration '%s/%s'\n", + conf_name, sig_name); return -ENOMEM; } @@ -972,8 +982,8 @@ static int fit_config_get_regions(const void *fit, int conf_noffset, } region_prop = malloc(len); if (!region_prop) { - printf("Out of memory setting up regions for configuration '%s/%s'\n", - conf_name, sig_name); + fprintf(stderr, "Out of memory setting up regions for configuration '%s/%s'\n", + conf_name, sig_name); return -ENOMEM; } for (i = len = 0; i < node_inc.count; @@ -1038,8 +1048,8 @@ static int fit_config_process_sig(const char *keydir, const char *keyfile, &value_len); free(region); if (ret) { - printf("Failed to sign '%s' signature node in '%s' conf node\n", - node_name, conf_name); + fprintf(stderr, "Failed to sign '%s' signature node in '%s' conf node\n", + node_name, conf_name); /* We allow keys to be missing */ if (ret == -ENOENT) @@ -1053,8 +1063,9 @@ static int fit_config_process_sig(const char *keydir, const char *keyfile, if (ret) { if (ret == -FDT_ERR_NOSPACE) return -ENOSPC; - printf("Can't write signature for '%s' signature node in '%s' conf node: %s\n", - node_name, conf_name, fdt_strerror(ret)); + fprintf(stderr, + "Can't write signature for '%s' signature node in '%s' conf node: %s\n", + node_name, conf_name, fdt_strerror(ret)); return -1; } free(value); @@ -1067,8 +1078,9 @@ static int fit_config_process_sig(const char *keydir, const char *keyfile, if (keydest) { ret = info.crypto->add_verify_data(&info, keydest); if (ret < 0) { - printf("Failed to add verification data for '%s' signature node in '%s' configuration node\n", - node_name, conf_name); + fprintf(stderr, + "Failed to add verification data for '%s' signature node in '%s' configuration node\n", + node_name, conf_name); } return ret; } @@ -1148,7 +1160,7 @@ static int read_pub_key(const char *keydir, const void *name, /* Read the certificate */ cert = NULL; if (!PEM_read_X509(f, &cert, NULL, NULL)) { - printf("Couldn't read certificate"); + fprintf(stderr, "Couldn't read certificate"); ret = -EINVAL; goto err_cert; } @@ -1156,7 +1168,7 @@ static int read_pub_key(const char *keydir, const void *name, /* Get the public key from the certificate. */ key = X509_get_pubkey(cert); if (!key) { - printf("Couldn't read public key\n"); + fprintf(stderr, "Couldn't read public key\n"); ret = -EINVAL; goto err_pubkey; } @@ -1164,7 +1176,7 @@ static int read_pub_key(const char *keydir, const void *name, /* Get DER form */ ret = i2d_PublicKey(key, pubkey); if (ret < 0) { - printf("Couldn't get DER form\n"); + fprintf(stderr, "Couldn't get DER form\n"); ret = -EINVAL; goto err_pubkey; } @@ -1203,11 +1215,11 @@ int fit_pre_load_data(const char *keydir, void *keydest, void *fit) /* Check that all mandatory properties are present */ if (!algo_name || !key_name) { if (!algo_name) - printf("The property algo-name is missing in the node %s\n", - IMAGE_PRE_LOAD_PATH); + fprintf(stderr, "The property algo-name is missing in the node %s\n", + IMAGE_PRE_LOAD_PATH); if (!key_name) - printf("The property key-name is missing in the node %s\n", - IMAGE_PRE_LOAD_PATH); + fprintf(stderr, "The property key-name is missing in the node %s\n", + IMAGE_PRE_LOAD_PATH); ret = -EINVAL; goto out; } @@ -1221,8 +1233,8 @@ int fit_pre_load_data(const char *keydir, void *keydest, void *fit) ret = fdt_setprop(keydest, pre_load_noffset, "public-key", pubkey, pubkey_len); if (ret) - printf("Can't set public-key in node %s (ret = %d)\n", - IMAGE_PRE_LOAD_PATH, ret); + fprintf(stderr, "Can't set public-key in node %s (ret = %d)\n", + IMAGE_PRE_LOAD_PATH, ret); out: return ret; @@ -1239,8 +1251,8 @@ int fit_cipher_data(const char *keydir, void *keydest, void *fit, /* Find images parent node offset */ images_noffset = fdt_path_offset(fit, FIT_IMAGES_PATH); if (images_noffset < 0) { - printf("Can't find images parent node '%s' (%s)\n", - FIT_IMAGES_PATH, fdt_strerror(images_noffset)); + fprintf(stderr, "Can't find images parent node '%s' (%s)\n", + FIT_IMAGES_PATH, fdt_strerror(images_noffset)); return images_noffset; } @@ -1276,8 +1288,8 @@ int fit_add_verification_data(const char *keydir, const char *keyfile, /* Find images parent node offset */ images_noffset = fdt_path_offset(fit, FIT_IMAGES_PATH); if (images_noffset < 0) { - printf("Can't find images parent node '%s' (%s)\n", - FIT_IMAGES_PATH, fdt_strerror(images_noffset)); + fprintf(stderr, "Can't find images parent node '%s' (%s)\n", + FIT_IMAGES_PATH, fdt_strerror(images_noffset)); return images_noffset; } @@ -1293,9 +1305,9 @@ int fit_add_verification_data(const char *keydir, const char *keyfile, fit, noffset, comment, require_keys, engine_id, cmdname, algo_name); if (ret) { - printf("Can't add verification data for node '%s' (%s)\n", - fdt_get_name(fit, noffset, NULL), - fdt_strerror(ret)); + fprintf(stderr, "Can't add verification data for node '%s' (%s)\n", + fdt_get_name(fit, noffset, NULL), + fdt_strerror(ret)); return ret; } } @@ -1307,8 +1319,8 @@ int fit_add_verification_data(const char *keydir, const char *keyfile, /* Find configurations parent node offset */ confs_noffset = fdt_path_offset(fit, FIT_CONFS_PATH); if (confs_noffset < 0) { - printf("Can't find images parent node '%s' (%s)\n", - FIT_CONFS_PATH, fdt_strerror(confs_noffset)); + fprintf(stderr, "Can't find images parent node '%s' (%s)\n", + FIT_CONFS_PATH, fdt_strerror(confs_noffset)); return -ENOENT; } diff --git a/tools/logos/ti.bmp b/tools/logos/ti_logo_414x97_32bpp.bmp Binary files differindex 7fee6e81e0..7fee6e81e0 100644 --- a/tools/logos/ti.bmp +++ b/tools/logos/ti_logo_414x97_32bpp.bmp diff --git a/tools/logos/ti.gz b/tools/logos/ti_logo_414x97_32bpp.bmp.gz Binary files differindex 3a5b45e035..3a5b45e035 100644 --- a/tools/logos/ti.gz +++ b/tools/logos/ti_logo_414x97_32bpp.bmp.gz diff --git a/tools/relocate-rela.c b/tools/relocate-rela.c index f230ec5676..613abd25ef 100644 --- a/tools/relocate-rela.c +++ b/tools/relocate-rela.c @@ -24,6 +24,30 @@ #define R_AARCH64_RELATIVE 1027 #endif +#ifndef EM_M68K +#define EM_M68K 4 +#endif + +#ifndef R_68K_NONE +#define R_68K_NONE 0 +#endif + +#ifndef R_68K_32 +#define R_68K_32 1 +#endif + +#ifndef R_68K_GLOB_DAT +#define R_68K_GLOB_DAT 20 +#endif + +#ifndef R_68K_JMP_SLOT +#define R_68K_JMP_SLOT 21 +#endif + +#ifndef R_68K_RELATIVE +#define R_68K_RELATIVE 22 +#endif + #ifndef EM_MICROBLAZE #define EM_MICROBLAZE 189 #endif @@ -46,6 +70,7 @@ static int ei_class; static int ei_data; +static int machine; static uint64_t rela_start, rela_end, text_base, dyn_start; @@ -78,6 +103,14 @@ static uint32_t elf32_to_cpu(uint32_t data) return be32_to_cpu(data); } +static uint32_t cpu_to_elf32(uint32_t data) +{ + if (ei_data == ELFDATA2LSB) + return cpu_to_le32(data); + + return cpu_to_be32(data); +} + static bool supported_rela(Elf64_Rela *rela) { uint64_t mask = 0xffffffffULL; /* would be different on 32-bit */ @@ -103,7 +136,7 @@ static int decode_elf64(FILE *felf, char **argv) uint64_t sh_addr, sh_offset, sh_size; Elf64_Half sh_index, sh_num; Elf64_Shdr *sh_table; /* Elf symbol table */ - int ret, i, machine; + int ret, i; char *sh_str; debug("64bit version\n"); @@ -237,7 +270,7 @@ static int decode_elf32(FILE *felf, char **argv) uint32_t sh_addr, sh_offset, sh_size; Elf32_Half sh_index, sh_num; Elf32_Shdr *sh_table; /* Elf symbol table */ - int ret, i, machine; + int ret, i; char *sh_str; debug("32bit version\n"); @@ -254,12 +287,20 @@ static int decode_elf32(FILE *felf, char **argv) machine = elf16_to_cpu(header.e_machine); debug("Machine %d\n", machine); - if (machine != EM_MICROBLAZE) { + if (machine != EM_MICROBLAZE && machine != EM_M68K) { fprintf(stderr, "%s: Not supported machine type\n", argv[0]); return 30; } text_base = elf32_to_cpu(header.e_entry); + /* + * M68K ELF entry point is MONITOR_BASE, not TEXT_BASE. + * TEXT_BASE is always MONITOR_BASE &~ 0x7ff, so clear + * those bits here. + */ + if (machine == EM_M68K) + text_base &= ~0x7ff; + section_header_base = elf32_to_cpu(header.e_shoff); section_header_size = elf16_to_cpu(header.e_shentsize) * elf16_to_cpu(header.e_shnum); @@ -480,25 +521,44 @@ static bool supported_rela32(Elf32_Rela *rela, uint32_t *type) debug("Type:\t"); - switch (*type) { - case R_MICROBLAZE_32: - debug("R_MICROBLAZE_32\n"); - return true; - case R_MICROBLAZE_GLOB_DAT: - debug("R_MICROBLAZE_GLOB_DAT\n"); - return true; - case R_MICROBLAZE_NONE: - debug("R_MICROBLAZE_NONE - ignoring - do nothing\n"); - return false; - case R_MICROBLAZE_REL: - debug("R_MICROBLAZE_REL\n"); - return true; - default: - fprintf(stderr, "warning: unsupported relocation type %" - PRIu32 " at %" PRIx32 "\n", *type, rela->r_offset); - - return false; + if (machine == EM_M68K) { + switch (*type) { + case R_68K_32: + debug("R_68K_32\n"); + return true; + case R_68K_GLOB_DAT: + debug("R_68K_GLOB_DAT\n"); + return true; + case R_68K_JMP_SLOT: + debug("R_68K_JMP_SLOT\n"); + return true; + case R_68K_NONE: + debug("R_68K_NONE - ignoring - do nothing\n"); + return false; + case R_68K_RELATIVE: + debug("R_68K_RELATIVE\n"); + return true; + } + } else { + switch (*type) { + case R_MICROBLAZE_32: + debug("R_MICROBLAZE_32\n"); + return true; + case R_MICROBLAZE_GLOB_DAT: + debug("R_MICROBLAZE_GLOB_DAT\n"); + return true; + case R_MICROBLAZE_NONE: + debug("R_MICROBLAZE_NONE - ignoring - do nothing\n"); + return false; + case R_MICROBLAZE_REL: + debug("R_MICROBLAZE_REL\n"); + return true; + } } + fprintf(stderr, "warning: unsupported relocation type %" + PRIu32 " at %" PRIx32 "\n", *type, rela->r_offset); + + return false; } static int rela_elf32(char **argv, FILE *f) @@ -561,8 +621,8 @@ static int rela_elf32(char **argv, FILE *f) debug("Addr:\t0x%" PRIx32 "\n", addr); - switch (type) { - case R_MICROBLAZE_REL: + if ((machine == EM_M68K && type == R_68K_RELATIVE) || + (machine == EM_MICROBLAZE && type == R_MICROBLAZE_REL)) { if (fseek(f, addr, SEEK_SET) < 0) { fprintf(stderr, "%s: %s: seek to %" PRIx32 " failed: %s\n", @@ -577,9 +637,12 @@ static int rela_elf32(char **argv, FILE *f) argv[0], argv[1], addr); return 4; } - break; - case R_MICROBLAZE_32: - case R_MICROBLAZE_GLOB_DAT: + } else if ((machine == EM_M68K && + (type == R_68K_32 || type == R_68K_GLOB_DAT || + type == R_68K_JMP_SLOT)) || + (machine == EM_MICROBLAZE && + (type == R_MICROBLAZE_32 || + type == R_MICROBLAZE_GLOB_DAT))) { /* global symbols read it and add reloc offset */ index = swrela.r_info >> 8; pos_dyn = dyn_start + sizeof(Elf32_Sym) * index; @@ -602,14 +665,16 @@ static int rela_elf32(char **argv, FILE *f) } debug("Symbol description:\n"); - debug(" st_name:\t0x%x\n", symbols.st_name); - debug(" st_value:\t0x%x\n", symbols.st_value); - debug(" st_size:\t0x%x\n", symbols.st_size); + debug(" st_name:\t0x%x\n", elf32_to_cpu(symbols.st_name)); + debug(" st_value:\t0x%x\n", elf32_to_cpu(symbols.st_value)); + debug(" st_size:\t0x%x\n", elf32_to_cpu(symbols.st_size)); - value = swrela.r_addend + symbols.st_value; + value = swrela.r_addend + elf32_to_cpu(symbols.st_value); debug("Value:\t0x%x\n", value); + value = cpu_to_elf32(value); + if (fseek(f, addr, SEEK_SET) < 0) { fprintf(stderr, "%s: %s: seek to %" PRIx32 " failed: %s\n", @@ -622,12 +687,11 @@ static int rela_elf32(char **argv, FILE *f) argv[0], argv[1], addr); return 4; } - - break; - case R_MICROBLAZE_NONE: + } else if (machine == EM_M68K && type == R_68K_NONE) { + debug("R_68K_NONE - skip\n"); + } else if (machine == EM_MICROBLAZE && type == R_MICROBLAZE_NONE) { debug("R_MICROBLAZE_NONE - skip\n"); - break; - default: + } else { fprintf(stderr, "warning: unsupported relocation type %" PRIu32 " at %" PRIx32 "\n", type, rela.r_offset); diff --git a/tools/sfspl.c b/tools/sfspl.c new file mode 100644 index 0000000000..ec18a0a77e --- /dev/null +++ b/tools/sfspl.c @@ -0,0 +1,174 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * Copyright Heinrich Schuchardt <heinrich.schuchardt@canonical.com> + * + * The StarFive JH7110 requires to prepend a header to u-boot-spl.bin describing + * the payload length and CRC32. + * + * This module implements support in mkimage and dumpimage for this file format. + * + * StarFive's spl_tool available under GPL-2.0-and-later at + * https://github.com/starfive-tech/Tools implements writing the same file + * format and served as a reference. + */ + +#include <compiler.h> +#include <fcntl.h> +#include <u-boot/crc.h> +#include <unistd.h> +#include "imagetool.h" + +#define DEFAULT_VERSION 0x01010101 +#define DEFAULT_BACKUP 0x200000U +#define DEFAULT_OFFSET 0x240 + +/** + * struct spl_hdr - header for SPL on JH7110 + * + * All fields are low-endian. + */ +struct spl_hdr { + /** @offset: offset to SPL header (0x240) */ + unsigned int offset; + /** @bkp_offs: address of backup SPL, defaults to DEFAULT_BACKUP */ + unsigned int bkp_offs; + /** @zero1: set to zero */ + unsigned int zero1[159]; + /** @version: header version, defaults to DEFAULT_VERSION */ + unsigned int version; + /** @file_size: file size */ + unsigned int file_size; + /** @hdr_size: size of the file header (0x400) */ + unsigned int hdr_size; + /** @crc32: CRC32 */ + unsigned int crc32; + /** @zero2: set to zero */ + unsigned int zero2[91]; +}; + +static int sfspl_check_params(struct image_tool_params *params) +{ + /* Only the RISC-V architecture is supported */ + if (params->Aflag && params->arch != IH_ARCH_RISCV) + return EXIT_FAILURE; + + return EXIT_SUCCESS; +} + +static int sfspl_verify_header(unsigned char *buf, int size, + struct image_tool_params *params) +{ + struct spl_hdr *hdr = (void *)buf; + unsigned int hdr_size = le32_to_cpu(hdr->hdr_size); + unsigned int file_size = le32_to_cpu(hdr->file_size); + unsigned int crc = le32_to_cpu(hdr->crc32); + unsigned int crc_check; + + if (size < 0 || + (size_t)size < sizeof(struct spl_hdr) || + (size_t)size < hdr_size + file_size) { + printf("Truncated file\n"); + return EXIT_FAILURE; + } + if (hdr->version != DEFAULT_VERSION) { + printf("Unknown file format version\n"); + return EXIT_FAILURE; + } + crc_check = crc32(0, &buf[hdr_size], size - hdr_size); + if (crc_check != crc) { + printf("Incorrect CRC32\n"); + return EXIT_FAILURE; + } + + return EXIT_SUCCESS; +} + +static void sfspl_print_header(const void *buf, + struct image_tool_params *params) +{ + struct spl_hdr *hdr = (void *)buf; + unsigned int hdr_size = le32_to_cpu(hdr->hdr_size); + unsigned int file_size = le32_to_cpu(hdr->file_size); + + printf("Header size: %u\n", hdr_size); + printf("Payload size: %u\n", file_size); +} + +static int sfspl_image_extract_subimage(void *ptr, + struct image_tool_params *params) +{ + struct spl_hdr *hdr = (void *)ptr; + unsigned char *buf = ptr; + int fd; + unsigned int hdr_size = le32_to_cpu(hdr->hdr_size); + unsigned int file_size = le32_to_cpu(hdr->file_size); + + if (params->pflag) { + printf("Invalid image index %d\n", params->pflag); + return EXIT_FAILURE; + } + + fd = open(params->outfile, O_WRONLY | O_CREAT | O_TRUNC, 0644); + if (fd == -1) { + perror("Can write file"); + return EXIT_FAILURE; + } + if (write(fd, &buf[hdr_size], file_size) != file_size) { + perror("Cannot write file"); + return EXIT_FAILURE; + } + close(fd); + + return EXIT_SUCCESS; +} + +static int sfspl_check_image_type(uint8_t type) +{ + if (type == IH_TYPE_STARFIVE_SPL) + return EXIT_SUCCESS; + + return EXIT_FAILURE; +} + +static void sfspl_set_header(void *buf, struct stat *sbuf, int infd, + struct image_tool_params *params) +{ + struct spl_hdr *hdr = buf; + unsigned int file_size; + unsigned int crc; + + file_size = params->file_size - sizeof(struct spl_hdr); + crc = crc32(0, &((unsigned char *)buf)[sizeof(struct spl_hdr)], + file_size); + + hdr->offset = cpu_to_le32(DEFAULT_OFFSET); + hdr->bkp_offs = cpu_to_le32(DEFAULT_BACKUP); + hdr->version = cpu_to_le32(DEFAULT_VERSION); + hdr->file_size = cpu_to_le32(file_size); + hdr->hdr_size = cpu_to_le32(sizeof(struct spl_hdr)); + hdr->crc32 = cpu_to_le32(crc); +} + +static int sfspl_vrec_header(struct image_tool_params *params, + struct image_type_params *tparams) +{ + tparams->hdr = calloc(sizeof(struct spl_hdr), 1); + + /* No padding */ + return 0; +} + +U_BOOT_IMAGE_TYPE( + sfspl, /* id */ + "StarFive SPL Image", /* name */ + sizeof(struct spl_hdr), /* header_size */ + NULL, /* header */ + sfspl_check_params, /* check_params */ + sfspl_verify_header, /* verify header */ + sfspl_print_header, /* print header */ + sfspl_set_header, /* set header */ + sfspl_image_extract_subimage, /* extract_subimage */ + sfspl_check_image_type, /* check_image_type */ + NULL, /* fflag_handle */ + sfspl_vrec_header /* vrec_header */ +); |