From 93a203d38b520db64e041e66f6bdad39ee5a3366 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Thu, 3 Aug 2023 17:23:58 -0600 Subject: binman: Renumber 291 and 292 test files These have ended up with the same numbers as earlier files. Fix them. Signed-off-by: Simon Glass --- tools/binman/ftest.py | 4 +- tools/binman/test/291_template_phandle.dts | 51 -------------------- tools/binman/test/292_template_phandle_dup.dts | 65 -------------------------- tools/binman/test/309_template_phandle.dts | 51 ++++++++++++++++++++ tools/binman/test/310_template_phandle_dup.dts | 65 ++++++++++++++++++++++++++ 5 files changed, 118 insertions(+), 118 deletions(-) delete mode 100644 tools/binman/test/291_template_phandle.dts delete mode 100644 tools/binman/test/292_template_phandle_dup.dts create mode 100644 tools/binman/test/309_template_phandle.dts create mode 100644 tools/binman/test/310_template_phandle_dup.dts diff --git a/tools/binman/ftest.py b/tools/binman/ftest.py index 36428ec3434..78389b34a71 100644 --- a/tools/binman/ftest.py +++ b/tools/binman/ftest.py @@ -6974,7 +6974,7 @@ fdt fdtmap Extract the devicetree blob from the fdtmap entry_args = { 'atf-bl31-path': 'bl31.elf', } - data = self._DoReadFileDtb('291_template_phandle.dts', + data = self._DoReadFileDtb('309_template_phandle.dts', entry_args=entry_args) fname = tools.get_output_filename('image.bin') out = tools.run('dumpimage', '-l', fname) @@ -6990,7 +6990,7 @@ fdt fdtmap Extract the devicetree blob from the fdtmap 'atf-bl31-path': 'bl31.elf', } with self.assertRaises(ValueError) as e: - self._DoReadFileDtb('292_template_phandle_dup.dts', + self._DoReadFileDtb('310_template_phandle_dup.dts', entry_args=entry_args) self.assertIn( 'Duplicate phandle 1 in nodes /binman/image/fit/images/atf/atf-bl31 and /binman/image-2/fit/images/atf/atf-bl31', diff --git a/tools/binman/test/291_template_phandle.dts b/tools/binman/test/291_template_phandle.dts deleted file mode 100644 index c4ec1dd41be..00000000000 --- a/tools/binman/test/291_template_phandle.dts +++ /dev/null @@ -1,51 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0+ - -/dts-v1/; - -/ { - #address-cells = <1>; - #size-cells = <1>; - - binman { - multiple-images; - - ti_spl_template: template-1 { - fit { - description = "test-desc"; - #address-cells = <1>; - images { - atf { - description = "atf"; - ti-secure { - type = "collection"; - content = <&atf>; - keyfile = "key.pem"; - }; - atf: atf-bl31 { - description = "atf"; - }; - }; - }; - }; - }; - - image { - insert-template = <&ti_spl_template>; - fit { - images { - fdt-0 { - description = "fdt"; - ti-secure { - type = "collection"; - content = <&foo_dtb>; - keyfile = "key.pem"; - }; - foo_dtb: blob-ext { - filename = "vga.bin"; - }; - }; - }; - }; - }; - }; -}; diff --git a/tools/binman/test/292_template_phandle_dup.dts b/tools/binman/test/292_template_phandle_dup.dts deleted file mode 100644 index dc86f06463b..00000000000 --- a/tools/binman/test/292_template_phandle_dup.dts +++ /dev/null @@ -1,65 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0+ - -/dts-v1/; - -/ { - #address-cells = <1>; - #size-cells = <1>; - - binman { - multiple-images; - - ti_spl_template: template-1 { - fit { - description = "test-desc"; - #address-cells = <1>; - images { - atf { - description = "atf"; - ti-secure { - type = "collection"; - content = <&atf>; - keyfile = "key.pem"; - }; - atf: atf-bl31 { - description = "atf"; - }; - }; - }; - }; - }; - - image { - insert-template = <&ti_spl_template>; - fit { - images { - fdt-0 { - description = "fdt"; - ti-secure { - type = "collection"; - content = <&foo_dtb>; - keyfile = "key.pem"; - }; - foo_dtb: blob-ext { - filename = "vga.bin"; - }; - }; - }; - }; - }; - - image-2 { - insert-template = <&ti_spl_template>; - fit { - images { - fdt-0 { - description = "fdt"; - blob-ext { - filename = "vga.bin"; - }; - }; - }; - }; - }; - }; -}; diff --git a/tools/binman/test/309_template_phandle.dts b/tools/binman/test/309_template_phandle.dts new file mode 100644 index 00000000000..c4ec1dd41be --- /dev/null +++ b/tools/binman/test/309_template_phandle.dts @@ -0,0 +1,51 @@ +// SPDX-License-Identifier: GPL-2.0+ + +/dts-v1/; + +/ { + #address-cells = <1>; + #size-cells = <1>; + + binman { + multiple-images; + + ti_spl_template: template-1 { + fit { + description = "test-desc"; + #address-cells = <1>; + images { + atf { + description = "atf"; + ti-secure { + type = "collection"; + content = <&atf>; + keyfile = "key.pem"; + }; + atf: atf-bl31 { + description = "atf"; + }; + }; + }; + }; + }; + + image { + insert-template = <&ti_spl_template>; + fit { + images { + fdt-0 { + description = "fdt"; + ti-secure { + type = "collection"; + content = <&foo_dtb>; + keyfile = "key.pem"; + }; + foo_dtb: blob-ext { + filename = "vga.bin"; + }; + }; + }; + }; + }; + }; +}; diff --git a/tools/binman/test/310_template_phandle_dup.dts b/tools/binman/test/310_template_phandle_dup.dts new file mode 100644 index 00000000000..dc86f06463b --- /dev/null +++ b/tools/binman/test/310_template_phandle_dup.dts @@ -0,0 +1,65 @@ +// SPDX-License-Identifier: GPL-2.0+ + +/dts-v1/; + +/ { + #address-cells = <1>; + #size-cells = <1>; + + binman { + multiple-images; + + ti_spl_template: template-1 { + fit { + description = "test-desc"; + #address-cells = <1>; + images { + atf { + description = "atf"; + ti-secure { + type = "collection"; + content = <&atf>; + keyfile = "key.pem"; + }; + atf: atf-bl31 { + description = "atf"; + }; + }; + }; + }; + }; + + image { + insert-template = <&ti_spl_template>; + fit { + images { + fdt-0 { + description = "fdt"; + ti-secure { + type = "collection"; + content = <&foo_dtb>; + keyfile = "key.pem"; + }; + foo_dtb: blob-ext { + filename = "vga.bin"; + }; + }; + }; + }; + }; + + image-2 { + insert-template = <&ti_spl_template>; + fit { + images { + fdt-0 { + description = "fdt"; + blob-ext { + filename = "vga.bin"; + }; + }; + }; + }; + }; + }; +}; -- cgit v1.3.1 From 7f51fe5c6db21592f7f2a914b2dab3f67e765d8b Mon Sep 17 00:00:00 2001 From: Lukas Funke Date: Thu, 3 Aug 2023 17:22:13 +0200 Subject: binman: btool: Add Xilinx Bootgen btool Add the Xilinx Bootgen as bintool. Xilinx Bootgen is used to create bootable SPL (FSBL in Xilinx terms) images for Zynq/ZynqMP devices. The btool creates a signed version of the SPL. Additionally to signing the key source for the decryption engine can be passend to the boot image. Signed-off-by: Lukas Funke --- tools/binman/bintools.rst | 2 +- tools/binman/btool/bootgen.py | 137 ++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 138 insertions(+), 1 deletion(-) create mode 100644 tools/binman/btool/bootgen.py diff --git a/tools/binman/bintools.rst b/tools/binman/bintools.rst index 20ee24395af..1336f4d0115 100644 --- a/tools/binman/bintools.rst +++ b/tools/binman/bintools.rst @@ -208,7 +208,7 @@ Using `fdt_add_pubkey` the key can be injected to the SPL independent of Bintool: bootgen: Sign ZynqMP FSBL image ---------------------------------------------- +---------------------------------------- This bintool supports running `bootgen` in order to sign a SPL for ZynqMP devices. diff --git a/tools/binman/btool/bootgen.py b/tools/binman/btool/bootgen.py new file mode 100644 index 00000000000..f2ca552dc28 --- /dev/null +++ b/tools/binman/btool/bootgen.py @@ -0,0 +1,137 @@ +# SPDX-License-Identifier: GPL-2.0+ +# Copyright (C) 2023 Weidmüller Interface GmbH & Co. KG +# Lukas Funke +# +"""Bintool implementation for bootgen + +bootgen allows creating bootable SPL for Zynq(MP) + +Documentation is available via: +https://www.xilinx.com/support/documents/sw_manuals/xilinx2022_1/ug1283-bootgen-user-guide.pdf + +Source code is available at: +https://github.com/Xilinx/bootgen + +""" + +from binman import bintool +from u_boot_pylib import tools + +# pylint: disable=C0103 +class Bintoolbootgen(bintool.Bintool): + """Generate bootable fsbl image for zynq/zynqmp + + This bintools supports running Xilinx "bootgen" in order + to generate a bootable, authenticated image form an SPL. + + """ + def __init__(self, name): + super().__init__(name, 'Xilinx Bootgen', + version_regex=r'^\*\*\*\*\*\* *Xilinx Bootgen *(.*)', + version_args='-help') + + # pylint: disable=R0913 + def sign(self, arch, spl_elf_fname, pmufw_elf_fname, + psk_fname, ssk_fname, fsbl_config, auth_params, keysrc_enc, + output_fname): + """Sign SPL elf file and bundle it with PMU firmware into an image + + The method bundels the SPL together with a 'Platform Management Unit' + (PMU)[1] firmware into a single bootable image. The image in turn is + signed with the provided 'secondary secret key' (ssk), which in turn is + signed with the 'primary secret key' (psk). In order to verify the + authenticity of the ppk, it's hash has to be fused into the device + itself. + + In Xilinx terms the SPL is usually called 'FSBL' + (First Stage Boot Loader). The jobs of the SPL and the FSBL are mostly + the same: load bitstream, bootstrap u-boot. + + Args: + arch (str): Xilinx SoC architecture. Currently only 'zynqmp' is + supported. + spl_elf_fname (str): Filename of SPL ELF file. The filename must end + with '.elf' in order for bootgen to recognized it as an ELF + file. Otherwise the start address field is missinterpreted. + pmufw_elf_fname (str): Filename PMU ELF firmware. + psk_fname (str): Filename of the primary secret key (psk). The psk + is a .pem file which holds the RSA private key used for signing + the secondary secret key. + ssk_fname (str): Filename of the secondary secret key. The ssk + is a .pem file which holds the RSA private key used for signing + the actual boot firmware. + fsbl_config (str): FSBL config options. A string list of fsbl config + options. Valid values according to [2] are: + "bh_auth_enable": Boot Header Authentication Enable: RSA + authentication of the bootimage is done + excluding the verification of PPK hash and SPK ID. This is + useful for debugging before bricking a device. + "auth_only": Boot image is only RSA signed. FSBL should not be + decrypted. See the + Zynq UltraScale+ Device Technical Reference Manual (UG1085) + for more information. + There are more options which relate to PUF (physical unclonable + functions). Please refer to Xilinx manuals for further info. + auth_params (str): Authentication parameter. A semicolon separated + list of authentication parameters. Valid values according to [3] + are: + "ppk_select=<0|1>" - Select which ppk to use + "spk_id=<32-bit spk id>" - Specifies which SPK can be + used or revoked, default is 0x0 + "spk_select=" - To differentiate spk and + user efuses. + "auth_header" - To authenticate headers when no partition + is authenticated. + keysrc_enc (str): This specifies the Key source for encryption. + Valid values according to [3] are: + "bbram_red_key" - RED key stored in BBRAM + "efuse_red_key" - RED key stored in eFUSE + "efuse_gry_key" - Grey (Obfuscated) Key stored in eFUSE. + "bh_gry_key" - Grey (Obfuscated) Key stored in boot header + "bh_blk_key" - Black Key stored in boot header + "efuse_blk_key" - Black Key stored in eFUSE + "kup_key" - User Key + + output_fname (str): Filename where bootgen should write the result + + Returns: + str: Bootgen output from stdout + + [1] https://xilinx-wiki.atlassian.net/wiki/spaces/A/pages/18841724/PMU+Firmware + [2] https://docs.xilinx.com/r/en-US/ug1283-bootgen-user-guide/fsbl_config + [3] https://docs.xilinx.com/r/en-US/ug1283-bootgen-user-guide/auth_params + [4] https://docs.xilinx.com/r/en-US/ug1283-bootgen-user-guide/keysrc_encryption + """ + + _fsbl_config = f"[fsbl_config] {fsbl_config}" if fsbl_config else "" + _auth_params = f"[auth_params] {auth_params}" if auth_params else "" + _keysrc_enc = f"[keysrc_encryption] {keysrc_enc}" if keysrc_enc else "" + + bif_template = f"""u_boot_spl_aes_rsa: {{ + [pskfile] {psk_fname} + [sskfile] {ssk_fname} + {_keysrc_enc} + {_fsbl_config} + {_auth_params} + [ bootloader, + authentication = rsa, + destination_cpu=a53-0] {spl_elf_fname} + [pmufw_image] {pmufw_elf_fname} + }}""" + args = ["-arch", arch] + + bif_fname = tools.get_output_filename('bootgen-in.sign.bif') + tools.write_file(bif_fname, bif_template, False) + args += ["-image", bif_fname, '-w', '-o', output_fname] + return self.run_cmd(*args) + + def fetch(self, method): + """Fetch bootgen from git""" + if method != bintool.FETCH_BUILD: + return None + + result = self.build_from_git( + 'https://github.com/Xilinx/bootgen', + 'all', + 'bootgen') + return result -- cgit v1.3.1 From 7fcfa9d930127377d5b3fb54256f468dcc288103 Mon Sep 17 00:00:00 2001 From: Lukas Funke Date: Thu, 3 Aug 2023 17:22:15 +0200 Subject: binman: etype: Add xilinx-bootgen etype This adds a new etype 'xilinx-bootgen'. By using this etype it is possible to created an signed SPL (FSBL in Xilinx terms) for ZynqMP boards. The etype uses Xilinx Bootgen tools in order to transform the SPL into a bootable image and sign the image with a given primary and secondary public key. For more information to signing the FSBL please refer to the Xilinx Bootgen documentation. Here is an example of the etype in use: spl { filename = "boot.signed.bin"; xilinx-bootgen { pmufw-filename = "pmu-firmware.elf"; psk-key-name-hint = "psk0"; ssk-key-name-hint = "ssk0"; auth-params = "ppk_select=0", "spk_id=0x00000000"; u-boot-spl-nodtb { }; u-boot-spl-dtb { }; }; }; For this to work the hash of the primary public key has to be fused into the ZynqMP device and authentication (RSA_EN) has to be set. For testing purposes: if ppk hash check should be skipped one can add the property 'fsbl_config = "bh_auth_enable";' to the etype. However, this should only be used for testing(!). Signed-off-by: Lukas Funke Reviewed-by: Simon Glass --- tools/binman/entries.rst | 75 ++++++++++++ tools/binman/etype/xilinx_bootgen.py | 225 +++++++++++++++++++++++++++++++++++ 2 files changed, 300 insertions(+) create mode 100644 tools/binman/etype/xilinx_bootgen.py diff --git a/tools/binman/entries.rst b/tools/binman/entries.rst index f2376932be6..e7dfe6b2a36 100644 --- a/tools/binman/entries.rst +++ b/tools/binman/entries.rst @@ -2667,3 +2667,78 @@ may be used instead. +.. _etype_xilinx_bootgen: + +Entry: xilinx-bootgen: Signed SPL boot image for Xilinx ZynqMP devices +---------------------------------------------------------------------- + +Properties / Entry arguments: + - auth-params: (Optional) Authentication parameters passed to bootgen + - fsbl-config: (Optional) FSBL parameters passed to bootgen + - keysrc-enc: (Optional) Key source when using decryption engine + - pmufw-filename: Filename of PMU firmware. Default: pmu-firmware.elf + - psk-key-name-hint: Name of primary secret key to use for signing the + secondardy public key. Format: .pem file + - ssk-key-name-hint: Name of secondardy secret key to use for signing + the boot image. Format: .pem file + +The etype is used to create a boot image for Xilinx ZynqMP +devices. + +Information for signed images: + +In AMD/Xilinx SoCs, two pairs of public and secret keys are used +- primary and secondary. The function of the primary public/secret key pair +is to authenticate the secondary public/secret key pair. +The function of the secondary key is to sign/verify the boot image. [1] + +AMD/Xilinx uses the following terms for private/public keys [1]: + + PSK = Primary Secret Key (Used to sign Secondary Public Key) + PPK = Primary Public Key (Used to verify Secondary Public Key) + SSK = Secondary Secret Key (Used to sign the boot image/partitions) + SPK = Used to verify the actual boot image + +The following example builds a signed boot image. The fuses of +the primary public key (ppk) should be fused together with the RSA_EN flag. + +Example node:: + + spl { + filename = "boot.signed.bin"; + + xilinx-bootgen { + psk-key-name-hint = "psk0"; + ssk-key-name-hint = "ssk0"; + auth-params = "ppk_select=0", "spk_id=0x00000000"; + + u-boot-spl-nodtb { + }; + u-boot-spl-pubkey-dtb { + algo = "sha384,rsa4096"; + required = "conf"; + key-name-hint = "dev"; + }; + }; + }; + +For testing purposes, e.g. if no RSA_EN should be fused, one could add +the "bh_auth_enable" flag in the fsbl-config field. This will skip the +verification of the ppk fuses and boot the image, even if ppk hash is +invalid. + +Example node:: + + xilinx-bootgen { + psk-key-name-hint = "psk0"; + psk-key-name-hint = "ssk0"; + ... + fsbl-config = "bh_auth_enable"; + ... + }; + +[1] https://docs.xilinx.com/r/en-US/ug1283-bootgen-user-guide/Using-Authentication + + + + diff --git a/tools/binman/etype/xilinx_bootgen.py b/tools/binman/etype/xilinx_bootgen.py new file mode 100644 index 00000000000..70a4b2e2429 --- /dev/null +++ b/tools/binman/etype/xilinx_bootgen.py @@ -0,0 +1,225 @@ +# SPDX-License-Identifier: GPL-2.0+ +# Copyright (c) 2023 Weidmueller GmbH +# Written by Lukas Funke +# +# Entry-type module for Zynq(MP) boot images (boot.bin) +# + +import tempfile + +from collections import OrderedDict + +from binman import elf +from binman.etype.section import Entry_section + +from dtoc import fdt_util + +from u_boot_pylib import tools +from u_boot_pylib import command + +# pylint: disable=C0103 +class Entry_xilinx_bootgen(Entry_section): + """Signed SPL boot image for Xilinx ZynqMP devices + + Properties / Entry arguments: + - auth-params: (Optional) Authentication parameters passed to bootgen + - fsbl-config: (Optional) FSBL parameters passed to bootgen + - keysrc-enc: (Optional) Key source when using decryption engine + - pmufw-filename: Filename of PMU firmware. Default: pmu-firmware.elf + - psk-key-name-hint: Name of primary secret key to use for signing the + secondardy public key. Format: .pem file + - ssk-key-name-hint: Name of secondardy secret key to use for signing + the boot image. Format: .pem file + + The etype is used to create a boot image for Xilinx ZynqMP + devices. + + Information for signed images: + + In AMD/Xilinx SoCs, two pairs of public and secret keys are used + - primary and secondary. The function of the primary public/secret key pair + is to authenticate the secondary public/secret key pair. + The function of the secondary key is to sign/verify the boot image. [1] + + AMD/Xilinx uses the following terms for private/public keys [1]: + + PSK = Primary Secret Key (Used to sign Secondary Public Key) + PPK = Primary Public Key (Used to verify Secondary Public Key) + SSK = Secondary Secret Key (Used to sign the boot image/partitions) + SPK = Used to verify the actual boot image + + The following example builds a signed boot image. The fuses of + the primary public key (ppk) should be fused together with the RSA_EN flag. + + Example node:: + + spl { + filename = "boot.signed.bin"; + + xilinx-bootgen { + psk-key-name-hint = "psk0"; + ssk-key-name-hint = "ssk0"; + auth-params = "ppk_select=0", "spk_id=0x00000000"; + + u-boot-spl-nodtb { + }; + u-boot-spl-pubkey-dtb { + algo = "sha384,rsa4096"; + required = "conf"; + key-name-hint = "dev"; + }; + }; + }; + + For testing purposes, e.g. if no RSA_EN should be fused, one could add + the "bh_auth_enable" flag in the fsbl-config field. This will skip the + verification of the ppk fuses and boot the image, even if ppk hash is + invalid. + + Example node:: + + xilinx-bootgen { + psk-key-name-hint = "psk0"; + psk-key-name-hint = "ssk0"; + ... + fsbl-config = "bh_auth_enable"; + ... + }; + + [1] https://docs.xilinx.com/r/en-US/ug1283-bootgen-user-guide/Using-Authentication + + """ + def __init__(self, section, etype, node): + super().__init__(section, etype, node) + self._auth_params = None + self._entries = OrderedDict() + self._filename = None + self._fsbl_config = None + self._keysrc_enc = None + self._pmufw_filename = None + self._psk_key_name_hint = None + self._ssk_key_name_hint = None + self.align_default = None + self.bootgen = None + self.required_props = ['pmufw-filename', + 'psk-key-name-hint', + 'ssk-key-name-hint'] + + def ReadNode(self): + """Read properties from the xilinx-bootgen node""" + super().ReadNode() + self._auth_params = fdt_util.GetStringList(self._node, + 'auth-params') + self._filename = fdt_util.GetString(self._node, 'filename') + self._fsbl_config = fdt_util.GetStringList(self._node, + 'fsbl-config') + self._keysrc_enc = fdt_util.GetString(self._node, + 'keysrc-enc') + self._pmufw_filename = fdt_util.GetString(self._node, 'pmufw-filename') + self._psk_key_name_hint = fdt_util.GetString(self._node, + 'psk-key-name-hint') + self._ssk_key_name_hint = fdt_util.GetString(self._node, + 'ssk-key-name-hint') + self.ReadEntries() + + @classmethod + def _ToElf(cls, data, output_fname): + """Convert SPL object file to bootable ELF file + + Args: + data (bytearray): u-boot-spl-nodtb + u-boot-spl-pubkey-dtb obj file + data + output_fname (str): Filename of converted FSBL ELF file + """ + platform_elfflags = {"aarch64": + ["-B", "aarch64", "-O", "elf64-littleaarch64"], + # amd64 support makes no sense for the target + # platform, but we include it here to enable + # testing on hosts + "x86_64": + ["-B", "i386", "-O", "elf64-x86-64"] + } + + gcc, args = tools.get_target_compile_tool('cc') + args += ['-dumpmachine'] + stdout = command.output(gcc, *args) + # split target machine triplet (arch, vendor, os) + arch, _, _ = stdout.split('-') + + spl_elf = elf.DecodeElf(tools.read_file( + tools.get_input_filename('spl/u-boot-spl')), 0) + + # Obj file to swap data and text section (rename-section) + with tempfile.NamedTemporaryFile(prefix="u-boot-spl-pubkey-", + suffix=".o.tmp", + dir=tools.get_output_dir())\ + as tmp_obj: + input_objcopy_fname = tmp_obj.name + # Align packed content to 4 byte boundary + pad = bytearray(tools.align(len(data), 4) - len(data)) + tools.write_file(input_objcopy_fname, data + pad) + # Final output elf file which contains a valid start address + with tempfile.NamedTemporaryFile(prefix="u-boot-spl-pubkey-elf-", + suffix=".o.tmp", + dir=tools.get_output_dir())\ + as tmp_elf_obj: + input_ld_fname = tmp_elf_obj.name + objcopy, args = tools.get_target_compile_tool('objcopy') + args += ["--rename-section", ".data=.text", + "-I", "binary"] + args += platform_elfflags[arch] + args += [input_objcopy_fname, input_ld_fname] + command.run(objcopy, *args) + + ld, args = tools.get_target_compile_tool('ld') + args += [input_ld_fname, '-o', output_fname, + "--defsym", f"_start={hex(spl_elf.entry)}", + "-Ttext", hex(spl_elf.entry)] + command.run(ld, *args) + + def BuildSectionData(self, required): + """Pack node content, and create bootable, signed ZynqMP boot image + + The method collects the content of this node (usually SPL + dtb) and + converts them to an ELF file. The ELF file is passed to the + Xilinx bootgen tool which packs the SPL ELF file together with + Platform Management Unit (PMU) firmware into a bootable image + for ZynqMP devices. The image is signed within this step. + + The result is a bootable, signed SPL image for Xilinx ZynqMP devices. + """ + data = super().BuildSectionData(required) + bootbin_fname = self._filename if self._filename else \ + tools.get_output_filename( + f'boot.{self.GetUniqueName()}.bin') + + pmufw_elf_fname = tools.get_input_filename(self._pmufw_filename) + psk_fname = tools.get_input_filename(self._psk_key_name_hint + ".pem") + ssk_fname = tools.get_input_filename(self._ssk_key_name_hint + ".pem") + fsbl_config = ";".join(self._fsbl_config) if self._fsbl_config else None + auth_params = ";".join(self._auth_params) if self._auth_params else None + + spl_elf_fname = tools.get_output_filename('u-boot-spl-pubkey.dtb.elf') + + # We need to convert to node content (see above) into an ELF + # file in order to be processed by bootgen. + self._ToElf(bytearray(data), spl_elf_fname) + + # Call Bootgen in order to sign the SPL + if self.bootgen.sign('zynqmp', spl_elf_fname, pmufw_elf_fname, + psk_fname, ssk_fname, fsbl_config, + auth_params, self._keysrc_enc, bootbin_fname) is None: + # Bintool is missing; just use empty data as the output + self.record_missing_bintool(self.bootgen) + data = tools.get_bytes(0, 1024) + else: + data = tools.read_file(bootbin_fname) + + self.SetContents(data) + + return data + + # pylint: disable=C0116 + def AddBintools(self, btools): + super().AddBintools(btools) + self.bootgen = self.AddBintool(btools, 'bootgen') -- cgit v1.3.1 From d8a2d3b2901932179c5ee562c01473dd8cf77ae1 Mon Sep 17 00:00:00 2001 From: Lukas Funke Date: Thu, 3 Aug 2023 17:22:14 +0200 Subject: binman: ftest: Add test for xilinx-bootgen etype Add test for the 'xilinx-bootgen' etype Signed-off-by: Lukas Funke Reviewed-by: Simon Glass Allow missing bootgen tool; comment testXilinxBootgenMissing() comment: Signed-off-by: Simon Glass --- tools/binman/ftest.py | 77 +++++++++++++++++++++++ tools/binman/test/307_xilinx_bootgen_sign.dts | 22 +++++++ tools/binman/test/308_xilinx_bootgen_sign_enc.dts | 24 +++++++ 3 files changed, 123 insertions(+) create mode 100644 tools/binman/test/307_xilinx_bootgen_sign.dts create mode 100644 tools/binman/test/308_xilinx_bootgen_sign_enc.dts diff --git a/tools/binman/ftest.py b/tools/binman/ftest.py index 78389b34a71..1293e9dbf42 100644 --- a/tools/binman/ftest.py +++ b/tools/binman/ftest.py @@ -7139,5 +7139,82 @@ fdt fdtmap Extract the devicetree blob from the fdtmap self.assertEqual(fdt_util.GetString(key_node, "key-name-hint"), "key") + def testXilinxBootgenSigning(self): + """Test xilinx-bootgen etype""" + bootgen = bintool.Bintool.create('bootgen') + self._CheckBintool(bootgen) + data = tools.read_file(self.TestFile("key.key")) + self._MakeInputFile("psk.pem", data) + self._MakeInputFile("ssk.pem", data) + self._SetupPmuFwlElf() + self._SetupSplElf() + self._DoReadFileRealDtb('307_xilinx_bootgen_sign.dts') + image_fname = tools.get_output_filename('image.bin') + + # Read partition header table and check if authentication is enabled + bootgen_out = bootgen.run_cmd("-arch", "zynqmp", + "-read", image_fname, "pht").splitlines() + attributes = {"authentication": None, + "core": None, + "encryption": None} + + for l in bootgen_out: + for a in attributes.keys(): + if a in l: + m = re.match(fr".*{a} \[([^]]+)\]", l) + attributes[a] = m.group(1) + + self.assertTrue(attributes['authentication'] == "rsa") + self.assertTrue(attributes['core'] == "a53-0") + self.assertTrue(attributes['encryption'] == "no") + + def testXilinxBootgenSigningEncryption(self): + """Test xilinx-bootgen etype""" + bootgen = bintool.Bintool.create('bootgen') + self._CheckBintool(bootgen) + data = tools.read_file(self.TestFile("key.key")) + self._MakeInputFile("psk.pem", data) + self._MakeInputFile("ssk.pem", data) + self._SetupPmuFwlElf() + self._SetupSplElf() + self._DoReadFileRealDtb('308_xilinx_bootgen_sign_enc.dts') + image_fname = tools.get_output_filename('image.bin') + + # Read boot header in order to verify encryption source and + # encryption parameter + bootgen_out = bootgen.run_cmd("-arch", "zynqmp", + "-read", image_fname, "bh").splitlines() + attributes = {"auth_only": + {"re": r".*auth_only \[([^]]+)\]", "value": None}, + "encryption_keystore": + {"re": r" *encryption_keystore \(0x28\) : (.*)", + "value": None}, + } + + for l in bootgen_out: + for a in attributes.keys(): + if a in l: + m = re.match(attributes[a]['re'], l) + attributes[a] = m.group(1) + + # Check if fsbl-attribute is set correctly + self.assertTrue(attributes['auth_only'] == "true") + # Check if key is stored in efuse + self.assertTrue(attributes['encryption_keystore'] == "0xa5c3c5a3") + + def testXilinxBootgenMissing(self): + """Test that binman still produces an image if bootgen is missing""" + data = tools.read_file(self.TestFile("key.key")) + self._MakeInputFile("psk.pem", data) + self._MakeInputFile("ssk.pem", data) + self._SetupPmuFwlElf() + self._SetupSplElf() + with test_util.capture_sys_output() as (_, stderr): + self._DoTestFile('307_xilinx_bootgen_sign.dts', + force_missing_bintools='bootgen') + err = stderr.getvalue() + self.assertRegex(err, + "Image 'image'.*missing bintools.*: bootgen") + if __name__ == "__main__": unittest.main() diff --git a/tools/binman/test/307_xilinx_bootgen_sign.dts b/tools/binman/test/307_xilinx_bootgen_sign.dts new file mode 100644 index 00000000000..02acf8652a5 --- /dev/null +++ b/tools/binman/test/307_xilinx_bootgen_sign.dts @@ -0,0 +1,22 @@ +// SPDX-License-Identifier: GPL-2.0+ + +/dts-v1/; + +/ { + #address-cells = <1>; + #size-cells = <1>; + + binman { + xilinx-bootgen { + auth-params = "ppk_select=0", "spk_id=0x00000000"; + pmufw-filename = "pmu-firmware.elf"; + psk-key-name-hint = "psk"; + ssk-key-name-hint = "ssk"; + + u-boot-spl-nodtb { + }; + u-boot-spl-dtb { + }; + }; + }; +}; diff --git a/tools/binman/test/308_xilinx_bootgen_sign_enc.dts b/tools/binman/test/308_xilinx_bootgen_sign_enc.dts new file mode 100644 index 00000000000..5d7ce4c1f5a --- /dev/null +++ b/tools/binman/test/308_xilinx_bootgen_sign_enc.dts @@ -0,0 +1,24 @@ +// SPDX-License-Identifier: GPL-2.0+ + +/dts-v1/; + +/ { + #address-cells = <1>; + #size-cells = <1>; + + binman { + xilinx-bootgen { + auth-params = "ppk_select=0", "spk_id=0x00000000"; + fsbl-config = "auth_only"; + keysrc-enc = "efuse_red_key"; + pmufw-filename = "pmu-firmware.elf"; + psk-key-name-hint = "psk"; + ssk-key-name-hint = "ssk"; + + u-boot-spl-nodtb { + }; + u-boot-spl-dtb { + }; + }; + }; +}; -- cgit v1.3.1 From b49662083fea511360e9502b6a239cb038610397 Mon Sep 17 00:00:00 2001 From: Jaehoon Chung Date: Tue, 1 Aug 2023 19:17:00 +0900 Subject: event: Fix a wrong type_name from dm_post_init to dm_post_init_f DM_POST_INIT was changed to DM_POST_INIT_F. To debug correct message, change type_name from dm_post_init to dm_post_init_f. Signed-off-by: Jaehoon Chung Reviewed-by: Simon Glass s/an/a/ : Signed-off-by: Simon Glass --- common/event.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/common/event.c b/common/event.c index 20720c52839..3224e281222 100644 --- a/common/event.c +++ b/common/event.c @@ -27,7 +27,7 @@ const char *const type_name[] = { "test", /* Events related to driver model */ - "dm_post_init", + "dm_post_init_f", "dm_pre_probe", "dm_post_probe", "dm_pre_remove", -- cgit v1.3.1 From 1c81e0808b57d6535182632bc45696e256a8671c Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Thu, 3 Aug 2023 12:51:36 -0600 Subject: buildman: Exit after reading toolchain Recent refactoring changed buildman to continue operation after fetching a toolchain. Fix this. Fixes: b8680646521 ("bulidman: Move toolchain handling to a function") Signed-off-by: Simon Glass --- tools/buildman/control.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/tools/buildman/control.py b/tools/buildman/control.py index 5c5720034b6..f2ffb7f5b4a 100644 --- a/tools/buildman/control.py +++ b/tools/buildman/control.py @@ -610,6 +610,9 @@ def do_buildman(args, toolchains=None, make_func=None, brds=None, toolchains = get_toolchains(toolchains, col, args.override_toolchain, args.fetch_arch, args.list_tool_chains, args.verbose) + if isinstance(toolchains, int): + return toolchains + output_dir = setup_output_dir( args.output_dir, args.work_in_output, args.branch, args.no_subdirs, col, clean_dir) -- cgit v1.3.1 From 48d4c0a85d6f7fdb46dddcaa8a5f5b5c4290819f Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Thu, 3 Aug 2023 12:51:37 -0600 Subject: buildman: Drop warning about orphaned defconfigs Some boards use a MAINTAINERS entry to specify common files without referencing any defconfigs. This is allowed and should not result in a warning. Drop the warning in this case. Signed-off-by: Simon Glass --- tools/buildman/boards.py | 7 ------- tools/buildman/func_test.py | 9 ++------- 2 files changed, 2 insertions(+), 14 deletions(-) diff --git a/tools/buildman/boards.py b/tools/buildman/boards.py index 83adbf167c7..eef3f19f7ad 100644 --- a/tools/buildman/boards.py +++ b/tools/buildman/boards.py @@ -377,16 +377,9 @@ class MaintainersDatabase: Args: linenum (int): Current line number """ - added = False if targets: for target in targets: self.database[target] = (status, maintainers) - added = True - if not added and (status != '-' and maintainers): - leaf = fname[len(srcdir) + 1:] - if leaf != 'MAINTAINERS': - self.warnings.append( - f'WARNING: orphaned defconfig in {leaf} ending at line {linenum + 1}') targets = [] maintainers = [] diff --git a/tools/buildman/func_test.py b/tools/buildman/func_test.py index 3115700f07b..55dd494fe8e 100644 --- a/tools/buildman/func_test.py +++ b/tools/buildman/func_test.py @@ -926,10 +926,7 @@ Active aarch64 armv8 - armltd total_compute board2 tools.write_file(main, data, binary=False) params_list, warnings = self._boards.build_board_list(config_dir, src) self.assertEquals(2, len(params_list)) - self.assertEquals( - ["WARNING: no maintainers for 'board0'", - 'WARNING: orphaned defconfig in boards/board0/MAINTAINERS ending at line 4', - ], warnings) + self.assertEquals(["WARNING: no maintainers for 'board0'"], warnings) # Mark a board as orphaned - this should give a warning lines = ['S: Orphaned' if line.startswith('S') else line @@ -969,9 +966,7 @@ Active aarch64 armv8 - armltd total_compute board2 tools.write_file(main, both_data + extra, binary=False) params_list, warnings = self._boards.build_board_list(config_dir, src) self.assertEquals(2, len(params_list)) - self.assertEquals( - ['WARNING: orphaned defconfig in boards/board0/MAINTAINERS ending at line 16'], - warnings) + self.assertFalse(warnings) # Add another TARGET to the Kconfig tools.write_file(main, both_data, binary=False) -- cgit v1.3.1