From 0ec3ac60d86b75d132e7a63fc09ea47e67f90bbd Mon Sep 17 00:00:00 2001 From: Manish V Badarkhe Date: Sun, 20 Jun 2021 20:35:25 +0100 Subject: [PATCH] feat(fwu): add FWU driver Implemented FWU metadata load and verification APIs. Also, exported below APIs to the platform: 1. fwu_init - Load FWU metadata in a structure. Also, set the addresses of updated components in I/O policy 2. fwu_is_trial_run_state - To detect trial run or regular run state Change-Id: I67eeabb52d9275ac83be635306997b7c353727cd Signed-off-by: Manish V Badarkhe --- drivers/fwu/fwu.c | 187 ++++++++++++++++++ drivers/fwu/fwu.mk | 11 ++ include/drivers/fwu/fwu.h | 15 ++ include/export/common/tbbr/tbbr_img_def_exp.h | 14 +- 4 files changed, 225 insertions(+), 2 deletions(-) create mode 100644 drivers/fwu/fwu.c create mode 100644 drivers/fwu/fwu.mk create mode 100644 include/drivers/fwu/fwu.h diff --git a/drivers/fwu/fwu.c b/drivers/fwu/fwu.c new file mode 100644 index 000000000..f155519af --- /dev/null +++ b/drivers/fwu/fwu.c @@ -0,0 +1,187 @@ +/* + * Copyright (c) 2021, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include +#include +#include +#include +#include +#include + +#include + +/* + * Assert that crc_32 is the first member of fwu_metadata structure. + * It avoids accessing data outside of the metadata structure during + * CRC32 computation if the crc_32 field gets moved due the structure + * member(s) addition in the future. + */ +CASSERT((offsetof(struct fwu_metadata, crc_32) == 0), + crc_32_must_be_first_member_of_structure); + +static struct fwu_metadata metadata; +static bool is_fwu_initialized; + +/******************************************************************************* + * Compute CRC32 of the FWU metadata, and check it against the CRC32 value + * present in the FWU metadata. + * + * return -1 on error, otherwise 0 + ******************************************************************************/ +static int fwu_metadata_crc_check(void) +{ + unsigned char *data = (unsigned char *)&metadata; + + uint32_t calc_crc = hw_crc32(0U, data + sizeof(metadata.crc_32), + (sizeof(metadata) - + sizeof(metadata.crc_32))); + + if (metadata.crc_32 != calc_crc) { + return -1; + } + + return 0; +} + +/******************************************************************************* + * Check the sanity of FWU metadata. + * + * return -1 on error, otherwise 0 + ******************************************************************************/ +static int fwu_metadata_sanity_check(void) +{ + /* ToDo: add more conditions for sanity check */ + if ((metadata.active_index >= NR_OF_FW_BANKS) || + (metadata.previous_active_index >= NR_OF_FW_BANKS)) { + return -1; + } + + return 0; +} + +/******************************************************************************* + * Verify and load specified FWU metadata image to local FWU metadata structure. + * + * @image_id: FWU metadata image id (either FWU_METADATA_IMAGE_ID or + * BKUP_FWU_METADATA_IMAGE_ID) + * + * return a negative value on error, otherwise 0 + ******************************************************************************/ +static int fwu_metadata_load(unsigned int image_id) +{ + int result; + uintptr_t dev_handle, image_handle, image_spec; + size_t bytes_read; + + assert((image_id == FWU_METADATA_IMAGE_ID) || + (image_id == BKUP_FWU_METADATA_IMAGE_ID)); + + result = plat_fwu_set_metadata_image_source(image_id, + &dev_handle, + &image_spec); + if (result != 0) { + WARN("Failed to set reference to image id=%u (%i)\n", + image_id, result); + return result; + } + + result = io_open(dev_handle, image_spec, &image_handle); + if (result != 0) { + WARN("Failed to load image id id=%u (%i)\n", + image_id, result); + return result; + } + + result = io_read(image_handle, (uintptr_t)&metadata, + sizeof(struct fwu_metadata), &bytes_read); + + if (result != 0) { + WARN("Failed to read image id=%u (%i)\n", image_id, result); + goto exit; + } + + if (sizeof(struct fwu_metadata) != bytes_read) { + /* return -1 in case of partial/no read */ + result = -1; + WARN("Read bytes (%zu) instead of expected (%zu) bytes\n", + bytes_read, sizeof(struct fwu_metadata)); + goto exit; + } + + /* sanity check on loaded parameters */ + result = fwu_metadata_sanity_check(); + if (result != 0) { + WARN("Sanity %s\n", "check failed on FWU metadata"); + goto exit; + } + + /* CRC check on loaded parameters */ + result = fwu_metadata_crc_check(); + if (result != 0) { + WARN("CRC %s\n", "check failed on FWU metadata"); + } + +exit: + (void)io_close(image_handle); + + return result; +} + +/******************************************************************************* + * The system runs in the trial run state if any of the images in the active + * firmware bank has not been accepted yet. + * + * Returns true if the system is running in the trial state. + ******************************************************************************/ +bool fwu_is_trial_run_state(void) +{ + bool trial_run = false; + + assert(is_fwu_initialized == true); + + for (unsigned int i = 0U; i < NR_OF_IMAGES_IN_FW_BANK; i++) { + struct fwu_image_entry *entry = &metadata.img_entry[i]; + struct fwu_image_properties *img_props = + &entry->img_props[metadata.active_index]; + if (img_props->accepted == 0) { + trial_run = true; + break; + } + } + + return trial_run; +} + +/******************************************************************************* + * Load verified copy of FWU metadata image kept in the platform NV storage + * into local FWU metadata structure. + * Also, update platform I/O policies with the offset address and length of + * firmware-updated images kept in the platform NV storage. + ******************************************************************************/ +void fwu_init(void) +{ + /* Load FWU metadata which will be used to load the images in the + * active bank as per PSA FWU specification + */ + int result = fwu_metadata_load(FWU_METADATA_IMAGE_ID); + + if (result != 0) { + WARN("loading of FWU-Metadata failed, " + "using Bkup-FWU-Metadata\n"); + + result = fwu_metadata_load(BKUP_FWU_METADATA_IMAGE_ID); + if (result != 0) { + ERROR("loading of Bkup-FWU-Metadata failed\n"); + panic(); + } + } + + plat_fwu_set_images_source(&metadata); + + is_fwu_initialized = true; +} diff --git a/drivers/fwu/fwu.mk b/drivers/fwu/fwu.mk new file mode 100644 index 000000000..f4452e03b --- /dev/null +++ b/drivers/fwu/fwu.mk @@ -0,0 +1,11 @@ +# +# Copyright (c) 2021, Arm Limited. All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause +# + +FWU_SRC_DIR := drivers/fwu/ + +FWU_SRCS := ${FWU_SRC_DIR}fwu.c + +BL2_SOURCES += ${FWU_SRCS} diff --git a/include/drivers/fwu/fwu.h b/include/drivers/fwu/fwu.h new file mode 100644 index 000000000..ae06da98f --- /dev/null +++ b/include/drivers/fwu/fwu.h @@ -0,0 +1,15 @@ +/* + * Copyright (c) 2021, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef FWU_H +#define FWU_H + +#include + +void fwu_init(void); +bool fwu_is_trial_run_state(void); + +#endif /* FWU_H */ diff --git a/include/export/common/tbbr/tbbr_img_def_exp.h b/include/export/common/tbbr/tbbr_img_def_exp.h index 18f012513..2623c7599 100644 --- a/include/export/common/tbbr/tbbr_img_def_exp.h +++ b/include/export/common/tbbr/tbbr_img_def_exp.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019-2020, ARM Limited and Contributors. All rights reserved. + * Copyright (c) 2019-2021, ARM Limited and Contributors. All rights reserved. * * SPDX-License-Identifier: BSD-3-Clause */ @@ -91,7 +91,17 @@ /* FW_CONFIG */ #define FW_CONFIG_ID U(31) +/* + * Primary FWU metadata image ID + */ +#define FWU_METADATA_IMAGE_ID U(32) + +/* + * Backup FWU metadata image ID + */ +#define BKUP_FWU_METADATA_IMAGE_ID U(33) + /* Max Images */ -#define MAX_IMAGE_IDS U(32) +#define MAX_IMAGE_IDS U(34) #endif /* ARM_TRUSTED_FIRMWARE_EXPORT_COMMON_TBBR_TBBR_IMG_DEF_EXP_H */