1*91f16700Schasinglulu /* 2*91f16700Schasinglulu * Copyright (c) 2021-2022, Arm Limited. All rights reserved. 3*91f16700Schasinglulu * 4*91f16700Schasinglulu * SPDX-License-Identifier: BSD-3-Clause 5*91f16700Schasinglulu */ 6*91f16700Schasinglulu 7*91f16700Schasinglulu #include <assert.h> 8*91f16700Schasinglulu 9*91f16700Schasinglulu #include <common/debug.h> 10*91f16700Schasinglulu #include <common/tf_crc32.h> 11*91f16700Schasinglulu #include <common/tbbr/tbbr_img_def.h> 12*91f16700Schasinglulu #include <drivers/fwu/fwu.h> 13*91f16700Schasinglulu #include <drivers/fwu/fwu_metadata.h> 14*91f16700Schasinglulu #include <drivers/io/io_storage.h> 15*91f16700Schasinglulu 16*91f16700Schasinglulu #include <plat/common/platform.h> 17*91f16700Schasinglulu 18*91f16700Schasinglulu /* 19*91f16700Schasinglulu * Assert that crc_32 is the first member of fwu_metadata structure. 20*91f16700Schasinglulu * It avoids accessing data outside of the metadata structure during 21*91f16700Schasinglulu * CRC32 computation if the crc_32 field gets moved due the structure 22*91f16700Schasinglulu * member(s) addition in the future. 23*91f16700Schasinglulu */ 24*91f16700Schasinglulu CASSERT((offsetof(struct fwu_metadata, crc_32) == 0), 25*91f16700Schasinglulu crc_32_must_be_first_member_of_structure); 26*91f16700Schasinglulu 27*91f16700Schasinglulu static struct fwu_metadata metadata; 28*91f16700Schasinglulu static bool is_metadata_initialized __unused; 29*91f16700Schasinglulu 30*91f16700Schasinglulu /******************************************************************************* 31*91f16700Schasinglulu * Compute CRC32 of the FWU metadata, and check it against the CRC32 value 32*91f16700Schasinglulu * present in the FWU metadata. 33*91f16700Schasinglulu * 34*91f16700Schasinglulu * return -1 on error, otherwise 0 35*91f16700Schasinglulu ******************************************************************************/ 36*91f16700Schasinglulu static int fwu_metadata_crc_check(void) 37*91f16700Schasinglulu { 38*91f16700Schasinglulu unsigned char *data = (unsigned char *)&metadata; 39*91f16700Schasinglulu 40*91f16700Schasinglulu uint32_t calc_crc = tf_crc32(0U, data + sizeof(metadata.crc_32), 41*91f16700Schasinglulu (sizeof(metadata) - 42*91f16700Schasinglulu sizeof(metadata.crc_32))); 43*91f16700Schasinglulu 44*91f16700Schasinglulu if (metadata.crc_32 != calc_crc) { 45*91f16700Schasinglulu return -1; 46*91f16700Schasinglulu } 47*91f16700Schasinglulu 48*91f16700Schasinglulu return 0; 49*91f16700Schasinglulu } 50*91f16700Schasinglulu 51*91f16700Schasinglulu /******************************************************************************* 52*91f16700Schasinglulu * Check the sanity of FWU metadata. 53*91f16700Schasinglulu * 54*91f16700Schasinglulu * return -1 on error, otherwise 0 55*91f16700Schasinglulu ******************************************************************************/ 56*91f16700Schasinglulu static int fwu_metadata_sanity_check(void) 57*91f16700Schasinglulu { 58*91f16700Schasinglulu /* ToDo: add more conditions for sanity check */ 59*91f16700Schasinglulu if ((metadata.active_index >= NR_OF_FW_BANKS) || 60*91f16700Schasinglulu (metadata.previous_active_index >= NR_OF_FW_BANKS)) { 61*91f16700Schasinglulu return -1; 62*91f16700Schasinglulu } 63*91f16700Schasinglulu 64*91f16700Schasinglulu return 0; 65*91f16700Schasinglulu } 66*91f16700Schasinglulu 67*91f16700Schasinglulu /******************************************************************************* 68*91f16700Schasinglulu * Verify and load specified FWU metadata image to local FWU metadata structure. 69*91f16700Schasinglulu * 70*91f16700Schasinglulu * @image_id: FWU metadata image id (either FWU_METADATA_IMAGE_ID or 71*91f16700Schasinglulu * BKUP_FWU_METADATA_IMAGE_ID) 72*91f16700Schasinglulu * 73*91f16700Schasinglulu * return a negative value on error, otherwise 0 74*91f16700Schasinglulu ******************************************************************************/ 75*91f16700Schasinglulu static int fwu_metadata_load(unsigned int image_id) 76*91f16700Schasinglulu { 77*91f16700Schasinglulu int result; 78*91f16700Schasinglulu uintptr_t dev_handle, image_handle, image_spec; 79*91f16700Schasinglulu size_t bytes_read; 80*91f16700Schasinglulu 81*91f16700Schasinglulu assert((image_id == FWU_METADATA_IMAGE_ID) || 82*91f16700Schasinglulu (image_id == BKUP_FWU_METADATA_IMAGE_ID)); 83*91f16700Schasinglulu 84*91f16700Schasinglulu result = plat_fwu_set_metadata_image_source(image_id, 85*91f16700Schasinglulu &dev_handle, 86*91f16700Schasinglulu &image_spec); 87*91f16700Schasinglulu if (result != 0) { 88*91f16700Schasinglulu WARN("Failed to set reference to image id=%u (%i)\n", 89*91f16700Schasinglulu image_id, result); 90*91f16700Schasinglulu return result; 91*91f16700Schasinglulu } 92*91f16700Schasinglulu 93*91f16700Schasinglulu result = io_open(dev_handle, image_spec, &image_handle); 94*91f16700Schasinglulu if (result != 0) { 95*91f16700Schasinglulu WARN("Failed to load image id id=%u (%i)\n", 96*91f16700Schasinglulu image_id, result); 97*91f16700Schasinglulu return result; 98*91f16700Schasinglulu } 99*91f16700Schasinglulu 100*91f16700Schasinglulu result = io_read(image_handle, (uintptr_t)&metadata, 101*91f16700Schasinglulu sizeof(struct fwu_metadata), &bytes_read); 102*91f16700Schasinglulu 103*91f16700Schasinglulu if (result != 0) { 104*91f16700Schasinglulu WARN("Failed to read image id=%u (%i)\n", image_id, result); 105*91f16700Schasinglulu goto exit; 106*91f16700Schasinglulu } 107*91f16700Schasinglulu 108*91f16700Schasinglulu if (sizeof(struct fwu_metadata) != bytes_read) { 109*91f16700Schasinglulu /* return -1 in case of partial/no read */ 110*91f16700Schasinglulu result = -1; 111*91f16700Schasinglulu WARN("Read bytes (%zu) instead of expected (%zu) bytes\n", 112*91f16700Schasinglulu bytes_read, sizeof(struct fwu_metadata)); 113*91f16700Schasinglulu goto exit; 114*91f16700Schasinglulu } 115*91f16700Schasinglulu 116*91f16700Schasinglulu /* sanity check on loaded parameters */ 117*91f16700Schasinglulu result = fwu_metadata_sanity_check(); 118*91f16700Schasinglulu if (result != 0) { 119*91f16700Schasinglulu WARN("Sanity %s\n", "check failed on FWU metadata"); 120*91f16700Schasinglulu goto exit; 121*91f16700Schasinglulu } 122*91f16700Schasinglulu 123*91f16700Schasinglulu /* CRC check on loaded parameters */ 124*91f16700Schasinglulu result = fwu_metadata_crc_check(); 125*91f16700Schasinglulu if (result != 0) { 126*91f16700Schasinglulu WARN("CRC %s\n", "check failed on FWU metadata"); 127*91f16700Schasinglulu } 128*91f16700Schasinglulu 129*91f16700Schasinglulu exit: 130*91f16700Schasinglulu (void)io_close(image_handle); 131*91f16700Schasinglulu 132*91f16700Schasinglulu return result; 133*91f16700Schasinglulu } 134*91f16700Schasinglulu 135*91f16700Schasinglulu /******************************************************************************* 136*91f16700Schasinglulu * The system runs in the trial run state if any of the images in the active 137*91f16700Schasinglulu * firmware bank has not been accepted yet. 138*91f16700Schasinglulu * 139*91f16700Schasinglulu * Returns true if the system is running in the trial state. 140*91f16700Schasinglulu ******************************************************************************/ 141*91f16700Schasinglulu bool fwu_is_trial_run_state(void) 142*91f16700Schasinglulu { 143*91f16700Schasinglulu bool trial_run = false; 144*91f16700Schasinglulu 145*91f16700Schasinglulu assert(is_metadata_initialized); 146*91f16700Schasinglulu 147*91f16700Schasinglulu for (unsigned int i = 0U; i < NR_OF_IMAGES_IN_FW_BANK; i++) { 148*91f16700Schasinglulu struct fwu_image_entry *entry = &metadata.img_entry[i]; 149*91f16700Schasinglulu struct fwu_image_properties *img_props = 150*91f16700Schasinglulu &entry->img_props[metadata.active_index]; 151*91f16700Schasinglulu if (img_props->accepted == 0) { 152*91f16700Schasinglulu trial_run = true; 153*91f16700Schasinglulu break; 154*91f16700Schasinglulu } 155*91f16700Schasinglulu } 156*91f16700Schasinglulu 157*91f16700Schasinglulu return trial_run; 158*91f16700Schasinglulu } 159*91f16700Schasinglulu 160*91f16700Schasinglulu const struct fwu_metadata *fwu_get_metadata(void) 161*91f16700Schasinglulu { 162*91f16700Schasinglulu assert(is_metadata_initialized); 163*91f16700Schasinglulu 164*91f16700Schasinglulu return &metadata; 165*91f16700Schasinglulu } 166*91f16700Schasinglulu 167*91f16700Schasinglulu /******************************************************************************* 168*91f16700Schasinglulu * Load verified copy of FWU metadata image kept in the platform NV storage 169*91f16700Schasinglulu * into local FWU metadata structure. 170*91f16700Schasinglulu * Also, update platform I/O policies with the offset address and length of 171*91f16700Schasinglulu * firmware-updated images kept in the platform NV storage. 172*91f16700Schasinglulu ******************************************************************************/ 173*91f16700Schasinglulu void fwu_init(void) 174*91f16700Schasinglulu { 175*91f16700Schasinglulu /* Load FWU metadata which will be used to load the images in the 176*91f16700Schasinglulu * active bank as per PSA FWU specification 177*91f16700Schasinglulu */ 178*91f16700Schasinglulu int result = fwu_metadata_load(FWU_METADATA_IMAGE_ID); 179*91f16700Schasinglulu 180*91f16700Schasinglulu if (result != 0) { 181*91f16700Schasinglulu WARN("loading of FWU-Metadata failed, " 182*91f16700Schasinglulu "using Bkup-FWU-Metadata\n"); 183*91f16700Schasinglulu 184*91f16700Schasinglulu result = fwu_metadata_load(BKUP_FWU_METADATA_IMAGE_ID); 185*91f16700Schasinglulu if (result != 0) { 186*91f16700Schasinglulu ERROR("loading of Bkup-FWU-Metadata failed\n"); 187*91f16700Schasinglulu panic(); 188*91f16700Schasinglulu } 189*91f16700Schasinglulu } 190*91f16700Schasinglulu 191*91f16700Schasinglulu is_metadata_initialized = true; 192*91f16700Schasinglulu 193*91f16700Schasinglulu plat_fwu_set_images_source(&metadata); 194*91f16700Schasinglulu } 195