From 0491144f78e2eff2058c1c40f077769d39f1f0c4 Mon Sep 17 00:00:00 2001 From: Mikko Parpala <114905865+mparpala@users.noreply.github.com> Date: Fri, 20 Dec 2024 11:52:37 +0200 Subject: [PATCH] suit: Add nRF9280 support (#151) Add nRF9280 to suit-generator. Signed-off-by: Mikko Parpala --- ncs/Kconfig | 26 ++++---- ncs/build.py | 8 +++ suit_generator/cmd_image.py | 129 +++++++++++++++++++++++++++++++++++- 3 files changed, 148 insertions(+), 15 deletions(-) diff --git a/ncs/Kconfig b/ncs/Kconfig index d6f7f1a..296f9fa 100755 --- a/ncs/Kconfig +++ b/ncs/Kconfig @@ -10,17 +10,17 @@ config SSF_SUIT_SERVICE_ENABLED config SUIT_ENVELOPE_TEMPLATE_FILENAME string "Path to the envelope template" - default "app_envelope.yaml.jinja2" if SOC_NRF54H20_CPUAPP_COMMON && !SUIT_RECOVERY - default "rad_envelope.yaml.jinja2" if SOC_NRF54H20_CPURAD_COMMON && !SUIT_RECOVERY - default "app_recovery_local_envelope.yaml.jinja2" if SOC_NRF54H20_CPUAPP_COMMON && SUIT_RECOVERY - default "rad_recovery_envelope.yaml.jinja2" if SOC_NRF54H20_CPURAD_COMMON && SUIT_RECOVERY + default "app_envelope.yaml.jinja2" if (SOC_NRF54H20_CPUAPP_COMMON || SOC_NRF9230_ENGB_CPUAPP) && !SUIT_RECOVERY + default "rad_envelope.yaml.jinja2" if (SOC_NRF54H20_CPURAD_COMMON || SOC_NRF9230_ENGB_CPURAD) && !SUIT_RECOVERY + default "app_recovery_local_envelope.yaml.jinja2" if (SOC_NRF54H20_CPUAPP_COMMON || SOC_NRF9230_ENGB_CPUAPP) && SUIT_RECOVERY + default "rad_recovery_envelope.yaml.jinja2" if (SOC_NRF54H20_CPURAD_COMMON || SOC_NRF9230_ENGB_CPURAD) && SUIT_RECOVERY config SUIT_ENVELOPE_TARGET string "Target name inside the envelope templates" - default "application" if SOC_NRF54H20_CPUAPP_COMMON && !SUIT_RECOVERY - default "radio" if SOC_NRF54H20_CPURAD_COMMON && !SUIT_RECOVERY - default "app_recovery_img" if SOC_NRF54H20_CPUAPP_COMMON && SUIT_RECOVERY - default "rad_recovery" if SOC_NRF54H20_CPURAD_COMMON && SUIT_RECOVERY + default "application" if (SOC_NRF54H20_CPUAPP_COMMON || SOC_NRF9230_ENGB_CPUAPP) && !SUIT_RECOVERY + default "radio" if (SOC_NRF54H20_CPURAD_COMMON || SOC_NRF9230_ENGB_CPURAD) && !SUIT_RECOVERY + default "app_recovery" if (SOC_NRF54H20_CPUAPP_COMMON || SOC_NRF9230_ENGB_CPUAPP) && SUIT_RECOVERY + default "rad_recovery" if (SOC_NRF54H20_CPURAD_COMMON || SOC_NRF9230_ENGB_CPURAD) && SUIT_RECOVERY config SUIT_ENVELOPE_OUTPUT_ARTIFACT string "Name of the output merged artifact" @@ -32,7 +32,7 @@ config SUIT_RECOVERY config SUIT_LOCAL_ENVELOPE_GENERATE bool "Generate local envelope" - default y if SOC_NRF54H20_CPUAPP_COMMON || SOC_NRF54H20_CPURAD_COMMON + default y if SOC_NRF54H20_CPUAPP_COMMON || SOC_NRF54H20_CPURAD_COMMON || SOC_NRF9230_ENGB_CPUAPP || SOC_NRF9230_ENGB_CPURAD config SUIT_DFU_CACHE_EXTRACT_IMAGE bool "Extract firmware image to DFU cache" @@ -53,9 +53,9 @@ config SUIT_DFU_CACHE_EXTRACT_IMAGE_PARTITION config SUIT_DFU_CACHE_EXTRACT_IMAGE_URI string "The URI used as key for the image in the DFU cache" - default "cache://application.bin" if SOC_NRF54H20_CPUAPP_COMMON && !SUIT_RECOVERY - default "cache://radio.bin" if SOC_NRF54H20_CPURAD_COMMON && !SUIT_RECOVERY - default "cache://app_recovery.bin" if SOC_NRF54H20_CPUAPP_COMMON && SUIT_RECOVERY - default "cache://rad_recovery.bin" if SOC_NRF54H20_CPURAD_COMMON && SUIT_RECOVERY + default "cache://application.bin" if (SOC_NRF54H20_CPUAPP_COMMON || SOC_NRF9230_ENGB_CPUAPP) && !SUIT_RECOVERY + default "cache://radio.bin" if (SOC_NRF54H20_CPURAD_COMMON || SOC_NRF9230_ENGB_CPURAD) && !SUIT_RECOVERY + default "cache://app_recovery.bin" if (SOC_NRF54H20_CPUAPP_COMMON || SOC_NRF9230_ENGB_CPUAPP) && SUIT_RECOVERY + default "cache://rad_recovery.bin" if (SOC_NRF54H20_CPURAD_COMMON || SOC_NRF9230_ENGB_CPURAD) && SUIT_RECOVERY endif # SUIT_DFU_CACHE_EXTRACT_IMAGE diff --git a/ncs/build.py b/ncs/build.py index e747c6a..96818b7 100755 --- a/ncs/build.py +++ b/ncs/build.py @@ -231,6 +231,13 @@ def get_absolute_address(node, use_offset: bool = True): default=None, help="Path to KConfig file", ) + cmd_storage_arg_parser.add_argument( + "--soc", + required=False, + type=str, + default="nrf54h20", + help="SoC device (nrf54h20 or nrf9280)", + ) cmd_update_arg_parser = subparsers.add_parser( UPDATE_CMD, help="Generate files needed for Secure Domain update", parents=[parent_parser] @@ -284,6 +291,7 @@ def get_absolute_address(node, use_offset: bool = True): storage_output_directory=arguments.storage_output_directory, storage_address=arguments.storage_address, config_file=arguments.config_file, + soc=arguments.soc, ) elif arguments.command == UPDATE_CMD: ImageCreator.create_files_for_update( diff --git a/suit_generator/cmd_image.py b/suit_generator/cmd_image.py index 420a0c4..f6dd1a9 100644 --- a/suit_generator/cmd_image.py +++ b/suit_generator/cmd_image.py @@ -167,6 +167,46 @@ class EnvelopeStorage: "class_name": "nRF54H20_sys", "role": ManifestRole.SEC_SYSCTRL, }, + { + "vendor_name": "nordicsemi.com", + "class_name": "nRF9280_sample_root", + "role": ManifestRole.APP_ROOT, + }, + { + "vendor_name": "nordicsemi.com", + "class_name": "nRF9280_sample_app", + "role": ManifestRole.APP_LOCAL_1, + }, + { + "vendor_name": "nordicsemi.com", + "class_name": "nRF9280_sample_app_recovery", + "role": ManifestRole.APP_RECOVERY, + }, + { + "vendor_name": "nordicsemi.com", + "class_name": "nRF9280_sample_rad", + "role": ManifestRole.RAD_LOCAL_1, + }, + { + "vendor_name": "nordicsemi.com", + "class_name": "nRF9280_sample_rad_recovery", + "role": ManifestRole.RAD_RECOVERY, + }, + { + "vendor_name": "nordicsemi.com", + "class_name": "nRF9280_nordic_top", + "role": ManifestRole.SEC_TOP, + }, + { + "vendor_name": "nordicsemi.com", + "class_name": "nRF9280_sec", + "role": ManifestRole.SEC_SDFW, + }, + { + "vendor_name": "nordicsemi.com", + "class_name": "nRF9280_sys", + "role": ManifestRole.SEC_SYSCTRL, + }, ] def __init__(self, base_address: int, load_defaults=True, kconfig=None): @@ -273,7 +313,9 @@ def add_envelope(self, envelope: SuitEnvelope): raise GeneratorError(f"Unable to find slot for manifest with class id {class_id.hex()}") if slot[1] < len(envelope_bytes): - raise GeneratorError(f"Unable to fit manifest with class id ({len(class_id.hex())} > {slot})") + raise GeneratorError( + f"Unable to fit manifest with class id {class_id.hex()} ({len(envelope_bytes)} > {slot[1]})" + ) if role in self._envelopes.keys(): raise GeneratorError(f"Manifest with role {role} already added") @@ -387,6 +429,79 @@ class EnvelopeStorageNrf54h20(EnvelopeStorage): ] +class EnvelopeStorageNrf9280(EnvelopeStorage): + """Class generating SUIT storage binary in upcoming format.""" + + _LAYOUT = [ + { + "role": ManifestRole.SEC_TOP, + "offset": 4096, + "size": 1536, + "domain": ManifestDomain.SECURE, + }, + { + "role": ManifestRole.SEC_SDFW, + "offset": 2048, + "size": 1024, + "domain": ManifestDomain.SECURE, + }, + { + "role": ManifestRole.SEC_SYSCTRL, + "offset": 3072, + "size": 1024, + "domain": ManifestDomain.SECURE, + }, + { + "role": ManifestRole.RAD_RECOVERY, + "offset": 8192 + 1024 * 1, + "size": 1024, + "domain": ManifestDomain.RADIO, + }, + { + "role": ManifestRole.RAD_LOCAL_1, + "offset": 8192 + 1024 * 2, + "size": 1024, + "domain": ManifestDomain.RADIO, + }, + { + "role": ManifestRole.RAD_LOCAL_2, + "offset": 8192 + 1024 * 3, + "size": 1024, + "domain": ManifestDomain.RADIO, + }, + { + "role": ManifestRole.APP_ROOT, + "offset": 12288 + 1024 * 1, + "size": 2048, + "domain": ManifestDomain.APPLICATION, + }, + { + "role": ManifestRole.APP_RECOVERY, + "offset": 12288 + 1024 * 3, + "size": 2048, + "domain": ManifestDomain.APPLICATION, + }, + { + "role": ManifestRole.APP_LOCAL_1, + "offset": 12288 + 1024 * 5, + "size": 1024, + "domain": ManifestDomain.APPLICATION, + }, + { + "role": ManifestRole.APP_LOCAL_2, + "offset": 12288 + 1024 * 6, + "size": 1024, + "domain": ManifestDomain.APPLICATION, + }, + { + "role": ManifestRole.APP_LOCAL_3, + "offset": 12288 + 1024 * 7, + "size": 1024, + "domain": ManifestDomain.APPLICATION, + }, + ] + + class ImageCreator: """Helper class for extracting data from SUIT envelope and creating hex files.""" @@ -446,8 +561,15 @@ def _create_suit_storage_files_for_boot( storage_address: int, dir_name: str, config_file: str, + soc: str = "nrf54h20", ) -> None: - storage = EnvelopeStorageNrf54h20(storage_address, kconfig=config_file) + if soc == "nrf54h20": + storage = EnvelopeStorageNrf54h20(storage_address, kconfig=config_file) + elif soc == "nrf9280": + storage = EnvelopeStorageNrf9280(storage_address, kconfig=config_file) + else: + raise GeneratorError(f"Unknown soc: {soc}") + for envelope in envelopes: storage.add_envelope(envelope) @@ -487,6 +609,7 @@ def create_files_for_boot( storage_output_directory: str, storage_address: int, config_file: str | None, + soc: str = "nrf54h20", ) -> None: """Create storage and payload hex files allowing boot execution path. @@ -494,6 +617,7 @@ def create_files_for_boot( :param storage_output_directory: directory path to store hex files with SUIT storage contents :param storage_address: address of SUIT storage :param config_file: path to KConfig file containing MPI settings + :param soc: soc in use, nrf54h20 or nrf9280 """ try: envelopes = [] @@ -509,6 +633,7 @@ def create_files_for_boot( storage_address, storage_output_directory, config_file, + soc, ) except FileNotFoundError as error: raise GeneratorError(error)