Simulated product dispenser
Fork of mbed-cloud-workshop-connect-HTS221 by
arm_uc_pal_flashiap_implementation.c
00001 // ---------------------------------------------------------------------------- 00002 // Copyright 2016-2017 ARM Ltd. 00003 // 00004 // SPDX-License-Identifier: Apache-2.0 00005 // 00006 // Licensed under the Apache License, Version 2.0 (the "License"); 00007 // you may not use this file except in compliance with the License. 00008 // You may obtain a copy of the License at 00009 // 00010 // http://www.apache.org/licenses/LICENSE-2.0 00011 // 00012 // Unless required by applicable law or agreed to in writing, software 00013 // distributed under the License is distributed on an "AS IS" BASIS, 00014 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 00015 // See the License for the specific language governing permissions and 00016 // limitations under the License. 00017 // ---------------------------------------------------------------------------- 00018 00019 #if defined(TARGET_LIKE_MBED) 00020 00021 #define __STDC_FORMAT_MACROS 00022 00023 #include "update-client-pal-flashiap/arm_uc_pal_flashiap.h" 00024 00025 #include "update-client-pal-flashiap/arm_uc_pal_flashiap_platform.h" 00026 00027 #include "update-client-common/arm_uc_metadata_header_v2.h" 00028 #include "update-client-common/arm_uc_types.h" 00029 #include "update-client-common/arm_uc_utilities.h" 00030 00031 #define TRACE_GROUP "UCPI" 00032 #include "update-client-common/arm_uc_trace.h" 00033 #include <inttypes.h> 00034 #include <stddef.h> 00035 00036 #ifndef MBED_CONF_UPDATE_CLIENT_APPLICATION_DETAILS 00037 #define MBED_CONF_UPDATE_CLIENT_APPLICATION_DETAILS 0 00038 #endif 00039 00040 #ifndef MBED_CONF_UPDATE_CLIENT_BOOTLOADER_DETAILS 00041 #define MBED_CONF_UPDATE_CLIENT_BOOTLOADER_DETAILS 0 00042 #endif 00043 00044 #ifndef MBED_CONF_UPDATE_CLIENT_STORAGE_ADDRESS 00045 #define MBED_CONF_UPDATE_CLIENT_STORAGE_ADDRESS 0 00046 #endif 00047 00048 #ifndef MBED_CONF_UPDATE_CLIENT_STORAGE_PAGE 00049 #define MBED_CONF_UPDATE_CLIENT_STORAGE_PAGE 1 00050 #endif 00051 00052 #ifndef MBED_CONF_UPDATE_CLIENT_STORAGE_LOCATIONS 00053 #define MBED_CONF_UPDATE_CLIENT_STORAGE_LOCATIONS 1 00054 #endif 00055 00056 /* consistency check */ 00057 #if (MBED_CONF_UPDATE_CLIENT_STORAGE_PAGE == 0) 00058 #error Update client storage page cannot be zero. 00059 #endif 00060 00061 #if (MBED_CONF_UPDATE_CLIENT_STORAGE_LOCATIONS == 0) 00062 #error Update client storage locations must be at least 1. 00063 #endif 00064 00065 /* Check that the statically allocated buffers are aligned with the block size */ 00066 #define ARM_UC_PAL_ONE_BUFFER (ARM_UC_BUFFER_SIZE / 2) 00067 #define ARM_UC_PAL_PAGES (ARM_UC_PAL_ONE_BUFFER / MBED_CONF_UPDATE_CLIENT_STORAGE_PAGE) 00068 00069 #if !((ARM_UC_PAL_PAGES * MBED_CONF_UPDATE_CLIENT_STORAGE_PAGE) == ARM_UC_PAL_ONE_BUFFER) 00070 #error Update client buffer must be divisible by the block page size 00071 #endif 00072 00073 /* Use internal header format because we are using internal flash and 00074 is assumed to be trusted */ 00075 #define ARM_UC_PAL_HEADER_SIZE (uint32_t) ARM_UC_INTERNAL_HEADER_SIZE_V2 00076 00077 static uint64_t arm_uc_pal_flashiap_firmware_size = 0; 00078 00079 static void (*arm_uc_pal_flashiap_callback)(uint32_t) = NULL; 00080 00081 static void arm_uc_pal_flashiap_signal_internal(uint32_t event) 00082 { 00083 if (arm_uc_pal_flashiap_callback) 00084 { 00085 arm_uc_pal_flashiap_callback(event); 00086 } 00087 } 00088 00089 /** 00090 * @brief Align address up/down to sector boundary 00091 * 00092 * @param addr The address that need to be rounded up 00093 * @param round_down if the value is 1, will align down to sector 00094 boundary otherwise align up. 00095 * @return Returns the address aligned to sector boundary 00096 */ 00097 static uint32_t arm_uc_pal_flashiap_align_to_sector(uint32_t addr, int8_t round_down) 00098 { 00099 uint32_t sector_start_addr = arm_uc_flashiap_get_flash_start(); 00100 00101 /* check the address is pointing to internal flash */ 00102 if ((addr > sector_start_addr + arm_uc_flashiap_get_flash_size()) || 00103 (addr < sector_start_addr)) 00104 { 00105 return ARM_UC_FLASH_INVALID_SIZE; 00106 } 00107 00108 /* add sectors from start of flash until exeeced the required address 00109 we cannot assume uniform sector size as in some mcu sectors have 00110 drastically different sizes */ 00111 uint32_t sector_size = ARM_UC_FLASH_INVALID_SIZE; 00112 while(sector_start_addr < addr) 00113 { 00114 sector_size = arm_uc_flashiap_get_sector_size(sector_start_addr); 00115 if (sector_size != ARM_UC_FLASH_INVALID_SIZE) 00116 { 00117 sector_start_addr += sector_size; 00118 } 00119 else 00120 { 00121 return ARM_UC_FLASH_INVALID_SIZE; 00122 } 00123 } 00124 00125 /* if round down to nearest section, remove the last sector from addr */ 00126 if (round_down != 0 && sector_start_addr > addr) 00127 { 00128 sector_start_addr -= sector_size; 00129 } 00130 00131 return sector_start_addr; 00132 } 00133 00134 /** 00135 * @brief Round size up to nearest page 00136 * 00137 * @param size The size that need to be rounded up 00138 * @return Returns the size rounded up to the nearest page 00139 */ 00140 static uint32_t arm_uc_pal_flashiap_round_up_to_page_size(uint32_t size) 00141 { 00142 uint32_t page_size = arm_uc_flashiap_get_page_size(); 00143 00144 if (size != 0) 00145 { 00146 size = ((size - 1)/page_size + 1) * page_size; 00147 } 00148 00149 return size; 00150 } 00151 00152 /** 00153 * @brief Get the physicl slot address and size given slot_id 00154 * 00155 * @param slot_id Storage location ID. 00156 * @param slot_addr the slot address is returned in this pointer 00157 * @param slot_size the slot size is returned in this pointer 00158 * @return Returns ERR_NONE on success. 00159 * Returns ERR_INVALID_PARAMETER on error. 00160 */ 00161 static arm_uc_error_t arm_uc_pal_flashiap_get_slot_addr_size(uint32_t slot_id, 00162 uint32_t* slot_addr, 00163 uint32_t* slot_size) 00164 { 00165 arm_uc_error_t result = { .code = ERR_INVALID_PARAMETER }; 00166 /* find the start address of the whole storage area. It needs to be aligned to 00167 sector boundary and we cannot go outside user defined storage area, hence 00168 rounding up to sector boundary */ 00169 uint32_t storage_start_addr = arm_uc_pal_flashiap_align_to_sector( 00170 MBED_CONF_UPDATE_CLIENT_STORAGE_ADDRESS, 0); 00171 /* find the end address of the whole storage area. It needs to be aligned to 00172 sector boundary and we cannot go outside user defined storage area, hence 00173 rounding down to sector boundary */ 00174 uint32_t storage_end_addr = arm_uc_pal_flashiap_align_to_sector( 00175 MBED_CONF_UPDATE_CLIENT_STORAGE_ADDRESS + \ 00176 MBED_CONF_UPDATE_CLIENT_STORAGE_SIZE, 1); 00177 /* find the maximum size each slot can have given the start and end, without 00178 considering the alignment of individual slots */ 00179 uint32_t max_slot_size = (storage_end_addr - storage_start_addr) / \ 00180 MBED_CONF_UPDATE_CLIENT_STORAGE_LOCATIONS; 00181 /* find the start address of slot. It needs to align to sector boundary. We 00182 choose here to round down at each slot boundary */ 00183 uint32_t slot_start_addr = arm_uc_pal_flashiap_align_to_sector( 00184 storage_start_addr + \ 00185 slot_id * max_slot_size, 1); 00186 /* find the end address of the slot, rounding down to sector boundary same as 00187 the slot start address so that we make sure two slot don't overlap */ 00188 uint32_t slot_end_addr = arm_uc_pal_flashiap_align_to_sector( 00189 slot_start_addr + \ 00190 max_slot_size, 1); 00191 00192 /* Any calculation above might result in an invalid address. */ 00193 if ((storage_start_addr == ARM_UC_FLASH_INVALID_SIZE) || 00194 (storage_end_addr == ARM_UC_FLASH_INVALID_SIZE) || 00195 (slot_start_addr == ARM_UC_FLASH_INVALID_SIZE) || 00196 (slot_end_addr == ARM_UC_FLASH_INVALID_SIZE) || 00197 (slot_id >= MBED_CONF_UPDATE_CLIENT_STORAGE_LOCATIONS)) 00198 { 00199 UC_PAAL_ERR_MSG("Aligning fw storage slot to erase sector failed" 00200 " storage_start_addr %" PRIX32 " slot_start_addr %" PRIX32 00201 " max_slot_size %" PRIX32, storage_start_addr, slot_start_addr, 00202 max_slot_size); 00203 *slot_addr = ARM_UC_FLASH_INVALID_SIZE; 00204 *slot_size = ARM_UC_FLASH_INVALID_SIZE; 00205 } 00206 else 00207 { 00208 *slot_addr = slot_start_addr; 00209 *slot_size = slot_end_addr - slot_start_addr; 00210 result.code = ERR_NONE; 00211 } 00212 00213 return result; 00214 } 00215 00216 /** 00217 * @brief Initialise the flash IAP API 00218 * 00219 * @param callback function pointer to the PAAL event handler 00220 * @return Returns ERR_NONE on success. 00221 * Returns ERR_INVALID_PARAMETER on error. 00222 */ 00223 arm_uc_error_t ARM_UC_PAL_FlashIAP_Initialize(void (*callback)(uint32_t)) 00224 { 00225 arm_uc_error_t result = { .code = ERR_INVALID_PARAMETER }; 00226 00227 int32_t status = arm_uc_flashiap_init(); 00228 00229 if (status == ARM_UC_FLASHIAP_SUCCESS) 00230 { 00231 arm_uc_pal_flashiap_callback = callback; 00232 arm_uc_pal_flashiap_signal_internal(ARM_UC_PAAL_EVENT_INITIALIZE_DONE); 00233 00234 result.code = ERR_NONE; 00235 } 00236 00237 return result; 00238 } 00239 00240 /** 00241 * @brief Get maximum number of supported storage locations. 00242 * 00243 * @return Number of storage locations. 00244 */ 00245 uint32_t ARM_UC_PAL_FlashIAP_GetMaxID(void) 00246 { 00247 return MBED_CONF_UPDATE_CLIENT_STORAGE_LOCATIONS; 00248 } 00249 00250 /** 00251 * @brief Prepare the storage layer for a new firmware image. 00252 * @details The storage location is set up to receive an image with 00253 * the details passed in the details struct. 00254 * 00255 * @param slot_id Storage location ID. 00256 * @param details Pointer to a struct with firmware details. 00257 * @param buffer Temporary buffer for formatting and storing metadata. 00258 * @return Returns ERR_NONE on accept, and signals the event handler with 00259 * either DONE or ERROR when complete. 00260 * Returns ERR_INVALID_PARAMETER on reject, and no signal is sent. 00261 */ 00262 arm_uc_error_t ARM_UC_PAL_FlashIAP_Prepare(uint32_t slot_id, 00263 const arm_uc_firmware_details_t* details, 00264 arm_uc_buffer_t* buffer) 00265 { 00266 UC_PAAL_TRACE("ARM_UC_PAL_FlashIAP_Prepare slot_id %" PRIu32 " details %p buffer %p", 00267 slot_id, details, buffer); 00268 00269 arm_uc_error_t result = { .code = ERR_INVALID_PARAMETER }; 00270 uint32_t slot_addr = ARM_UC_FLASH_INVALID_SIZE; 00271 uint32_t slot_size = ARM_UC_FLASH_INVALID_SIZE; 00272 uint32_t erase_size = ARM_UC_FLASH_INVALID_SIZE; 00273 00274 /* validate input */ 00275 if (details && buffer && buffer->ptr && \ 00276 slot_id < MBED_CONF_UPDATE_CLIENT_STORAGE_LOCATIONS) 00277 { 00278 UC_PAAL_TRACE("FW size %" PRIu64, details->size); 00279 result.error = ERR_NONE; 00280 } 00281 else 00282 { 00283 UC_PAAL_TRACE("Input validation failed"); 00284 } 00285 00286 /* calculate space for new firmware */ 00287 if (result.error == ERR_NONE) 00288 { 00289 /* find slot start address */ 00290 result = arm_uc_pal_flashiap_get_slot_addr_size(slot_id, &slot_addr, &slot_size); 00291 00292 /* find the amount of space that need to be erased */ 00293 erase_size = arm_uc_pal_flashiap_align_to_sector( 00294 slot_addr + \ 00295 arm_uc_pal_flashiap_round_up_to_page_size(details->size) + \ 00296 arm_uc_pal_flashiap_round_up_to_page_size(ARM_UC_PAL_HEADER_SIZE), 00297 0) - slot_addr; 00298 00299 if ((result.error == ERR_NONE) && (erase_size > slot_size)) 00300 { 00301 result.code = ERR_INVALID_PARAMETER; 00302 UC_PAAL_ERR_MSG("Firmware too large! required %" PRIX32 " available: %" PRIX32, 00303 erase_size, slot_size); 00304 } 00305 } 00306 00307 /* erase space for new firmware */ 00308 if (result.error == ERR_NONE) 00309 { 00310 uint32_t erase_addr = slot_addr; 00311 while (erase_addr < slot_addr + erase_size) 00312 { 00313 uint32_t sector_size = arm_uc_flashiap_get_sector_size(erase_addr); 00314 UC_PAAL_TRACE("erase: addr %" PRIX32 " size %" PRIX32, 00315 erase_addr, sector_size); 00316 if (sector_size != ARM_UC_FLASH_INVALID_SIZE) 00317 { 00318 int32_t status = arm_uc_flashiap_erase(erase_addr, sector_size); 00319 if (status == ARM_UC_FLASHIAP_SUCCESS) 00320 { 00321 erase_addr += sector_size; 00322 } 00323 else 00324 { 00325 UC_PAAL_ERR_MSG("Flash erase failed with status %" PRIi32, status); 00326 result.code = ERR_INVALID_PARAMETER; 00327 break; 00328 } 00329 } 00330 else 00331 { 00332 UC_PAAL_ERR_MSG("Get sector size for addr %" PRIX32 " failed", erase_addr); 00333 result.code = ERR_INVALID_PARAMETER; 00334 break; 00335 } 00336 } 00337 } 00338 00339 /* generate header blob */ 00340 if (result.error == ERR_NONE) 00341 { 00342 result = arm_uc_create_internal_header_v2(details, buffer); 00343 if (result.error != ERR_NONE) 00344 { 00345 UC_PAAL_ERR_MSG("arm_uc_create_internal_header_v2 failed"); 00346 } 00347 } 00348 00349 /* write header blob */ 00350 if (result.error == ERR_NONE) 00351 { 00352 uint32_t hdr_size = arm_uc_pal_flashiap_round_up_to_page_size(ARM_UC_PAL_HEADER_SIZE); 00353 UC_PAAL_TRACE("program: %" PRIX32 " %" PRIX32, 00354 slot_addr, hdr_size); 00355 00356 /* write header */ 00357 int32_t status = arm_uc_flashiap_program((const uint8_t*) buffer->ptr, 00358 slot_addr, 00359 hdr_size); 00360 if (status != ARM_UC_FLASHIAP_SUCCESS) 00361 { 00362 /* set return code */ 00363 result.code = ERR_INVALID_PARAMETER; 00364 } 00365 } 00366 00367 if (result.error == ERR_NONE) 00368 { 00369 /* store firmware size in global */ 00370 arm_uc_pal_flashiap_firmware_size = details->size; 00371 00372 /* signal done */ 00373 arm_uc_pal_flashiap_signal_internal(ARM_UC_PAAL_EVENT_PREPARE_DONE); 00374 } 00375 00376 return result; 00377 } 00378 00379 /** 00380 * @brief Write a fragment to the indicated storage location. 00381 * @details The storage location must have been allocated using the Prepare 00382 * call. The call is expected to write the entire fragment before 00383 * signaling completion. 00384 * 00385 * @param slot_id Storage location ID. 00386 * @param offset Offset in bytes to where the fragment should be written. 00387 * @param buffer Pointer to buffer struct with fragment. 00388 * @return Returns ERR_NONE on accept, and signals the event handler with 00389 * either DONE or ERROR when complete. 00390 * Returns ERR_INVALID_PARAMETER on reject, and no signal is sent. 00391 */ 00392 arm_uc_error_t ARM_UC_PAL_FlashIAP_Write(uint32_t slot_id, 00393 uint32_t offset, 00394 const arm_uc_buffer_t* buffer) 00395 { 00396 /* find slot address and size */ 00397 uint32_t slot_addr = ARM_UC_FLASH_INVALID_SIZE; 00398 uint32_t slot_size = ARM_UC_FLASH_INVALID_SIZE; 00399 arm_uc_error_t result = arm_uc_pal_flashiap_get_slot_addr_size(slot_id, 00400 &slot_addr, 00401 &slot_size); 00402 00403 if (buffer && buffer->ptr && result.error == ERR_NONE) 00404 { 00405 UC_PAAL_TRACE("ARM_UC_PAL_FlashIAP_Write: %p %" PRIX32 " %" PRIX32 " %" PRIX32, 00406 buffer->ptr, buffer->size, slot_addr, offset); 00407 00408 /* set default error */ 00409 result.code = ERR_INVALID_PARAMETER; 00410 00411 /* find physical address of the write */ 00412 uint32_t page_size = arm_uc_flashiap_get_page_size(); 00413 uint32_t hdr_size = arm_uc_pal_flashiap_round_up_to_page_size(ARM_UC_PAL_HEADER_SIZE); 00414 uint32_t physical_address = slot_addr + hdr_size + offset; 00415 uint32_t write_size = buffer->size; 00416 00417 /* if last chunk, pad out to page_size aligned size */ 00418 if ((buffer->size % page_size != 0) && 00419 ((offset + buffer->size) >= arm_uc_pal_flashiap_firmware_size) && 00420 (arm_uc_pal_flashiap_round_up_to_page_size(buffer->size) <= buffer->size_max)) 00421 { 00422 write_size = arm_uc_pal_flashiap_round_up_to_page_size(buffer->size); 00423 } 00424 00425 /* check page alignment of the program address and size */ 00426 if ((write_size % page_size == 0) && (physical_address % page_size == 0)) 00427 { 00428 UC_PAAL_TRACE("programming addr %" PRIX32 " size %" PRIX32, 00429 physical_address, write_size); 00430 int status = arm_uc_flashiap_program((const uint8_t*) buffer->ptr, 00431 physical_address, 00432 write_size); 00433 if (status != ARM_UC_FLASHIAP_SUCCESS) 00434 { 00435 UC_PAAL_ERR_MSG("arm_uc_flashiap_program failed"); 00436 } 00437 else 00438 { 00439 result.code = ERR_NONE; 00440 arm_uc_pal_flashiap_signal_internal(ARM_UC_PAAL_EVENT_WRITE_DONE); 00441 } 00442 } 00443 else 00444 { 00445 UC_PAAL_ERR_MSG("program size %" PRIX32 " or address %" PRIX32 00446 " not aligned to page size %" PRIX32, buffer->size, 00447 physical_address, page_size); 00448 } 00449 } 00450 else 00451 { 00452 result.code = ERR_INVALID_PARAMETER; 00453 } 00454 00455 return result; 00456 } 00457 00458 /** 00459 * @brief Close storage location for writing and flush pending data. 00460 * 00461 * @param slot_id Storage location ID. 00462 * @return Returns ERR_NONE on accept, and signals the event handler with 00463 * either DONE or ERROR when complete. 00464 * Returns ERR_INVALID_PARAMETER on reject, and no signal is sent. 00465 */ 00466 arm_uc_error_t ARM_UC_PAL_FlashIAP_Finalize(uint32_t slot_id) 00467 { 00468 arm_uc_error_t result = { .code = ERR_NONE }; 00469 00470 UC_PAAL_TRACE("ARM_UC_PAL_FlashIAP_Finalize"); 00471 00472 arm_uc_pal_flashiap_signal_internal(ARM_UC_PAAL_EVENT_FINALIZE_DONE); 00473 00474 return result; 00475 } 00476 00477 /** 00478 * @brief Read a fragment from the indicated storage location. 00479 * @details The function will read until the buffer is full or the end of 00480 * the storage location has been reached. The actual amount of 00481 * bytes read is set in the buffer struct. 00482 * 00483 * @param slot_id Storage location ID. 00484 * @param offset Offset in bytes to read from. 00485 * @param buffer Pointer to buffer struct to store fragment. buffer->size 00486 * contains the intended read size. 00487 * @return Returns ERR_NONE on accept, and signals the event handler with 00488 * either DONE or ERROR when complete. 00489 * Returns ERR_INVALID_PARAMETER on reject, and no signal is sent. 00490 * buffer->size contains actual bytes read on return. 00491 */ 00492 arm_uc_error_t ARM_UC_PAL_FlashIAP_Read(uint32_t slot_id, 00493 uint32_t offset, 00494 arm_uc_buffer_t* buffer) 00495 { 00496 /* find slot address and size */ 00497 uint32_t slot_addr = ARM_UC_FLASH_INVALID_SIZE; 00498 uint32_t slot_size = ARM_UC_FLASH_INVALID_SIZE; 00499 arm_uc_error_t result = arm_uc_pal_flashiap_get_slot_addr_size(slot_id, 00500 &slot_addr, 00501 &slot_size); 00502 00503 if (buffer && buffer->ptr && result.error == ERR_NONE) 00504 { 00505 UC_PAAL_TRACE("ARM_UC_PAL_FlashIAP_Read: %" PRIX32 " %" PRIX32 " %" PRIX32, 00506 slot_id, offset, buffer->size); 00507 00508 /* find physical address of the read */ 00509 uint32_t read_size = buffer->size; 00510 uint32_t hdr_size = arm_uc_pal_flashiap_round_up_to_page_size(ARM_UC_PAL_HEADER_SIZE); 00511 uint32_t physical_address = slot_addr + hdr_size + offset; 00512 00513 UC_PAAL_TRACE("reading addr %" PRIX32 " size %" PRIX32, 00514 physical_address, read_size); 00515 00516 int status = arm_uc_flashiap_read(buffer->ptr, 00517 physical_address, 00518 read_size); 00519 00520 if (status == ARM_UC_FLASHIAP_SUCCESS) 00521 { 00522 result.code = ERR_NONE; 00523 arm_uc_pal_flashiap_signal_internal(ARM_UC_PAAL_EVENT_READ_DONE); 00524 } 00525 else 00526 { 00527 result.code = ERR_INVALID_PARAMETER; 00528 UC_PAAL_ERR_MSG("arm_uc_flashiap_read failed"); 00529 } 00530 } 00531 else 00532 { 00533 result.code = ERR_INVALID_PARAMETER; 00534 } 00535 00536 return result; 00537 } 00538 00539 /** 00540 * @brief Set the firmware image in the slot to be the new active image. 00541 * @details This call is responsible for initiating the process for 00542 * applying a new/different image. Depending on the platform this 00543 * could be: 00544 * * An empty call, if the installer can deduce which slot to 00545 * choose from based on the firmware details. 00546 * * Setting a flag to indicate which slot to use next. 00547 * * Decompressing/decrypting/installing the firmware image on 00548 * top of another. 00549 * 00550 * @param slot_id Storage location ID. 00551 * @return Returns ERR_NONE on accept, and signals the event handler with 00552 * either DONE or ERROR when complete. 00553 * Returns ERR_INVALID_PARAMETER on reject, and no signal is sent. 00554 */ 00555 arm_uc_error_t ARM_UC_PAL_FlashIAP_Activate(uint32_t slot_id) 00556 { 00557 arm_uc_error_t result = { .code = ERR_NONE }; 00558 00559 UC_PAAL_TRACE("ARM_UC_PAL_FlashIAP_Activate"); 00560 00561 arm_uc_pal_flashiap_signal_internal(ARM_UC_PAAL_EVENT_ACTIVATE_DONE); 00562 00563 return result; 00564 } 00565 00566 /** 00567 * @brief Get firmware details for the firmware image in the slot passed. 00568 * @details This call populates the passed details struct with information 00569 * about the firmware image in the slot passed. Only the fields 00570 * marked as supported in the capabilities bitmap will have valid 00571 * values. 00572 * 00573 * @param details Pointer to firmware details struct to be populated. 00574 * @return Returns ERR_NONE on accept, and signals the event handler with 00575 * either DONE or ERROR when complete. 00576 * Returns ERR_INVALID_PARAMETER on reject, and no signal is sent. 00577 */ 00578 arm_uc_error_t ARM_UC_PAL_FlashIAP_GetFirmwareDetails( 00579 uint32_t slot_id, 00580 arm_uc_firmware_details_t* details) 00581 { 00582 UC_PAAL_TRACE("ARM_UC_PAL_FlashIAP_GetFirmwareDetails"); 00583 00584 /* find slot address and size */ 00585 uint32_t slot_addr = ARM_UC_FLASH_INVALID_SIZE; 00586 uint32_t slot_size = ARM_UC_FLASH_INVALID_SIZE; 00587 arm_uc_error_t result = arm_uc_pal_flashiap_get_slot_addr_size(slot_id, 00588 &slot_addr, 00589 &slot_size); 00590 00591 if (details && result.error == ERR_NONE) 00592 { 00593 uint8_t buffer[ARM_UC_PAL_HEADER_SIZE] = { 0 }; 00594 00595 int status = arm_uc_flashiap_read(buffer, 00596 slot_addr, 00597 ARM_UC_PAL_HEADER_SIZE); 00598 00599 if (status == ARM_UC_FLASHIAP_SUCCESS) 00600 { 00601 result = arm_uc_parse_internal_header_v2(buffer, details); 00602 00603 if (result.error == ERR_NONE) 00604 { 00605 /* signal done */ 00606 arm_uc_pal_flashiap_signal_internal(ARM_UC_PAAL_EVENT_GET_FIRMWARE_DETAILS_DONE); 00607 } 00608 else 00609 { 00610 UC_PAAL_ERR_MSG("arm_uc_parse_internal_header_v2 failed"); 00611 } 00612 } 00613 else 00614 { 00615 UC_PAAL_ERR_MSG("arm_uc_flashiap_read failed"); 00616 } 00617 } 00618 00619 return result; 00620 } 00621 00622 /*****************************************************************************/ 00623 00624 arm_uc_error_t ARM_UC_PAL_FlashIAP_GetActiveDetails(arm_uc_firmware_details_t* details) 00625 { 00626 arm_uc_error_t result = { .code = ERR_INVALID_PARAMETER }; 00627 00628 if (details) 00629 { 00630 /* read details from memory if offset is set */ 00631 if (MBED_CONF_UPDATE_CLIENT_APPLICATION_DETAILS) 00632 { 00633 /* set default error code */ 00634 result.code = ERR_NOT_READY; 00635 00636 /* Use flash driver eventhough we are reading from internal flash. 00637 This will make it easier to use with uVisor. 00638 */ 00639 uint8_t version_buffer[8] = { 0 }; 00640 00641 /* read metadata magic and version from flash */ 00642 int rc = arm_uc_flashiap_read(version_buffer, 00643 MBED_CONF_UPDATE_CLIENT_APPLICATION_DETAILS, 00644 8); 00645 00646 if (rc == ARM_UC_FLASHIAP_SUCCESS) 00647 { 00648 /* read out header magic */ 00649 uint32_t headerMagic = arm_uc_parse_uint32(&version_buffer[0]); 00650 00651 /* read out header magic */ 00652 uint32_t headerVersion = arm_uc_parse_uint32(&version_buffer[4]); 00653 00654 /* choose version to decode */ 00655 switch(headerVersion) 00656 { 00657 case ARM_UC_INTERNAL_HEADER_VERSION_V2: 00658 { 00659 result.code = ERR_NONE; 00660 /* Check the header magic */ 00661 if (headerMagic != ARM_UC_INTERNAL_HEADER_MAGIC_V2) 00662 { 00663 UC_PAAL_ERR_MSG("firmware header is v2, but does not contain v2 magic"); 00664 result.code = ERR_NOT_READY; 00665 } 00666 00667 uint8_t read_buffer[ARM_UC_INTERNAL_HEADER_SIZE_V2] = { 0 }; 00668 /* Read the rest of the header */ 00669 if (result.error == ERR_NONE) 00670 { 00671 rc = arm_uc_flashiap_read(read_buffer, 00672 MBED_CONF_UPDATE_CLIENT_APPLICATION_DETAILS, 00673 ARM_UC_INTERNAL_HEADER_SIZE_V2); 00674 if (rc != 0) 00675 { 00676 result.code = ERR_NOT_READY; 00677 UC_PAAL_ERR_MSG("failed to read v2 header"); 00678 } 00679 } 00680 /* Parse the header */ 00681 if (result.error == ERR_NONE) 00682 { 00683 result = arm_uc_parse_internal_header_v2(read_buffer, details); 00684 if (result.error != ERR_NONE) 00685 { 00686 UC_PAAL_ERR_MSG("failed to parse v2 header"); 00687 } 00688 } 00689 break; 00690 } 00691 /* 00692 * Other firmware header versions can be supported here. 00693 */ 00694 default: 00695 { 00696 UC_PAAL_ERR_MSG("unrecognized firmware header version"); 00697 result.code = ERR_NOT_READY; 00698 } 00699 } 00700 } 00701 else 00702 { 00703 UC_PAAL_ERR_MSG("flash read failed"); 00704 } 00705 } 00706 else 00707 { 00708 /* offset not set - zero out struct */ 00709 memset(details, 0, sizeof(arm_uc_firmware_details_t)); 00710 00711 result.code = ERR_NONE; 00712 } 00713 00714 /* signal event if operation was successful */ 00715 if (result.error == ERR_NONE) 00716 { 00717 UC_PAAL_TRACE("callback"); 00718 00719 arm_uc_pal_flashiap_signal_internal(ARM_UC_PAAL_EVENT_GET_ACTIVE_FIRMWARE_DETAILS_DONE); 00720 } 00721 } 00722 00723 return result; 00724 } 00725 00726 /** 00727 * @brief Get details for the firmware installer. 00728 * @details This call populates the passed details struct with information 00729 * about the firmware installer. 00730 * 00731 * @param details Pointer to firmware details struct to be populated. 00732 * @return Returns ERR_NONE on accept, and signals the event handler with 00733 * either DONE or ERROR when complete. 00734 * Returns ERR_INVALID_PARAMETER on reject, and no signal is sent. 00735 */ 00736 arm_uc_error_t ARM_UC_PAL_FlashIAP_GetInstallerDetails(arm_uc_installer_details_t* details) 00737 { 00738 arm_uc_error_t result = { .code = ERR_INVALID_PARAMETER }; 00739 00740 if (details) 00741 { 00742 /* only read from memory if offset is set */ 00743 if (MBED_CONF_UPDATE_CLIENT_BOOTLOADER_DETAILS) 00744 { 00745 uint8_t* arm = (uint8_t*) (MBED_CONF_UPDATE_CLIENT_BOOTLOADER_DETAILS + 00746 offsetof(arm_uc_installer_details_t, arm_hash)); 00747 00748 uint8_t* oem = (uint8_t*) (MBED_CONF_UPDATE_CLIENT_BOOTLOADER_DETAILS + 00749 offsetof(arm_uc_installer_details_t, oem_hash)); 00750 00751 uint8_t* layout = (uint8_t*) (MBED_CONF_UPDATE_CLIENT_BOOTLOADER_DETAILS + 00752 offsetof(arm_uc_installer_details_t, layout)); 00753 00754 /* populate installer details struct */ 00755 memcpy(&details->arm_hash, arm, ARM_UC_SHA256_SIZE); 00756 memcpy(&details->oem_hash, oem, ARM_UC_SHA256_SIZE); 00757 details->layout = arm_uc_parse_uint32(layout); 00758 } 00759 else 00760 { 00761 /* offset not set, zero details struct */ 00762 memset(details, 0, sizeof(arm_uc_installer_details_t)); 00763 } 00764 00765 arm_uc_pal_flashiap_signal_internal(ARM_UC_PAAL_EVENT_GET_INSTALLER_DETAILS_DONE); 00766 00767 result.code = ERR_NONE; 00768 } 00769 00770 return result; 00771 } 00772 00773 #endif
Generated on Tue Jul 12 2022 19:12:11 by 1.7.2