summaryrefslogtreecommitdiff
path: root/bl1
diff options
context:
space:
mode:
Diffstat (limited to 'bl1')
-rw-r--r--bl1/bl1_fwu.c61
1 files changed, 61 insertions, 0 deletions
diff --git a/bl1/bl1_fwu.c b/bl1/bl1_fwu.c
index 43bb4d2b..205ea922 100644
--- a/bl1/bl1_fwu.c
+++ b/bl1/bl1_fwu.c
@@ -40,6 +40,8 @@ static register_t bl1_fwu_image_resume(register_t image_param,
unsigned int flags);
static int bl1_fwu_sec_image_done(void **handle,
unsigned int flags);
+static int bl1_fwu_image_reset(unsigned int image_id,
+ unsigned int flags);
__dead2 static void bl1_fwu_done(void *client_cookie, void *reserved);
/*
@@ -47,6 +49,9 @@ __dead2 static void bl1_fwu_done(void *client_cookie, void *reserved);
*/
static unsigned int sec_exec_image_id = INVALID_IMAGE_ID;
+/* Authentication status of each image. */
+extern unsigned int auth_img_flags[];
+
void cm_set_next_context(void *cpu_context);
/*******************************************************************************
@@ -78,6 +83,9 @@ register_t bl1_fwu_smc_handler(unsigned int smc_fid,
case FWU_SMC_SEC_IMAGE_DONE:
SMC_RET1(handle, bl1_fwu_sec_image_done(&handle, flags));
+ case FWU_SMC_IMAGE_RESET:
+ SMC_RET1(handle, bl1_fwu_image_reset(x1, flags));
+
case FWU_SMC_UPDATE_DONE:
bl1_fwu_done((void *)x1, NULL);
/* We should never return from bl1_fwu_done() */
@@ -666,3 +674,56 @@ __dead2 static void bl1_fwu_done(void *client_cookie, void *reserved)
bl1_plat_fwu_done(client_cookie, reserved);
assert(0);
}
+
+/*******************************************************************************
+ * This function resets an image to IMAGE_STATE_RESET. It fails if the image is
+ * being executed.
+ ******************************************************************************/
+static int bl1_fwu_image_reset(unsigned int image_id, unsigned int flags)
+{
+ image_desc_t *image_desc = bl1_plat_get_image_desc(image_id);
+
+ if ((!image_desc) || (GET_SECURITY_STATE(flags) == SECURE)) {
+ WARN("BL1-FWU: Reset not allowed due to invalid args\n");
+ return -EPERM;
+ }
+
+ switch (image_desc->state) {
+
+ case IMAGE_STATE_RESET:
+ /* Nothing to do. */
+ break;
+
+ case IMAGE_STATE_INTERRUPTED:
+ case IMAGE_STATE_AUTHENTICATED:
+ case IMAGE_STATE_COPIED:
+ case IMAGE_STATE_COPYING:
+
+ if (bl1_fwu_remove_loaded_id(image_id)) {
+ WARN("BL1-FWU: Image reset couldn't find the image ID\n");
+ return -EPERM;
+ }
+
+ /* Clear the memory.*/
+ zero_normalmem((void *)image_desc->image_info.image_base,
+ image_desc->copied_size);
+ flush_dcache_range(image_desc->image_info.image_base,
+ image_desc->copied_size);
+
+ /* Reset status variables */
+ image_desc->copied_size = 0;
+ image_desc->image_info.image_size = 0;
+ image_desc->state = IMAGE_STATE_RESET;
+
+ /* Clear authentication state */
+ auth_img_flags[image_id] = 0;
+
+ break;
+
+ case IMAGE_STATE_EXECUTED:
+ default:
+ assert(0);
+ }
+
+ return 0;
+}