drivers: firmware: nrf_ironside: add IRONside update service

Add an IPC service API for triggering updates of the Nordic IRONside SE
firmware using the IRONside call module.

Co-authored-by: Håkon Amundsen <haakon.amundsen@nordicsemi.no>
Signed-off-by: Jonathan Nilsen <jonathan.nilsen@nordicsemi.no>
This commit is contained in:
Jonathan Nilsen 2025-04-30 11:48:57 +02:00 committed by Benjamin Cabé
parent afc83895f4
commit 51609f0380
4 changed files with 107 additions and 0 deletions

View File

@ -6,3 +6,4 @@ zephyr_library()
zephyr_library_sources_ifdef(CONFIG_NRF_IRONSIDE_CALL call.c)
zephyr_library_sources_ifdef(CONFIG_NRF_IRONSIDE_CPUCONF_SERVICE cpuconf.c)
zephyr_library_sources_ifdef(CONFIG_NRF_IRONSIDE_UPDATE_SERVICE update.c)

View File

@ -37,4 +37,10 @@ config NRF_IRONSIDE_CPUCONF_SERVICE
help
Service used to boot local domain cores.
config NRF_IRONSIDE_UPDATE_SERVICE
bool "IRONside update service"
select NRF_IRONSIDE_CALL
help
Service used to update the IRONside SE firmware.
endmenu

View File

@ -0,0 +1,28 @@
/*
* Copyright (c) 2025 Nordic Semiconductor ASA
* SPDX-License-Identifier: Apache-2.0
*/
#include <zephyr/drivers/firmware/nrf_ironside/update.h>
#include <zephyr/drivers/firmware/nrf_ironside/call.h>
int ironside_update(const struct ironside_update_blob *update)
{
int err;
struct ironside_call_buf *const buf = ironside_call_alloc();
buf->id = IRONSIDE_CALL_ID_UPDATE_SERVICE_V0;
buf->args[IRONSIDE_UPDATE_SERVICE_UPDATE_PTR_IDX] = (uintptr_t)update;
ironside_call_dispatch(buf);
if (buf->status == IRONSIDE_CALL_STATUS_RSP_SUCCESS) {
err = buf->args[IRONSIDE_UPDATE_SERVICE_RETCODE_IDX];
} else {
err = buf->status;
}
ironside_call_release(buf);
return err;
}

View File

@ -0,0 +1,72 @@
/*
* Copyright (c) 2025 Nordic Semiconductor ASA
* SPDX-License-Identifier: Apache-2.0
*/
#ifndef ZEPHYR_INCLUDE_ZEPHYR_DRIVERS_FIRMWARE_NRF_IRONSIDE_UPDATE_H_
#define ZEPHYR_INCLUDE_ZEPHYR_DRIVERS_FIRMWARE_NRF_IRONSIDE_UPDATE_H_
#include <stdint.h>
#include <stddef.h>
/**
* @name Update service error codes.
* @{
*/
/** Caller does not have access to the provided update candidate buffer. */
#define IRONSIDE_UPDATE_ERROR_NOT_PERMITTED (1)
/** Failed to write the update metadata to SICR. */
#define IRONSIDE_UPDATE_ERROR_SICR_WRITE_FAILED (2)
/**
* @}
*/
/** Length of the update manifest in bytes */
#define IRONSIDE_UPDATE_MANIFEST_LENGTH (256)
/** Length of the update public key in bytes. */
#define IRONSIDE_UPDATE_PUBKEY_LENGTH (32)
/** Length of the update signature in bytes. */
#define IRONSIDE_UPDATE_SIGNATURE_LENGTH (64)
/* IRONside call identifiers with implicit versions.
*
* With the initial "version 0", the service ABI is allowed to break until the
* first production release of IRONside SE.
*/
#define IRONSIDE_CALL_ID_UPDATE_SERVICE_V0 1
/* Index of the update blob pointer within the service buffer. */
#define IRONSIDE_UPDATE_SERVICE_UPDATE_PTR_IDX (0)
/* Index of the return code within the service buffer. */
#define IRONSIDE_UPDATE_SERVICE_RETCODE_IDX (0)
/**
* @brief IRONside update blob.
*/
struct ironside_update_blob {
uint8_t manifest[IRONSIDE_UPDATE_MANIFEST_LENGTH];
uint8_t pubkey[IRONSIDE_UPDATE_PUBKEY_LENGTH];
uint8_t signature[IRONSIDE_UPDATE_SIGNATURE_LENGTH];
uint32_t firmware[];
};
/**
* @brief Request a firmware upgrade of the IRONside SE.
*
* This invokes the IRONside SE update service. The device must be restarted for the update
* to be installed. Check the update status in the application boot report to see if the update
* was successfully installed.
*
* @param update Pointer to update blob
*
* @retval -IRONSIDE_UPDATE_ERROR_NOT_PERMITTED if missing access to the update candidate.
* @retval -IRONSIDE_UPDATE_ERROR_SICR_WRITE_FAILED if writing update parameters to SICR failed.
* @returns Positive non-0 error status if reported by IRONside call.
* @returns 0 on a successful request (although the update itself may still fail).
*
*/
int ironside_update(const struct ironside_update_blob *update);
#endif /* ZEPHYR_INCLUDE_ZEPHYR_DRIVERS_FIRMWARE_NRF_IRONSIDE_UPDATE_H_ */