diff --git a/subsys/sdfw_services/services/suit_service/CMakeLists.txt b/subsys/sdfw_services/services/suit_service/CMakeLists.txt index f0eb63fe42e3..e526d77cf75c 100644 --- a/subsys/sdfw_services/services/suit_service/CMakeLists.txt +++ b/subsys/sdfw_services/services/suit_service/CMakeLists.txt @@ -12,9 +12,11 @@ zephyr_library_sources(suit_mci.c) zephyr_library_sources(suit_invoke.c) zephyr_library_sources_ifdef(CONFIG_SUIT_PROCESSOR suit_auth.c) zephyr_library_sources_ifdef(CONFIG_SUIT_MANIFEST_VARIABLES suit_mfst_var.c) +zephyr_library_sources_ifdef(CONFIG_SUIT_IPUC suit_ipuc.c) zephyr_library_link_libraries(suit_utils) zephyr_library_link_libraries_ifdef(CONFIG_SUIT_MANIFEST_VARIABLES suit_manifest_variables) +zephyr_library_link_libraries_ifdef(CONFIG_SUIT_IPUC suit_ipuc) if(CONFIG_SUIT_STREAM_SOURCE_IPC) zephyr_library_link_libraries(suit_stream_sources_interface) diff --git a/subsys/sdfw_services/services/suit_service/suit_ipuc.c b/subsys/sdfw_services/services/suit_service/suit_ipuc.c new file mode 100644 index 000000000000..702a3af150f9 --- /dev/null +++ b/subsys/sdfw_services/services/suit_service/suit_ipuc.c @@ -0,0 +1,195 @@ +/* + * Copyright (c) 2025 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: LicenseRef-Nordic-5-Clause + */ + +#include +#include +#include +#include +#include +#include +#include "suit_service_decode.h" +#include "suit_service_encode.h" +#include "suit_service_types.h" +#include "suit_service_utils.h" + +#include +LOG_MODULE_REGISTER(suit_ipuc, CONFIG_SSF_SUIT_SERVICE_LOG_LEVEL); + +extern const struct ssf_client_srvc suit_srvc; + +suit_plat_err_t suit_ipuc_get_count(size_t *count) +{ + int err; + struct suit_req req = {0}; + struct suit_rsp rsp = {0}; + struct suit_get_ipuc_count_rsp *rsp_data = NULL; + const uint8_t *rsp_pkt = NULL; + + if (count == NULL) { + return SUIT_PLAT_ERR_INVAL; + } + + req.suit_req_msg_choice = SSF_SUIT_REQ_CHOICE(get_ipuc_count); + err = ssf_client_send_request(&suit_srvc, &req, &rsp, &rsp_pkt); + if (err != 0) { + LOG_ERR("ssf_client_send_request failed"); + return SUIT_PLAT_ERR_IPC; + } + + rsp_data = &rsp.SSF_SUIT_RSP(get_ipuc_count); + err = rsp_data->SSF_SUIT_RSP_ARG(get_ipuc_count, ret); + if (err != SUIT_PLAT_SUCCESS) { + ssf_client_decode_done(rsp_pkt); + LOG_ERR("ssf_client response return code: %d", err); + return err; + } + + *count = rsp_data->SSF_SUIT_RSP_ARG(get_ipuc_count, count); + + ssf_client_decode_done(rsp_pkt); + return err; +} + +suit_plat_err_t suit_ipuc_get_info(size_t idx, struct zcbor_string *component_id, + suit_manifest_role_t *role) +{ + int err; + struct suit_req req = {0}; + struct suit_rsp rsp = {0}; + struct suit_get_ipuc_info_req *req_data = NULL; + struct suit_get_ipuc_info_rsp *rsp_data = NULL; + const uint8_t *rsp_pkt = NULL; + + if (component_id == NULL || role == NULL) { + return SUIT_PLAT_ERR_INVAL; + } + + if (component_id->value == NULL) { + return SUIT_PLAT_ERR_INVAL; + } + + req.suit_req_msg_choice = SSF_SUIT_REQ_CHOICE(get_ipuc_info); + req_data = &req.SSF_SUIT_REQ(get_ipuc_info); + req_data->SSF_SUIT_REQ_ARG(get_ipuc_info, idx) = idx; + + err = ssf_client_send_request(&suit_srvc, &req, &rsp, &rsp_pkt); + if (err != 0) { + LOG_ERR("ssf_client_send_request failed"); + return SUIT_PLAT_ERR_IPC; + } + rsp_data = &rsp.SSF_SUIT_RSP(get_ipuc_info); + err = rsp_data->SSF_SUIT_RSP_ARG(get_ipuc_info, ret); + if (err != SUIT_PLAT_SUCCESS) { + ssf_client_decode_done(rsp_pkt); + LOG_ERR("ssf_client response return code: %d", err); + return err; + } + + struct zcbor_string *src_component_id = + &rsp_data->SSF_SUIT_RSP_ARG(get_ipuc_info, component_id); + + if (component_id->len < src_component_id->len) { + + ssf_client_decode_done(rsp_pkt); + return SUIT_PLAT_ERR_SIZE; + } + + memcpy((void *)component_id->value, src_component_id->value, src_component_id->len); + component_id->len = src_component_id->len; + *role = rsp_data->SSF_SUIT_RSP_ARG(get_ipuc_info, role); + ssf_client_decode_done(rsp_pkt); + +#if (defined CONFIG_SUIT_LOG_LEVEL_INF || defined CONFIG_SUIT_LOG_LEVEL_DBG) + suit_component_type_t component_type = SUIT_COMPONENT_TYPE_UNSUPPORTED; + + suit_plat_decode_component_type(component_id, &component_type); + + if (component_type == SUIT_COMPONENT_TYPE_MEM) { + uint8_t core_id = 0; + intptr_t run_address = 0; + size_t slot_size = 0; + + suit_plat_decode_component_id(component_id, &core_id, &run_address, &slot_size); + + LOG_INF("MEM, %08X, %d bytes, core: %d, mfst role: 0x%02X", + (unsigned int)run_address, slot_size, core_id, *role); + + } else { + LOG_INF("component_type: %d, mfst role: 0x%02X", component_type, *role); + } +#endif + + return err; +} + +suit_plat_err_t suit_ipuc_write_setup(struct zcbor_string *component_id, + struct zcbor_string *encryption_info, + struct zcbor_string *compression_info) +{ + int err; + struct suit_req req = {0}; + struct suit_rsp rsp = {0}; + struct suit_setup_write_ipuc_req *req_data = {0}; + + if (component_id == NULL) { + return SUIT_PLAT_ERR_INVAL; + } + + if (encryption_info != NULL || compression_info != NULL) { + /* Encryption and/or Compression are not supported yet + */ + return SUIT_PLAT_ERR_UNSUPPORTED; + } + + req.suit_req_msg_choice = SSF_SUIT_REQ_CHOICE(setup_write_ipuc); + req_data = &req.SSF_SUIT_REQ(setup_write_ipuc); + + req_data->SSF_SUIT_REQ_ARG(setup_write_ipuc, component_id).value = component_id->value; + req_data->SSF_SUIT_REQ_ARG(setup_write_ipuc, component_id).len = component_id->len; + req_data->SSF_SUIT_REQ_ARG(setup_write_ipuc, encryption_info).value = NULL; + req_data->SSF_SUIT_REQ_ARG(setup_write_ipuc, encryption_info).len = 0; + req_data->SSF_SUIT_REQ_ARG(setup_write_ipuc, compression_info).value = NULL; + req_data->SSF_SUIT_REQ_ARG(setup_write_ipuc, compression_info).len = 0; + + err = ssf_client_send_request(&suit_srvc, &req, &rsp, NULL); + if (err != 0) { + LOG_ERR("ssf_client_send_request failed"); + return SUIT_PLAT_ERR_IPC; + } + + return rsp.SSF_SUIT_RSP(setup_write_ipuc).SSF_SUIT_RSP_ARG(setup_write_ipuc, ret); +} + +suit_plat_err_t suit_ipuc_write(struct zcbor_string *component_id, size_t offset, uintptr_t buffer, + size_t chunk_size, bool last_chunk) +{ + int err; + struct suit_req req = {0}; + struct suit_rsp rsp = {0}; + struct suit_write_ipuc_req *req_data = {0}; + + if (component_id == NULL) { + return SUIT_PLAT_ERR_INVAL; + } + + req.suit_req_msg_choice = SSF_SUIT_REQ_CHOICE(write_ipuc); + req_data = &req.SSF_SUIT_REQ(write_ipuc); + + req_data->SSF_SUIT_REQ_ARG(write_ipuc, component_id).value = component_id->value; + req_data->SSF_SUIT_REQ_ARG(write_ipuc, component_id).len = component_id->len; + req_data->SSF_SUIT_REQ_ARG(write_ipuc, offset) = offset; + req_data->SSF_SUIT_REQ_ARG(write_ipuc, addr) = buffer; + req_data->SSF_SUIT_REQ_ARG(write_ipuc, size) = chunk_size; + req_data->SSF_SUIT_REQ_ARG(write_ipuc, last_chunk) = last_chunk; + + err = ssf_client_send_request(&suit_srvc, &req, &rsp, NULL); + if (err != 0) { + LOG_ERR("ssf_client_send_request failed"); + return SUIT_PLAT_ERR_IPC; + } + + return rsp.SSF_SUIT_RSP(write_ipuc).SSF_SUIT_RSP_ARG(write_ipuc, ret); +} diff --git a/subsys/sdfw_services/services/suit_service/suit_service.cddl b/subsys/sdfw_services/services/suit_service/suit_service.cddl index 5ee81f7b0118..85a6cf9abfe6 100644 --- a/subsys/sdfw_services/services/suit_service/suit_service.cddl +++ b/subsys/sdfw_services/services/suit_service/suit_service.cddl @@ -266,6 +266,54 @@ suit_authorize_process_dependency_rsp = ( ret: int, ) +; In-place updateable components +suit_get_ipuc_count_req = ( + 30, +) + +suit_get_ipuc_count_rsp = ( + 30, + ret: int, + count: uint +) + +suit_get_ipuc_info_req = ( + 31, + idx: uint +) + +suit_get_ipuc_info_rsp = ( + 31, + ret: int, + component_id: bstr, + role: int, +) + +suit_setup_write_ipuc_req = ( + 32, + component_id: bstr, + encryption_info: bstr, + compression_info: bstr, +) + +suit_setup_write_ipuc_rsp = ( + 32, + ret: int, +) + +suit_write_ipuc_req = ( + 33, + component_id: bstr, + offset: uint, + last_chunk: bool, + addr: uint, + size: uint, +) + +suit_write_ipuc_rsp = ( + 33, + ret: int, +) ; Missing image event notification message suit_evt_sub_req = ( @@ -397,6 +445,11 @@ suit_req = [ suit_get_supported_manifest_info_req / suit_authorize_process_dependency_req / + suit_get_ipuc_count_req / + suit_get_ipuc_info_req / + suit_setup_write_ipuc_req / + suit_write_ipuc_req / + suit_get_manifest_var_req / suit_set_manifest_var_req / @@ -428,6 +481,11 @@ suit_rsp = [ suit_get_supported_manifest_info_rsp / suit_authorize_process_dependency_rsp / + suit_get_ipuc_count_rsp / + suit_get_ipuc_info_rsp / + suit_setup_write_ipuc_rsp / + suit_write_ipuc_rsp / + suit_get_manifest_var_rsp / suit_set_manifest_var_rsp / diff --git a/subsys/sdfw_services/services/suit_service/zcbor_generated/suit_service_decode.c b/subsys/sdfw_services/services/suit_service/zcbor_generated/suit_service_decode.c index 8527ef1ebcc2..85eb214b844c 100644 --- a/subsys/sdfw_services/services/suit_service/zcbor_generated/suit_service_decode.c +++ b/subsys/sdfw_services/services/suit_service/zcbor_generated/suit_service_decode.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2024 Nordic Semiconductor ASA + * Copyright (c) 2025 Nordic Semiconductor ASA * * SPDX-License-Identifier: LicenseRef-Nordic-5-Clause */ @@ -65,6 +65,14 @@ static bool decode_suit_get_supported_manifest_info_req( static bool decode_suit_authorize_process_dependency_req( zcbor_state_t *state, struct suit_authorize_process_dependency_req *result); static bool +decode_suit_get_ipuc_info_req(zcbor_state_t *state, + struct suit_get_ipuc_info_req *result); +static bool +decode_suit_setup_write_ipuc_req(zcbor_state_t *state, + struct suit_setup_write_ipuc_req *result); +static bool decode_suit_write_ipuc_req(zcbor_state_t *state, + struct suit_write_ipuc_req *result); +static bool decode_suit_get_manifest_var_req(zcbor_state_t *state, struct suit_get_manifest_var_req *result); static bool @@ -107,6 +115,17 @@ static bool decode_suit_get_supported_manifest_info_rsp( static bool decode_suit_authorize_process_dependency_rsp( zcbor_state_t *state, struct suit_authorize_process_dependency_rsp *result); static bool +decode_suit_get_ipuc_count_rsp(zcbor_state_t *state, + struct suit_get_ipuc_count_rsp *result); +static bool +decode_suit_get_ipuc_info_rsp(zcbor_state_t *state, + struct suit_get_ipuc_info_rsp *result); +static bool +decode_suit_setup_write_ipuc_rsp(zcbor_state_t *state, + struct suit_setup_write_ipuc_rsp *result); +static bool decode_suit_write_ipuc_rsp(zcbor_state_t *state, + struct suit_write_ipuc_rsp *result); +static bool decode_suit_get_manifest_var_rsp(zcbor_state_t *state, struct suit_get_manifest_var_rsp *result); static bool @@ -368,6 +387,55 @@ static bool decode_suit_authorize_process_dependency_req( return res; } +static bool +decode_suit_get_ipuc_info_req(zcbor_state_t *state, + struct suit_get_ipuc_info_req *result) { + zcbor_log("%s\r\n", __func__); + + bool res = (((((zcbor_uint32_expect(state, (31)))) && + ((zcbor_uint32_decode( + state, (&(*result).suit_get_ipuc_info_req_idx))))))); + + log_result(state, res, __func__); + return res; +} + +static bool +decode_suit_setup_write_ipuc_req(zcbor_state_t *state, + struct suit_setup_write_ipuc_req *result) { + zcbor_log("%s\r\n", __func__); + + bool res = (( + (((zcbor_uint32_expect(state, (32)))) && + ((zcbor_bstr_decode( + state, (&(*result).suit_setup_write_ipuc_req_component_id)))) && + ((zcbor_bstr_decode( + state, (&(*result).suit_setup_write_ipuc_req_encryption_info)))) && + ((zcbor_bstr_decode( + state, (&(*result).suit_setup_write_ipuc_req_compression_info))))))); + + log_result(state, res, __func__); + return res; +} + +static bool decode_suit_write_ipuc_req(zcbor_state_t *state, + struct suit_write_ipuc_req *result) { + zcbor_log("%s\r\n", __func__); + + bool res = ((( + ((zcbor_uint32_expect(state, (33)))) && + ((zcbor_bstr_decode(state, + (&(*result).suit_write_ipuc_req_component_id)))) && + ((zcbor_uint32_decode(state, (&(*result).suit_write_ipuc_req_offset)))) && + ((zcbor_bool_decode(state, + (&(*result).suit_write_ipuc_req_last_chunk)))) && + ((zcbor_uint32_decode(state, (&(*result).suit_write_ipuc_req_addr)))) && + ((zcbor_uint32_decode(state, (&(*result).suit_write_ipuc_req_size))))))); + + log_result(state, res, __func__); + return res; +} + static bool decode_suit_get_manifest_var_req(zcbor_state_t *state, struct suit_get_manifest_var_req *result) { @@ -696,6 +764,63 @@ static bool decode_suit_authorize_process_dependency_rsp( return res; } +static bool +decode_suit_get_ipuc_count_rsp(zcbor_state_t *state, + struct suit_get_ipuc_count_rsp *result) { + zcbor_log("%s\r\n", __func__); + + bool res = ((( + ((zcbor_uint32_expect(state, (30)))) && + ((zcbor_int32_decode(state, (&(*result).suit_get_ipuc_count_rsp_ret)))) && + ((zcbor_uint32_decode(state, + (&(*result).suit_get_ipuc_count_rsp_count))))))); + + log_result(state, res, __func__); + return res; +} + +static bool +decode_suit_get_ipuc_info_rsp(zcbor_state_t *state, + struct suit_get_ipuc_info_rsp *result) { + zcbor_log("%s\r\n", __func__); + + bool res = (( + (((zcbor_uint32_expect(state, (31)))) && + ((zcbor_int32_decode(state, (&(*result).suit_get_ipuc_info_rsp_ret)))) && + ((zcbor_bstr_decode( + state, (&(*result).suit_get_ipuc_info_rsp_component_id)))) && + ((zcbor_int32_decode(state, + (&(*result).suit_get_ipuc_info_rsp_role))))))); + + log_result(state, res, __func__); + return res; +} + +static bool +decode_suit_setup_write_ipuc_rsp(zcbor_state_t *state, + struct suit_setup_write_ipuc_rsp *result) { + zcbor_log("%s\r\n", __func__); + + bool res = (((((zcbor_uint32_expect(state, (32)))) && + ((zcbor_int32_decode( + state, (&(*result).suit_setup_write_ipuc_rsp_ret))))))); + + log_result(state, res, __func__); + return res; +} + +static bool decode_suit_write_ipuc_rsp(zcbor_state_t *state, + struct suit_write_ipuc_rsp *result) { + zcbor_log("%s\r\n", __func__); + + bool res = + (((((zcbor_uint32_expect(state, (33)))) && + ((zcbor_int32_decode(state, (&(*result).suit_write_ipuc_rsp_ret))))))); + + log_result(state, res, __func__); + return res; +} + static bool decode_suit_get_manifest_var_rsp(zcbor_state_t *state, struct suit_get_manifest_var_rsp *result) { @@ -973,6 +1098,35 @@ static bool decode_suit_rsp(zcbor_state_t *state, struct suit_rsp *result) { (((*result).suit_rsp_msg_choice = suit_rsp_msg_suit_authorize_process_dependency_rsp_m_c), true))) || + (zcbor_union_elem_code(state) && + (((decode_suit_get_ipuc_count_rsp( + state, + (&(*result).suit_rsp_msg_suit_get_ipuc_count_rsp_m)))) && + (((*result).suit_rsp_msg_choice = + suit_rsp_msg_suit_get_ipuc_count_rsp_m_c), + true))) || + (zcbor_union_elem_code(state) && + (((decode_suit_get_ipuc_info_rsp( + state, + (&(*result).suit_rsp_msg_suit_get_ipuc_info_rsp_m)))) && + (((*result).suit_rsp_msg_choice = + suit_rsp_msg_suit_get_ipuc_info_rsp_m_c), + true))) || + (zcbor_union_elem_code(state) && + (((decode_suit_setup_write_ipuc_rsp( + state, + (&(*result) + .suit_rsp_msg_suit_setup_write_ipuc_rsp_m)))) && + (((*result).suit_rsp_msg_choice = + suit_rsp_msg_suit_setup_write_ipuc_rsp_m_c), + true))) || + (zcbor_union_elem_code(state) && + (((decode_suit_write_ipuc_rsp( + state, + (&(*result).suit_rsp_msg_suit_write_ipuc_rsp_m)))) && + (((*result).suit_rsp_msg_choice = + suit_rsp_msg_suit_write_ipuc_rsp_m_c), + true))) || (zcbor_union_elem_code(state) && (((decode_suit_get_manifest_var_rsp( state, @@ -1131,6 +1285,31 @@ static bool decode_suit_req(zcbor_state_t *state, struct suit_req *result) { (((*result).suit_req_msg_choice = suit_req_msg_suit_authorize_process_dependency_req_m_c), true))) || + (((zcbor_uint32_expect_union(state, (30)))) && + (((*result).suit_req_msg_choice = + suit_req_msg_suit_get_ipuc_count_req_m_c), + true)) || + (((decode_suit_get_ipuc_info_req( + state, + (&(*result).suit_req_msg_suit_get_ipuc_info_req_m)))) && + (((*result).suit_req_msg_choice = + suit_req_msg_suit_get_ipuc_info_req_m_c), + true)) || + (zcbor_union_elem_code(state) && + (((decode_suit_setup_write_ipuc_req( + state, + (&(*result) + .suit_req_msg_suit_setup_write_ipuc_req_m)))) && + (((*result).suit_req_msg_choice = + suit_req_msg_suit_setup_write_ipuc_req_m_c), + true))) || + (zcbor_union_elem_code(state) && + (((decode_suit_write_ipuc_req( + state, + (&(*result).suit_req_msg_suit_write_ipuc_req_m)))) && + (((*result).suit_req_msg_choice = + suit_req_msg_suit_write_ipuc_req_m_c), + true))) || (zcbor_union_elem_code(state) && (((decode_suit_get_manifest_var_req( state, diff --git a/subsys/sdfw_services/services/suit_service/zcbor_generated/suit_service_decode.h b/subsys/sdfw_services/services/suit_service/zcbor_generated/suit_service_decode.h index 027e454b4e24..807486014976 100644 --- a/subsys/sdfw_services/services/suit_service/zcbor_generated/suit_service_decode.h +++ b/subsys/sdfw_services/services/suit_service/zcbor_generated/suit_service_decode.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2024 Nordic Semiconductor ASA + * Copyright (c) 2025 Nordic Semiconductor ASA * * SPDX-License-Identifier: LicenseRef-Nordic-5-Clause */ diff --git a/subsys/sdfw_services/services/suit_service/zcbor_generated/suit_service_encode.c b/subsys/sdfw_services/services/suit_service/zcbor_generated/suit_service_encode.c index 9a452ac65cf4..78192a8b7003 100644 --- a/subsys/sdfw_services/services/suit_service/zcbor_generated/suit_service_encode.c +++ b/subsys/sdfw_services/services/suit_service/zcbor_generated/suit_service_encode.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2024 Nordic Semiconductor ASA + * Copyright (c) 2025 Nordic Semiconductor ASA * * SPDX-License-Identifier: LicenseRef-Nordic-5-Clause */ @@ -68,6 +68,14 @@ static bool encode_suit_authorize_process_dependency_req( zcbor_state_t *state, const struct suit_authorize_process_dependency_req *input); static bool +encode_suit_get_ipuc_info_req(zcbor_state_t *state, + const struct suit_get_ipuc_info_req *input); +static bool +encode_suit_setup_write_ipuc_req(zcbor_state_t *state, + const struct suit_setup_write_ipuc_req *input); +static bool encode_suit_write_ipuc_req(zcbor_state_t *state, + const struct suit_write_ipuc_req *input); +static bool encode_suit_get_manifest_var_req(zcbor_state_t *state, const struct suit_get_manifest_var_req *input); static bool @@ -116,6 +124,17 @@ static bool encode_suit_authorize_process_dependency_rsp( zcbor_state_t *state, const struct suit_authorize_process_dependency_rsp *input); static bool +encode_suit_get_ipuc_count_rsp(zcbor_state_t *state, + const struct suit_get_ipuc_count_rsp *input); +static bool +encode_suit_get_ipuc_info_rsp(zcbor_state_t *state, + const struct suit_get_ipuc_info_rsp *input); +static bool +encode_suit_setup_write_ipuc_rsp(zcbor_state_t *state, + const struct suit_setup_write_ipuc_rsp *input); +static bool encode_suit_write_ipuc_rsp(zcbor_state_t *state, + const struct suit_write_ipuc_rsp *input); +static bool encode_suit_get_manifest_var_rsp(zcbor_state_t *state, const struct suit_get_manifest_var_rsp *input); static bool @@ -366,6 +385,55 @@ static bool encode_suit_authorize_process_dependency_req( return res; } +static bool +encode_suit_get_ipuc_info_req(zcbor_state_t *state, + const struct suit_get_ipuc_info_req *input) { + zcbor_log("%s\r\n", __func__); + + bool res = ((( + ((zcbor_uint32_put(state, (31)))) && + ((zcbor_uint32_encode(state, (&(*input).suit_get_ipuc_info_req_idx))))))); + + log_result(state, res, __func__); + return res; +} + +static bool encode_suit_setup_write_ipuc_req( + zcbor_state_t *state, const struct suit_setup_write_ipuc_req *input) { + zcbor_log("%s\r\n", __func__); + + bool res = (( + (((zcbor_uint32_put(state, (32)))) && + ((zcbor_bstr_encode( + state, (&(*input).suit_setup_write_ipuc_req_component_id)))) && + ((zcbor_bstr_encode( + state, (&(*input).suit_setup_write_ipuc_req_encryption_info)))) && + ((zcbor_bstr_encode( + state, (&(*input).suit_setup_write_ipuc_req_compression_info))))))); + + log_result(state, res, __func__); + return res; +} + +static bool +encode_suit_write_ipuc_req(zcbor_state_t *state, + const struct suit_write_ipuc_req *input) { + zcbor_log("%s\r\n", __func__); + + bool res = (( + (((zcbor_uint32_put(state, (33)))) && + ((zcbor_bstr_encode(state, + (&(*input).suit_write_ipuc_req_component_id)))) && + ((zcbor_uint32_encode(state, (&(*input).suit_write_ipuc_req_offset)))) && + ((zcbor_bool_encode(state, + (&(*input).suit_write_ipuc_req_last_chunk)))) && + ((zcbor_uint32_encode(state, (&(*input).suit_write_ipuc_req_addr)))) && + ((zcbor_uint32_encode(state, (&(*input).suit_write_ipuc_req_size))))))); + + log_result(state, res, __func__); + return res; +} + static bool encode_suit_get_manifest_var_req( zcbor_state_t *state, const struct suit_get_manifest_var_req *input) { zcbor_log("%s\r\n", __func__); @@ -669,6 +737,62 @@ static bool encode_suit_authorize_process_dependency_rsp( return res; } +static bool +encode_suit_get_ipuc_count_rsp(zcbor_state_t *state, + const struct suit_get_ipuc_count_rsp *input) { + zcbor_log("%s\r\n", __func__); + + bool res = (( + (((zcbor_uint32_put(state, (30)))) && + ((zcbor_int32_encode(state, (&(*input).suit_get_ipuc_count_rsp_ret)))) && + ((zcbor_uint32_encode(state, + (&(*input).suit_get_ipuc_count_rsp_count))))))); + + log_result(state, res, __func__); + return res; +} + +static bool +encode_suit_get_ipuc_info_rsp(zcbor_state_t *state, + const struct suit_get_ipuc_info_rsp *input) { + zcbor_log("%s\r\n", __func__); + + bool res = ((( + ((zcbor_uint32_put(state, (31)))) && + ((zcbor_int32_encode(state, (&(*input).suit_get_ipuc_info_rsp_ret)))) && + ((zcbor_bstr_encode(state, + (&(*input).suit_get_ipuc_info_rsp_component_id)))) && + ((zcbor_int32_encode(state, (&(*input).suit_get_ipuc_info_rsp_role))))))); + + log_result(state, res, __func__); + return res; +} + +static bool encode_suit_setup_write_ipuc_rsp( + zcbor_state_t *state, const struct suit_setup_write_ipuc_rsp *input) { + zcbor_log("%s\r\n", __func__); + + bool res = (((((zcbor_uint32_put(state, (32)))) && + ((zcbor_int32_encode( + state, (&(*input).suit_setup_write_ipuc_rsp_ret))))))); + + log_result(state, res, __func__); + return res; +} + +static bool +encode_suit_write_ipuc_rsp(zcbor_state_t *state, + const struct suit_write_ipuc_rsp *input) { + zcbor_log("%s\r\n", __func__); + + bool res = + (((((zcbor_uint32_put(state, (33)))) && + ((zcbor_int32_encode(state, (&(*input).suit_write_ipuc_rsp_ret))))))); + + log_result(state, res, __func__); + return res; +} + static bool encode_suit_get_manifest_var_rsp( zcbor_state_t *state, const struct suit_get_manifest_var_rsp *input) { zcbor_log("%s\r\n", __func__); @@ -911,85 +1035,125 @@ static bool encode_suit_rsp(zcbor_state_t *state, suit_rsp_msg_suit_get_supported_manifest_info_rsp_m_c) ? ((encode_suit_get_supported_manifest_info_rsp(state, (&(*input) .suit_rsp_msg_suit_get_supported_manifest_info_rsp_m)))) - : ( - ( - (*input) - .suit_rsp_msg_choice == - suit_rsp_msg_suit_authorize_process_dependency_rsp_m_c) - ? (( - encode_suit_authorize_process_dependency_rsp(state, - (&(*input) - .suit_rsp_msg_suit_authorize_process_dependency_rsp_m)))) - : ( - ( - (*input) - .suit_rsp_msg_choice == - suit_rsp_msg_suit_get_manifest_var_rsp_m_c) - ? ((encode_suit_get_manifest_var_rsp( - state, - (&(*input) - .suit_rsp_msg_suit_get_manifest_var_rsp_m)))) - : (( - (*input) - .suit_rsp_msg_choice == - suit_rsp_msg_suit_set_manifest_var_rsp_m_c) - ? ((encode_suit_set_manifest_var_rsp( - state, - (&(*input) - .suit_rsp_msg_suit_set_manifest_var_rsp_m)))) - : ( - ( - (*input) - .suit_rsp_msg_choice == - suit_rsp_msg_suit_evt_sub_rsp_m_c) - ? ((encode_suit_evt_sub_rsp( - state, - (&(*input) - .suit_rsp_msg_suit_evt_sub_rsp_m)))) - : (((*input) + : (((*input) + .suit_rsp_msg_choice == + suit_rsp_msg_suit_authorize_process_dependency_rsp_m_c) + ? ((encode_suit_authorize_process_dependency_rsp( + state, (&( + *input) + .suit_rsp_msg_suit_authorize_process_dependency_rsp_m)))) + : (((*input) + .suit_rsp_msg_choice == + suit_rsp_msg_suit_get_ipuc_count_rsp_m_c) + ? ((encode_suit_get_ipuc_count_rsp(state, + ( + &(*input) + .suit_rsp_msg_suit_get_ipuc_count_rsp_m)))) + : (((*input) + .suit_rsp_msg_choice == + suit_rsp_msg_suit_get_ipuc_info_rsp_m_c) + ? ((encode_suit_get_ipuc_info_rsp(state, + ( + &(*input) + .suit_rsp_msg_suit_get_ipuc_info_rsp_m)))) + : ( + ( + (*input) + .suit_rsp_msg_choice == + suit_rsp_msg_suit_setup_write_ipuc_rsp_m_c) + ? ( + ( + encode_suit_setup_write_ipuc_rsp( + state, ( + &(*input) + .suit_rsp_msg_suit_setup_write_ipuc_rsp_m)))) + : ( + ( + (*input) .suit_rsp_msg_choice == - suit_rsp_msg_suit_chunk_enqueue_rsp_m_c) - ? ((encode_suit_chunk_enqueue_rsp(state, - ( - &(*input) - .suit_rsp_msg_suit_chunk_enqueue_rsp_m)))) - : (((*input) - .suit_rsp_msg_choice == - suit_rsp_msg_suit_chunk_status_rsp_m_c) - ? ((encode_suit_chunk_status_rsp( - state, - (&(*input) - .suit_rsp_msg_suit_chunk_status_rsp_m)))) - : (((*input) - .suit_rsp_msg_choice == suit_rsp_msg_suit_boot_mode_read_rsp_m_c) - ? ((encode_suit_boot_mode_read_rsp( - state, - (&(*input) - .suit_rsp_msg_suit_boot_mode_read_rsp_m)))) - : (((*input) - .suit_rsp_msg_choice == - suit_rsp_msg_suit_invoke_confirm_rsp_m_c) - ? (( - encode_suit_invoke_confirm_rsp( - state, - (&(*input) - .suit_rsp_msg_suit_invoke_confirm_rsp_m)))) - : ( - ( - (*input) - .suit_rsp_msg_choice == - suit_rsp_msg_suit_boot_flags_reset_rsp_m_c) - ? ((encode_suit_boot_flags_reset_rsp( - state, - (&(*input) - .suit_rsp_msg_suit_boot_flags_reset_rsp_m)))) - : (((*input) - .suit_rsp_msg_choice == - suit_rsp_msg_suit_foreground_dfu_required_rsp_m_c) - ? ((encode_suit_foreground_dfu_required_rsp( - state, (&(*input) - .suit_rsp_msg_suit_foreground_dfu_required_rsp_m)))) - : false)))))))))))))))))))))) || + suit_rsp_msg_suit_write_ipuc_rsp_m_c) + ? (( + encode_suit_write_ipuc_rsp(state, + ( + &(*input) + .suit_rsp_msg_suit_write_ipuc_rsp_m)))) + : ( + ( + (*input) + .suit_rsp_msg_choice == + suit_rsp_msg_suit_get_manifest_var_rsp_m_c) + ? ( + ( + encode_suit_get_manifest_var_rsp(state, (&(*input) + .suit_rsp_msg_suit_get_manifest_var_rsp_m)))) + : (( + (*input) + .suit_rsp_msg_choice == + suit_rsp_msg_suit_set_manifest_var_rsp_m_c) + ? ( + ( + encode_suit_set_manifest_var_rsp(state, ( + &(*input) + .suit_rsp_msg_suit_set_manifest_var_rsp_m)))) + : ( + ( + (*input) + .suit_rsp_msg_choice == + suit_rsp_msg_suit_evt_sub_rsp_m_c) + ? ( + ( + encode_suit_evt_sub_rsp( + state, (&(*input) + .suit_rsp_msg_suit_evt_sub_rsp_m)))) + : ( + ( + (*input) + .suit_rsp_msg_choice == + suit_rsp_msg_suit_chunk_enqueue_rsp_m_c) + ? (( + encode_suit_chunk_enqueue_rsp(state, ( + &(*input) + .suit_rsp_msg_suit_chunk_enqueue_rsp_m)))) + : ( + ( + (*input) + .suit_rsp_msg_choice == + suit_rsp_msg_suit_chunk_status_rsp_m_c) + ? (( + encode_suit_chunk_status_rsp( + state, (&(*input) + .suit_rsp_msg_suit_chunk_status_rsp_m)))) + : (((*input) + .suit_rsp_msg_choice == + suit_rsp_msg_suit_boot_mode_read_rsp_m_c) + ? ( + (encode_suit_boot_mode_read_rsp(state, ( + &( + *input) + .suit_rsp_msg_suit_boot_mode_read_rsp_m)))) + : (((*input) + .suit_rsp_msg_choice == + suit_rsp_msg_suit_invoke_confirm_rsp_m_c) + ? ((encode_suit_invoke_confirm_rsp( + state, + (&(*input) + .suit_rsp_msg_suit_invoke_confirm_rsp_m)))) + : ( + ( + (*input) + .suit_rsp_msg_choice == + suit_rsp_msg_suit_boot_flags_reset_rsp_m_c) + ? ((encode_suit_boot_flags_reset_rsp( + state, + (&(*input) + .suit_rsp_msg_suit_boot_flags_reset_rsp_m)))) + : (((*input) + .suit_rsp_msg_choice == + suit_rsp_msg_suit_foreground_dfu_required_rsp_m_c) + ? ((encode_suit_foreground_dfu_required_rsp( + state, (&(*input) + .suit_rsp_msg_suit_foreground_dfu_required_rsp_m)))) + : false)))))))))))))))))))))))))) || (zcbor_list_map_end_force_encode(state), false)) && zcbor_list_end_encode(state, 8)))); @@ -1001,157 +1165,178 @@ static bool encode_suit_req(zcbor_state_t *state, const struct suit_req *input) { zcbor_log("%s\r\n", __func__); - bool res = (( - (zcbor_list_start_encode(state, 7) && - (((( - ((*input).suit_req_msg_choice == - suit_req_msg_suit_trigger_update_req_m_c) - ? ((encode_suit_trigger_update_req( - state, - (&(*input).suit_req_msg_suit_trigger_update_req_m)))) - : (((*input).suit_req_msg_choice == - suit_req_msg_suit_check_installed_component_digest_req_m_c) - ? ((encode_suit_check_installed_component_digest_req( - state, - (&(*input) - .suit_req_msg_suit_check_installed_component_digest_req_m)))) - : (((*input).suit_req_msg_choice == - suit_req_msg_suit_get_installed_manifest_info_req_m_c) - ? ((encode_suit_get_installed_manifest_info_req( - state, - (&(*input) - .suit_req_msg_suit_get_installed_manifest_info_req_m)))) - : (((*input).suit_req_msg_choice == - suit_req_msg_suit_get_install_candidate_info_req_m_c) - ? ((zcbor_uint32_put(state, (4)))) - : (((*input).suit_req_msg_choice == - suit_req_msg_suit_authenticate_manifest_req_m_c) - ? ((encode_suit_authenticate_manifest_req( - state, - (&(*input) - .suit_req_msg_suit_authenticate_manifest_req_m)))) - : (((*input).suit_req_msg_choice == - suit_req_msg_suit_authorize_unsigned_manifest_req_m_c) - ? ((encode_suit_authorize_unsigned_manifest_req( - state, - (&(*input) - .suit_req_msg_suit_authorize_unsigned_manifest_req_m)))) - : (((*input) - .suit_req_msg_choice == - suit_req_msg_suit_authorize_seq_num_req_m_c) - ? ((encode_suit_authorize_seq_num_req( - state, - (&(*input) - .suit_req_msg_suit_authorize_seq_num_req_m)))) - : (((*input) - .suit_req_msg_choice == - suit_req_msg_suit_check_component_compatibility_req_m_c) - ? ((encode_suit_check_component_compatibility_req( - state, - (&(*input) - .suit_req_msg_suit_check_component_compatibility_req_m)))) - : (((*input).suit_req_msg_choice == suit_req_msg_suit_get_supported_manifest_roles_req_m_c) ? ((zcbor_uint32_put( - state, - (18)))) - : ( - ( - (*input) - .suit_req_msg_choice == - suit_req_msg_suit_get_supported_manifest_info_req_m_c) - ? ((encode_suit_get_supported_manifest_info_req( - state, - (&(*input) - .suit_req_msg_suit_get_supported_manifest_info_req_m)))) - : ( - ( - (*input) - .suit_req_msg_choice == - suit_req_msg_suit_authorize_process_dependency_req_m_c) - ? ( - ( - encode_suit_authorize_process_dependency_req( - state, - ( - &( - *input) - .suit_req_msg_suit_authorize_process_dependency_req_m)))) - : ( - ( - (*input) - .suit_req_msg_choice == - suit_req_msg_suit_get_manifest_var_req_m_c) - ? ((encode_suit_get_manifest_var_req( - state, ( - &( - *input) - .suit_req_msg_suit_get_manifest_var_req_m)))) - : ( - ( - (*input) - .suit_req_msg_choice == - suit_req_msg_suit_set_manifest_var_req_m_c) - ? (( - encode_suit_set_manifest_var_req( - state, (&(*input) - .suit_req_msg_suit_set_manifest_var_req_m)))) - : ( - ( - (*input) - .suit_req_msg_choice == - suit_req_msg_suit_evt_sub_req_m_c) - ? (( - encode_suit_evt_sub_req( - state, ( + bool res = ((( + zcbor_list_start_encode(state, 7) && + ((((((*input).suit_req_msg_choice == + suit_req_msg_suit_trigger_update_req_m_c) + ? ((encode_suit_trigger_update_req( + state, (&(*input).suit_req_msg_suit_trigger_update_req_m)))) + : (((*input).suit_req_msg_choice == + suit_req_msg_suit_check_installed_component_digest_req_m_c) + ? ((encode_suit_check_installed_component_digest_req( + state, + (&(*input) + .suit_req_msg_suit_check_installed_component_digest_req_m)))) + : (((*input).suit_req_msg_choice == + suit_req_msg_suit_get_installed_manifest_info_req_m_c) + ? ((encode_suit_get_installed_manifest_info_req( + state, + (&(*input) + .suit_req_msg_suit_get_installed_manifest_info_req_m)))) + : (((*input).suit_req_msg_choice == + suit_req_msg_suit_get_install_candidate_info_req_m_c) + ? ((zcbor_uint32_put(state, (4)))) + : (((*input).suit_req_msg_choice == + suit_req_msg_suit_authenticate_manifest_req_m_c) + ? ((encode_suit_authenticate_manifest_req( + state, + (&(*input) + .suit_req_msg_suit_authenticate_manifest_req_m)))) + : (((*input).suit_req_msg_choice == + suit_req_msg_suit_authorize_unsigned_manifest_req_m_c) + ? ((encode_suit_authorize_unsigned_manifest_req( + state, + (&(*input) + .suit_req_msg_suit_authorize_unsigned_manifest_req_m)))) + : (((*input) + .suit_req_msg_choice == + suit_req_msg_suit_authorize_seq_num_req_m_c) + ? ((encode_suit_authorize_seq_num_req( + state, + (&(*input) + .suit_req_msg_suit_authorize_seq_num_req_m)))) + : (((*input) + .suit_req_msg_choice == + suit_req_msg_suit_check_component_compatibility_req_m_c) + ? ((encode_suit_check_component_compatibility_req( + state, + (&(*input) + .suit_req_msg_suit_check_component_compatibility_req_m)))) + : (((*input).suit_req_msg_choice == suit_req_msg_suit_get_supported_manifest_roles_req_m_c) ? ((zcbor_uint32_put( + state, + (18)))) + : ( + ( + (*input) + .suit_req_msg_choice == + suit_req_msg_suit_get_supported_manifest_info_req_m_c) + ? ( + ( + encode_suit_get_supported_manifest_info_req(state, + (&(*input) + .suit_req_msg_suit_get_supported_manifest_info_req_m)))) + : ( + ( + (*input) + .suit_req_msg_choice == + suit_req_msg_suit_authorize_process_dependency_req_m_c) + ? ((encode_suit_authorize_process_dependency_req(state, + ( &(*input) - .suit_req_msg_suit_evt_sub_req_m)))) - : ( - ( - (*input) - .suit_req_msg_choice == - suit_req_msg_suit_chunk_enqueue_req_m_c) - ? (( - encode_suit_chunk_enqueue_req(state, - (&(*input) - .suit_req_msg_suit_chunk_enqueue_req_m)))) + .suit_req_msg_suit_authorize_process_dependency_req_m)))) + : (((*input) + .suit_req_msg_choice == + suit_req_msg_suit_get_ipuc_count_req_m_c) + ? ((zcbor_uint32_put(state, (30)))) + : (((*input) + .suit_req_msg_choice == + suit_req_msg_suit_get_ipuc_info_req_m_c) + ? (( + encode_suit_get_ipuc_info_req( + state, + (&(*input) + .suit_req_msg_suit_get_ipuc_info_req_m)))) + : (((*input) + .suit_req_msg_choice == + suit_req_msg_suit_setup_write_ipuc_req_m_c) + ? ((encode_suit_setup_write_ipuc_req( + state, + (&(*input) + .suit_req_msg_suit_setup_write_ipuc_req_m)))) + : (((*input) + .suit_req_msg_choice == + suit_req_msg_suit_write_ipuc_req_m_c) + ? ((encode_suit_write_ipuc_req( + state, + (&(*input) + .suit_req_msg_suit_write_ipuc_req_m)))) + : (((*input) + .suit_req_msg_choice == + suit_req_msg_suit_get_manifest_var_req_m_c) + ? ((encode_suit_get_manifest_var_req( + state, + ( + &(*input) + .suit_req_msg_suit_get_manifest_var_req_m)))) + : (((*input) + .suit_req_msg_choice == + suit_req_msg_suit_set_manifest_var_req_m_c) + ? ((encode_suit_set_manifest_var_req( + state, + (&(*input) + .suit_req_msg_suit_set_manifest_var_req_m)))) : ( ( (*input) - .suit_req_msg_choice == suit_req_msg_suit_chunk_status_req_m_c) - ? ((encode_suit_chunk_status_req( - state, - ( - &(*input) - .suit_req_msg_suit_chunk_status_req_m)))) + .suit_req_msg_choice == + suit_req_msg_suit_evt_sub_req_m_c) + ? (( + encode_suit_evt_sub_req( + state, + (&(*input) + .suit_req_msg_suit_evt_sub_req_m)))) : ( ( (*input) .suit_req_msg_choice == - suit_req_msg_suit_boot_mode_read_req_m_c) - ? ((zcbor_uint32_put( - state, (50)))) - : (((*input) - .suit_req_msg_choice == - suit_req_msg_suit_invoke_confirm_req_m_c) - ? ((encode_suit_invoke_confirm_req(state, ( - &(*input) - .suit_req_msg_suit_invoke_confirm_req_m)))) - : ( - ( - (*input) - .suit_req_msg_choice == - suit_req_msg_suit_boot_flags_reset_req_m_c) - ? ((zcbor_uint32_put( - state, - (52)))) - : (((*input) - .suit_req_msg_choice == - suit_req_msg_suit_foreground_dfu_required_req_m_c) - ? ((zcbor_uint32_put( - state, - (53)))) - : false)))))))))))))))))))))) || - (zcbor_list_map_end_force_encode(state), false)) && - zcbor_list_end_encode(state, 7)))); + suit_req_msg_suit_chunk_enqueue_req_m_c) + ? ((encode_suit_chunk_enqueue_req( + state, + ( + &(*input) + .suit_req_msg_suit_chunk_enqueue_req_m)))) + : ( + ( + ( + *input) + .suit_req_msg_choice == + suit_req_msg_suit_chunk_status_req_m_c) + ? ((encode_suit_chunk_status_req( + state, + (&(*input) + .suit_req_msg_suit_chunk_status_req_m)))) + : ( + ( + (*input) + .suit_req_msg_choice == + suit_req_msg_suit_boot_mode_read_req_m_c) + ? ( + ( + zcbor_uint32_put(state, (50)))) + : (((*input) + .suit_req_msg_choice == + suit_req_msg_suit_invoke_confirm_req_m_c) + ? ((encode_suit_invoke_confirm_req( + state, + (&(*input) + .suit_req_msg_suit_invoke_confirm_req_m)))) + : (((*input) + .suit_req_msg_choice == + suit_req_msg_suit_boot_flags_reset_req_m_c) + ? ((zcbor_uint32_put( + state, + (52)))) + : ( + ( + (*input) + .suit_req_msg_choice == + suit_req_msg_suit_foreground_dfu_required_req_m_c) + ? ( + ( + zcbor_uint32_put(state, (53)))) + : false)))))))))))))))))))))))))) || + (zcbor_list_map_end_force_encode(state), false)) && + zcbor_list_end_encode(state, 7)))); log_result(state, res, __func__); return res; diff --git a/subsys/sdfw_services/services/suit_service/zcbor_generated/suit_service_encode.h b/subsys/sdfw_services/services/suit_service/zcbor_generated/suit_service_encode.h index ad73bcba515b..845ec8a752fd 100644 --- a/subsys/sdfw_services/services/suit_service/zcbor_generated/suit_service_encode.h +++ b/subsys/sdfw_services/services/suit_service/zcbor_generated/suit_service_encode.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2024 Nordic Semiconductor ASA + * Copyright (c) 2025 Nordic Semiconductor ASA * * SPDX-License-Identifier: LicenseRef-Nordic-5-Clause */ diff --git a/subsys/sdfw_services/services/suit_service/zcbor_generated/suit_service_types.h b/subsys/sdfw_services/services/suit_service/zcbor_generated/suit_service_types.h index 5358f26137cc..b24674fa2778 100644 --- a/subsys/sdfw_services/services/suit_service/zcbor_generated/suit_service_types.h +++ b/subsys/sdfw_services/services/suit_service/zcbor_generated/suit_service_types.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2024 Nordic Semiconductor ASA + * Copyright (c) 2025 Nordic Semiconductor ASA * * SPDX-License-Identifier: LicenseRef-Nordic-5-Clause */ @@ -109,6 +109,24 @@ struct suit_authorize_process_dependency_req { int32_t suit_authorize_process_dependency_req_seq_id; }; +struct suit_get_ipuc_info_req { + uint32_t suit_get_ipuc_info_req_idx; +}; + +struct suit_setup_write_ipuc_req { + struct zcbor_string suit_setup_write_ipuc_req_component_id; + struct zcbor_string suit_setup_write_ipuc_req_encryption_info; + struct zcbor_string suit_setup_write_ipuc_req_compression_info; +}; + +struct suit_write_ipuc_req { + struct zcbor_string suit_write_ipuc_req_component_id; + uint32_t suit_write_ipuc_req_offset; + bool suit_write_ipuc_req_last_chunk; + uint32_t suit_write_ipuc_req_addr; + uint32_t suit_write_ipuc_req_size; +}; + struct suit_get_manifest_var_req { uint32_t suit_get_manifest_var_req_id; }; @@ -157,6 +175,9 @@ struct suit_req { suit_req_msg_suit_get_supported_manifest_info_req_m; struct suit_authorize_process_dependency_req suit_req_msg_suit_authorize_process_dependency_req_m; + struct suit_get_ipuc_info_req suit_req_msg_suit_get_ipuc_info_req_m; + struct suit_setup_write_ipuc_req suit_req_msg_suit_setup_write_ipuc_req_m; + struct suit_write_ipuc_req suit_req_msg_suit_write_ipuc_req_m; struct suit_get_manifest_var_req suit_req_msg_suit_get_manifest_var_req_m; struct suit_set_manifest_var_req suit_req_msg_suit_set_manifest_var_req_m; struct suit_evt_sub_req suit_req_msg_suit_evt_sub_req_m; @@ -176,6 +197,10 @@ struct suit_req { suit_req_msg_suit_get_supported_manifest_roles_req_m_c, suit_req_msg_suit_get_supported_manifest_info_req_m_c, suit_req_msg_suit_authorize_process_dependency_req_m_c, + suit_req_msg_suit_get_ipuc_count_req_m_c, + suit_req_msg_suit_get_ipuc_info_req_m_c, + suit_req_msg_suit_setup_write_ipuc_req_m_c, + suit_req_msg_suit_write_ipuc_req_m_c, suit_req_msg_suit_get_manifest_var_req_m_c, suit_req_msg_suit_set_manifest_var_req_m_c, suit_req_msg_suit_evt_sub_req_m_c, @@ -252,6 +277,25 @@ struct suit_authorize_process_dependency_rsp { int32_t suit_authorize_process_dependency_rsp_ret; }; +struct suit_get_ipuc_count_rsp { + int32_t suit_get_ipuc_count_rsp_ret; + uint32_t suit_get_ipuc_count_rsp_count; +}; + +struct suit_get_ipuc_info_rsp { + int32_t suit_get_ipuc_info_rsp_ret; + struct zcbor_string suit_get_ipuc_info_rsp_component_id; + int32_t suit_get_ipuc_info_rsp_role; +}; + +struct suit_setup_write_ipuc_rsp { + int32_t suit_setup_write_ipuc_rsp_ret; +}; + +struct suit_write_ipuc_rsp { + int32_t suit_write_ipuc_rsp_ret; +}; + struct suit_get_manifest_var_rsp { int32_t suit_get_manifest_var_rsp_ret; uint32_t suit_get_manifest_var_rsp_value; @@ -320,6 +364,10 @@ struct suit_rsp { suit_rsp_msg_suit_get_supported_manifest_info_rsp_m; struct suit_authorize_process_dependency_rsp suit_rsp_msg_suit_authorize_process_dependency_rsp_m; + struct suit_get_ipuc_count_rsp suit_rsp_msg_suit_get_ipuc_count_rsp_m; + struct suit_get_ipuc_info_rsp suit_rsp_msg_suit_get_ipuc_info_rsp_m; + struct suit_setup_write_ipuc_rsp suit_rsp_msg_suit_setup_write_ipuc_rsp_m; + struct suit_write_ipuc_rsp suit_rsp_msg_suit_write_ipuc_rsp_m; struct suit_get_manifest_var_rsp suit_rsp_msg_suit_get_manifest_var_rsp_m; struct suit_set_manifest_var_rsp suit_rsp_msg_suit_set_manifest_var_rsp_m; struct suit_evt_sub_rsp suit_rsp_msg_suit_evt_sub_rsp_m; @@ -343,6 +391,10 @@ struct suit_rsp { suit_rsp_msg_suit_get_supported_manifest_roles_rsp_m_c, suit_rsp_msg_suit_get_supported_manifest_info_rsp_m_c, suit_rsp_msg_suit_authorize_process_dependency_rsp_m_c, + suit_rsp_msg_suit_get_ipuc_count_rsp_m_c, + suit_rsp_msg_suit_get_ipuc_info_rsp_m_c, + suit_rsp_msg_suit_setup_write_ipuc_rsp_m_c, + suit_rsp_msg_suit_write_ipuc_rsp_m_c, suit_rsp_msg_suit_get_manifest_var_rsp_m_c, suit_rsp_msg_suit_set_manifest_var_rsp_m_c, suit_rsp_msg_suit_evt_sub_rsp_m_c, diff --git a/subsys/suit/CMakeLists.txt b/subsys/suit/CMakeLists.txt index 9d66d39a5943..57c05760448e 100644 --- a/subsys/suit/CMakeLists.txt +++ b/subsys/suit/CMakeLists.txt @@ -22,3 +22,4 @@ add_subdirectory_ifdef(CONFIG_SUIT_EXECUTION_MODE execution_mode) add_subdirectory_ifdef(CONFIG_SUIT_VALIDATOR validator) add_subdirectory_ifdef(CONFIG_SUIT_EVENTS events) add_subdirectory_ifdef(CONFIG_SUIT_MANIFEST_VARIABLES manifest_variables) +add_subdirectory_ifdef(CONFIG_SUIT_IPUC ipuc) diff --git a/subsys/suit/Kconfig b/subsys/suit/Kconfig index c6175ccba083..437eb3075472 100644 --- a/subsys/suit/Kconfig +++ b/subsys/suit/Kconfig @@ -80,6 +80,7 @@ config SUIT_DFU_CANDIDATE_PROCESSING_FULL imply SUIT_MEMPTR_STORAGE imply SUIT_PLATFORM imply SUIT_PROCESSOR + imply SUIT_IPUC imply SUIT_MANIFEST_VARIABLES imply SUIT_SINK_SELECTOR @@ -196,6 +197,7 @@ rsource "validator/Kconfig" rsource "events/Kconfig" rsource "app_tools/Kconfig" rsource "manifest_variables/Kconfig" +rsource "ipuc/Kconfig" # Configure SUIT_LOG_LEVEL module = SUIT diff --git a/subsys/suit/ipuc/CMakeLists.txt b/subsys/suit/ipuc/CMakeLists.txt new file mode 100644 index 000000000000..60e758480748 --- /dev/null +++ b/subsys/suit/ipuc/CMakeLists.txt @@ -0,0 +1,23 @@ +# +# Copyright (c) 2025 Nordic Semiconductor ASA +# +# SPDX-License-Identifier: LicenseRef-Nordic-5-Clause +# + +# Module giving an access to in-place updateable components + +zephyr_interface_library_named(suit_ipuc) +target_include_directories(suit_ipuc INTERFACE include) +target_link_libraries(suit_ipuc INTERFACE suit_platform_err) +target_link_libraries(suit_ipuc INTERFACE suit_metadata) + +if(CONFIG_SUIT_IPUC_IMPL_SDFW) + zephyr_library() + zephyr_library_sources(src/suit_ipuc_sdfw.c) + + zephyr_library_link_libraries(suit_ipuc) + zephyr_library_link_libraries(suit_utils) + zephyr_library_link_libraries(suit_memory_layout_interface) + zephyr_library_link_libraries(suit_source_selector_interface) + zephyr_library_link_libraries(suit_stream_sources_interface) +endif() diff --git a/subsys/suit/ipuc/Kconfig b/subsys/suit/ipuc/Kconfig new file mode 100644 index 000000000000..6b6d758644e5 --- /dev/null +++ b/subsys/suit/ipuc/Kconfig @@ -0,0 +1,41 @@ +# +# Copyright (c) 2025 Nordic Semiconductor ASA +# +# SPDX-License-Identifier: LicenseRef-Nordic-5-Clause +# + +config SUIT_IPUC + bool "Enable in-place updateable components" + help + SUIT manifest may instruct the platform that component is inactive, by overriding + image-size parameter with value 0. Such component may be updated in place, + also memory associated to such component may be utilized for other purposes. + depends on SUIT_METADATA + +if SUIT_IPUC + +choice SUIT_IPUC_IMPL + prompt "Implementation selection" + default SUIT_IPUC_IMPL_SDFW if SUIT_PLATFORM_VARIANT_SDFW + default SUIT_IPUC_IMPL_IPC if SUIT_PLATFORM_VARIANT_APP + +config SUIT_IPUC_IMPL_SDFW + bool "SDFW" + depends on SUIT_PLATFORM_VARIANT_SDFW + +config SUIT_IPUC_IMPL_IPC + bool "IPC" + depends on SUIT_PLATFORM_VARIANT_APP + depends on SSF_SUIT_SERVICE_ENABLED + +endchoice + +if SUIT_IPUC_IMPL_SDFW + +config SUIT_IPUC_SIZE + int "Maximum number of supported in-place updateable components" + default 8 + +endif + +endif diff --git a/subsys/suit/ipuc/include/suit_ipuc.h b/subsys/suit/ipuc/include/suit_ipuc.h new file mode 100644 index 000000000000..79c17706e89b --- /dev/null +++ b/subsys/suit/ipuc/include/suit_ipuc.h @@ -0,0 +1,95 @@ +/* + * Copyright (c) 2025 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: LicenseRef-Nordic-5-Clause + */ + +/** + * @brief Support for in-place updateable component. + * + * SUIT manifest may instruct the platform that component is inactive, by overriding + * image-size parameter with value 0. Such component may be updated in place. + */ + +#ifndef SUIT_IPUC_H__ +#define SUIT_IPUC_H__ + +#include +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/** @brief Get amount of declared in-place updateable components + * + * @param[out] count Amount of declared in-place updateable components + * + * @retval SUIT_PLAT_ERR_INVAL invalid parameter. + * @retval SUIT_PLAT_ERR_IPC error while communicating with secure domain. + * @retval SUIT_PLAT_SUCCESS operation completed successfully. + */ +suit_plat_err_t suit_ipuc_get_count(size_t *count); + +/** @brief Get information about in-place updateable component + * + * @param[in] idx 0-based component number. + * @param[out] component_id component identifier. + * @param[out] role role of manifest which declared component as in-place updateable. + * + * @retval SUIT_PLAT_ERR_INVAL invalid parameter. + * @retval SUIT_PLAT_ERR_NOT_FOUND component not declared as in-place updateable. + * @retval SUIT_PLAT_ERR_IPC error while communicating with secure domain. + * @retval SUIT_PLAT_SUCCESS operation completed successfully. + */ +suit_plat_err_t suit_ipuc_get_info(size_t idx, struct zcbor_string *component_id, + suit_manifest_role_t *role); + +/** @brief Prepare in-place updateable component for future write operations. + * + * @param[in] component_id component identifier. + * @param[in] encryption_info placeholder for future encryption-related parameters. + * @param[in] compression_info placeholder for future compression-related parameters. + * + * @retval SUIT_PLAT_ERR_INVAL invalid parameter. + * @retval SUIT_PLAT_ERR_NOT_FOUND component not declared as in-place updateable. + * @retval SUIT_PLAT_ERR_INCORRECT_STATE component in incorrect state, i.e. occupied by other client + * @retval SUIT_PLAT_ERR_UNSUPPORTED compression/encryption requested, unsupported component + * type. + * @retval SUIT_PLAT_ERR_IO erase operation has failed + * @retval SUIT_PLAT_ERR_IPC error while communicating with secure domain. + * @retval SUIT_PLAT_SUCCESS operation completed successfully. + */ +suit_plat_err_t suit_ipuc_write_setup(struct zcbor_string *component_id, + struct zcbor_string *encryption_info, + struct zcbor_string *compression_info); + +/** @brief Write data chunk to in-place updateable component. + * + * @param[in] component_id component identifier. + * @param[in] offset Chunk offset in image. + * @param[in] buffer Address of memory buffer where image chunk is stored. Must be + * dcache-line aligned. + * @param[in] chunk_size Size of image chunk, in bytes. + * @param[in] last_chunk 'true' signalizes last write operation. No further write operations + * will be accepted, till another suit_ipuc_write_setup() is called. + * + * @retval SUIT_PLAT_ERR_INVAL invalid parameter. + * @retval SUIT_PLAT_ERR_NOT_FOUND component not declared as in-place updateable. + * @retval SUIT_PLAT_ERR_INCORRECT_STATE component in incorrect state, i.e. occupied by other client + * or not prepared for write. + * @retval SUIT_PLAT_ERR_UNSUPPORTED unsupported component type. + * @retval SUIT_PLAT_ERR_IO seek or write operation has failed. + * @retval SUIT_PLAT_ERR_IPC error while communicating with secure domain. + * @retval SUIT_PLAT_SUCCESS operation completed successfully. + */ +suit_plat_err_t suit_ipuc_write(struct zcbor_string *component_id, size_t offset, uintptr_t buffer, + size_t chunk_size, bool last_chunk); + +#ifdef __cplusplus +} +#endif + +#endif /* SUIT_IPUC_H__ */ diff --git a/subsys/suit/ipuc/include/suit_ipuc_sdfw.h b/subsys/suit/ipuc/include/suit_ipuc_sdfw.h new file mode 100644 index 000000000000..c0c5ae818d37 --- /dev/null +++ b/subsys/suit/ipuc/include/suit_ipuc_sdfw.h @@ -0,0 +1,148 @@ +/* + * Copyright (c) 2025 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: LicenseRef-Nordic-5-Clause + */ + +/** + * @brief Support for in-place updateable component. + * + * SUIT manifest may instruct the platform that component is inactive, by overriding + * image-size parameter with value 0. Such component may be updated in place, + * also memory associated to such component may be utilized for other purposes, + * like updating SDFW or SDFW_Recovery from external flash. + */ + +#ifndef SUIT_IPUC_SDFW_H__ +#define SUIT_IPUC_SDFW_H__ + +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/** @brief Declare component as updateable. + * + * @param[in] handle Handle to the updateable component. + * + * @retval SUIT_PLAT_ERR_INVAL component handle is invalid or component is not supported. + * @retval SUIT_PLAT_ERR_NOMEM the maximum number of updateable components has been reached. + * @retval SUIT_PLAT_SUCCESS updateable component was successfully declared. + */ +suit_plat_err_t suit_ipuc_sdfw_declare(suit_component_t handle, suit_manifest_role_t role); + +/** @brief Revoke declaration of updateable component. + * + * @param[in] handle Handle to the component that is no longer updateable. + * + * @retval SUIT_PLAT_ERR_NOT_FOUND component is not declared as IPUC + * @retval SUIT_PLAT_SUCCESS declaration of updateable component was + * successfully revoked. + */ +suit_plat_err_t suit_ipuc_sdfw_revoke(suit_component_t handle); + +/** @brief Get amount of declared in-place updateable components + * + * @param[out] count Amount of declared in-place updateable components + * + * @retval SUIT_PLAT_ERR_INVAL invalid parameter. + * @retval SUIT_PLAT_ERR_IPC error while communicating with secure domain. + * @retval SUIT_PLAT_SUCCESS operation completed successfully. + */ +suit_plat_err_t suit_ipuc_sdfw_get_count(size_t *count); + +/** @brief Get information about in-place updateable component + * + * @param[in] idx 0-based component number. + * @param[out] component_id component identifier. + * @param[out] role role of manifest which declared component as in-place updateable. + * + * @retval SUIT_PLAT_ERR_INVAL invalid parameter. + * @retval SUIT_PLAT_ERR_NOT_FOUND component not declared as in-place updateable. + * @retval SUIT_PLAT_ERR_IPC error while communicating with secure domain. + * @retval SUIT_PLAT_SUCCESS operation completed successfully. + */ +suit_plat_err_t suit_ipuc_sdfw_get_info(size_t idx, struct zcbor_string *component_id, + suit_manifest_role_t *role); + +/** @brief Prepare in-place updateable component for future write operations in secure domain. + * + * @param[in] ipc_client_id client identifier for future write operations. + * @param[in] component_id component identifier. + * @param[in] encryption_info placeholder for future encryption-related parameters. + * @param[in] compression_info placeholder for future compression-related parameters. + * + * @retval SUIT_PLAT_ERR_INVAL invalid parameter. + * @retval SUIT_PLAT_ERR_NOT_FOUND component not declared as in-place updateable. + * @retval SUIT_PLAT_ERR_INCORRECT_STATE component in incorrect state, i.e. occupied by other client + * @retval SUIT_PLAT_ERR_UNSUPPORTED compression/encryption requested, unsupported component + * type. + * @retval SUIT_PLAT_ERR_IO erase operation has failed + * @retval SUIT_PLAT_SUCCESS operation completed successfully. + */ +suit_plat_err_t suit_ipuc_sdfw_write_setup(int ipc_client_id, struct zcbor_string *component_id, + struct zcbor_string *encryption_info, + struct zcbor_string *compression_info); + +/** @brief Write data chunk to in-place updateable component in secure domain. + * + * @param[in] ipc_client_id client identifier. Must be the same value as provided in + * suit_ipuc_sdfw_write_setup() + * @param[in] component_id component identifier. + * @param[in] offset Chunk offset in image. + * @param[in] buffer Address of memory buffer where image chunk is stored. Must be + * dcache-line aligned. Dcache must be flushed/invalidated. + * @param[in] chunk_size Size of image chunk, in bytes. + * @param[in] last_chunk 'true' signalizes last write operation. No further write operations + * will be accepted, till another suit_ipuc_sdfw_write_setup() is called. + * + * @retval SUIT_PLAT_ERR_INVAL invalid parameter. + * @retval SUIT_PLAT_ERR_NOT_FOUND component not declared as in-place updateable. + * @retval SUIT_PLAT_ERR_INCORRECT_STATE component in incorrect state, i.e. occupied by other client + * or not prepared for write. + * @retval SUIT_PLAT_ERR_UNSUPPORTED unsupported component type. + * @retval SUIT_PLAT_ERR_IO seek or write operation has failed. + * @retval SUIT_PLAT_SUCCESS operation completed successfully. + */ +suit_plat_err_t suit_ipuc_sdfw_write(int ipc_client_id, struct zcbor_string *component_id, + size_t offset, uintptr_t buffer, size_t chunk_size, + bool last_chunk); + +/** + * @brief Check if the digest calculated over stored data matches provided one. + * + * @param[in] component_id component identifier. + * @param[in] alg_id algorithm used to calculate the digest. + * @param[in] digest CBOR string containing the digest to compare against. + * + * @retval SUIT_PLAT_ERR_INVAL invalid parameter or digest does not match. + * @retval SUIT_PLAT_ERR_NOT_FOUND component not declared as in-place updateable. + * @retval SUIT_PLAT_ERR_INCORRECT_STATE component in incorrect state, i.e. write operations in + * progress. Digest may be calculated on completely transferred image. + * @retval SUIT_PLAT_ERR_UNSUPPORTED unsupported component type. + * @retval SUIT_PLAT_ERR_IO digest calculation operation has failed. + * @retval SUIT_PLAT_SUCCESS operation completed successfully. + */ +suit_plat_err_t suit_ipuc_sdfw_digest_compare(struct zcbor_string *component_id, + enum suit_cose_alg alg_id, + struct zcbor_string *digest); + +/** @brief Find an updateable component which is capable to store SDFW update candidate. + * + * @details Since Secure ROM imposes requirements related to SDFW candidate location, returned + * pointer does not necessarily points to the begin of updateable component. + * + * @param[in] required_size Required size of area capable to store SDFW candidate. + * + * @returns Pointer to area capable to store SDFW candidate, 0 otherwise. + */ +uintptr_t suit_ipuc_sdfw_mirror_addr(size_t required_size); + +#ifdef __cplusplus +} +#endif + +#endif /* SUIT_IPUC_SDFW_H__ */ diff --git a/subsys/suit/ipuc/src/suit_ipuc_sdfw.c b/subsys/suit/ipuc/src/suit_ipuc_sdfw.c new file mode 100644 index 000000000000..629872f1f986 --- /dev/null +++ b/subsys/suit/ipuc/src/suit_ipuc_sdfw.c @@ -0,0 +1,688 @@ +/* + * Copyright (c) 2025 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: LicenseRef-Nordic-5-Clause + */ + +#include "suit_ipuc_sdfw.h" +#include +#include +#include +#include +#include +#include +#include +#include + +#if CONFIG_SUIT_DIGEST_CACHE +#include +#endif /* CONFIG_SUIT_DIGEST_CACHE */ + +#ifdef CONFIG_SUIT_STREAM_SINK_DIGEST +#include +#include +#endif /* CONFIG_SUIT_STREAM_SINK_DIGEST */ + +#include +#include +LOG_MODULE_REGISTER(suit_ipuc, CONFIG_SUIT_LOG_LEVEL); + +#define READ_CHUNK_MAX_SIZE 16 + +typedef enum { + IPUC_UNUSED, + IPUC_SDFW_MIRROR, + IPUC_IPC_IN_PLACE_UPDATE +} ipuc_usage_t; + +typedef struct { + struct zcbor_string component_id; + suit_manifest_role_t role; + ipuc_usage_t usage; + int ipc_client_id; + size_t write_peek_offset; + bool last_chunk_stored; +} suit_ipuc_entry_t; + +static suit_ipuc_entry_t components[CONFIG_SUIT_IPUC_SIZE]; +static K_MUTEX_DEFINE(ipuc_mutex); + +static struct zcbor_string *ipuc_component_id_from_handle(suit_component_t handle) +{ + struct zcbor_string *component_id = NULL; + suit_component_type_t component_type = SUIT_COMPONENT_TYPE_UNSUPPORTED; + + if (suit_plat_component_id_get(handle, &component_id) != SUIT_SUCCESS) { + return NULL; + } + + if (suit_plat_decode_component_type(component_id, &component_type) != SUIT_PLAT_SUCCESS) { + return NULL; + } + + if (component_type != SUIT_COMPONENT_TYPE_MEM) { + /* The only supported component type is MEM + */ + return NULL; + } + + return component_id; +} + +static suit_ipuc_entry_t *ipuc_entry_from_component_id(struct zcbor_string *component_id) +{ + if (component_id == NULL) { + return NULL; + } + + for (size_t i = 0; i < CONFIG_SUIT_IPUC_SIZE; i++) { + suit_ipuc_entry_t *p_entry = &components[i]; + + if (suit_compare_zcbor_strings(component_id, &p_entry->component_id)) { + return p_entry; + } + } + + return NULL; +} + +static suit_ipuc_entry_t *ipuc_entry_from_handle(suit_component_t handle) +{ + struct zcbor_string *component_id = ipuc_component_id_from_handle(handle); + + return ipuc_entry_from_component_id(component_id); +} + +static suit_plat_err_t ipuc_decode_mem_component_id(struct zcbor_string *component_id, + intptr_t *slot_address, size_t *slot_size) +{ + suit_component_type_t component_type = SUIT_COMPONENT_TYPE_UNSUPPORTED; + intptr_t decoded_slot_address = 0; + size_t decoded_slot_size = 0; + + if (suit_plat_decode_component_type(component_id, &component_type) != SUIT_PLAT_SUCCESS || + component_type != SUIT_COMPONENT_TYPE_MEM) { + return SUIT_PLAT_ERR_UNSUPPORTED; + } + + if (suit_plat_decode_address_size(component_id, &decoded_slot_address, + &decoded_slot_size) != SUIT_PLAT_SUCCESS || + decoded_slot_address == 0 || decoded_slot_size == 0) { + return SUIT_PLAT_ERR_UNSUPPORTED; + } + + *slot_address = decoded_slot_address; + *slot_size = decoded_slot_size; + + return SUIT_PLAT_SUCCESS; +} + +suit_plat_err_t suit_ipuc_sdfw_get_count(size_t *count) +{ + + if (count == NULL) { + return SUIT_PLAT_ERR_INVAL; + } + + size_t declared_count = 0; + + k_mutex_lock(&ipuc_mutex, K_FOREVER); + for (size_t i = 0; i < CONFIG_SUIT_IPUC_SIZE; i++) { + suit_ipuc_entry_t *ipuc_entry = &components[i]; + + if (ipuc_entry->component_id.value != NULL && ipuc_entry->component_id.len != 0) { + declared_count++; + } + } + *count = declared_count; + k_mutex_unlock(&ipuc_mutex); + return SUIT_PLAT_SUCCESS; +} + +suit_plat_err_t suit_ipuc_sdfw_get_info(size_t idx, struct zcbor_string *component_id, + suit_manifest_role_t *role) +{ + if (component_id == NULL || role == NULL) { + return SUIT_PLAT_ERR_INVAL; + } + + size_t cur_idx = 0; + + k_mutex_lock(&ipuc_mutex, K_FOREVER); + for (size_t i = 0; i < CONFIG_SUIT_IPUC_SIZE; i++) { + suit_ipuc_entry_t *ipuc_entry = &components[i]; + + if (ipuc_entry->component_id.value != NULL && ipuc_entry->component_id.len != 0) { + if (cur_idx == idx) { + component_id->value = ipuc_entry->component_id.value; + component_id->len = ipuc_entry->component_id.len; + *role = ipuc_entry->role; + k_mutex_unlock(&ipuc_mutex); + return SUIT_PLAT_SUCCESS; + } + cur_idx++; + } + } + + k_mutex_unlock(&ipuc_mutex); + return SUIT_PLAT_ERR_NOT_FOUND; +} + +suit_plat_err_t suit_ipuc_sdfw_write_setup(int ipc_client_id, struct zcbor_string *component_id, + struct zcbor_string *encryption_info, + struct zcbor_string *compression_info) +{ + intptr_t slot_address = 0; + size_t slot_size = 0; + + if (component_id == NULL) { + return SUIT_PLAT_ERR_INVAL; + } + + if (ipuc_decode_mem_component_id(component_id, &slot_address, &slot_size) != + SUIT_PLAT_SUCCESS) { + /* Only MEM components are supported + */ + return SUIT_PLAT_ERR_UNSUPPORTED; + } + + if (encryption_info != NULL && encryption_info->value != NULL && + encryption_info->len != 0) { + /* Encryption not supported yet + */ + return SUIT_PLAT_ERR_UNSUPPORTED; + } + + if (compression_info != NULL && compression_info->value != NULL && + compression_info->len != 0) { + /* Compression not supported yet + */ + return SUIT_PLAT_ERR_UNSUPPORTED; + } + + k_mutex_lock(&ipuc_mutex, K_FOREVER); + suit_ipuc_entry_t *ipuc_entry = ipuc_entry_from_component_id(component_id); + + if (ipuc_entry == NULL) { + k_mutex_unlock(&ipuc_mutex); + return SUIT_PLAT_ERR_NOT_FOUND; + } + + if (!(ipuc_entry->usage == IPUC_UNUSED || (ipuc_entry->usage == IPUC_IPC_IN_PLACE_UPDATE && + ipuc_entry->ipc_client_id == ipc_client_id))) { + LOG_ERR("suit_ipuc_sdfw_write_setup, IPUC address: %p, busy", (void *)slot_address); + k_mutex_unlock(&ipuc_mutex); + return SUIT_PLAT_ERR_INCORRECT_STATE; + } + + /* Erasing if necessary + */ + uint8_t read_buffer[READ_CHUNK_MAX_SIZE]; + struct stream_sink ram_sink; + + if (suit_ram_sink_get(&ram_sink, read_buffer, READ_CHUNK_MAX_SIZE) != SUIT_PLAT_SUCCESS) { + LOG_ERR("Could not acquire RAM sink"); + k_mutex_unlock(&ipuc_mutex); + return SUIT_PLAT_ERR_IO; + } + + bool clear = true; + + for (size_t off = 0; off < slot_size && clear == true; off += READ_CHUNK_MAX_SIZE) { + size_t cur_chunk_size = slot_size - off; + + if (cur_chunk_size > READ_CHUNK_MAX_SIZE) { + cur_chunk_size = READ_CHUNK_MAX_SIZE; + } + + suit_address_streamer stream_fn = + suit_address_streamer_select_by_address((uint8_t *)(slot_address + off)); + if (stream_fn == NULL) { + LOG_ERR("Could not find streamer for address: %p", + (void *)(slot_address + off)); + if (ram_sink.release) { + ram_sink.release(ram_sink.ctx); + } + k_mutex_unlock(&ipuc_mutex); + return SUIT_PLAT_ERR_IO; + } + + if (ram_sink.seek) { + ram_sink.seek(ram_sink.ctx, 0); + } + + if (stream_fn((uint8_t *)(slot_address + off), cur_chunk_size, &ram_sink) != + SUIT_PLAT_SUCCESS) { + LOG_ERR("Stream function has failed"); + if (ram_sink.release) { + ram_sink.release(ram_sink.ctx); + } + k_mutex_unlock(&ipuc_mutex); + return SUIT_PLAT_ERR_IO; + } + + for (size_t ram_off = 0; ram_off < cur_chunk_size; ram_off++) { + if (read_buffer[ram_off] != 0xFF) { + clear = false; + break; + } + } + } + + if (ram_sink.release) { + ram_sink.release(ram_sink.ctx); + } + + if (!clear) { + struct stream_sink ipuc_sink; + bool ipuc_sink_allocated = false; + + LOG_INF("suit_ipuc_sdfw_write_setup, address: %p, size: %d bytes, erasing " + "needed", + (void *)slot_address, slot_size); + + if (suit_flash_sink_is_address_supported((uint8_t *)slot_address)) { + if (suit_flash_sink_get(&ipuc_sink, (uint8_t *)slot_address, slot_size) == + SUIT_PLAT_SUCCESS) { + ipuc_sink_allocated = true; + } + } + + if (!ipuc_sink_allocated) { + k_mutex_unlock(&ipuc_mutex); + return SUIT_PLAT_ERR_IO; + } + +#if CONFIG_SUIT_DIGEST_CACHE + suit_plat_digest_cache_remove(component_id); +#endif /* CONFIG_SUIT_DIGEST_CACHE */ + + if (ipuc_sink.erase == NULL || + ipuc_sink.erase(ipuc_sink.ctx) != SUIT_PLAT_SUCCESS) { + LOG_ERR("Erase operation not supported or failed"); + if (ipuc_sink.release) { + ipuc_sink.release(ipuc_sink.ctx); + } + k_mutex_unlock(&ipuc_mutex); + return SUIT_PLAT_ERR_IO; + } + + if (ipuc_sink.release) { + ipuc_sink.release(ipuc_sink.ctx); + } + } + + ipuc_entry->usage = IPUC_IPC_IN_PLACE_UPDATE; + ipuc_entry->ipc_client_id = ipc_client_id; + ipuc_entry->write_peek_offset = 0; + ipuc_entry->last_chunk_stored = false; + + LOG_INF("suit_ipuc_sdfw_write_setup success, IPUC address: %p", (void *)slot_address); + + k_mutex_unlock(&ipuc_mutex); + return SUIT_PLAT_SUCCESS; +} + +suit_plat_err_t suit_ipuc_sdfw_write(int ipc_client_id, struct zcbor_string *component_id, + size_t offset, uintptr_t buffer, size_t chunk_size, + bool last_chunk) +{ + intptr_t slot_address = 0; + size_t slot_size = 0; + + if (component_id == NULL) { + return SUIT_PLAT_ERR_INVAL; + } + + if (ipuc_decode_mem_component_id(component_id, &slot_address, &slot_size) != + SUIT_PLAT_SUCCESS) { + /* Only MEM components are supported + */ + return SUIT_PLAT_ERR_UNSUPPORTED; + } + + k_mutex_lock(&ipuc_mutex, K_FOREVER); + suit_ipuc_entry_t *ipuc_entry = ipuc_entry_from_component_id(component_id); + + if (ipuc_entry == NULL) { + k_mutex_unlock(&ipuc_mutex); + return SUIT_PLAT_ERR_NOT_FOUND; + } + + if (ipuc_entry->usage != IPUC_IPC_IN_PLACE_UPDATE || + ipuc_entry->ipc_client_id != ipc_client_id) { + k_mutex_unlock(&ipuc_mutex); + return SUIT_PLAT_ERR_INCORRECT_STATE; + } + + if (ipuc_entry->last_chunk_stored) { + k_mutex_unlock(&ipuc_mutex); + return SUIT_PLAT_ERR_INCORRECT_STATE; + } + + if (buffer && chunk_size > 0) { + + struct stream_sink ipuc_sink; + + if (suit_flash_sink_get(&ipuc_sink, (uint8_t *)slot_address, slot_size) != + SUIT_PLAT_SUCCESS) { + LOG_ERR("IPUC sink not allocated"); + k_mutex_unlock(&ipuc_mutex); + return SUIT_PLAT_ERR_IO; + } + + if (ipuc_sink.seek == NULL || + ipuc_sink.seek(ipuc_sink.ctx, offset) != SUIT_PLAT_SUCCESS) { + LOG_ERR("Seek operation not supported or failed"); + if (ipuc_sink.release) { + ipuc_sink.release(ipuc_sink.ctx); + } + k_mutex_unlock(&ipuc_mutex); + return SUIT_PLAT_ERR_IO; + } + + if (ipuc_sink.write == NULL || ipuc_sink.write(ipuc_sink.ctx, (uint8_t *)buffer, + chunk_size) != SUIT_PLAT_SUCCESS) { + LOG_ERR("Write operation not supported or failed"); + if (ipuc_sink.release) { + ipuc_sink.release(ipuc_sink.ctx); + } + k_mutex_unlock(&ipuc_mutex); + return SUIT_PLAT_ERR_IO; + } + + size_t cur_offset = offset + chunk_size; + + if (ipuc_sink.release) { + ipuc_sink.release(ipuc_sink.ctx); + } + + if (ipuc_entry->write_peek_offset < cur_offset) { + ipuc_entry->write_peek_offset = cur_offset; + } + } + + if (last_chunk) { + ipuc_entry->last_chunk_stored = last_chunk; + LOG_INF("suit_ipuc_sdfw_write, IPUC address: %p, last chunk written", + (void *)slot_address); + } + + k_mutex_unlock(&ipuc_mutex); + return SUIT_PLAT_SUCCESS; +} + +suit_plat_err_t suit_ipuc_sdfw_digest_compare(struct zcbor_string *component_id, + enum suit_cose_alg alg_id, + struct zcbor_string *digest) +{ + if (component_id == NULL || digest == NULL) { + return SUIT_PLAT_ERR_INVAL; + } + + k_mutex_lock(&ipuc_mutex, K_FOREVER); + suit_ipuc_entry_t *ipuc_entry = ipuc_entry_from_component_id(component_id); + intptr_t slot_address = 0; + size_t slot_size = 0; + + if (ipuc_entry == NULL) { + k_mutex_unlock(&ipuc_mutex); + return SUIT_PLAT_ERR_NOT_FOUND; + } + + if (ipuc_entry->usage != IPUC_IPC_IN_PLACE_UPDATE || !ipuc_entry->last_chunk_stored) { + k_mutex_unlock(&ipuc_mutex); + return SUIT_PLAT_ERR_INCORRECT_STATE; + } + + if (ipuc_decode_mem_component_id(component_id, &slot_address, &slot_size) != + SUIT_PLAT_SUCCESS) { + /* Only MEM components are supported + */ + k_mutex_unlock(&ipuc_mutex); + return SUIT_PLAT_ERR_UNSUPPORTED; + } + +#ifdef CONFIG_SUIT_STREAM_SINK_DIGEST + psa_algorithm_t psa_alg; + + if (suit_cose_sha512 == alg_id) { + psa_alg = PSA_ALG_SHA_512; + } else if (suit_cose_sha256 == alg_id) { + psa_alg = PSA_ALG_SHA_256; + } else { + LOG_ERR("Unsupported hash algorithm: %d", alg_id); + k_mutex_unlock(&ipuc_mutex); + return SUIT_PLAT_ERR_UNSUPPORTED; + } + + struct stream_sink digest_sink; + + if (suit_digest_sink_get(&digest_sink, psa_alg, digest->value) != SUIT_PLAT_SUCCESS) { + + LOG_ERR("Failed to get digest sink"); + k_mutex_unlock(&ipuc_mutex); + return SUIT_PLAT_ERR_IO; + } + + if (suit_generic_address_streamer_stream((uint8_t *)slot_address, + ipuc_entry->write_peek_offset, + &digest_sink) != SUIT_PLAT_SUCCESS) { + LOG_ERR("Failed to stream to digest sink"); + if (digest_sink.release) { + digest_sink.release(digest_sink.ctx); + } + k_mutex_unlock(&ipuc_mutex); + return SUIT_PLAT_ERR_IO; + } + + if (suit_digest_sink_digest_match(digest_sink.ctx) != SUIT_PLAT_SUCCESS) { + LOG_ERR("Digest does not match"); + if (digest_sink.release) { + digest_sink.release(digest_sink.ctx); + } + k_mutex_unlock(&ipuc_mutex); + return SUIT_PLAT_ERR_INVAL; + } + + if (digest_sink.release) { + digest_sink.release(digest_sink.ctx); + } + + LOG_INF("suit_ipuc_sdfw_digest_compare success, IPUC address: %p", (void *)slot_address); + + k_mutex_unlock(&ipuc_mutex); + return SUIT_PLAT_SUCCESS; + +#else /* CONFIG_SUIT_STREAM_SINK_DIGEST */ + LOG_ERR("Digest sink not enabled, see CONFIG_SUIT_STREAM_SINK_DIGEST"); + k_mutex_unlock(&ipuc_mutex); + return SUIT_PLAT_ERR_UNSUPPORTED; + +#endif /* CONFIG_SUIT_STREAM_SINK_DIGEST */ +} + +suit_plat_err_t suit_ipuc_sdfw_revoke(suit_component_t handle) +{ + + k_mutex_lock(&ipuc_mutex, K_FOREVER); + suit_ipuc_entry_t *ipuc_entry = ipuc_entry_from_handle(handle); + + if (ipuc_entry == NULL) { + k_mutex_unlock(&ipuc_mutex); + return SUIT_PLAT_ERR_NOT_FOUND; + } + +#if (defined CONFIG_SUIT_LOG_LEVEL_INF || defined CONFIG_SUIT_LOG_LEVEL_DBG) + intptr_t slot_address = 0; + size_t slot_size = 0; + + if (suit_plat_decode_address_size(&ipuc_entry->component_id, &slot_address, &slot_size) == + SUIT_PLAT_SUCCESS) { + LOG_INF("Revoking IPUC, address: %p, size: %d bytes", (void *)slot_address, + slot_size); + } +#endif + + ipuc_entry->component_id.value = NULL; + ipuc_entry->component_id.len = 0; + ipuc_entry->role = SUIT_MANIFEST_UNKNOWN; + ipuc_entry->usage = IPUC_UNUSED; + ipuc_entry->ipc_client_id = 0; + ipuc_entry->write_peek_offset = 0; + ipuc_entry->last_chunk_stored = false; + + k_mutex_unlock(&ipuc_mutex); + return SUIT_PLAT_SUCCESS; +} + +suit_plat_err_t suit_ipuc_sdfw_declare(suit_component_t handle, suit_manifest_role_t role) +{ + suit_ipuc_entry_t *allocated_entry = NULL; + struct zcbor_string *component_id = ipuc_component_id_from_handle(handle); + intptr_t slot_address = 0; + size_t slot_size = 0; + + if (component_id == NULL) { + return SUIT_PLAT_ERR_INVAL; + } + + if (ipuc_decode_mem_component_id(component_id, &slot_address, &slot_size) != + SUIT_PLAT_SUCCESS) { + /* Only MEM components are supported + */ + return SUIT_PLAT_ERR_UNSUPPORTED; + } + + k_mutex_lock(&ipuc_mutex, K_FOREVER); + for (size_t i = 0; i < CONFIG_SUIT_IPUC_SIZE; i++) { + suit_ipuc_entry_t *p_entry = &components[i]; + + if (allocated_entry == NULL && p_entry->component_id.value == NULL) { + allocated_entry = p_entry; + + } else if (suit_compare_zcbor_strings(component_id, &p_entry->component_id)) { + allocated_entry = p_entry; + break; + } + } + + if (allocated_entry == NULL) { + k_mutex_unlock(&ipuc_mutex); + return SUIT_PLAT_ERR_NOMEM; + } + + LOG_INF("Declaring IPUC, address: %p, size: %d bytes, mfst role: 0x%02X", + (void *)slot_address, slot_size, role); + + allocated_entry->component_id.value = component_id->value; + allocated_entry->component_id.len = component_id->len; + allocated_entry->role = role; + allocated_entry->usage = IPUC_UNUSED; + allocated_entry->ipc_client_id = 0; + allocated_entry->write_peek_offset = 0; + allocated_entry->last_chunk_stored = false; + + k_mutex_unlock(&ipuc_mutex); + return SUIT_PLAT_SUCCESS; +} + +uintptr_t suit_ipuc_sdfw_mirror_addr(size_t required_size) +{ + uintptr_t sdfw_update_area_addr = 0; + size_t sdfw_update_area_size = 0; + + suit_memory_sdfw_update_area_info_get(&sdfw_update_area_addr, &sdfw_update_area_size); + + if (required_size == 0 || sdfw_update_area_size == 0) { + + LOG_ERR("suit_ipuc_sdfw_mirror_addr, required_size: %d, sdfw_update_area_size " + "%d", + required_size, sdfw_update_area_size); + return 0; + } + + k_mutex_lock(&ipuc_mutex, K_FOREVER); + for (size_t i = 0; i < CONFIG_SUIT_IPUC_SIZE; i++) { + + suit_ipuc_entry_t *ipuc_entry = &components[i]; + struct zcbor_string *component_id = &ipuc_entry->component_id; + intptr_t slot_address = 0; + size_t slot_size = 0; + + if (ipuc_entry->usage != IPUC_UNUSED && ipuc_entry->usage != IPUC_SDFW_MIRROR) { + continue; + } + + if (ipuc_decode_mem_component_id(component_id, &slot_address, &slot_size) != + SUIT_PLAT_SUCCESS) { + /* Only MEM components are supported + */ + continue; + } + + if (slot_size < required_size) { + continue; + } + + uintptr_t adjusted_slot_address = slot_address; + + /* Adjusting mirror address if IPUC is located in address lower than + * area acceptable by SDROM + */ + if (slot_address < sdfw_update_area_addr) { + adjusted_slot_address = sdfw_update_area_addr; + size_t shift = (sdfw_update_area_addr - slot_address); + + if (shift + required_size > slot_size) { + continue; + } + } + + if (adjusted_slot_address + required_size > + sdfw_update_area_addr + sdfw_update_area_size) { + continue; + } + + /* clang-format off */ + struct arbiter_mem_params_access mem_params = { + .allowed_types = ARBITER_MEM_TYPE(RESERVED, FIXED), + .access = { + .owner = NRF_OWNER_APPLICATION, + .permissions = ARBITER_MEM_PERM(READ, SECURE), + .address = adjusted_slot_address, + .size = required_size, + }, + }; + /* clang-format on */ + + LOG_INF("Checking IPUC ownership, address: %p, size: %d bytes", + (void *)mem_params.access.address, mem_params.access.size); + + if (arbiter_mem_access_check(&mem_params) == ARBITER_STATUS_OK) { + /* ... belonging to app domain + */ +#if CONFIG_SUIT_DIGEST_CACHE + suit_plat_digest_cache_remove(component_id); +#endif /* CONFIG_SUIT_DIGEST_CACHE */ + ipuc_entry->usage = IPUC_SDFW_MIRROR; + k_mutex_unlock(&ipuc_mutex); + return adjusted_slot_address; + } + + mem_params.access.owner = NRF_OWNER_RADIOCORE; + if (arbiter_mem_access_check(&mem_params) == ARBITER_STATUS_OK) { + /* ... or belonging to radio domain + */ +#if CONFIG_SUIT_DIGEST_CACHE + suit_plat_digest_cache_remove(component_id); +#endif /* CONFIG_SUIT_DIGEST_CACHE */ + ipuc_entry->usage = IPUC_SDFW_MIRROR; + k_mutex_unlock(&ipuc_mutex); + return adjusted_slot_address; + } + } + + k_mutex_unlock(&ipuc_mutex); + return 0; +} diff --git a/subsys/suit/platform/CMakeLists.txt b/subsys/suit/platform/CMakeLists.txt index a8109f4be30e..9dedfa82a9ed 100644 --- a/subsys/suit/platform/CMakeLists.txt +++ b/subsys/suit/platform/CMakeLists.txt @@ -36,6 +36,7 @@ zephyr_library_link_libraries_ifdef(CONFIG_SUIT_MEMPTR_STORAGE suit_memptr_stora zephyr_library_link_libraries_ifdef(CONFIG_SUIT_SINK_SELECTOR suit_sink_selector_interface) zephyr_library_link_libraries_ifdef(CONFIG_SUIT_STREAM_FILTER_DECRYPT suit_stream_filters_interface) zephyr_library_link_libraries_ifdef(CONFIG_SUIT_MANIFEST_VARIABLES suit_manifest_variables) +zephyr_library_link_libraries_ifdef(CONFIG_SUIT_IPUC suit_ipuc) if(CONFIG_SUIT_PLATFORM_VARIANT_APP) add_subdirectory(app) diff --git a/subsys/suit/platform/include/suit_plat_ipuc.h b/subsys/suit/platform/include/suit_plat_ipuc.h deleted file mode 100644 index ebd48977d0ad..000000000000 --- a/subsys/suit/platform/include/suit_plat_ipuc.h +++ /dev/null @@ -1,93 +0,0 @@ -/* - * Copyright (c) 2024 Nordic Semiconductor ASA - * - * SPDX-License-Identifier: LicenseRef-Nordic-5-Clause - */ - -/** - * @brief Support for in-place updateable componenet. - * - * SUIT manifest may instruct the platform that component is inactive, by overriding - * image-size parameter with value 0. Such component may be updated in place, - * also memory associated to such component may be utilized for other purposes, - * like updating SDFW or SDFW_Recovery from external flash. - */ - -#ifndef SUIT_PLAT_IPUC_H__ -#define SUIT_PLAT_IPUC_H__ - -#include -#include - -#ifdef __cplusplus -extern "C" { -#endif - -/** @brief Declare component as updateable. - * - * @param[in] handle Handle to the updateable component. - * - * @retval SUIT_PLAT_ERR_INVAL component handle is invalid or component is not supported. - * @retval SUIT_PLAT_ERR_NOMEM the maximum number of updateable components has been reached. - * @retval SUIT_PLAT_SUCCESS updateable component was successfully declared. - */ -suit_plat_err_t suit_plat_ipuc_declare(suit_component_t handle); - -/** @brief Revoke declaration of updateable component. - * - * @param[in] handle Handle to the component that is no longer updateable. - * - * @retval SUIT_PLAT_ERR_NOT_FOUND component is not declared as IPUC - * @retval SUIT_PLAT_SUCCESS declaration of updateable component was successfully revoked. - */ -suit_plat_err_t suit_plat_ipuc_revoke(suit_component_t handle); - -/** @brief Writes a chunk of data to IPUC - * - * @note offset parameter equal to 0 resets the data transfer. That allows to restart a image - * transfer, or even to transfer a new image. - * - * @param[in] handle Handle to the updateable component. - * @param[in] offset Offset to write data chunk. Discontinuous writes are not supported. - * @param[in] buffer Pointer to source data chunk. - * @param[in] chunk_size Size of data chunk. - * @param[in] last_chunk True if this is the last chunk of image. - * - * @retval SUIT_PLAT_ERR_NOT_FOUND component is not declared as IPUC - * @retval SUIT_PLAT_ERR_INCORRECT_STATE discontinued write attempt - * @retval SUIT_PLAT_ERR_IO sink not found, sink does not support seek operation, seek operation - * failed, streaming to sink failed - * @retval SUIT_PLAT_SUCCESS opration completed successfully - * - */ -suit_plat_err_t suit_plat_ipuc_write(suit_component_t handle, size_t offset, uintptr_t buffer, - size_t chunk_size, bool last_chunk); - -/** @brief Gets size of image written to IPUC - * - * @param[in] handle Handle to the updateable component. - * @param[out] size Size of image stored in IPUC - * - * @retval SUIT_PLAT_ERR_INVAL invalid parameter - * @retval SUIT_PLAT_ERR_NOT_FOUND component is not declared as IPUC - * @retval SUIT_PLAT_ERR_INCORRECT_STATE writing to IPUC is still in progress - * @retval SUIT_PLAT_SUCCESS opration completed successfully - */ -suit_plat_err_t suit_plat_ipuc_get_stored_img_size(suit_component_t handle, size_t *size); - -/** @brief Find an updateable component which is capable to store SDFW update candidate. - * - * @details Since Secure ROM imposes requirements related to SDFW candidate location, returned - * pointer does not necessarily points to the begin of updateable component. - * - * @param[in] required_size Required size of area capable to store SDFW candidate. - * - * @returns Pointer to area capable to store SDFW candidate, 0 otherwise. - */ -uintptr_t suit_plat_ipuc_sdfw_mirror_addr(size_t required_size); - -#ifdef __cplusplus -} -#endif - -#endif /* SUIT_PLAT_IPUC_H__ */ diff --git a/subsys/suit/platform/sdfw/CMakeLists.txt b/subsys/suit/platform/sdfw/CMakeLists.txt index 1a56fa40fedb..d3f0cc5053ad 100644 --- a/subsys/suit/platform/sdfw/CMakeLists.txt +++ b/subsys/suit/platform/sdfw/CMakeLists.txt @@ -18,7 +18,6 @@ zephyr_library_sources(src/suit_plat_write_sdfw_specific.c) zephyr_library_sources(src/suit_plat_retrieve_manifest_sdfw_specific.c) zephyr_library_sources(src/suit_plat_version_sdfw_specific.c) zephyr_library_sources_ifdef(CONFIG_SUIT_DIGEST_CACHE src/suit_plat_digest_cache.c) -zephyr_library_sources_ifdef(CONFIG_SUIT_IPUC src/suit_plat_ipuc.c) zephyr_library_sources_ifdef(CONFIG_SUIT_CHECK_IMAGE_MATCH src/suit_plat_check_image_match_sdfw_specific.c) zephyr_library_sources(src/suit_plat_check_content_sdfw_specific.c) zephyr_library_sources_ifdef(CONFIG_SUIT_DEVCONFIG src/suit_plat_devconfig.c) @@ -46,6 +45,7 @@ zephyr_library_link_libraries_ifdef(CONFIG_SUIT_PLAT_CHECK_COMPONENT_COMPATIBILI zephyr_library_link_libraries_ifdef(CONFIG_SUIT_STREAM_FILTER_DECRYPT suit_stream_filters_interface) zephyr_library_link_libraries_ifdef(CONFIG_SUIT_EVENTS suit_events) zephyr_library_link_libraries_ifdef(CONFIG_SUIT_MANIFEST_VARIABLES suit_manifest_variables) +zephyr_library_link_libraries_ifdef(CONFIG_SUIT_IPUC suit_ipuc) zephyr_library_link_libraries(suit_sdfw_platform) zephyr_library_link_libraries(suit_utils) diff --git a/subsys/suit/platform/sdfw/Kconfig b/subsys/suit/platform/sdfw/Kconfig index 958fb5811333..73261ba40b52 100644 --- a/subsys/suit/platform/sdfw/Kconfig +++ b/subsys/suit/platform/sdfw/Kconfig @@ -22,20 +22,6 @@ config SUIT_DIGEST_CACHE_SIZE endif -config SUIT_IPUC - bool "Enable in-place updateable components" - help - SUIT manifest may instruct the platform that component is inactive, by overriding - image-size parameter with value 0. Such component may be updated in place, - also memory associated to such component may be utilized for other purposes. - -if SUIT_IPUC - -config SUIT_IPUC_SIZE - int "Maximum number of supported in-place updateable components" - default 8 -endif - config SUIT_AUTHENTICATE bool "Enable message/data authentication" depends on SUIT_CRYPTO diff --git a/subsys/suit/platform/sdfw/src/suit_plat_copy_sdfw_specific.c b/subsys/suit/platform/sdfw/src/suit_plat_copy_sdfw_specific.c index 7e1f294c5b18..d4c24f0ab59e 100644 --- a/subsys/suit/platform/sdfw/src/suit_plat_copy_sdfw_specific.c +++ b/subsys/suit/platform/sdfw/src/suit_plat_copy_sdfw_specific.c @@ -15,8 +15,8 @@ #include #include -#if CONFIG_SUIT_IPUC -#include +#ifdef CONFIG_SUIT_IPUC +#include #include #endif /* CONFIG_SUIT_IPUC */ @@ -263,7 +263,7 @@ int suit_plat_copy_domain_specific(suit_component_t dst_handle, */ #if CONFIG_SUIT_IPUC - suit_plat_ipuc_revoke(dst_handle); + suit_ipuc_sdfw_revoke(dst_handle); #endif /* CONFIG_SUIT_IPUC */ #if CONFIG_SUIT_DIGEST_CACHE @@ -326,7 +326,7 @@ int suit_plat_copy_domain_specific(suit_component_t dst_handle, #ifdef CONFIG_SUIT_IPUC struct stream_sink mirror_sink; intptr_t mirror_addr = - suit_plat_ipuc_sdfw_mirror_addr(payload_size); + suit_ipuc_sdfw_mirror_addr(payload_size); if (mirror_addr == 0) { LOG_ERR("SDFW or SDFW_RECOVERY update - candidate mirror " diff --git a/subsys/suit/platform/sdfw/src/suit_plat_ipuc.c b/subsys/suit/platform/sdfw/src/suit_plat_ipuc.c deleted file mode 100644 index c981aa46add8..000000000000 --- a/subsys/suit/platform/sdfw/src/suit_plat_ipuc.c +++ /dev/null @@ -1,345 +0,0 @@ -/* - * Copyright (c) 2024 Nordic Semiconductor ASA - * - * SPDX-License-Identifier: LicenseRef-Nordic-5-Clause - */ - -#include "suit_plat_ipuc.h" -#include -#include -#include -#include -#include -#include -#include -#include - -LOG_MODULE_REGISTER(suit_ipuc, CONFIG_SUIT_LOG_LEVEL); - -typedef struct { - struct zcbor_string component_id; - size_t write_offset; - bool last_chunk_stored; - -} suit_plat_ipuc_entry_t; - -static suit_plat_ipuc_entry_t components[CONFIG_SUIT_IPUC_SIZE]; -static K_MUTEX_DEFINE(ipuc_mutex); - -static struct zcbor_string *ipuc_component_id_from_handle(suit_component_t handle) -{ - struct zcbor_string *component_id = NULL; - suit_component_type_t component_type = SUIT_COMPONENT_TYPE_UNSUPPORTED; - - if (suit_plat_component_id_get(handle, &component_id) != SUIT_SUCCESS) { - return NULL; - } - - if (suit_plat_decode_component_type(component_id, &component_type) != SUIT_PLAT_SUCCESS) { - return NULL; - } - - if (component_type != SUIT_COMPONENT_TYPE_MEM) { - /* The only supported component type is MEM - */ - return NULL; - } - - return component_id; -} - -static suit_plat_ipuc_entry_t *ipuc_entry_from_handle(suit_component_t handle) -{ - struct zcbor_string *component_id = ipuc_component_id_from_handle(handle); - - if (component_id == NULL) { - return NULL; - } - - for (size_t i = 0; i < CONFIG_SUIT_IPUC_SIZE; i++) { - suit_plat_ipuc_entry_t *p_entry = &components[i]; - - if (suit_compare_zcbor_strings(component_id, &p_entry->component_id)) { - return p_entry; - } - } - - return NULL; -} - -suit_plat_err_t suit_plat_ipuc_write(suit_component_t handle, size_t offset, uintptr_t buffer, - size_t chunk_size, bool last_chunk) -{ - suit_plat_err_t plat_ret = SUIT_PLAT_SUCCESS; - struct stream_sink ipuc_sink; - bool sink_allocated = false; - - k_mutex_lock(&ipuc_mutex, K_FOREVER); - suit_plat_ipuc_entry_t *ipuc_entry = ipuc_entry_from_handle(handle); - - if (ipuc_entry == NULL) { - plat_ret = SUIT_PLAT_ERR_NOT_FOUND; - } - - if (plat_ret == SUIT_PLAT_SUCCESS) { - - if (offset == 0) { - ipuc_entry->write_offset = 0; - ipuc_entry->last_chunk_stored = false; - } - - if (offset != ipuc_entry->write_offset || ipuc_entry->last_chunk_stored) { - plat_ret = SUIT_PLAT_ERR_INCORRECT_STATE; - } - } - - if (plat_ret == SUIT_PLAT_SUCCESS) { - plat_ret = suit_sink_select(handle, &ipuc_sink); - if (plat_ret != SUIT_PLAT_SUCCESS) { - plat_ret = SUIT_PLAT_ERR_IO; - } else { - sink_allocated = true; - } - } - - if (plat_ret == SUIT_PLAT_SUCCESS) { - if (ipuc_sink.seek == NULL) { - plat_ret = SUIT_PLAT_ERR_IO; - } - } - - if (plat_ret == SUIT_PLAT_SUCCESS) { - if (offset == 0 && ipuc_sink.erase != NULL) { - ipuc_sink.erase(ipuc_sink.ctx); - } - - plat_ret = ipuc_sink.seek(ipuc_sink.ctx, offset); - if (plat_ret != SUIT_PLAT_SUCCESS) { - plat_ret = SUIT_PLAT_ERR_IO; - } - } - - if (plat_ret == SUIT_PLAT_SUCCESS && chunk_size > 0) { - plat_ret = suit_generic_address_streamer_stream((uint8_t *)buffer, chunk_size, - &ipuc_sink); - if (plat_ret != SUIT_PLAT_SUCCESS) { - plat_ret = SUIT_PLAT_ERR_IO; - } - } - - if (plat_ret == SUIT_PLAT_SUCCESS) { - ipuc_entry->write_offset = offset + chunk_size; - if (last_chunk) { - ipuc_entry->last_chunk_stored = true; - } - } - - if (sink_allocated) { - if (ipuc_sink.release != NULL) { - ipuc_sink.release(ipuc_sink.ctx); - } - } - - k_mutex_unlock(&ipuc_mutex); - return plat_ret; -} - -suit_plat_err_t suit_plat_ipuc_get_stored_img_size(suit_component_t handle, size_t *size) -{ - if (size == NULL) { - return SUIT_PLAT_ERR_INVAL; - } - - k_mutex_lock(&ipuc_mutex, K_FOREVER); - suit_plat_ipuc_entry_t *ipuc_entry = ipuc_entry_from_handle(handle); - - if (ipuc_entry == NULL) { - k_mutex_unlock(&ipuc_mutex); - return SUIT_PLAT_ERR_NOT_FOUND; - } - - if (ipuc_entry->last_chunk_stored == false) { - k_mutex_unlock(&ipuc_mutex); - return SUIT_PLAT_ERR_INCORRECT_STATE; - } - - *size = ipuc_entry->write_offset; - k_mutex_unlock(&ipuc_mutex); - return SUIT_PLAT_SUCCESS; -} - -suit_plat_err_t suit_plat_ipuc_revoke(suit_component_t handle) -{ - - k_mutex_lock(&ipuc_mutex, K_FOREVER); - suit_plat_ipuc_entry_t *ipuc_entry = ipuc_entry_from_handle(handle); - - if (ipuc_entry == NULL) { - k_mutex_unlock(&ipuc_mutex); - return SUIT_PLAT_ERR_NOT_FOUND; - } - -#ifdef CONFIG_SUIT_LOG_LEVEL_INF - intptr_t slot_address = 0; - size_t slot_size = 0; - - if (suit_plat_decode_address_size(&ipuc_entry->component_id, &slot_address, &slot_size) == - SUIT_PLAT_SUCCESS) { - LOG_INF("Revoking IPUC, address: %p, size: %d bytes", (void *)slot_address, - slot_size); - } -#endif - - ipuc_entry->component_id.value = NULL; - ipuc_entry->component_id.len = 0; - ipuc_entry->write_offset = 0; - ipuc_entry->last_chunk_stored = false; - - k_mutex_unlock(&ipuc_mutex); - return SUIT_PLAT_SUCCESS; -} - -suit_plat_err_t suit_plat_ipuc_declare(suit_component_t handle) -{ - suit_plat_ipuc_entry_t *allocated_entry = NULL; - struct zcbor_string *component_id = ipuc_component_id_from_handle(handle); - - if (component_id == NULL) { - return SUIT_PLAT_ERR_INVAL; - } - - k_mutex_lock(&ipuc_mutex, K_FOREVER); - for (size_t i = 0; i < CONFIG_SUIT_IPUC_SIZE; i++) { - suit_plat_ipuc_entry_t *p_entry = &components[i]; - - if (allocated_entry == NULL && p_entry->component_id.value == NULL) { - allocated_entry = p_entry; - - } else if (suit_compare_zcbor_strings(component_id, &p_entry->component_id)) { - allocated_entry = p_entry; - break; - } - } - - if (allocated_entry == NULL) { - k_mutex_unlock(&ipuc_mutex); - return SUIT_PLAT_ERR_NOMEM; - } - -#ifdef CONFIG_SUIT_LOG_LEVEL_INF - intptr_t slot_address = 0; - size_t slot_size = 0; - - if (suit_plat_decode_address_size(component_id, &slot_address, &slot_size) == - SUIT_PLAT_SUCCESS) { - LOG_INF("Declaring IPUC, address: %p, size: %d bytes", (void *)slot_address, - slot_size); - } -#endif - - allocated_entry->component_id.value = component_id->value; - allocated_entry->component_id.len = component_id->len; - allocated_entry->write_offset = 0; - allocated_entry->last_chunk_stored = false; - - k_mutex_unlock(&ipuc_mutex); - return SUIT_PLAT_SUCCESS; -} - -uintptr_t suit_plat_ipuc_sdfw_mirror_addr(size_t required_size) -{ - uintptr_t sdfw_update_area_addr = 0; - size_t sdfw_update_area_size = 0; - - suit_memory_sdfw_update_area_info_get(&sdfw_update_area_addr, &sdfw_update_area_size); - - if (required_size == 0 || sdfw_update_area_size == 0) { - - LOG_ERR("suit_plat_ipuc_sdfw_mirror_addr, required_size: %d, sdfw_update_area_size " - "%d", - required_size, sdfw_update_area_size); - return 0; - } - - k_mutex_lock(&ipuc_mutex, K_FOREVER); - for (size_t i = 0; i < CONFIG_SUIT_IPUC_SIZE; i++) { - - struct zcbor_string *component_id = &components[i].component_id; - - if (component_id->value == NULL) { - continue; - } - - suit_component_type_t component_type = SUIT_COMPONENT_TYPE_UNSUPPORTED; - - intptr_t slot_address = 0; - size_t slot_size = 0; - - if (suit_plat_decode_component_type(component_id, &component_type) != - SUIT_PLAT_SUCCESS || - component_type != SUIT_COMPONENT_TYPE_MEM) { - continue; - } - - if (suit_plat_decode_address_size(component_id, &slot_address, &slot_size) != - SUIT_PLAT_SUCCESS) { - continue; - } - - if (slot_address == 0 || slot_size < required_size) { - continue; - } - - uintptr_t adjusted_slot_address = slot_address; - - /* Adjusting mirror address if IPUC is located in address lower than - * area acceptable by SDROM - */ - if (slot_address < sdfw_update_area_addr) { - adjusted_slot_address = sdfw_update_area_addr; - size_t shift = (sdfw_update_area_addr - slot_address); - - if (shift + required_size > slot_size) { - continue; - } - } - - if (adjusted_slot_address + required_size > - sdfw_update_area_addr + sdfw_update_area_size) { - continue; - } - - /* clang-format off */ - struct arbiter_mem_params_access mem_params = { - .allowed_types = ARBITER_MEM_TYPE(RESERVED, FIXED), - .access = { - .owner = NRF_OWNER_APPLICATION, - .permissions = ARBITER_MEM_PERM(READ, SECURE), - .address = adjusted_slot_address, - .size = required_size, - }, - }; - /* clang-format on */ - - LOG_INF("Checking IPUC ownership, address: %p, size: %d bytes", - (void *)mem_params.access.address, mem_params.access.size); - - if (arbiter_mem_access_check(&mem_params) == ARBITER_STATUS_OK) { - /* ... belonging to app domain - */ - k_mutex_unlock(&ipuc_mutex); - return adjusted_slot_address; - } - - mem_params.access.owner = NRF_OWNER_RADIOCORE; - if (arbiter_mem_access_check(&mem_params) == ARBITER_STATUS_OK) { - /* ... or belonging to radio domain - */ - k_mutex_unlock(&ipuc_mutex); - return adjusted_slot_address; - } - } - - k_mutex_unlock(&ipuc_mutex); - return 0; -} diff --git a/subsys/suit/platform/sdfw/src/suit_plat_write_sdfw_specific.c b/subsys/suit/platform/sdfw/src/suit_plat_write_sdfw_specific.c index 049a4d6d48ae..81b38b0fe139 100644 --- a/subsys/suit/platform/sdfw/src/suit_plat_write_sdfw_specific.c +++ b/subsys/suit/platform/sdfw/src/suit_plat_write_sdfw_specific.c @@ -13,8 +13,8 @@ #include #include -#if CONFIG_SUIT_IPUC -#include +#ifdef CONFIG_SUIT_IPUC +#include #endif /* CONFIG_SUIT_IPUC */ #ifdef CONFIG_SUIT_STREAM @@ -180,7 +180,7 @@ int suit_plat_write_domain_specific(suit_component_t dst_handle, */ #if CONFIG_SUIT_IPUC - suit_plat_ipuc_revoke(dst_handle); + suit_ipuc_sdfw_revoke(dst_handle); #endif /* CONFIG_SUIT_IPUC */ #if CONFIG_SUIT_DIGEST_CACHE diff --git a/subsys/suit/platform/src/suit_plat_components.c b/subsys/suit/platform/src/suit_plat_components.c index 36c4116da7c6..385f4c45cb62 100644 --- a/subsys/suit/platform/src/suit_plat_components.c +++ b/subsys/suit/platform/src/suit_plat_components.c @@ -10,9 +10,9 @@ #include #include -#if CONFIG_SUIT_IPUC -#include -#endif /* CONFIG_SUIT_IPUC */ +#if (defined CONFIG_SUIT_IPUC && defined CONFIG_SUIT_PLATFORM_VARIANT_SDFW) +#include +#endif LOG_MODULE_REGISTER(plat_components, CONFIG_SUIT_LOG_LEVEL); @@ -275,13 +275,15 @@ int suit_plat_override_image_size(suit_component_t handle, size_t size) return SUIT_ERR_CRASH; } -#if CONFIG_SUIT_IPUC +#if (defined CONFIG_SUIT_IPUC && defined CONFIG_SUIT_PLATFORM_VARIANT_SDFW) if (size == 0) { - suit_plat_ipuc_declare(handle); + suit_manifest_role_t role = SUIT_MANIFEST_UNKNOWN; + + suit_ipuc_sdfw_declare(handle, role); } else { - suit_plat_ipuc_revoke(handle); + suit_ipuc_sdfw_revoke(handle); } -#endif /* CONFIG_SUIT_IPUC */ +#endif return SUIT_SUCCESS; } diff --git a/subsys/suit/platform/src/suit_plat_fetch.c b/subsys/suit/platform/src/suit_plat_fetch.c index 295d00379b33..edd4ccfd257c 100644 --- a/subsys/suit/platform/src/suit_plat_fetch.c +++ b/subsys/suit/platform/src/suit_plat_fetch.c @@ -13,9 +13,9 @@ #include #endif /* CONFIG_SUIT_DIGEST_CACHE */ -#if CONFIG_SUIT_IPUC -#include -#endif /* CONFIG_SUIT_IPUC */ +#if (defined CONFIG_SUIT_IPUC && defined CONFIG_SUIT_PLATFORM_VARIANT_SDFW) +#include +#endif #ifdef CONFIG_SUIT_STREAM #include @@ -203,9 +203,9 @@ int suit_plat_fetch(suit_component_t dst_handle, struct zcbor_string *uri, * Stream the data. */ -#if CONFIG_SUIT_IPUC - suit_plat_ipuc_revoke(dst_handle); -#endif /* CONFIG_SUIT_IPUC */ +#if (defined CONFIG_SUIT_IPUC && defined CONFIG_SUIT_PLATFORM_VARIANT_SDFW) + suit_ipuc_sdfw_revoke(dst_handle); +#endif #if CONFIG_SUIT_DIGEST_CACHE /* Invalidate digest cache for the destination component. */ @@ -337,7 +337,6 @@ int suit_plat_fetch_integrated(suit_component_t dst_handle, struct zcbor_string (void)manifest_component_id; #endif - /* * Validate streaming operation. */ @@ -393,9 +392,9 @@ int suit_plat_fetch_integrated(suit_component_t dst_handle, struct zcbor_string * Stream the data. */ -#if CONFIG_SUIT_IPUC - suit_plat_ipuc_revoke(dst_handle); -#endif /* CONFIG_SUIT_IPUC */ +#if (defined CONFIG_SUIT_IPUC && defined CONFIG_SUIT_PLATFORM_VARIANT_SDFW) + suit_ipuc_sdfw_revoke(dst_handle); +#endif #if CONFIG_SUIT_DIGEST_CACHE /* Invalidate digest cache for the destination component. */ diff --git a/tests/subsys/suit/copy/CMakeLists.txt b/tests/subsys/suit/copy/CMakeLists.txt index 11c0b22fb8df..3959466e84f5 100644 --- a/tests/subsys/suit/copy/CMakeLists.txt +++ b/tests/subsys/suit/copy/CMakeLists.txt @@ -17,3 +17,4 @@ zephyr_library_link_libraries(suit_memptr_storage_interface) zephyr_library_link_libraries(suit_sink_selector_interface) zephyr_library_link_libraries(suit_storage_interface) zephyr_library_link_libraries(suit_manifest_variables) +zephyr_library_link_libraries(suit_ipuc) diff --git a/tests/subsys/suit/copy/prj.conf b/tests/subsys/suit/copy/prj.conf index 96c394a2708e..45f6e12f289e 100644 --- a/tests/subsys/suit/copy/prj.conf +++ b/tests/subsys/suit/copy/prj.conf @@ -15,6 +15,7 @@ CONFIG_SUIT_STREAM=y CONFIG_SUIT_SINK_SELECTOR=y CONFIG_SUIT_STREAM_SOURCE_MEMPTR=y CONFIG_SUIT_STREAM_SINK_FLASH=y +CONFIG_SUIT_STREAM_SINK_RAM=y CONFIG_SUIT_STREAM_SINK_MEMPTR=y CONFIG_SUIT_UTILS=y diff --git a/tests/subsys/suit/copy/src/main.c b/tests/subsys/suit/copy/src/main.c index c5dda79b6a08..a0a528575d2c 100644 --- a/tests/subsys/suit/copy/src/main.c +++ b/tests/subsys/suit/copy/src/main.c @@ -10,7 +10,7 @@ #include #include #include -#include +#include #include #include #include @@ -81,6 +81,7 @@ ZTEST(copy_tests, test_integrated_fetch_to_memptr_and_copy_to_msink_OK) .len = sizeof(valid_src_value), }; + int ipc_client_id = 1234; int ret = suit_plat_create_component_handle(&valid_src_component_id, false, &src_handle); zassert_equal(ret, SUIT_SUCCESS, "create_component_handle failed - error %i", ret); @@ -116,19 +117,19 @@ ZTEST(copy_tests, test_integrated_fetch_to_memptr_and_copy_to_msink_OK) ret = suit_plat_create_component_handle(&valid_dst_component_id, false, &dst_handle); zassert_equal(ret, SUIT_SUCCESS, "create_component_handle failed - error %i", ret); - ret = suit_plat_ipuc_write(dst_handle, 0, (uintptr_t)test_data, sizeof(test_data), true); + ret = suit_ipuc_sdfw_write_setup(ipc_client_id, &valid_dst_component_id, NULL, NULL); zassert_equal(ret, SUIT_PLAT_ERR_NOT_FOUND, "in-place updateable component found"); - ret = suit_plat_ipuc_declare(dst_handle); - zassert_equal(ret, SUIT_PLAT_SUCCESS, "suit_plat_ipuc_declare failed - error %i", ret); + ret = suit_ipuc_sdfw_declare(dst_handle, SUIT_MANIFEST_UNKNOWN); + zassert_equal(ret, SUIT_PLAT_SUCCESS, "suit_ipuc_sdfw_declare failed - error %i", ret); - ret = suit_plat_ipuc_write(dst_handle, 0, (uintptr_t)test_data, sizeof(test_data), true); - zassert_equal(ret, SUIT_PLAT_SUCCESS, "cannot write to in-place updateable component"); + ret = suit_ipuc_sdfw_write_setup(ipc_client_id, &valid_dst_component_id, NULL, NULL); + zassert_equal(ret, SUIT_PLAT_SUCCESS, "suit_ipuc_sdfw_write_setup failed - error %i", ret); ret = suit_plat_copy(dst_handle, src_handle, &valid_manifest_component_id, NULL); zassert_equal(ret, SUIT_SUCCESS, "suit_plat_copy failed - error %i", ret); - ret = suit_plat_ipuc_write(dst_handle, 0, (uintptr_t)test_data, sizeof(test_data), true); + ret = suit_ipuc_sdfw_write_setup(ipc_client_id, &valid_dst_component_id, NULL, NULL); zassert_equal(ret, SUIT_PLAT_ERR_NOT_FOUND, "in-place updateable component found"); ret = suit_plat_release_component_handle(dst_handle); diff --git a/tests/subsys/suit/fetch/CMakeLists.txt b/tests/subsys/suit/fetch/CMakeLists.txt index b7545f8f23b0..97ca8c37a211 100644 --- a/tests/subsys/suit/fetch/CMakeLists.txt +++ b/tests/subsys/suit/fetch/CMakeLists.txt @@ -13,3 +13,4 @@ include(../cmake/test_template.cmake) zephyr_library_link_libraries(suit_memptr_storage_interface) zephyr_library_link_libraries(suit_platform_interface) +zephyr_library_link_libraries(suit_ipuc) diff --git a/tests/subsys/suit/fetch/src/main.c b/tests/subsys/suit/fetch/src/main.c index 266807b60261..6e77fe14039f 100644 --- a/tests/subsys/suit/fetch/src/main.c +++ b/tests/subsys/suit/fetch/src/main.c @@ -8,7 +8,7 @@ #include #include #include -#include +#include #include #include @@ -106,22 +106,23 @@ ZTEST(fetch_tests, test_integrated_fetch_to_msink_OK) .len = sizeof(valid_dst_value), }; + int ipc_client_id = 1234; int ret = suit_plat_create_component_handle(&valid_dst_component_id, false, &dst_handle); zassert_equal(ret, SUIT_SUCCESS, "create_component_handle failed - error %i", ret); - ret = suit_plat_ipuc_write(dst_handle, 0, (uintptr_t)test_data, sizeof(test_data), true); + ret = suit_ipuc_sdfw_write_setup(ipc_client_id, &valid_dst_component_id, NULL, NULL); zassert_equal(ret, SUIT_PLAT_ERR_NOT_FOUND, "in-place updateable component found"); - ret = suit_plat_ipuc_declare(dst_handle); - zassert_equal(ret, SUIT_PLAT_SUCCESS, "suit_plat_ipuc_declare failed - error %i", ret); + ret = suit_ipuc_sdfw_declare(dst_handle, SUIT_MANIFEST_UNKNOWN); + zassert_equal(ret, SUIT_PLAT_SUCCESS, "suit_ipuc_sdfw_declare failed - error %i", ret); - ret = suit_plat_ipuc_write(dst_handle, 0, (uintptr_t)test_data, sizeof(test_data), true); - zassert_equal(ret, SUIT_PLAT_SUCCESS, "cannot write to in-place updateable component"); + ret = suit_ipuc_sdfw_write_setup(ipc_client_id, &valid_dst_component_id, NULL, NULL); + zassert_equal(ret, SUIT_PLAT_SUCCESS, "suit_ipuc_sdfw_write_setup failed - error %i", ret); ret = suit_plat_fetch_integrated(dst_handle, &source, &valid_dst_component_id, NULL); zassert_equal(ret, SUIT_SUCCESS, "suit_plat_fetch failed - error %i", ret); - ret = suit_plat_ipuc_write(dst_handle, 0, (uintptr_t)test_data, sizeof(test_data), true); + ret = suit_ipuc_sdfw_write_setup(ipc_client_id, &valid_dst_component_id, NULL, NULL); zassert_equal(ret, SUIT_PLAT_ERR_NOT_FOUND, "in-place updateable component found"); ret = suit_plat_release_component_handle(dst_handle); @@ -219,8 +220,8 @@ ZTEST(fetch_tests, test_fetch_to_memptr_NOK_uri_not_in_cache) ret = suit_plat_fetch(component_handle, &uri, &valid_manifest_component_id, NULL); zassert_equal(ret, SUIT_SUCCESS, - "suit_plat_fetch should succeed - supplied uri is not in cache, " - "treated as empty payload"); + "suit_plat_fetch should succeed - supplied uri is not in cache, " + "treated as empty payload"); ret = suit_plat_release_component_handle(component_handle); zassert_equal(ret, SUIT_SUCCESS, "Handle release failed - error %i", ret); diff --git a/tests/subsys/suit/ipuc/CMakeLists.txt b/tests/subsys/suit/ipuc/CMakeLists.txt index fef75bbbf689..98f4a38d03e8 100644 --- a/tests/subsys/suit/ipuc/CMakeLists.txt +++ b/tests/subsys/suit/ipuc/CMakeLists.txt @@ -14,8 +14,5 @@ include(../cmake/test_template.cmake) target_compile_options(suit_memory_layout_interface INTERFACE -DSDFW_UPDATE_AREA_ADDR=0x1000) target_compile_options(suit_memory_layout_interface INTERFACE -DSDFW_UPDATE_AREA_SIZE=0xFFFFE000) -zephyr_library_link_libraries(suit) -zephyr_library_link_libraries(suit_platform_interface) -zephyr_library_link_libraries(suit_memptr_storage_interface) -zephyr_library_link_libraries(suit_sink_selector_interface) +zephyr_library_link_libraries(suit_ipuc) zephyr_library_link_libraries(suit_memory_layout_interface) diff --git a/tests/subsys/suit/ipuc/prj.conf b/tests/subsys/suit/ipuc/prj.conf index a21234bde761..269b6bcbb494 100644 --- a/tests/subsys/suit/ipuc/prj.conf +++ b/tests/subsys/suit/ipuc/prj.conf @@ -15,7 +15,11 @@ CONFIG_SUIT_STREAM=y CONFIG_SUIT_SINK_SELECTOR=y CONFIG_SUIT_STREAM_SOURCE_MEMPTR=y CONFIG_SUIT_STREAM_SINK_FLASH=y +CONFIG_SUIT_STREAM_SINK_RAM=y CONFIG_SUIT_STREAM_SINK_MEMPTR=y +CONFIG_SUIT_STREAM_SINK_DIGEST=y +CONFIG_SUIT_DIGEST=y +CONFIG_SUIT_CRYPTO=y CONFIG_SUIT_UTILS=y CONFIG_SUIT_MEMPTR_STORAGE=y diff --git a/tests/subsys/suit/ipuc/src/main.c b/tests/subsys/suit/ipuc/src/main.c index 2a298a1e822e..2b9fbdaba36d 100644 --- a/tests/subsys/suit/ipuc/src/main.c +++ b/tests/subsys/suit/ipuc/src/main.c @@ -9,12 +9,24 @@ #include #include #include -#include +#include #include #include #include -static uint8_t test_data[] = {0, 1, 2, 3, 4, 5, 6, 7}; +static uint8_t test_data[] = {0xde, 0xad, 0xbe, 0xef}; + +static uint8_t test_digest_bstr[] = {0x5f, 0x78, 0xc3, 0x32, 0x74, 0xe4, 0x3f, 0xa9, + 0xde, 0x56, 0x59, 0x26, 0x5c, 0x1d, 0x91, 0x7e, + 0x25, 0xc0, 0x37, 0x22, 0xdc, 0xb0, 0xb8, 0xd2, + 0x7d, 0xb8, 0xd5, 0xfe, 0xaa, 0x81, 0x39, 0x53}; + +static struct zcbor_string test_digest = { + .value = test_digest_bstr, + .len = sizeof(test_digest_bstr), +}; + +static const enum suit_cose_alg digest_algorithm = suit_cose_sha256; static suit_component_t ipuc_handle; /* [h'MEM', h'02', h'1A00080000', h'191000'] */ @@ -36,17 +48,16 @@ static void test_before(void *data) int ret = suit_plat_create_component_handle(&ipuc_component_id, false, &ipuc_handle); - zassert_equal(ret, SUIT_SUCCESS, "suit_plat_create_component_handle failed - error %i", - ret); + zassert_equal(ret, SUIT_SUCCESS, "suit_plat_create_component_handle failed - ret: %i", ret); - suit_plat_ipuc_revoke(ipuc_handle); + suit_ipuc_sdfw_revoke(ipuc_handle); } static void test_after(void *data) { int ret = suit_plat_release_component_handle(ipuc_handle); - zassert_equal(ret, SUIT_SUCCESS, "suit_plat_release_component_handle failed - error %i", + zassert_equal(ret, SUIT_SUCCESS, "suit_plat_release_component_handle failed - ret: %i", ret); } @@ -55,126 +66,188 @@ ZTEST_SUITE(ipuc_tests, NULL, NULL, test_before, test_after, NULL); ZTEST(ipuc_tests, test_ipuc_revoke_OK) { suit_plat_err_t ret = SUIT_PLAT_SUCCESS; + suit_manifest_role_t role = SUIT_MANIFEST_APP_LOCAL_1; - ret = suit_plat_ipuc_declare(ipuc_handle); - zassert_equal(ret, SUIT_PLAT_SUCCESS, "suit_plat_ipuc_declare failed - error %i", ret); + ret = suit_ipuc_sdfw_declare(ipuc_handle, role); + zassert_equal(ret, SUIT_PLAT_SUCCESS, "suit_ipuc_sdfw_declare failed - ret: %i", ret); - ret = suit_plat_ipuc_revoke(ipuc_handle); - zassert_equal(ret, SUIT_PLAT_SUCCESS, "suit_plat_ipuc_revoke failed - error %i", ret); + ret = suit_ipuc_sdfw_revoke(ipuc_handle); + zassert_equal(ret, SUIT_PLAT_SUCCESS, "suit_ipuc_sdfw_revoke failed - ret: %i", ret); - ret = suit_plat_ipuc_revoke(ipuc_handle); - zassert_equal(ret, SUIT_PLAT_ERR_NOT_FOUND, "suit_plat_ipuc_revoke failed - error %i", ret); + ret = suit_ipuc_sdfw_revoke(ipuc_handle); + zassert_equal(ret, SUIT_PLAT_ERR_NOT_FOUND, "suit_ipuc_sdfw_revoke failed - ret: %i", ret); } -ZTEST(ipuc_tests, test_ipuc_copy_OK) +ZTEST(ipuc_tests, test_ipuc_write_OK) { suit_plat_err_t ret = SUIT_PLAT_SUCCESS; + suit_manifest_role_t role = SUIT_MANIFEST_APP_LOCAL_1; + int ipc_client_id = 1234; + + ret = suit_ipuc_sdfw_declare(ipuc_handle, role); + zassert_equal(ret, SUIT_PLAT_SUCCESS, "suit_ipuc_sdfw_declare failed - ret: %i", ret); - ret = suit_plat_ipuc_declare(ipuc_handle); - zassert_equal(ret, SUIT_PLAT_SUCCESS, "suit_plat_ipuc_declare failed - error %i", ret); + ret = suit_ipuc_sdfw_write_setup(ipc_client_id, &ipuc_component_id, NULL, NULL); + zassert_equal(ret, SUIT_PLAT_SUCCESS, "suit_ipuc_sdfw_write_setup failed - ret: %i", ret); - size_t offset = 0; + size_t offset = 2; + size_t chunk_size = 2; bool last_chunk = false; - ret = suit_plat_ipuc_write(ipuc_handle, offset, (uintptr_t)test_data, sizeof(test_data), - last_chunk); - zassert_equal(ret, SUIT_PLAT_SUCCESS, "suit_plat_ipuc_write failed - error %i", ret); + ret = suit_ipuc_sdfw_write(ipc_client_id, &ipuc_component_id, offset, + (uintptr_t)test_data + offset, chunk_size, last_chunk); + zassert_equal(ret, SUIT_PLAT_SUCCESS, "suit_ipuc_sdfw_write failed - ret: %i", ret); - offset += sizeof(test_data); + offset = 0; + chunk_size = 2; last_chunk = true; - ret = suit_plat_ipuc_write(ipuc_handle, offset, (uintptr_t)test_data, sizeof(test_data), - last_chunk); - zassert_equal(ret, SUIT_PLAT_SUCCESS, "suit_plat_ipuc_write failed - error %i", ret); - offset += sizeof(test_data); - size_t stored_img_size = 0; + ret = suit_ipuc_sdfw_write(ipc_client_id, &ipuc_component_id, offset, + (uintptr_t)test_data + offset, chunk_size, last_chunk); + zassert_equal(ret, SUIT_PLAT_SUCCESS, "suit_ipuc_sdfw_write failed - ret: %i", ret); + + ret = suit_ipuc_sdfw_digest_compare(&ipuc_component_id, digest_algorithm, &test_digest); + zassert_equal(ret, SUIT_PLAT_SUCCESS, "suit_ipuc_sdfw_digest_compare failed - ret: %i", + ret); + + /* Let's check if suit_ipuc_sdfw_write_setup erases IPUC + */ + ret = suit_ipuc_sdfw_write_setup(ipc_client_id, &ipuc_component_id, NULL, NULL); + zassert_equal(ret, SUIT_PLAT_SUCCESS, "suit_ipuc_sdfw_write_setup failed - ret: %i", ret); + + offset = 2; + chunk_size = 1; + last_chunk = true; + + ret = suit_ipuc_sdfw_write(ipc_client_id, &ipuc_component_id, offset, + (uintptr_t)test_data + offset, chunk_size, last_chunk); + zassert_equal(ret, SUIT_PLAT_SUCCESS, "suit_ipuc_sdfw_write failed - ret: %i", ret); - ret = suit_plat_ipuc_get_stored_img_size(ipuc_handle, &stored_img_size); - zassert_equal(ret, SUIT_PLAT_SUCCESS, - "suit_plat_ipuc_get_stored_img_size failed - error %i", ret); - zassert_equal(stored_img_size, offset, "incorrect stored image size"); + ret = suit_ipuc_sdfw_digest_compare(&ipuc_component_id, digest_algorithm, &test_digest); + zassert_equal(ret, SUIT_PLAT_ERR_INVAL, + "suit_ipuc_sdfw_digest_compare - wrong return code - ret: %i", ret); - /* Let's write again + /* Let's check 2nd method of last_chunk signallization */ + ret = suit_ipuc_sdfw_write_setup(ipc_client_id, &ipuc_component_id, NULL, NULL); + zassert_equal(ret, SUIT_PLAT_SUCCESS, "suit_ipuc_sdfw_write_setup failed - ret: %i", ret); + + offset = 2; + chunk_size = 2; + last_chunk = false; + + ret = suit_ipuc_sdfw_write(ipc_client_id, &ipuc_component_id, offset, + (uintptr_t)test_data + offset, chunk_size, last_chunk); + zassert_equal(ret, SUIT_PLAT_SUCCESS, "suit_ipuc_sdfw_write failed - ret: %i", ret); + + offset = 0; + chunk_size = 2; + last_chunk = false; + + ret = suit_ipuc_sdfw_write(ipc_client_id, &ipuc_component_id, offset, + (uintptr_t)test_data + offset, chunk_size, last_chunk); + zassert_equal(ret, SUIT_PLAT_SUCCESS, "suit_ipuc_sdfw_write failed - ret: %i", ret); + offset = 0; + chunk_size = 0; last_chunk = true; - ret = suit_plat_ipuc_write(ipuc_handle, offset, (uintptr_t)test_data, sizeof(test_data), + + ret = suit_ipuc_sdfw_write(ipc_client_id, &ipuc_component_id, offset, 0, chunk_size, last_chunk); - zassert_equal(ret, SUIT_PLAT_SUCCESS, "suit_plat_ipuc_write failed - error %i", ret); - - offset += sizeof(test_data); - stored_img_size = 0; - ret = suit_plat_ipuc_get_stored_img_size(ipuc_handle, &stored_img_size); - zassert_equal(ret, SUIT_PLAT_SUCCESS, - "suit_plat_ipuc_get_stored_img_size failed - error %i", ret); - zassert_equal(stored_img_size, offset, "incorrect stored image size"); + zassert_equal(ret, SUIT_PLAT_SUCCESS, "suit_ipuc_sdfw_write failed - ret: %i", ret); + + ret = suit_ipuc_sdfw_digest_compare(&ipuc_component_id, digest_algorithm, &test_digest); + zassert_equal(ret, SUIT_PLAT_SUCCESS, "suit_ipuc_sdfw_digest_compare failed - ret: %i", + ret); } -ZTEST(ipuc_tests, test_ipuc_copy_NOK_not_declared) +ZTEST(ipuc_tests, test_ipuc_write_setup_NOK_not_declared) { suit_plat_err_t ret = SUIT_PLAT_SUCCESS; - size_t offset = 0; - bool last_chunk = false; + int ipc_client_id = 1234; - ret = suit_plat_ipuc_write(ipuc_handle, offset, (uintptr_t)test_data, sizeof(test_data), - last_chunk); - zassert_equal(ret, SUIT_PLAT_ERR_NOT_FOUND, "suit_plat_ipuc_write failed - error %i", ret); + ret = suit_ipuc_sdfw_write_setup(ipc_client_id, &ipuc_component_id, NULL, NULL); + zassert_equal(ret, SUIT_PLAT_ERR_NOT_FOUND, "suit_ipuc_sdfw_write_setup failed - ret: %i", + ret); } -ZTEST(ipuc_tests, test_ipuc_copy_NOK_wrong_offset) +ZTEST(ipuc_tests, test_ipuc_write_setup_NOK_busy_other_client) { suit_plat_err_t ret = SUIT_PLAT_SUCCESS; + suit_manifest_role_t role = SUIT_MANIFEST_APP_LOCAL_1; + int ipc_client_id = 1234; - ret = suit_plat_ipuc_declare(ipuc_handle); - zassert_equal(ret, SUIT_PLAT_SUCCESS, "suit_plat_ipuc_declare failed - error %i", ret); + ret = suit_ipuc_sdfw_declare(ipuc_handle, role); + zassert_equal(ret, SUIT_PLAT_SUCCESS, "suit_ipuc_sdfw_declare failed - ret: %i", ret); - size_t offset = sizeof(test_data); - bool last_chunk = false; + ret = suit_ipuc_sdfw_write_setup(ipc_client_id, &ipuc_component_id, NULL, NULL); + zassert_equal(ret, SUIT_PLAT_SUCCESS, "suit_ipuc_sdfw_write_setup failed - ret: %i", ret); - ret = suit_plat_ipuc_write(ipuc_handle, offset, (uintptr_t)test_data, sizeof(test_data), - last_chunk); - zassert_equal(ret, SUIT_PLAT_ERR_INCORRECT_STATE, "suit_plat_ipuc_write failed - error %i", - ret); + ipc_client_id++; + + ret = suit_ipuc_sdfw_write_setup(ipc_client_id, &ipuc_component_id, NULL, NULL); + zassert_equal(ret, SUIT_PLAT_ERR_INCORRECT_STATE, + "suit_ipuc_sdfw_write_setup wrong return code - ret: %i", ret); } -ZTEST(ipuc_tests, test_ipuc_copy_NOK_wrong_state_write_in_progress) +ZTEST(ipuc_tests, test_ipuc_write_setup_NOK_busy_sdfw_mirror) { suit_plat_err_t ret = SUIT_PLAT_SUCCESS; + suit_manifest_role_t role = SUIT_MANIFEST_APP_LOCAL_1; + int ipc_client_id = 1234; - ret = suit_plat_ipuc_declare(ipuc_handle); - zassert_equal(ret, SUIT_PLAT_SUCCESS, "suit_plat_ipuc_declare failed - error %i", ret); + ret = suit_ipuc_sdfw_declare(ipuc_handle, role); + zassert_equal(ret, SUIT_PLAT_SUCCESS, "suit_ipuc_sdfw_declare failed - ret: %i", ret); - size_t stored_img_size = 0; + uintptr_t sdfw_update_area_addr = 0; + size_t sdfw_update_area_size = 0; - ret = suit_plat_ipuc_get_stored_img_size(ipuc_handle, &stored_img_size); - zassert_equal(ret, SUIT_PLAT_ERR_INCORRECT_STATE, - "suit_plat_ipuc_get_stored_img_size failed - error %i", ret); + suit_memory_sdfw_update_area_info_get(&sdfw_update_area_addr, &sdfw_update_area_size); - size_t offset = 0; - bool last_chunk = true; + zassert_not_equal(sdfw_update_area_size, 0, ""); - ret = suit_plat_ipuc_write(ipuc_handle, offset, 0, 0, last_chunk); + arbiter_mem_access_check_fake.return_val = ARBITER_STATUS_OK; + arbiter_mem_access_check_fake.call_count = 0; - stored_img_size = 0; - ret = suit_plat_ipuc_get_stored_img_size(ipuc_handle, &stored_img_size); - zassert_equal(ret, SUIT_PLAT_SUCCESS, - "suit_plat_ipuc_get_stored_img_size failed - error %i", ret); - zassert_equal(stored_img_size, offset, "incorrect stored image size"); + uintptr_t mirror_addr = suit_ipuc_sdfw_mirror_addr(16); - offset = sizeof(test_data); - ret = suit_plat_ipuc_write(ipuc_handle, offset, (uintptr_t)test_data, sizeof(test_data), - last_chunk); + zassert_between_inclusive(mirror_addr, sdfw_update_area_addr, + sdfw_update_area_addr + sdfw_update_area_size, ""); - zassert_equal(ret, SUIT_PLAT_ERR_INCORRECT_STATE, "suit_plat_ipuc_write failed - error %i", - ret); + zassert_equal(arbiter_mem_access_check_fake.call_count, 1, + "Incorrect number of arbiter_mem_access_check() calls"); + + ret = suit_ipuc_sdfw_write_setup(ipc_client_id, &ipuc_component_id, NULL, NULL); + zassert_equal(ret, SUIT_PLAT_ERR_INCORRECT_STATE, + "suit_ipuc_sdfw_write_setup wrong return code - ret: %i", ret); +} + +ZTEST(ipuc_tests, test_ipuc_write_NOK_not_setup) +{ + suit_plat_err_t ret = SUIT_PLAT_SUCCESS; + suit_manifest_role_t role = SUIT_MANIFEST_APP_LOCAL_1; + int ipc_client_id = 1234; + + ret = suit_ipuc_sdfw_declare(ipuc_handle, role); + zassert_equal(ret, SUIT_PLAT_SUCCESS, "suit_ipuc_sdfw_declare failed - ret: %i", ret); + + size_t offset = 2; + size_t chunk_size = 2; + bool last_chunk = false; + + ret = suit_ipuc_sdfw_write(ipc_client_id, &ipuc_component_id, offset, + (uintptr_t)test_data + offset, chunk_size, last_chunk); + zassert_equal(ret, SUIT_PLAT_ERR_INCORRECT_STATE, + "suit_ipuc_sdfw_write wrong return code - ret: %i", ret); } ZTEST(ipuc_tests, test_ipuc_sdfw_mirror_OK) { suit_plat_err_t ret = SUIT_PLAT_SUCCESS; + suit_manifest_role_t role = SUIT_MANIFEST_APP_LOCAL_1; - ret = suit_plat_ipuc_declare(ipuc_handle); - zassert_equal(ret, SUIT_PLAT_SUCCESS, "suit_plat_ipuc_declare failed - error %i", ret); + ret = suit_ipuc_sdfw_declare(ipuc_handle, role); + zassert_equal(ret, SUIT_PLAT_SUCCESS, "suit_ipuc_sdfw_declare failed - ret: %i", ret); uintptr_t sdfw_update_area_addr = 0; size_t sdfw_update_area_size = 0; @@ -186,7 +259,7 @@ ZTEST(ipuc_tests, test_ipuc_sdfw_mirror_OK) arbiter_mem_access_check_fake.return_val = ARBITER_STATUS_OK; arbiter_mem_access_check_fake.call_count = 0; - uintptr_t mirror_addr = suit_plat_ipuc_sdfw_mirror_addr(16); + uintptr_t mirror_addr = suit_ipuc_sdfw_mirror_addr(16); zassert_between_inclusive(mirror_addr, sdfw_update_area_addr, sdfw_update_area_addr + sdfw_update_area_size, ""); @@ -194,10 +267,51 @@ ZTEST(ipuc_tests, test_ipuc_sdfw_mirror_OK) zassert_equal(arbiter_mem_access_check_fake.call_count, 1, "Incorrect number of arbiter_mem_access_check() calls"); - ret = suit_plat_ipuc_revoke(ipuc_handle); - zassert_equal(ret, SUIT_PLAT_SUCCESS, "suit_plat_ipuc_revoke failed - error %i", ret); + ret = suit_ipuc_sdfw_revoke(ipuc_handle); + zassert_equal(ret, SUIT_PLAT_SUCCESS, "suit_ipuc_sdfw_revoke failed - ret: %i", ret); + + mirror_addr = suit_ipuc_sdfw_mirror_addr(16); + + zassert_equal(mirror_addr, 0, "valid mirror_addr after suit_ipuc_sdfw_revoke() call"); +} + +ZTEST(ipuc_tests, test_ipuc_sdfw_mirror_NOK_not_declared) +{ + uintptr_t sdfw_update_area_addr = 0; + size_t sdfw_update_area_size = 0; + + suit_memory_sdfw_update_area_info_get(&sdfw_update_area_addr, &sdfw_update_area_size); + + zassert_not_equal(sdfw_update_area_size, 0, ""); + + uintptr_t mirror_addr = suit_ipuc_sdfw_mirror_addr(16); + + zassert_equal(mirror_addr, 0, "valid mirror_addr when IPUC not declared"); +} + +ZTEST(ipuc_tests, test_ipuc_sdfw_mirror_NOK_busy_other_client) +{ + suit_plat_err_t ret = SUIT_PLAT_SUCCESS; + suit_manifest_role_t role = SUIT_MANIFEST_APP_LOCAL_1; + int ipc_client_id = 1234; + + ret = suit_ipuc_sdfw_declare(ipuc_handle, role); + zassert_equal(ret, SUIT_PLAT_SUCCESS, "suit_ipuc_sdfw_declare failed - ret: %i", ret); + + ret = suit_ipuc_sdfw_write_setup(ipc_client_id, &ipuc_component_id, NULL, NULL); + zassert_equal(ret, SUIT_PLAT_SUCCESS, "suit_ipuc_sdfw_write_setup failed - ret: %i", ret); + + uintptr_t sdfw_update_area_addr = 0; + size_t sdfw_update_area_size = 0; + + suit_memory_sdfw_update_area_info_get(&sdfw_update_area_addr, &sdfw_update_area_size); + + zassert_not_equal(sdfw_update_area_size, 0, ""); + + arbiter_mem_access_check_fake.return_val = ARBITER_STATUS_OK; + arbiter_mem_access_check_fake.call_count = 0; - mirror_addr = suit_plat_ipuc_sdfw_mirror_addr(16); + uintptr_t mirror_addr = suit_ipuc_sdfw_mirror_addr(16); - zassert_equal(mirror_addr, 0, "valid mirror_addr after suit_plat_ipuc_revoke() call"); + zassert_equal(mirror_addr, 0, "valid mirror_addr when IPUC not declared"); } diff --git a/tests/subsys/suit/unit/mocks/CMakeLists.txt b/tests/subsys/suit/unit/mocks/CMakeLists.txt index 1ae2099fbe51..b17d1c3ca037 100644 --- a/tests/subsys/suit/unit/mocks/CMakeLists.txt +++ b/tests/subsys/suit/unit/mocks/CMakeLists.txt @@ -93,7 +93,8 @@ endif() if (CONFIG_MOCK_SUIT_IPUC) target_compile_options(test_interface INTERFACE -DCONFIG_SUIT_IPUC) - target_include_directories(testbinary PRIVATE ${SUIT_SUBSYS_DIR}/platform/include) + target_compile_options(test_interface INTERFACE -DCONFIG_SUIT_PLATFORM_VARIANT_SDFW) + target_include_directories(testbinary PRIVATE ${SUIT_SUBSYS_DIR}/ipuc/include) endif() if (CONFIG_MOCK_DIGEST_SINK) diff --git a/tests/subsys/suit/unit/mocks/include/mock_suit_ipuc_sdfw.h b/tests/subsys/suit/unit/mocks/include/mock_suit_ipuc_sdfw.h new file mode 100644 index 000000000000..86252957eeb0 --- /dev/null +++ b/tests/subsys/suit/unit/mocks/include/mock_suit_ipuc_sdfw.h @@ -0,0 +1,23 @@ +/* + * Copyright (c) 2025 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: LicenseRef-Nordic-5-Clause + */ + +#ifndef MOCK_SUIT_IPUC_SDFW_H__ +#define MOCK_SUIT_IPUC_SDFW_H__ + +#include +#include +#include + +FAKE_VALUE_FUNC(int, suit_ipuc_sdfw_declare, suit_component_t, suit_manifest_role_t); +FAKE_VALUE_FUNC(int, suit_ipuc_sdfw_revoke, suit_component_t); + +static inline void mock_suit_plat_ipuc_reset(void) +{ + RESET_FAKE(suit_ipuc_sdfw_declare); + RESET_FAKE(suit_ipuc_sdfw_revoke); +} + +#endif /* MOCK_SUIT_IPUC_SDFW_H__ */ diff --git a/tests/subsys/suit/unit/mocks/include/mock_suit_plat_ipuc.h b/tests/subsys/suit/unit/mocks/include/mock_suit_plat_ipuc.h deleted file mode 100644 index 5878b7220f6b..000000000000 --- a/tests/subsys/suit/unit/mocks/include/mock_suit_plat_ipuc.h +++ /dev/null @@ -1,23 +0,0 @@ -/* - * Copyright (c) 2024 Nordic Semiconductor ASA - * - * SPDX-License-Identifier: LicenseRef-Nordic-5-Clause - */ - -#ifndef MOCK_SUIT_PLAT_IPUC_H__ -#define MOCK_SUIT_PLAT_IPUC_H__ - -#include -#include -#include - -FAKE_VALUE_FUNC(int, suit_plat_ipuc_declare, suit_component_t); -FAKE_VALUE_FUNC(int, suit_plat_ipuc_revoke, suit_component_t); - -static inline void mock_suit_plat_ipuc_reset(void) -{ - RESET_FAKE(suit_plat_ipuc_declare); - RESET_FAKE(suit_plat_ipuc_revoke); -} - -#endif /* MOCK_SUIT_PLAT_IPUC_H__ */ diff --git a/tests/subsys/suit/unit/mocks/include/mocks.h b/tests/subsys/suit/unit/mocks/include/mocks.h index b595546e0d31..49116d2117cf 100644 --- a/tests/subsys/suit/unit/mocks/include/mocks.h +++ b/tests/subsys/suit/unit/mocks/include/mocks.h @@ -55,7 +55,7 @@ #endif /* CONFIG_MOCK_SUIT_PLATFORM */ #ifdef CONFIG_MOCK_SUIT_IPUC -#include +#include #endif /* CONFIG_MOCK_SUIT_IPUC */ #ifdef CONFIG_MOCK_DIGEST_SINK diff --git a/tests/subsys/suit/unit/suit_plat_override_image_size/CMakeLists.txt b/tests/subsys/suit/unit/suit_plat_override_image_size/CMakeLists.txt index f1b19a060107..199a221b1523 100644 --- a/tests/subsys/suit/unit/suit_plat_override_image_size/CMakeLists.txt +++ b/tests/subsys/suit/unit/suit_plat_override_image_size/CMakeLists.txt @@ -11,6 +11,7 @@ include(../cmake/test_template.cmake) project(plat_override_image_size) target_include_directories(testbinary PRIVATE ${SUIT_SUBSYS_DIR}/platform/include) +target_include_directories(testbinary PRIVATE ${SUIT_SUBSYS_DIR}/metadata/include) target_compile_options(test_interface INTERFACE -DCONFIG_SUIT_PLATFORM) target_sources(testbinary PRIVATE diff --git a/tests/subsys/suit/unit/suit_plat_override_image_size/src/main.c b/tests/subsys/suit/unit/suit_plat_override_image_size/src/main.c index 8a5b16cf0115..1e17f8c195fe 100644 --- a/tests/subsys/suit/unit/suit_plat_override_image_size/src/main.c +++ b/tests/subsys/suit/unit/suit_plat_override_image_size/src/main.c @@ -128,13 +128,13 @@ ZTEST(suit_platform_override_image_size_tests, test_suit_plat_override_image_siz suit_memptr_storage_ptr_store_fake.arg2_history[1], expected_size); /* ... and IPUC component should be revoked */ - zassert_equal(suit_plat_ipuc_revoke_fake.call_count, 1, - "Incorrect number of suit_plat_ipuc_revoke() calls"); - zassert_equal(suit_plat_ipuc_revoke_fake.arg0_history[0], component, + zassert_equal(suit_ipuc_sdfw_revoke_fake.call_count, 1, + "Incorrect number of suit_ipuc_sdfw_revoke() calls"); + zassert_equal(suit_ipuc_sdfw_revoke_fake.arg0_history[0], component, "Wrong component handle: %d instead of %d", - suit_plat_ipuc_revoke_fake.arg0_history[0], component); - zassert_equal(suit_plat_ipuc_declare_fake.call_count, 0, - "Incorrect number of suit_plat_ipuc_declare() calls"); + suit_ipuc_sdfw_revoke_fake.arg0_history[0], component); + zassert_equal(suit_ipuc_sdfw_declare_fake.call_count, 0, + "Incorrect number of suit_ipuc_sdfw_declare() calls"); } ZTEST(suit_platform_override_image_size_tests, test_suit_override_size_and_declare_ipuc) @@ -167,13 +167,13 @@ ZTEST(suit_platform_override_image_size_tests, test_suit_override_size_and_decla suit_memptr_storage_ptr_store_fake.arg2_history[1], expected_size); /* ... and IPUC component should be revoked */ - zassert_equal(suit_plat_ipuc_declare_fake.call_count, 1, - "Incorrect number of suit_plat_ipuc_declare() calls"); - zassert_equal(suit_plat_ipuc_declare_fake.arg0_history[0], component, + zassert_equal(suit_ipuc_sdfw_declare_fake.call_count, 1, + "Incorrect number of suit_ipuc_sdfw_declare() calls"); + zassert_equal(suit_ipuc_sdfw_declare_fake.arg0_history[0], component, "Wrong component handle: %d instead of %d", - suit_plat_ipuc_declare_fake.arg0_history[0], component); - zassert_equal(suit_plat_ipuc_revoke_fake.call_count, 0, - "Incorrect number of suit_plat_ipuc_revoke() calls"); + suit_ipuc_sdfw_declare_fake.arg0_history[0], component); + zassert_equal(suit_ipuc_sdfw_revoke_fake.call_count, 0, + "Incorrect number of suit_ipuc_sdfw_revoke() calls"); } ZTEST(suit_platform_override_image_size_tests, @@ -194,10 +194,10 @@ ZTEST(suit_platform_override_image_size_tests, expected_error); /* ... and IPUC component should not be revoked */ - zassert_equal(suit_plat_ipuc_revoke_fake.call_count, 0, - "Incorrect number of suit_plat_ipuc_revoke() calls"); - zassert_equal(suit_plat_ipuc_declare_fake.call_count, 0, - "Incorrect number of suit_plat_ipuc_declare() calls"); + zassert_equal(suit_ipuc_sdfw_revoke_fake.call_count, 0, + "Incorrect number of suit_ipuc_sdfw_revoke() calls"); + zassert_equal(suit_ipuc_sdfw_declare_fake.call_count, 0, + "Incorrect number of suit_ipuc_sdfw_declare() calls"); } ZTEST(suit_platform_override_image_size_tests, test_suit_plat_override_image_size_fail_get) @@ -216,10 +216,10 @@ ZTEST(suit_platform_override_image_size_tests, test_suit_plat_override_image_siz expected_error); /* ... and IPUC component should not be revoked */ - zassert_equal(suit_plat_ipuc_revoke_fake.call_count, 0, - "Incorrect number of suit_plat_ipuc_revoke() calls"); - zassert_equal(suit_plat_ipuc_declare_fake.call_count, 0, - "Incorrect number of suit_plat_ipuc_declare() calls"); + zassert_equal(suit_ipuc_sdfw_revoke_fake.call_count, 0, + "Incorrect number of suit_ipuc_sdfw_revoke() calls"); + zassert_equal(suit_ipuc_sdfw_declare_fake.call_count, 0, + "Incorrect number of suit_ipuc_sdfw_declare() calls"); } ZTEST(suit_platform_override_image_size_tests, test_suit_plat_override_image_size_fail_store) @@ -237,10 +237,10 @@ ZTEST(suit_platform_override_image_size_tests, test_suit_plat_override_image_siz expected_error); /* ... and IPUC component should not be revoked */ - zassert_equal(suit_plat_ipuc_revoke_fake.call_count, 0, - "Incorrect number of suit_plat_ipuc_revoke() calls"); - zassert_equal(suit_plat_ipuc_declare_fake.call_count, 0, - "Incorrect number of suit_plat_ipuc_declare() calls"); + zassert_equal(suit_ipuc_sdfw_revoke_fake.call_count, 0, + "Incorrect number of suit_ipuc_sdfw_revoke() calls"); + zassert_equal(suit_ipuc_sdfw_declare_fake.call_count, 0, + "Incorrect number of suit_ipuc_sdfw_declare() calls"); } ZTEST(suit_platform_override_image_size_tests, @@ -259,10 +259,10 @@ ZTEST(suit_platform_override_image_size_tests, expected_error); /* ... and IPUC component should not be revoked */ - zassert_equal(suit_plat_ipuc_revoke_fake.call_count, 0, - "Incorrect number of suit_plat_ipuc_revoke() calls"); - zassert_equal(suit_plat_ipuc_declare_fake.call_count, 0, - "Incorrect number of suit_plat_ipuc_declare() calls"); + zassert_equal(suit_ipuc_sdfw_revoke_fake.call_count, 0, + "Incorrect number of suit_ipuc_sdfw_revoke() calls"); + zassert_equal(suit_ipuc_sdfw_declare_fake.call_count, 0, + "Incorrect number of suit_ipuc_sdfw_declare() calls"); /* Cleanup: create component to satisfy test_after */ suit_plat_decode_component_type_fake.custom_fake = @@ -290,10 +290,10 @@ ZTEST(suit_platform_override_image_size_tests, expected_error); /* ... and IPUC component should not be revoked */ - zassert_equal(suit_plat_ipuc_revoke_fake.call_count, 0, - "Incorrect number of suit_plat_ipuc_revoke() calls"); - zassert_equal(suit_plat_ipuc_declare_fake.call_count, 0, - "Incorrect number of suit_plat_ipuc_declare() calls"); + zassert_equal(suit_ipuc_sdfw_revoke_fake.call_count, 0, + "Incorrect number of suit_ipuc_sdfw_revoke() calls"); + zassert_equal(suit_ipuc_sdfw_declare_fake.call_count, 0, + "Incorrect number of suit_ipuc_sdfw_declare() calls"); } ZTEST(suit_platform_override_image_size_tests, @@ -312,10 +312,10 @@ ZTEST(suit_platform_override_image_size_tests, expected_error); /* ... and IPUC component should not be revoked */ - zassert_equal(suit_plat_ipuc_revoke_fake.call_count, 0, - "Incorrect number of suit_plat_ipuc_revoke() calls"); - zassert_equal(suit_plat_ipuc_declare_fake.call_count, 0, - "Incorrect number of suit_plat_ipuc_declare() calls"); + zassert_equal(suit_ipuc_sdfw_revoke_fake.call_count, 0, + "Incorrect number of suit_ipuc_sdfw_revoke() calls"); + zassert_equal(suit_ipuc_sdfw_declare_fake.call_count, 0, + "Incorrect number of suit_ipuc_sdfw_declare() calls"); } ZTEST(suit_platform_override_image_size_tests, test_suit_plat_override_image_size_exceeding_size) @@ -330,8 +330,8 @@ ZTEST(suit_platform_override_image_size_tests, test_suit_plat_override_image_siz expected_error); /* ... and IPUC component should not be revoked */ - zassert_equal(suit_plat_ipuc_revoke_fake.call_count, 0, - "Incorrect number of suit_plat_ipuc_revoke() calls"); - zassert_equal(suit_plat_ipuc_declare_fake.call_count, 0, - "Incorrect number of suit_plat_ipuc_declare() calls"); + zassert_equal(suit_ipuc_sdfw_revoke_fake.call_count, 0, + "Incorrect number of suit_ipuc_sdfw_revoke() calls"); + zassert_equal(suit_ipuc_sdfw_declare_fake.call_count, 0, + "Incorrect number of suit_ipuc_sdfw_declare() calls"); } diff --git a/tests/subsys/suit/write/CMakeLists.txt b/tests/subsys/suit/write/CMakeLists.txt index 97f6de2e989e..5f320ea13772 100644 --- a/tests/subsys/suit/write/CMakeLists.txt +++ b/tests/subsys/suit/write/CMakeLists.txt @@ -18,3 +18,4 @@ zephyr_library_link_libraries(suit_sink_selector_interface) zephyr_library_link_libraries(suit_memory_layout_interface) zephyr_library_link_libraries(suit_storage_interface) zephyr_library_link_libraries(suit_manifest_variables) +zephyr_library_link_libraries(suit_ipuc) diff --git a/tests/subsys/suit/write/src/main.c b/tests/subsys/suit/write/src/main.c index 984fd83e64ee..eeda24bccae7 100644 --- a/tests/subsys/suit/write/src/main.c +++ b/tests/subsys/suit/write/src/main.c @@ -10,7 +10,7 @@ #include #include #include -#include +#include #include #include #include @@ -87,22 +87,23 @@ ZTEST(write_tests, test_write_to_flash_sink_OK) .len = sizeof(valid_dst_value), }; + int ipc_client_id = 1234; int ret = suit_plat_create_component_handle(&valid_dst_component_id, false, &dst_handle); zassert_equal(ret, SUIT_SUCCESS, "create_component_handle failed - error %i", ret); - ret = suit_plat_ipuc_write(dst_handle, 0, (uintptr_t)test_data, sizeof(test_data), true); + ret = suit_ipuc_sdfw_write_setup(ipc_client_id, &valid_dst_component_id, NULL, NULL); zassert_equal(ret, SUIT_PLAT_ERR_NOT_FOUND, "in-place updateable component found"); - ret = suit_plat_ipuc_declare(dst_handle); - zassert_equal(ret, SUIT_PLAT_SUCCESS, "suit_plat_ipuc_declare failed - error %i", ret); + ret = suit_ipuc_sdfw_declare(dst_handle, SUIT_MANIFEST_UNKNOWN); + zassert_equal(ret, SUIT_PLAT_SUCCESS, "suit_ipuc_sdfw_declare failed - error %i", ret); - ret = suit_plat_ipuc_write(dst_handle, 0, (uintptr_t)test_data, sizeof(test_data), true); - zassert_equal(ret, SUIT_PLAT_SUCCESS, "cannot write to in-place updateable component"); + ret = suit_ipuc_sdfw_write_setup(ipc_client_id, &valid_dst_component_id, NULL, NULL); + zassert_equal(ret, SUIT_PLAT_SUCCESS, "suit_ipuc_sdfw_write_setup failed - error %i", ret); ret = suit_plat_write(dst_handle, &source, &valid_manifest_component_id, NULL); zassert_equal(ret, SUIT_SUCCESS, "suit_plat_write failed - error %i", ret); - ret = suit_plat_ipuc_write(dst_handle, 0, (uintptr_t)test_data, sizeof(test_data), true); + ret = suit_ipuc_sdfw_write_setup(ipc_client_id, &valid_dst_component_id, NULL, NULL); zassert_equal(ret, SUIT_PLAT_ERR_NOT_FOUND, "in-place updateable component found"); ret = suit_plat_release_component_handle(dst_handle);