aboutsummaryrefslogtreecommitdiff
path: root/secure_fw/partitions/firmware_update/tfm_fwu_req_mngr.c
diff options
context:
space:
mode:
Diffstat (limited to 'secure_fw/partitions/firmware_update/tfm_fwu_req_mngr.c')
-rw-r--r--secure_fw/partitions/firmware_update/tfm_fwu_req_mngr.c781
1 files changed, 399 insertions, 382 deletions
diff --git a/secure_fw/partitions/firmware_update/tfm_fwu_req_mngr.c b/secure_fw/partitions/firmware_update/tfm_fwu_req_mngr.c
index 507d9f96a0..b37bdc0d47 100644
--- a/secure_fw/partitions/firmware_update/tfm_fwu_req_mngr.c
+++ b/secure_fw/partitions/firmware_update/tfm_fwu_req_mngr.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2021, Arm Limited. All rights reserved.
+ * Copyright (c) 2021-2022, Arm Limited. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*
@@ -7,517 +7,534 @@
#include <stdint.h>
#include <stdbool.h>
-#include "tfm_fwu_req_mngr.h"
-#include "tfm_fwu.h"
+#include <string.h>
+#include "config_tfm.h"
+#include "tfm_platform_api.h"
+#include "tfm_bootloader_fwu_abstraction.h"
#include "psa/update.h"
#include "service_api.h"
-#include "tfm_api.h"
-
-#ifdef TFM_PSA_API
#include "psa/service.h"
#include "psa_manifest/tfm_firmware_update.h"
-#include "tfm_memory_utils.h"
-#endif
+#include "compiler_ext_defs.h"
+
+#define COMPONENTS_ITER(x) \
+ for ((x) = 0; (x) < (FWU_COMPONENT_NUMBER); (x)++)
typedef struct tfm_fwu_ctx_s {
- psa_image_id_t image_id;
- uint8_t image_state;
+ psa_status_t error;
+ uint8_t component_state;
bool in_use;
} tfm_fwu_ctx_t;
/**
* \brief The context of FWU service.
*/
-static tfm_fwu_ctx_t fwu_ctx[TFM_FWU_MAX_IMAGES];
+static tfm_fwu_ctx_t fwu_ctx[FWU_COMPONENT_NUMBER];
-/**
- * \brief Check if the image is in FWU process, return the index if it is.
- */
-static bool get_image_index(psa_image_id_t image_id, uint8_t *index)
-{
- if (!index) {
- return false;
- }
-
- for (uint8_t i = 0; i < TFM_FWU_MAX_IMAGES; i++) {
- if (fwu_ctx[i].in_use && (fwu_ctx[i].image_id == image_id)) {
- *index = i;
- return true;
- }
- }
- return false;
-}
-
-/**
- * \brief The the next free index in fwu_ctx.
- */
-static bool get_next_free_index(uint8_t *index)
-{
- for (uint8_t i = 0; i < TFM_FWU_MAX_IMAGES; i++) {
- if (!fwu_ctx[i].in_use) {
- *index = i;
- return true;
- }
- }
- return false;
-}
+#if PSA_FRAMEWORK_HAS_MM_IOVEC != 1
+static uint8_t block[TFM_FWU_BUF_SIZE] __aligned(4);
+#endif
-#ifndef TFM_PSA_API
-psa_status_t tfm_fwu_write_req(psa_invec *in_vec, size_t in_len,
- psa_outvec *out_vec, size_t out_len)
+static psa_status_t tfm_fwu_start(const psa_msg_t *msg)
{
- psa_image_id_t image_id;
- size_t block_offset;
- uint8_t *p_data;
- size_t data_length;
- psa_status_t status = PSA_SUCCESS;
- uint8_t image_index;
-
- (void)out_vec;
+ psa_fwu_component_t component;
+#if PSA_FRAMEWORK_HAS_MM_IOVEC == 1 || TFM_CONFIG_FWU_MAX_MANIFEST_SIZE == 0
+ uint8_t *manifest = NULL;
+#else
+ uint8_t manifest_data[TFM_CONFIG_FWU_MAX_MANIFEST_SIZE];
+ uint8_t *manifest = manifest_data;
+#endif
+ size_t manifest_size;
+ psa_status_t status;
+ psa_fwu_component_info_t info;
/* Check input parameters. */
- if (in_vec[0].len != sizeof(image_id) ||
- in_vec[1].len != sizeof(block_offset)) {
- /* The size of one of the arguments is incorrect */
- return PSA_ERROR_INVALID_ARGUMENT;
+ if (msg->in_size[0] != sizeof(component)) {
+ return PSA_ERROR_PROGRAMMER_ERROR;
}
-
- p_data = (uint8_t * const)in_vec[2].base;
-
- if (p_data == NULL) {
- return PSA_ERROR_INVALID_ARGUMENT;
+ if (msg->in_size[1] > TFM_CONFIG_FWU_MAX_MANIFEST_SIZE) {
+ return PSA_ERROR_NOT_SUPPORTED;
}
+ psa_read(msg->handle, 0, &component, sizeof(component));
- block_offset = *((size_t *)in_vec[1].base);
- data_length = in_vec[2].len;
- image_id = *((psa_image_id_t *)in_vec[0].base);
+ if (component >= FWU_COMPONENT_NUMBER) {
+ return PSA_ERROR_DOES_NOT_EXIST;
+ }
+ manifest_size = msg->in_size[1];
+ if (manifest_size > 0) {
+#if PSA_FRAMEWORK_HAS_MM_IOVEC == 1
+ manifest = (uint8_t *)psa_map_invec(msg->handle, 1);
+#else
+ psa_read(msg->handle, 1, manifest, manifest_size);
+#endif
+ }
- if (get_image_index(image_id, &image_index)) {
- /* The image is in FWU process. */
- if ((fwu_ctx[image_index].image_state != PSA_IMAGE_CANDIDATE) &&
- (fwu_ctx[image_index].image_state != PSA_IMAGE_REJECTED)) {
- return PSA_ERROR_CURRENTLY_INSTALLING;
+ /* The component is in FWU process. */
+ if (fwu_ctx[component].in_use) {
+ if (fwu_ctx[component].component_state != PSA_FWU_READY) {
+ return PSA_ERROR_BAD_STATE;
}
} else {
- /* The image is not in FWU process. */
- if (get_next_free_index(&image_index)) {
- /* Get a free index. Start the FWU process of this image. */
- status = tfm_internal_fwu_initialize(image_id);
- if (status != PSA_SUCCESS) {
- return status;
- }
- fwu_ctx[image_index].in_use = true;
- fwu_ctx[image_index].image_id = image_id;
- fwu_ctx[image_index].image_state = PSA_IMAGE_CANDIDATE;
- } else {
- /* No more resource can be used. */
- return PSA_ERROR_INSUFFICIENT_MEMORY;
+ /* Query the state of the component. */
+ status = fwu_bootloader_get_image_info(component, true, false, &info);
+ if (status != PSA_SUCCESS) {
+ return status;
+ }
+ if (info.state != PSA_FWU_READY) {
+ return PSA_ERROR_BAD_STATE;
}
- }
- return tfm_internal_fwu_write(image_id,
- block_offset,
- p_data,
- data_length);
+ /* The component is not in FWU process. Initialize the ctx for this component. */
+ status = fwu_bootloader_staging_area_init(component,
+ (const void *)manifest,
+ manifest_size);
+ if (status != PSA_SUCCESS) {
+ return status;
+ }
+ fwu_ctx[component].in_use = true;
+ fwu_ctx[component].component_state = PSA_FWU_WRITING;
+ }
+ return PSA_SUCCESS;
}
-psa_status_t tfm_fwu_install_req(psa_invec *in_vec, size_t in_len,
- psa_outvec *out_vec, size_t out_len)
+static psa_status_t tfm_fwu_write(const psa_msg_t *msg)
{
- psa_image_id_t image_id;
- psa_image_id_t *dependency_id;
- psa_image_version_t *dependency_version;
- psa_status_t status;
- uint8_t image_index;
+ psa_fwu_component_t component;
+ size_t image_offset;
+ size_t block_size;
+ psa_status_t status = PSA_SUCCESS;
+#if PSA_FRAMEWORK_HAS_MM_IOVEC == 1
+ uint8_t *block;
+#else
+ size_t write_size, num;
+#endif
- /* Check input/output parameters. */
- if (in_vec[0].len != sizeof(image_id) ||
- out_vec[0].len != sizeof(*dependency_id) ||
- out_vec[1].len != sizeof(*dependency_version)) {
- /* The size of one of the arguments is incorrect. */
+ /* Check input parameters. */
+ if (msg->in_size[2] > PSA_FWU_MAX_WRITE_SIZE) {
return PSA_ERROR_INVALID_ARGUMENT;
}
+ block_size = msg->in_size[2];
- image_id = *((psa_image_id_t *)in_vec[0].base);
- dependency_id = out_vec[0].base;
- dependency_version = out_vec[1].base;
-
- if ((!get_image_index(image_id, &image_index)) ||
- (fwu_ctx[image_index].image_state != PSA_IMAGE_CANDIDATE)) {
- return PSA_ERROR_INVALID_ARGUMENT;
- } else {
- status = tfm_internal_fwu_install(image_id,
- dependency_id,
- dependency_version);
- if (status == PSA_SUCCESS) {
- fwu_ctx[image_index].image_state = PSA_IMAGE_INSTALLED;
-
- /* The image has been successfully installed, free the index. */
- fwu_ctx[image_index].in_use = false;
- } else if (status == PSA_SUCCESS_REBOOT) {
- fwu_ctx[image_index].image_state = PSA_IMAGE_REBOOT_NEEDED;
- } else {
- fwu_ctx[image_index].image_state = PSA_IMAGE_REJECTED;
- }
+ if (msg->in_size[0] != sizeof(component) ||
+ msg->in_size[1] != sizeof(image_offset)) {
+ return PSA_ERROR_PROGRAMMER_ERROR;
+ }
- return status;
+ psa_read(msg->handle, 0, &component, sizeof(component));
+ if (component >= FWU_COMPONENT_NUMBER) {
+ return PSA_ERROR_DOES_NOT_EXIST;
}
-}
-psa_status_t tfm_fwu_query_req(psa_invec *in_vec, size_t in_len,
- psa_outvec *out_vec, size_t out_len)
-{
- psa_image_id_t image_id;
- psa_image_info_t *info_p;
- psa_status_t result = 0;
- uint8_t image_index;
+ psa_read(msg->handle, 1, &image_offset, sizeof(image_offset));
- if ((in_vec[0].len != sizeof(image_id)) ||
- (out_vec[0].len != sizeof(*info_p))) {
- return PSA_ERROR_INVALID_ARGUMENT;
+ /* Check the component state. */
+ if (!fwu_ctx[component].in_use ||
+ fwu_ctx[component].component_state != PSA_FWU_WRITING) {
+ return PSA_ERROR_BAD_STATE;
}
+#if PSA_FRAMEWORK_HAS_MM_IOVEC == 1
+ if (block_size > 0) {
+ block = (uint8_t *)psa_map_invec(msg->handle, 2);
+ status = fwu_bootloader_load_image(component,
+ image_offset,
+ block,
+ block_size);
+ }
+#else
+ while (block_size > 0) {
+ write_size = sizeof(block) <= block_size ?
+ sizeof(block) : block_size;
+ num = psa_read(msg->handle, 2, block, write_size);
+ if (num != write_size) {
+ return PSA_ERROR_PROGRAMMER_ERROR;
+ }
- image_id = *((psa_image_id_t *)in_vec[0].base);
- info_p = (psa_image_info_t *)out_vec[0].base;
- result = tfm_internal_fwu_query(image_id, info_p);
- if (result == PSA_SUCCESS) {
- /* Fill the image state if the query image is not the running image. */
- if (info_p->state == PSA_IMAGE_UNDEFINED) {
- if (get_image_index(image_id, &image_index)) {
- /* The queried image is the currently updating image. */
- info_p->state = fwu_ctx[image_index].image_state;
- }
+ status = fwu_bootloader_load_image(component,
+ image_offset,
+ block,
+ write_size);
+ if (status != PSA_SUCCESS) {
+ return status;
}
+ block_size -= write_size;
+ image_offset += write_size;
}
-
- return result;
+#endif
+ return status;
}
-psa_status_t tfm_fwu_request_reboot_req(psa_invec *in_vec, size_t in_len,
- psa_outvec *out_vec, size_t out_len)
+static psa_status_t tfm_fwu_finish(const psa_msg_t *msg)
{
- (void)in_vec;
- (void)out_vec;
- (void)in_len;
- (void)out_len;
+ psa_fwu_component_t component;
- tfm_internal_fwu_request_reboot();
-
- /* If it goes here, then the reboot fails. */
- return PSA_ERROR_SERVICE_FAILURE;
-}
+ /* Check input parameters. */
+ if (msg->in_size[0] != sizeof(component)) {
+ return PSA_ERROR_PROGRAMMER_ERROR;
+ }
+ psa_read(msg->handle, 0, &component, sizeof(component));
+ if (component >= FWU_COMPONENT_NUMBER) {
+ return PSA_ERROR_DOES_NOT_EXIST;
+ }
-psa_status_t tfm_fwu_accept_req(psa_invec *in_vec, size_t in_len,
- psa_outvec *out_vec, size_t out_len)
-{
- (void)in_vec;
- (void)out_vec;
- (void)in_len;
- (void)out_len;
+ /* Check the component state. */
+ if (!fwu_ctx[component].in_use ||
+ fwu_ctx[component].component_state != PSA_FWU_WRITING) {
+ return PSA_ERROR_BAD_STATE;
+ }
- /* This operation set the running image to INSTALLED state, the images
- * in the staging area does not impact this operation.
+ /* Validity, authenticity and integrity of the image is deferred to system
+ * reboot.
*/
- return tfm_internal_fwu_accept();
+ fwu_ctx[component].component_state = PSA_FWU_CANDIDATE;
+ return PSA_SUCCESS;
}
-/* Abort the currently running FWU. */
-psa_status_t tfm_fwu_abort_req(psa_invec *in_vec, size_t in_len,
- psa_outvec *out_vec, size_t out_len)
+static psa_status_t tfm_fwu_install(void)
{
- psa_image_id_t image_id;
+ psa_fwu_component_t component = 0;
psa_status_t status;
- uint8_t image_index;
-
- (void)out_vec;
-
- if (in_vec[0].len != sizeof(image_id)) {
- return PSA_ERROR_INVALID_ARGUMENT;
- }
+ uint8_t candidate_number = 0, index;
+ psa_fwu_component_info_t info;
+ psa_fwu_component_t candidates[FWU_COMPONENT_NUMBER];
- image_id = *((psa_image_id_t *)in_vec[0].base);
- if (get_image_index(image_id, &image_index)) {
- /* The image is in FWU process. */
- if ((fwu_ctx[image_index].image_state == PSA_IMAGE_CANDIDATE) ||
- (fwu_ctx[image_index].image_state == PSA_IMAGE_REBOOT_NEEDED) ||
- (fwu_ctx[image_index].image_state == PSA_IMAGE_REJECTED)) {
- status = tfm_internal_fwu_abort(image_id);
+ /* If at least one component is in STAGED, TRIAL or REJECTED state results
+ * PSA_ERROR_BAD_STATE error.
+ */
+ COMPONENTS_ITER(component) {
+ if (fwu_ctx[component].in_use) {
+ if (fwu_ctx[component].component_state == PSA_FWU_STAGED ||
+ fwu_ctx[component].component_state == PSA_FWU_REJECTED) {
+ return PSA_ERROR_BAD_STATE;
+ } else if (fwu_ctx[component].component_state == PSA_FWU_CANDIDATE) {
+ candidates[candidate_number++] = component;
+ }
+ } else {
+ status = fwu_bootloader_get_image_info(component, true, false, &info);
if (status != PSA_SUCCESS) {
return status;
}
+ if (info.state == PSA_FWU_TRIAL) {
+ return PSA_ERROR_BAD_STATE;
+ }
+ }
+ }
- fwu_ctx[image_index].image_state = PSA_IMAGE_UNDEFINED;
- fwu_ctx[image_index].in_use = false;
- fwu_ctx[image_index].image_id = TFM_FWU_INVALID_IMAGE_ID;
- return PSA_SUCCESS;
+ /* No components in CANDIDATE state. */
+ if (candidate_number == 0) {
+ return PSA_ERROR_BAD_STATE;
+ }
+
+ status = fwu_bootloader_install_image(candidates,
+ candidate_number);
+
+ if (status == PSA_ERROR_DEPENDENCY_NEEDED) {
+ /* No need to update the CANDIDATE components' state in this case. */
+ return status;
+ }
+
+ /* Update the CANDIDATE components' state and error context accordingly. */
+ for (index = 0; index < candidate_number; index++) {
+ component = candidates[index];
+ if (status == PSA_SUCCESS) {
+ /* Check TRIAL state is supported or not. */
+#ifdef FWU_SUPPORT_TRIAL_STATE
+ fwu_ctx[component].component_state = PSA_FWU_TRIAL;
+#else
+ fwu_ctx[component].component_state = PSA_FWU_UPDATED;
+#endif
+ } else if (status != PSA_SUCCESS_REBOOT && status != PSA_SUCCESS_RESTART) {
+ /* Switch to FAILED state on other errors. */
+ fwu_ctx[component].component_state = PSA_FWU_FAILED;
+ fwu_ctx[component].error = status;
} else {
- /* If the image is in INSTALLED state or UNDEFINED, it should not in
- * a FWU process.
- */
- return PSA_ERROR_PROGRAMMER_ERROR;
+ fwu_ctx[component].component_state = PSA_FWU_STAGED;
}
- } else {
- /* No image with the provided image_id is not in FWU process. */
- return PSA_ERROR_INVALID_ARGUMENT;
}
+ return status;
}
-#else
-typedef psa_status_t (*fwu_func_t)(void);
-static psa_msg_t msg;
-static psa_status_t tfm_fwu_write_ipc(void)
+static psa_status_t tfm_fwu_query(const psa_msg_t *msg)
{
- psa_image_id_t image_id;
- size_t block_offset;
- size_t data_length, num;
- psa_status_t status = PSA_SUCCESS;
- uint8_t data_block[PSA_FWU_MAX_BLOCK_SIZE];
- uint8_t image_index;
+ psa_fwu_component_t component = { 0 };
+ psa_fwu_component_info_t info;
+ psa_status_t result;
+ bool query_impl_info = false, query_state = true;
/* Check input parameters. */
- if (msg.in_size[0] != sizeof(image_id) ||
- msg.in_size[1] != sizeof(block_offset)) {
+ if (msg->in_size[0] != sizeof(component) ||
+ msg->out_size[0] != sizeof(psa_fwu_component_info_t)) {
return PSA_ERROR_PROGRAMMER_ERROR;
}
-
- num = psa_read(msg.handle, 0, &image_id, sizeof(image_id));
- if (num != sizeof(image_id)) {
- return PSA_ERROR_PROGRAMMER_ERROR;
+ psa_read(msg->handle, 0, &component, sizeof(component));
+ if (component >= FWU_COMPONENT_NUMBER) {
+ return PSA_ERROR_DOES_NOT_EXIST;
}
- num = psa_read(msg.handle, 1, &block_offset, sizeof(block_offset));
- if (num != sizeof(block_offset)) {
- return PSA_ERROR_PROGRAMMER_ERROR;
+ if (fwu_ctx[component].in_use) {
+ info.state = fwu_ctx[component].component_state;
+ query_state = false;
+ /* The psa_fwu_impl_info_t contains the digest of second image when
+ * store state is CANDIDATE. Calculate the digest when store state is
+ * CANDIDATE.
+ */
+ if (fwu_ctx[component].component_state == PSA_FWU_CANDIDATE) {
+ query_impl_info = true;
+ } else if (fwu_ctx[component].component_state == PSA_FWU_REJECTED ||
+ fwu_ctx[component].component_state == PSA_FWU_FAILED) {
+ info.error = fwu_ctx[component].error;
+ }
}
- tfm_memset(data_block, 0, sizeof(data_block));
- data_length = msg.in_size[2];
- num = psa_read(msg.handle, 2, data_block, data_length);
- if (num != data_length) {
- return PSA_ERROR_PROGRAMMER_ERROR;
+ /* If there is no active ctx, the possible component states are READY and
+ * TRIAL.
+ */
+ result = fwu_bootloader_get_image_info(component, query_state,
+ query_impl_info, &info);
+ if (result == PSA_SUCCESS) {
+ psa_write(msg->handle, 0, &info, sizeof(info));
}
- if (get_image_index(image_id, &image_index)) {
- /* The image is in FWU process. */
- if ((fwu_ctx[image_index].image_state != PSA_IMAGE_CANDIDATE) &&
- (fwu_ctx[image_index].image_state != PSA_IMAGE_REJECTED)) {
- return PSA_ERROR_CURRENTLY_INSTALLING;
- }
- } else {
- /* The image is not in FWU process. */
- if (get_next_free_index(&image_index)) {
- /* Get a free index. Start the FWU process of this image. */
- status = tfm_internal_fwu_initialize(image_id);
+ return result;
+}
+
+static psa_status_t tfm_fwu_request_reboot(void)
+{
+ tfm_platform_system_reset();
+
+ return PSA_SUCCESS;
+}
+
+static psa_status_t tfm_fwu_accept(void)
+{
+#ifdef FWU_SUPPORT_TRIAL_STATE
+ psa_fwu_component_t component = 0;
+ psa_status_t status = PSA_ERROR_BAD_STATE;
+ psa_fwu_component_info_t info;
+ psa_fwu_component_t trials[FWU_COMPONENT_NUMBER];
+ uint8_t trials_number = 0, index;
+
+ COMPONENTS_ITER(component) {
+ if (fwu_ctx[component].in_use) {
+ if (fwu_ctx[component].component_state == PSA_FWU_TRIAL) {
+ trials[trials_number++] = component;
+ }
+ } else {
+ status = fwu_bootloader_get_image_info(component, true, false, &info);
if (status != PSA_SUCCESS) {
return status;
}
- fwu_ctx[image_index].in_use = true;
- fwu_ctx[image_index].image_id = image_id;
- fwu_ctx[image_index].image_state = PSA_IMAGE_CANDIDATE;
- } else {
- /* No more resource can be used. */
- return PSA_ERROR_INSUFFICIENT_MEMORY;
+ if (info.state == PSA_FWU_TRIAL) {
+ trials[trials_number++] = component;
+ fwu_ctx[component].in_use = true;
+ fwu_ctx[component].component_state = PSA_FWU_TRIAL;
+ }
}
}
- return tfm_internal_fwu_write(image_id,
- block_offset,
- data_block,
- data_length);
+ if (trials_number == 0) {
+ return PSA_ERROR_BAD_STATE;
+ }
+ status = fwu_bootloader_mark_image_accepted(trials, trials_number);
+ if (status != PSA_SUCCESS) {
+ /* Rebooting the system results in the image being automatically rejected.
+ * Keep the component in TRIAL state.
+ */
+ return status;
+ }
+
+ for (index = 0; index < trials_number; index++) {
+ component = trials[index];
+ fwu_ctx[component].component_state = PSA_FWU_UPDATED;
+ }
+ return status;
+#else
+ return PSA_ERROR_NOT_SUPPORTED;
+#endif
}
-static psa_status_t tfm_fwu_install_ipc(void)
+psa_status_t tfm_fwu_reject(const psa_msg_t *msg)
{
- psa_image_id_t image_id;
- psa_image_id_t dependency_id;
- psa_image_version_t dependency_version;
+ psa_fwu_component_t component = 0;
+ psa_status_t status = PSA_SUCCESS, error;
+ psa_fwu_component_info_t info;
+ bool staged_trial_component_found = false, in_trial_state = false;
size_t num;
- psa_status_t status;
- uint8_t image_index;
/* Check input parameters. */
- if (msg.in_size[0] != sizeof(image_id) ||
- msg.out_size[0] != sizeof(dependency_id) ||
- msg.out_size[1] != sizeof(dependency_version)) {
+ if (msg->in_size[0] != sizeof(error)) {
return PSA_ERROR_PROGRAMMER_ERROR;
}
-
- num = psa_read(msg.handle, 0, &image_id, sizeof(image_id));
- if (num != sizeof(image_id)) {
+ num = psa_read(msg->handle, 0, &error, sizeof(error));
+ if (num != sizeof(error)) {
return PSA_ERROR_PROGRAMMER_ERROR;
}
- if ((!get_image_index(image_id, &image_index)) ||
- (fwu_ctx[image_index].image_state != PSA_IMAGE_CANDIDATE)) {
- return PSA_ERROR_INVALID_ARGUMENT;
- } else {
- status = tfm_internal_fwu_install(image_id,
- &dependency_id,
- &dependency_version);
- if (status == PSA_SUCCESS) {
- fwu_ctx[image_index].image_state = PSA_IMAGE_INSTALLED;
-
- /* The image has been successfully installed, free the index. */
- fwu_ctx[image_index].in_use = false;
- } else if (status == PSA_SUCCESS_REBOOT) {
- fwu_ctx[image_index].image_state = PSA_IMAGE_REBOOT_NEEDED;
- } else if (status == PSA_ERROR_DEPENDENCY_NEEDED) {
- psa_write(msg.handle, 0, &dependency_id, sizeof(dependency_id));
- psa_write(msg.handle, 1, &dependency_version,
- sizeof(dependency_version));
- fwu_ctx[image_index].image_state = PSA_IMAGE_REJECTED;
+ COMPONENTS_ITER(component) {
+ in_trial_state = false;
+ if (fwu_ctx[component].in_use) {
+ if (fwu_ctx[component].component_state == PSA_FWU_STAGED) {
+ /* If the installation state is STAGED, then the state of
+ * affected components changes to FAILED.
+ */
+ fwu_ctx[component].component_state = PSA_FWU_FAILED;
+ fwu_ctx[component].error = error;
+ staged_trial_component_found = true;
+ /* Reject the staged image. */
+ status = fwu_bootloader_reject_staged_image(component);
+ if (status != PSA_SUCCESS) {
+ return status;
+ }
+ } else if (fwu_ctx[component].component_state == PSA_FWU_TRIAL) {
+ staged_trial_component_found = true;
+ in_trial_state = true;
+ }
} else {
- fwu_ctx[image_index].image_state = PSA_IMAGE_REJECTED;
- }
+ status = fwu_bootloader_get_image_info(component, true, false, &info);
+ if (status != PSA_SUCCESS) {
+ return status;
+ }
- return status;
+ /* Reject the component if it is in TRIAL state. Reserve a ctx
+ * for the component to record its state.
+ */
+ if (info.state == PSA_FWU_TRIAL) {
+ fwu_ctx[component].in_use = true;
+ in_trial_state = true;
+ fwu_ctx[component].component_state = PSA_FWU_TRIAL;
+ staged_trial_component_found = true;
+ }
+ }
+ if (in_trial_state) {
+ /* Reject the running(trial) image. */
+ status = fwu_bootloader_reject_trial_image(component);
+ /* If a reboot is required, the state of affected components
+ * changes to REJECTED and PSA_SUCCESS_REBOOT is returned.
+ * If a component restart is required, the state of affected
+ * components changes to REJECTED and PSA_SUCCESS_RESTART is
+ * returned.
+ * If no reboot or component restart is required, the state
+ * of affected components changes to FAILED and PSA_SUCCESS
+ * is returned.
+ */
+ if (status == PSA_SUCCESS_REBOOT || status == PSA_SUCCESS_RESTART) {
+ fwu_ctx[component].component_state = PSA_FWU_REJECTED;
+ fwu_ctx[component].error = error;
+ } else if (status == PSA_SUCCESS) {
+ fwu_ctx[component].component_state = PSA_FWU_FAILED;
+ fwu_ctx[component].error = error;
+ } else {
+ return status;
+ }
+ }
}
+ if (!staged_trial_component_found) {
+ /* There are no components in the STAGED or TRIAL state. */
+ return PSA_ERROR_BAD_STATE;
+ }
+ return status;
}
-static psa_status_t tfm_fwu_query_ipc(void)
+static psa_status_t tfm_fwu_cancel(const psa_msg_t *msg)
{
- psa_image_id_t image_id;
- size_t num;
- psa_image_info_t info;
- psa_status_t result;
- uint8_t image_index;
+ psa_fwu_component_t component;
- /* Check input parameters. */
- if (msg.in_size[0] != sizeof(image_id)) {
- return PSA_ERROR_PROGRAMMER_ERROR;
- }
- num = psa_read(msg.handle, 0, &image_id, sizeof(image_id));
- if (num != sizeof(image_id)) {
+ if (msg->in_size[0] != sizeof(component)) {
return PSA_ERROR_PROGRAMMER_ERROR;
}
- result = tfm_internal_fwu_query(image_id, &info);
- if (result == PSA_SUCCESS) {
- /* Fill the image state if the query image is not the running image. */
- if (info.state == PSA_IMAGE_UNDEFINED) {
- if (get_image_index(image_id, &image_index)) {
- /* The queried image is the currently updating image. */
- info.state = fwu_ctx[image_index].image_state;
- }
- }
- psa_write(msg.handle, 0, &info, sizeof(info));
+ psa_read(msg->handle, 0, &component, sizeof(component));
+ if (component >= FWU_COMPONENT_NUMBER) {
+ return PSA_ERROR_DOES_NOT_EXIST;
}
- return result;
-}
-
-static psa_status_t tfm_fwu_request_reboot_ipc(void)
-{
- tfm_internal_fwu_request_reboot();
-
- return PSA_SUCCESS;
-}
-
-static psa_status_t tfm_fwu_accept_ipc(void)
-{
- /* This operation set the running image to INSTALLED state, the images
- * in the staging area does not impact this operation.
- */
- return tfm_internal_fwu_accept();
+ if (fwu_ctx[component].in_use) {
+ /* The component is in FWU process. */
+ if ((fwu_ctx[component].component_state == PSA_FWU_WRITING) ||
+ (fwu_ctx[component].component_state == PSA_FWU_CANDIDATE)) {
+ fwu_ctx[component].component_state = PSA_FWU_FAILED;
+ fwu_ctx[component].error = PSA_SUCCESS;
+ return PSA_SUCCESS;
+ } else {
+ /* If the image is in INSTALLED state or UNDEFINED, it should not in
+ * a FWU process.
+ */
+ return PSA_ERROR_BAD_STATE;
+ }
+ } else {
+ /* The component is not in WRITING or CANDIDATE state. */
+ return PSA_ERROR_BAD_STATE;
+ }
}
-static psa_status_t tfm_fwu_abort_ipc(void)
+static psa_status_t tfm_fwu_clean(const psa_msg_t *msg)
{
- psa_image_id_t image_id;
- size_t num;
- uint8_t image_index;
+ psa_fwu_component_t component;
psa_status_t status;
- if (msg.in_size[0] != sizeof(image_id)) {
+ if (msg->in_size[0] != sizeof(component)) {
return PSA_ERROR_PROGRAMMER_ERROR;
}
- num = psa_read(msg.handle, 0, &image_id, sizeof(image_id));
- if (num != sizeof(image_id)) {
- return PSA_ERROR_PROGRAMMER_ERROR;
+ psa_read(msg->handle, 0, &component, sizeof(component));
+ if (component >= FWU_COMPONENT_NUMBER) {
+ return PSA_ERROR_DOES_NOT_EXIST;
}
- if (get_image_index(image_id, &image_index)) {
- /* The image is in FWU process. */
- if ((fwu_ctx[image_index].image_state == PSA_IMAGE_CANDIDATE) ||
- (fwu_ctx[image_index].image_state == PSA_IMAGE_REBOOT_NEEDED) ||
- (fwu_ctx[image_index].image_state == PSA_IMAGE_REJECTED)) {
- status = tfm_internal_fwu_abort(image_id);
+ if (fwu_ctx[component].in_use) {
+ /* The component is in FWU process. */
+ if ((fwu_ctx[component].component_state == PSA_FWU_FAILED) ||
+ (fwu_ctx[component].component_state == PSA_FWU_UPDATED)) {
+ status = fwu_bootloader_clean_component(component);
if (status != PSA_SUCCESS) {
return status;
}
-
- fwu_ctx[image_index].image_state = PSA_IMAGE_UNDEFINED;
- fwu_ctx[image_index].in_use = false;
- fwu_ctx[image_index].image_id = TFM_FWU_INVALID_IMAGE_ID;
+ fwu_ctx[component].component_state = PSA_FWU_READY;
+ fwu_ctx[component].in_use = false;
return PSA_SUCCESS;
} else {
/* If the image is in INSTALLED state or UNDEFINED, it should not in
* a FWU process.
*/
- return PSA_ERROR_PROGRAMMER_ERROR;
+ return PSA_ERROR_BAD_STATE;
}
} else {
- /* No image with the provided image_id is not in FWU process. */
- return PSA_ERROR_INVALID_ARGUMENT;
+ /* The component is not in FAILED or UPDATED state. */
+ return PSA_ERROR_BAD_STATE;
}
}
-static void fwu_signal_handle(psa_signal_t signal, fwu_func_t pfn)
+psa_status_t tfm_firmware_update_service_sfn(const psa_msg_t *msg)
{
- psa_status_t status;
-
- status = psa_get(signal, &msg);
- if (status != PSA_SUCCESS) {
- return;
- }
-
- switch (msg.type) {
- case PSA_IPC_CONNECT:
- psa_reply(msg.handle, PSA_SUCCESS);
- break;
- case PSA_IPC_CALL:
- status = pfn();
- psa_reply(msg.handle, status);
- break;
- case PSA_IPC_DISCONNECT:
- psa_reply(msg.handle, PSA_SUCCESS);
- break;
+ switch (msg->type) {
+ case TFM_FWU_START:
+ return tfm_fwu_start(msg);
+ case TFM_FWU_WRITE:
+ return tfm_fwu_write(msg);
+ case TFM_FWU_FINISH:
+ return tfm_fwu_finish(msg);
+ case TFM_FWU_INSTALL:
+ return tfm_fwu_install();
+ case TFM_FWU_CANCEL:
+ return tfm_fwu_cancel(msg);
+ case TFM_FWU_CLEAN:
+ return tfm_fwu_clean(msg);
+ case TFM_FWU_QUERY:
+ return tfm_fwu_query(msg);
+ case TFM_FWU_REQUEST_REBOOT:
+ return tfm_fwu_request_reboot();
+ case TFM_FWU_ACCEPT:
+ return tfm_fwu_accept();
+ case TFM_FWU_REJECT:
+ return tfm_fwu_reject(msg);
default:
- psa_panic();
+ return PSA_ERROR_NOT_SUPPORTED;
}
}
-#endif
-psa_status_t tfm_fwu_init(void)
+psa_status_t tfm_fwu_entry(void)
{
-#ifdef TFM_PSA_API
- psa_signal_t signals = 0;
-
if (fwu_bootloader_init() != 0) {
- psa_panic();
- }
-
- while (1) {
- signals = psa_wait(PSA_WAIT_ANY, PSA_BLOCK);
- if (signals & TFM_FWU_WRITE_SIGNAL) {
- fwu_signal_handle(TFM_FWU_WRITE_SIGNAL, tfm_fwu_write_ipc);
- } else if (signals & TFM_FWU_INSTALL_SIGNAL) {
- fwu_signal_handle(TFM_FWU_INSTALL_SIGNAL, tfm_fwu_install_ipc);
- } else if (signals & TFM_FWU_ABORT_SIGNAL) {
- fwu_signal_handle(TFM_FWU_ABORT_SIGNAL, tfm_fwu_abort_ipc);
- } else if (signals & TFM_FWU_QUERY_SIGNAL) {
- fwu_signal_handle(TFM_FWU_QUERY_SIGNAL, tfm_fwu_query_ipc);
- } else if (signals & TFM_FWU_REQUEST_REBOOT_SIGNAL) {
- fwu_signal_handle(TFM_FWU_REQUEST_REBOOT_SIGNAL,
- tfm_fwu_request_reboot_ipc);
- } else if (signals & TFM_FWU_ACCEPT_SIGNAL) {
- fwu_signal_handle(TFM_FWU_ACCEPT_SIGNAL, tfm_fwu_accept_ipc);
- } else {
- psa_panic();
- }
+ return PSA_ERROR_GENERIC_ERROR;
}
-#else
- return fwu_bootloader_init();
-#endif
+ return PSA_SUCCESS;
}