Lukas Funke | 09cb50f | 2023-08-03 17:22:13 +0200 | [diff] [blame] | 1 | # SPDX-License-Identifier: GPL-2.0+ |
| 2 | # Copyright (C) 2023 Weidmüller Interface GmbH & Co. KG |
| 3 | # Lukas Funke <lukas.funke@weidmueller.com> |
| 4 | # |
| 5 | """Bintool implementation for bootgen |
| 6 | |
| 7 | bootgen allows creating bootable SPL for Zynq(MP) |
| 8 | |
| 9 | Documentation is available via: |
| 10 | https://www.xilinx.com/support/documents/sw_manuals/xilinx2022_1/ug1283-bootgen-user-guide.pdf |
| 11 | |
| 12 | Source code is available at: |
| 13 | https://github.com/Xilinx/bootgen |
| 14 | |
| 15 | """ |
| 16 | |
| 17 | from binman import bintool |
| 18 | from u_boot_pylib import tools |
| 19 | |
| 20 | # pylint: disable=C0103 |
| 21 | class Bintoolbootgen(bintool.Bintool): |
| 22 | """Generate bootable fsbl image for zynq/zynqmp |
| 23 | |
| 24 | This bintools supports running Xilinx "bootgen" in order |
| 25 | to generate a bootable, authenticated image form an SPL. |
| 26 | |
| 27 | """ |
| 28 | def __init__(self, name): |
| 29 | super().__init__(name, 'Xilinx Bootgen', |
| 30 | version_regex=r'^\*\*\*\*\*\* *Xilinx Bootgen *(.*)', |
| 31 | version_args='-help') |
| 32 | |
| 33 | # pylint: disable=R0913 |
| 34 | def sign(self, arch, spl_elf_fname, pmufw_elf_fname, |
| 35 | psk_fname, ssk_fname, fsbl_config, auth_params, keysrc_enc, |
| 36 | output_fname): |
| 37 | """Sign SPL elf file and bundle it with PMU firmware into an image |
| 38 | |
| 39 | The method bundels the SPL together with a 'Platform Management Unit' |
| 40 | (PMU)[1] firmware into a single bootable image. The image in turn is |
| 41 | signed with the provided 'secondary secret key' (ssk), which in turn is |
| 42 | signed with the 'primary secret key' (psk). In order to verify the |
| 43 | authenticity of the ppk, it's hash has to be fused into the device |
| 44 | itself. |
| 45 | |
| 46 | In Xilinx terms the SPL is usually called 'FSBL' |
| 47 | (First Stage Boot Loader). The jobs of the SPL and the FSBL are mostly |
| 48 | the same: load bitstream, bootstrap u-boot. |
| 49 | |
| 50 | Args: |
| 51 | arch (str): Xilinx SoC architecture. Currently only 'zynqmp' is |
| 52 | supported. |
| 53 | spl_elf_fname (str): Filename of SPL ELF file. The filename must end |
| 54 | with '.elf' in order for bootgen to recognized it as an ELF |
| 55 | file. Otherwise the start address field is missinterpreted. |
| 56 | pmufw_elf_fname (str): Filename PMU ELF firmware. |
| 57 | psk_fname (str): Filename of the primary secret key (psk). The psk |
| 58 | is a .pem file which holds the RSA private key used for signing |
| 59 | the secondary secret key. |
| 60 | ssk_fname (str): Filename of the secondary secret key. The ssk |
| 61 | is a .pem file which holds the RSA private key used for signing |
| 62 | the actual boot firmware. |
| 63 | fsbl_config (str): FSBL config options. A string list of fsbl config |
| 64 | options. Valid values according to [2] are: |
| 65 | "bh_auth_enable": Boot Header Authentication Enable: RSA |
| 66 | authentication of the bootimage is done |
| 67 | excluding the verification of PPK hash and SPK ID. This is |
| 68 | useful for debugging before bricking a device. |
| 69 | "auth_only": Boot image is only RSA signed. FSBL should not be |
| 70 | decrypted. See the |
| 71 | Zynq UltraScale+ Device Technical Reference Manual (UG1085) |
| 72 | for more information. |
| 73 | There are more options which relate to PUF (physical unclonable |
| 74 | functions). Please refer to Xilinx manuals for further info. |
| 75 | auth_params (str): Authentication parameter. A semicolon separated |
| 76 | list of authentication parameters. Valid values according to [3] |
| 77 | are: |
| 78 | "ppk_select=<0|1>" - Select which ppk to use |
| 79 | "spk_id=<32-bit spk id>" - Specifies which SPK can be |
| 80 | used or revoked, default is 0x0 |
| 81 | "spk_select=<spk-efuse/user-efuse>" - To differentiate spk and |
| 82 | user efuses. |
| 83 | "auth_header" - To authenticate headers when no partition |
| 84 | is authenticated. |
| 85 | keysrc_enc (str): This specifies the Key source for encryption. |
| 86 | Valid values according to [3] are: |
| 87 | "bbram_red_key" - RED key stored in BBRAM |
| 88 | "efuse_red_key" - RED key stored in eFUSE |
| 89 | "efuse_gry_key" - Grey (Obfuscated) Key stored in eFUSE. |
| 90 | "bh_gry_key" - Grey (Obfuscated) Key stored in boot header |
| 91 | "bh_blk_key" - Black Key stored in boot header |
| 92 | "efuse_blk_key" - Black Key stored in eFUSE |
| 93 | "kup_key" - User Key |
| 94 | |
| 95 | output_fname (str): Filename where bootgen should write the result |
| 96 | |
| 97 | Returns: |
| 98 | str: Bootgen output from stdout |
| 99 | |
| 100 | [1] https://xilinx-wiki.atlassian.net/wiki/spaces/A/pages/18841724/PMU+Firmware |
| 101 | [2] https://docs.xilinx.com/r/en-US/ug1283-bootgen-user-guide/fsbl_config |
| 102 | [3] https://docs.xilinx.com/r/en-US/ug1283-bootgen-user-guide/auth_params |
| 103 | [4] https://docs.xilinx.com/r/en-US/ug1283-bootgen-user-guide/keysrc_encryption |
| 104 | """ |
| 105 | |
| 106 | _fsbl_config = f"[fsbl_config] {fsbl_config}" if fsbl_config else "" |
| 107 | _auth_params = f"[auth_params] {auth_params}" if auth_params else "" |
| 108 | _keysrc_enc = f"[keysrc_encryption] {keysrc_enc}" if keysrc_enc else "" |
| 109 | |
| 110 | bif_template = f"""u_boot_spl_aes_rsa: {{ |
| 111 | [pskfile] {psk_fname} |
| 112 | [sskfile] {ssk_fname} |
| 113 | {_keysrc_enc} |
| 114 | {_fsbl_config} |
| 115 | {_auth_params} |
| 116 | [ bootloader, |
| 117 | authentication = rsa, |
| 118 | destination_cpu=a53-0] {spl_elf_fname} |
| 119 | [pmufw_image] {pmufw_elf_fname} |
| 120 | }}""" |
| 121 | args = ["-arch", arch] |
| 122 | |
| 123 | bif_fname = tools.get_output_filename('bootgen-in.sign.bif') |
| 124 | tools.write_file(bif_fname, bif_template, False) |
| 125 | args += ["-image", bif_fname, '-w', '-o', output_fname] |
| 126 | return self.run_cmd(*args) |
| 127 | |
| 128 | def fetch(self, method): |
| 129 | """Fetch bootgen from git""" |
| 130 | if method != bintool.FETCH_BUILD: |
| 131 | return None |
| 132 | |
| 133 | result = self.build_from_git( |
| 134 | 'https://github.com/Xilinx/bootgen', |
| 135 | 'all', |
| 136 | 'bootgen') |
| 137 | return result |