[PATCH 1/5] tools: binman: add nxp_imx93cst etype for i.MX93 flash.bin signing
Jérémie Dautheribes (Schneider Electric) via U-Bo ot <[email protected]>
| Newsgroups | org.u-boot-project.lists.u-boot |
|---|---|
| Message-ID | <[email protected]> |
Add a new binman etype which allows signing both the SPL and U-Boot proper sections of i.MX93 flash.bin using CST. The implementation is largely derived from the nxp_imx8mcst etype, as the signing procedures for both platforms are quite similar. Signed-off-by: Jérémie Dautheribes (Schneider Electric) <[email protected]> --- .gitignore | 2 + tools/binman/etype/nxp_imx93cst.py | 143 +++++++++++++++++++++++++++++++++++++ 2 files changed, 145 insertions(+) diff --git a/.gitignore b/.gitignore index 0e09715cc60..5cb135fc58c 100644 --- a/.gitignore +++ b/.gitignore @@ -82,6 +82,8 @@ fit-dtb.blob* /keep-syms-lto.* /*imx8mimage* /*imx8mcst* +/*imx9image* +/*imx93cst* /*rcar4-sa0* /drivers/video/u_boot_logo.bmp.S /test/fdt_overlay/test-fdt-overlay-stacked.dtbo.S diff --git a/tools/binman/etype/nxp_imx93cst.py b/tools/binman/etype/nxp_imx93cst.py new file mode 100644 index 00000000000..e1528b13102 --- /dev/null +++ b/tools/binman/etype/nxp_imx93cst.py @@ -0,0 +1,143 @@ +# SPDX-License-Identifier: GPL-2.0+ +# Copyright 2026 (C) Bootlin +# Author: Jérémie Dautheribes <[email protected]> +# +# Derived from nxp_imx8mcst.py +# Copyright 2023-2024 Marek Vasut <[email protected]> + + +# Entry-type module for generating the i.MX93 code signing tool +# input configuration file and invocation of cst on generated +# input configuration file and input data to be signed. +# + +import configparser +import os +import struct + +from binman.etype.mkimage import Entry_mkimage +from binman.etype.section import Entry_section +from dtoc import fdt_util +from u_boot_pylib import tools + +CONTAINER_HDR_TAG = 0x87 +SPL_CONTAINER_OFFSET = 1024 # 0x400 +CONTAINER_HDR_SIZE = 16 +AHAB_IMAGE_ENTRY_FLAGS_OFFSET = 24 +ELE_IMAGE_CORE_AND_TYPE = 0x66 + +KEY_NAME = "sha384_secp384r1_v3_usr_crt" + +CSF_CONFIG_TEMPLATE = f""" +[Header] + Target = AHAB + Version = 1.0 + +[Install SRK] + File = "SRK_1_2_3_4_table.bin" + Source = "SRK1_{KEY_NAME}.pem" + Source index = 0 + Source set = OEM + Revocations = 0x0 + +[Authenticate Data] + File = "data.bin" + Offsets = 0x400 0x490 + +""" + + +class Entry_nxp_imx93cst(Entry_mkimage): + """NXP i.MX93 CST .cfg file generator and cst invoker""" + + def __init__(self, section, etype, node): + super().__init__(section, etype, node) + + def ReadNode(self): + super().ReadNode() + self.srk_table = os.getenv( + "SRK_TABLE", + fdt_util.GetString(self._node, "nxp,srk-table", "SRK_1_2_3_4_table.bin"), + ) + self.srk_crt = os.getenv( + "SRK_KEY", + fdt_util.GetString(self._node, "nxp,srk-crt", f"SRK1_{KEY_NAME}.pem"), + ) + self.ReadEntries() + + def BuildSectionData(self, required): + data, input_fname, uniq = self.collect_contents_to_file( + self._entries.values(), "input" + ) + + if struct.unpack("<B", data[3:4])[0] != CONTAINER_HDR_TAG: + # Unknown section type, pass input data through. + return data + + hdr_addr = 0 + + # The SPL AHAB image can optionally contain and start with the ELE FW, + # which is already signed by NXP. + # In this case, the SPL container header address is not 0x0. + + flags_offset = CONTAINER_HDR_SIZE + AHAB_IMAGE_ENTRY_FLAGS_OFFSET + image_flags = struct.unpack("<I", data[flags_offset : flags_offset + 4])[0] + # Detect the ELE FW from the core/type fields of its image entries + if (image_flags & 0xFF) == ELE_IMAGE_CORE_AND_TYPE: + hdr_addr = SPL_CONTAINER_OFFSET + + # Extract the signing offset from the i.MX container + signoffset = struct.unpack("<H", data[hdr_addr + 12 : hdr_addr + 14])[0] + + # The signing offset is relative to the container header address, + # so compute the absolute signing offset address + signoffset = signoffset + hdr_addr + + # Write out customized data to be signed + output_dname = tools.get_output_filename(f"nxp.cst-input-data.{uniq}") + tools.write_file(output_dname, data) + + # Generate CST configuration file used to sign payload + cfg_fname = tools.get_output_filename(f"nxp.csf-config-txt.{uniq}") + config = configparser.ConfigParser() + # Do not make key names lowercase + config.optionxform = str + # Load configuration template and modify keys of interest + config.read_string(CSF_CONFIG_TEMPLATE) + config["Install SRK"]["File"] = f'"{self.srk_table}"' + config["Install SRK"]["Source"] = f'"{self.srk_crt}"' + config["Authenticate Data"]["File"] = f'"{output_dname}"' + config["Authenticate Data"]["Offsets"] = f"{hdr_addr:#x} {signoffset:#x}" + + with open(cfg_fname, "w") as cfgf: + config.write(cfgf) + + output_fname = tools.get_output_filename(f"nxp.csf-output-blob.{uniq}") + args = ["-i", cfg_fname, "-o", output_fname] + if self.cst.run_cmd(*args) is not None: + outdata = tools.read_file(output_fname) + return outdata + else: + # Bintool is missing; just use the input data as the output + self.record_missing_bintool(self.cst) + return data + + def SetImagePos(self, image_pos): + # Customized SoC specific SetImagePos which skips the mkimage etype + # implementation and removes the 0x48 offset introduced there. That + # offset is only used for uImage/fitImage, which is not the case in + # here. + upto = 0x00 + for entry in super().GetEntries().values(): + entry.SetOffsetSize(upto, None) + + # Give up if any entries lack a size + if entry.size is None: + return + upto += entry.size + + Entry_section.SetImagePos(self, image_pos) + + def AddBintools(self, btools): + super().AddBintools(btools) + self.cst = self.AddBintool(btools, "cst") -- 2.55.0