Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Dependencies: FXAS21002 FXOS8700Q
arm_uc_pal_blockdevice_implementation.c
00001 // ---------------------------------------------------------------------------- 00002 // Copyright 2017-2018 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 #include "arm_uc_config.h" 00020 #if defined(ARM_UC_FEATURE_PAL_BLOCKDEVICE) && (ARM_UC_FEATURE_PAL_BLOCKDEVICE == 1) 00021 00022 #define __STDC_FORMAT_MACROS 00023 00024 #include "update-client-pal-blockdevice/arm_uc_pal_blockdevice.h" 00025 #include "update-client-pal-blockdevice/arm_uc_pal_blockdevice_platform.h" 00026 00027 #include "update-client-metadata-header/arm_uc_metadata_header_v2.h" 00028 00029 #include <inttypes.h> 00030 00031 #ifndef MBED_CONF_UPDATE_CLIENT_STORAGE_ADDRESS 00032 #define MBED_CONF_UPDATE_CLIENT_STORAGE_ADDRESS 0 00033 #endif 00034 00035 #ifndef MBED_CONF_UPDATE_CLIENT_STORAGE_SIZE 00036 #define MBED_CONF_UPDATE_CLIENT_STORAGE_SIZE 0 00037 #endif 00038 00039 #ifndef MBED_CONF_UPDATE_CLIENT_STORAGE_PAGE 00040 #define MBED_CONF_UPDATE_CLIENT_STORAGE_PAGE 1 00041 #endif 00042 00043 #ifndef MBED_CONF_UPDATE_CLIENT_STORAGE_LOCATIONS 00044 #define MBED_CONF_UPDATE_CLIENT_STORAGE_LOCATIONS 1 00045 #endif 00046 00047 /* consistency check */ 00048 #if (MBED_CONF_UPDATE_CLIENT_STORAGE_PAGE == 0) 00049 #error Update client storage page cannot be zero. 00050 #endif 00051 00052 #if (MBED_CONF_UPDATE_CLIENT_STORAGE_LOCATIONS == 0) 00053 #error Update client storage locations must be at least 1. 00054 #endif 00055 00056 #if (MBED_CONF_UPDATE_CLIENT_STORAGE_SIZE == 0) 00057 #error Update client storage size cannot be zero. 00058 #endif 00059 00060 /* Check that the statically allocated buffers are aligned with the block size */ 00061 #define ARM_UC_PAL_ONE_BUFFER (ARM_UC_BUFFER_SIZE / 2) 00062 #define ARM_UC_PAL_PAGES (ARM_UC_PAL_ONE_BUFFER / MBED_CONF_UPDATE_CLIENT_STORAGE_PAGE) 00063 00064 #if !((ARM_UC_PAL_PAGES * MBED_CONF_UPDATE_CLIENT_STORAGE_PAGE) == ARM_UC_PAL_ONE_BUFFER) 00065 #error Update client buffer must be divisible by the block page size 00066 #endif 00067 00068 static ARM_UC_PAAL_UPDATE_SignalEvent_t pal_blockdevice_event_handler = NULL; 00069 static uint32_t pal_blockdevice_firmware_size = 0; 00070 static uint32_t pal_blockdevice_page_size = 0; 00071 static uint32_t pal_blockdevice_sector_size = 0; 00072 static uint32_t pal_blockdevice_hdr_size = 0; 00073 00074 static void pal_blockdevice_signal_internal(uint32_t event) 00075 { 00076 if (pal_blockdevice_event_handler) { 00077 pal_blockdevice_event_handler(event); 00078 } 00079 } 00080 00081 /** 00082 * @brief Round size up to nearest page 00083 * 00084 * @param size The size that need to be rounded up 00085 * @return Returns the size rounded up to the nearest page 00086 */ 00087 static uint32_t pal_blockdevice_round_up_to_page(uint32_t size) 00088 { 00089 uint32_t round_up = 0; 00090 /* 0 is an aligned address and math operation below would not return 0. 00091 It would return pal_blockdevice_page_size*/ 00092 if (size != 0){ 00093 round_up = ((size - 1) / pal_blockdevice_page_size + 1) * pal_blockdevice_page_size; 00094 } 00095 return round_up; 00096 } 00097 00098 /** 00099 * @brief Round size down to nearest page 00100 * 00101 * @param size The size that need to be rounded up 00102 * @return Returns the size rounded up to the nearest page 00103 */ 00104 static uint32_t pal_blockdevice_round_down_to_page(uint32_t size) 00105 { 00106 return (size / pal_blockdevice_page_size) * pal_blockdevice_page_size; 00107 } 00108 00109 /** 00110 * @brief Align size up to sector size 00111 * 00112 * @param size The size that need to be rounded up 00113 * @return Returns the size aligned to sector size 00114 */ 00115 static uint32_t pal_blockdevice_round_up_to_sector(uint32_t size) 00116 { 00117 uint32_t round_up = 0; 00118 /* 0 is an aligned address and math operation below would not return 0. 00119 It would return pal_blockdevice_sector_size*/ 00120 if (size != 0){ 00121 round_up = ((size - 1) / pal_blockdevice_sector_size + 1) * pal_blockdevice_sector_size; 00122 } 00123 return round_up; 00124 } 00125 00126 /** 00127 * @brief Align size down to sector size 00128 * 00129 * @param size The size that need to be rounded up 00130 * @return Returns the size aligned to sector boundary 00131 */ 00132 static uint32_t pal_blockdevice_round_down_to_sector(uint32_t size) 00133 { 00134 return (size / pal_blockdevice_sector_size) * pal_blockdevice_sector_size; 00135 } 00136 00137 /** 00138 * @brief Get the physicl slot address and size given slot_id 00139 * 00140 * @param slot_id Storage location ID. 00141 * @param slot_addr the slot address is returned in this pointer 00142 * @param slot_size the slot size is returned in this pointer 00143 * @return Returns ERR_NONE on success. 00144 * Returns ERR_INVALID_PARAMETER on error. 00145 */ 00146 static arm_uc_error_t pal_blockdevice_get_slot_addr_size(uint32_t slot_id, 00147 uint32_t *slot_addr, 00148 uint32_t *slot_size) 00149 { 00150 arm_uc_error_t result = { .code = ERR_INVALID_PARAMETER }; 00151 00152 if ((slot_id < MBED_CONF_UPDATE_CLIENT_STORAGE_LOCATIONS) && 00153 (slot_addr != NULL) && 00154 (slot_size != NULL)) { 00155 /* find the start address of the whole storage area. It needs to be aligned to 00156 sector boundary and we cannot go outside user defined storage area, hence 00157 rounding up to sector boundary */ 00158 uint32_t storage_start_addr = pal_blockdevice_round_up_to_sector( 00159 MBED_CONF_UPDATE_CLIENT_STORAGE_ADDRESS); 00160 /* find the end address of the whole storage area. It needs to be aligned to 00161 sector boundary and we cannot go outside user defined storage area, hence 00162 rounding down to sector boundary */ 00163 uint32_t storage_end_addr = pal_blockdevice_round_down_to_sector( 00164 MBED_CONF_UPDATE_CLIENT_STORAGE_ADDRESS + \ 00165 MBED_CONF_UPDATE_CLIENT_STORAGE_SIZE); 00166 /* find the maximum size each slot can have given the start and end, without 00167 considering the alignment of individual slots */ 00168 uint32_t max_slot_size = (storage_end_addr - storage_start_addr) / \ 00169 MBED_CONF_UPDATE_CLIENT_STORAGE_LOCATIONS; 00170 /* find the start address of slot. It needs to align to sector boundary. We 00171 choose here to round down at each slot boundary */ 00172 *slot_addr = storage_start_addr + pal_blockdevice_round_down_to_sector( 00173 slot_id * max_slot_size); 00174 /* Rounding down slot size to sector boundary same as 00175 the slot start address so that we make sure two slot don't overlap */ 00176 *slot_size = pal_blockdevice_round_down_to_sector(max_slot_size); 00177 result.code = ERR_NONE; 00178 } 00179 00180 return result; 00181 } 00182 00183 /** 00184 * @brief Initialize the underlying storage and set the callback handler. 00185 * 00186 * @param callback Function pointer to event handler. 00187 * @return Returns ERR_NONE on accept, and signals the event handler with 00188 * either DONE or ERROR when complete. 00189 * Returns ERR_INVALID_PARAMETER on reject, and no signal is sent. 00190 */ 00191 arm_uc_error_t ARM_UC_PAL_BlockDevice_Initialize(ARM_UC_PAAL_UPDATE_SignalEvent_t callback) 00192 { 00193 arm_uc_error_t result = { .code = ERR_INVALID_PARAMETER }; 00194 00195 if (callback) { 00196 UC_PAAL_TRACE("ARM_UC_PAL_BlockDevice_Initialize"); 00197 00198 int status = arm_uc_blockdevice_init(); 00199 pal_blockdevice_page_size = arm_uc_blockdevice_get_program_size(); 00200 pal_blockdevice_sector_size = arm_uc_blockdevice_get_erase_size(); 00201 pal_blockdevice_hdr_size = pal_blockdevice_round_up_to_page(ARM_UC_EXTERNAL_HEADER_SIZE_V2); 00202 00203 if (status == ARM_UC_BLOCKDEVICE_SUCCESS) { 00204 pal_blockdevice_event_handler = callback; 00205 pal_blockdevice_signal_internal(ARM_UC_PAAL_EVENT_INITIALIZE_DONE); 00206 result.code = ERR_NONE; 00207 } 00208 } 00209 00210 return result; 00211 } 00212 00213 /** 00214 * @brief Get maximum number of supported storage locations. 00215 * 00216 * @return Number of storage locations. 00217 */ 00218 uint32_t ARM_UC_PAL_BlockDevice_GetMaxID(void) 00219 { 00220 return MBED_CONF_UPDATE_CLIENT_STORAGE_LOCATIONS; 00221 } 00222 00223 /** 00224 * @brief Prepare the storage layer for a new firmware image. 00225 * @details The storage location is set up to receive an image with 00226 * the details passed in the details struct. 00227 * 00228 * @param slot_id Storage location ID. 00229 * @param details Pointer to a struct with firmware details. 00230 * @param buffer Temporary buffer for formatting and storing metadata. 00231 * @return Returns ERR_NONE on accept, and signals the event handler with 00232 * either DONE or ERROR when complete. 00233 * Returns ERR_INVALID_PARAMETER on reject, and no signal is sent. 00234 */ 00235 arm_uc_error_t ARM_UC_PAL_BlockDevice_Prepare(uint32_t slot_id, 00236 const arm_uc_firmware_details_t *details, 00237 arm_uc_buffer_t *buffer) 00238 { 00239 arm_uc_error_t result = { .code = ERR_INVALID_PARAMETER }; 00240 00241 if (details && buffer && buffer->ptr) { 00242 UC_PAAL_TRACE("ARM_UC_PAL_BlockDevice_Prepare: %" PRIX32 " %" PRIX64, 00243 slot_id, details->size); 00244 00245 /* encode firmware details in buffer */ 00246 arm_uc_error_t header_status = arm_uc_create_external_header_v2(details, 00247 buffer); 00248 if (header_status.error == ERR_NONE) { 00249 /* find the size needed to erase. Header is stored contiguous with firmware */ 00250 uint32_t erase_size = pal_blockdevice_round_up_to_sector(pal_blockdevice_hdr_size + \ 00251 details->size); 00252 00253 /* find address of slot */ 00254 uint32_t slot_addr = ARM_UC_BLOCKDEVICE_INVALID_SIZE; 00255 uint32_t slot_size = ARM_UC_BLOCKDEVICE_INVALID_SIZE; 00256 result = pal_blockdevice_get_slot_addr_size(slot_id, &slot_addr, &slot_size); 00257 00258 UC_PAAL_TRACE("erase: %" PRIX32 " %" PRIX32 " %" PRIX32, slot_addr, erase_size, slot_size); 00259 00260 int status = ARM_UC_BLOCKDEVICE_FAIL; 00261 if (result.error == ERR_NONE) { 00262 if (erase_size <= slot_size) { 00263 /* erase */ 00264 status = arm_uc_blockdevice_erase(slot_addr, erase_size); 00265 } else { 00266 UC_PAAL_ERR_MSG("not enough space for firmware image"); 00267 result.code = PAAL_ERR_FIRMWARE_TOO_LARGE; 00268 } 00269 } 00270 00271 if (status == ARM_UC_BLOCKDEVICE_SUCCESS) { 00272 /* write header */ 00273 status = arm_uc_blockdevice_program(buffer->ptr, 00274 slot_addr, 00275 pal_blockdevice_hdr_size); 00276 00277 if (status == ARM_UC_BLOCKDEVICE_SUCCESS) { 00278 /* set return code */ 00279 result.code = ERR_NONE; 00280 00281 /* store firmware size in global */ 00282 pal_blockdevice_firmware_size = details->size; 00283 00284 /* signal done */ 00285 pal_blockdevice_signal_internal(ARM_UC_PAAL_EVENT_PREPARE_DONE); 00286 } else { 00287 UC_PAAL_ERR_MSG("arm_uc_blockdevice_program failed"); 00288 } 00289 } else { 00290 UC_PAAL_ERR_MSG("arm_uc_blockdevice_erase failed"); 00291 } 00292 } else { 00293 UC_PAAL_ERR_MSG("arm_uc_create_external_header_v2 failed"); 00294 } 00295 } 00296 00297 return result; 00298 } 00299 00300 /** 00301 * @brief Write a fragment to the indicated storage location. 00302 * @details The storage location must have been allocated using the Prepare 00303 * call. The call is expected to write the entire fragment before 00304 * signaling completion. 00305 * 00306 * @param slot_id Storage location ID. 00307 * @param offset Offset in bytes to where the fragment should be written. 00308 * @param buffer Pointer to buffer struct with fragment. 00309 * @return Returns ERR_NONE on accept, and signals the event handler with 00310 * either DONE or ERROR when complete. 00311 * Returns ERR_INVALID_PARAMETER on reject, and no signal is sent. 00312 */ 00313 arm_uc_error_t ARM_UC_PAL_BlockDevice_Write(uint32_t slot_id, 00314 uint32_t offset, 00315 const arm_uc_buffer_t *buffer) 00316 { 00317 arm_uc_error_t result = { .code = ERR_INVALID_PARAMETER }; 00318 00319 if (buffer && buffer->ptr) { 00320 UC_PAAL_TRACE("ARM_UC_PAL_BlockDevice_Write: %" PRIX32 " %" PRIX32 " %" PRIX32, 00321 slot_id, offset, buffer->size); 00322 int status = ARM_UC_BLOCKDEVICE_SUCCESS; 00323 00324 /* find address of slot */ 00325 uint32_t slot_addr = ARM_UC_BLOCKDEVICE_INVALID_SIZE; 00326 uint32_t slot_size = ARM_UC_BLOCKDEVICE_INVALID_SIZE; 00327 result = pal_blockdevice_get_slot_addr_size(slot_id, &slot_addr, &slot_size); 00328 uint32_t physical_address = slot_addr + pal_blockdevice_hdr_size + offset; 00329 00330 /* check that we are not writing too much */ 00331 uint32_t aligned_size = 0; 00332 if (pal_blockdevice_firmware_size < offset + buffer->size) { 00333 UC_PAAL_ERR_MSG("programming more than firmware size %" PRIu32 00334 " < %" PRIu32 " + %" PRIu32, 00335 pal_blockdevice_firmware_size, offset, buffer->size); 00336 } else if ((pal_blockdevice_firmware_size > offset + buffer->size) && 00337 (buffer->size % pal_blockdevice_page_size != 0)) { 00338 UC_PAAL_ERR_MSG("program size %" PRIu32 " does not align to page size %" PRIu32, 00339 buffer->size, pal_blockdevice_page_size); 00340 } else if (pal_blockdevice_firmware_size == offset + buffer->size) { 00341 /* last chunk write page aligned data first */ 00342 aligned_size = pal_blockdevice_round_down_to_page(buffer->size); 00343 } else { 00344 aligned_size = buffer->size; 00345 } 00346 00347 /* aligned write */ 00348 if (result.error == ERR_NONE && aligned_size > 0) { 00349 status = arm_uc_blockdevice_program(buffer->ptr, 00350 physical_address, 00351 aligned_size); 00352 if (status == ARM_UC_BLOCKDEVICE_FAIL) { 00353 UC_PAAL_ERR_MSG("arm_uc_blockdevice_program failed"); 00354 } 00355 } 00356 00357 /* last chunk write remainder */ 00358 uint32_t remainder_size = buffer->size - aligned_size; 00359 00360 if ((status == ARM_UC_BLOCKDEVICE_SUCCESS) && (remainder_size > 0)) { 00361 /* check if it is safe to use buffer, i.e. buffer is larger than a page */ 00362 if (buffer->size_max >= pal_blockdevice_page_size) { 00363 memmove(buffer->ptr, &(buffer->ptr[aligned_size]), remainder_size); 00364 status = arm_uc_blockdevice_program(buffer->ptr, 00365 physical_address + aligned_size, 00366 pal_blockdevice_page_size); 00367 } else { 00368 UC_PAAL_ERR_MSG("arm_uc_blockdevice_program failed"); 00369 00370 status = ARM_UC_BLOCKDEVICE_FAIL; 00371 } 00372 } 00373 00374 if (status == ARM_UC_BLOCKDEVICE_SUCCESS) { 00375 /* set return code */ 00376 result.code = ERR_NONE; 00377 00378 /* signal done */ 00379 pal_blockdevice_signal_internal(ARM_UC_PAAL_EVENT_WRITE_DONE); 00380 } else { 00381 UC_PAAL_ERR_MSG("arm_uc_blockdevice_program failed"); 00382 } 00383 } 00384 00385 return result; 00386 } 00387 00388 /** 00389 * @brief Close storage location for writing and flush pending data. 00390 * 00391 * @param slot_id Storage location ID. 00392 * @return Returns ERR_NONE on accept, and signals the event handler with 00393 * either DONE or ERROR when complete. 00394 * Returns ERR_INVALID_PARAMETER on reject, and no signal is sent. 00395 */ 00396 arm_uc_error_t ARM_UC_PAL_BlockDevice_Finalize(uint32_t slot_id) 00397 { 00398 arm_uc_error_t result = { .code = ERR_NONE }; 00399 00400 UC_PAAL_TRACE("ARM_UC_PAL_BlockDevice_Finalize"); 00401 00402 pal_blockdevice_signal_internal(ARM_UC_PAAL_EVENT_FINALIZE_DONE); 00403 00404 return result; 00405 } 00406 00407 /** 00408 * @brief Read a fragment from the indicated storage location. 00409 * @details The function will read until the buffer is full or the end of 00410 * the storage location has been reached. The actual amount of 00411 * bytes read is set in the buffer struct. 00412 * 00413 * @param slot_id Storage location ID. 00414 * @param offset Offset in bytes to read from. 00415 * @param buffer Pointer to buffer struct to store fragment. buffer->size 00416 * contains the intended read size. 00417 * @return Returns ERR_NONE on accept, and signals the event handler with 00418 * either DONE or ERROR when complete. 00419 * Returns ERR_INVALID_PARAMETER on reject, and no signal is sent. 00420 * buffer->size contains actual bytes read on return. 00421 */ 00422 arm_uc_error_t ARM_UC_PAL_BlockDevice_Read(uint32_t slot_id, 00423 uint32_t offset, 00424 arm_uc_buffer_t *buffer) 00425 { 00426 arm_uc_error_t result = { .code = ERR_INVALID_PARAMETER }; 00427 00428 if (buffer && buffer->ptr) { 00429 UC_PAAL_TRACE("ARM_UC_PAL_BlockDevice_Read: %" PRIX32 " %" PRIX32 " %" PRIX32, 00430 slot_id, offset, buffer->size); 00431 00432 /* find address of slot */ 00433 uint32_t slot_addr = ARM_UC_BLOCKDEVICE_INVALID_SIZE; 00434 uint32_t slot_size = ARM_UC_BLOCKDEVICE_INVALID_SIZE; 00435 result = pal_blockdevice_get_slot_addr_size(slot_id, 00436 &slot_addr, 00437 &slot_size); 00438 uint32_t physical_address = slot_addr + pal_blockdevice_hdr_size + offset; 00439 uint32_t read_size = pal_blockdevice_round_up_to_page(buffer->size); 00440 int32_t status = ARM_UC_BLOCKDEVICE_FAIL; 00441 00442 if (read_size <= buffer->size_max) { 00443 status = arm_uc_blockdevice_read(buffer->ptr, 00444 physical_address, 00445 read_size); 00446 } 00447 00448 if (status == ARM_UC_BLOCKDEVICE_SUCCESS) { 00449 /* set return code */ 00450 result.code = ERR_NONE; 00451 00452 /* signal done */ 00453 pal_blockdevice_signal_internal(ARM_UC_PAAL_EVENT_READ_DONE); 00454 } else { 00455 UC_PAAL_ERR_MSG("arm_uc_blockdevice_read failed"); 00456 } 00457 } 00458 00459 return result; 00460 } 00461 00462 /** 00463 * @brief Set the firmware image in the slot to be the new active image. 00464 * @details This call is responsible for initiating the process for 00465 * applying a new/different image. Depending on the platform this 00466 * could be: 00467 * * An empty call, if the installer can deduce which slot to 00468 * choose from based on the firmware details. 00469 * * Setting a flag to indicate which slot to use next. 00470 * * Decompressing/decrypting/installing the firmware image on 00471 * top of another. 00472 * 00473 * @param slot_id Storage location ID. 00474 * @return Returns ERR_NONE on accept, and signals the event handler with 00475 * either DONE or ERROR when complete. 00476 * Returns ERR_INVALID_PARAMETER on reject, and no signal is sent. 00477 */ 00478 arm_uc_error_t ARM_UC_PAL_BlockDevice_Activate(uint32_t slot_id) 00479 { 00480 arm_uc_error_t result = { .code = ERR_NONE }; 00481 00482 UC_PAAL_TRACE("ARM_UC_PAL_BlockDevice_Activate"); 00483 00484 pal_blockdevice_signal_internal(ARM_UC_PAAL_EVENT_ACTIVATE_DONE); 00485 00486 return result; 00487 } 00488 00489 /** 00490 * @brief Get firmware details for the firmware image in the slot passed. 00491 * @details This call populates the passed details struct with information 00492 * about the firmware image in the slot passed. Only the fields 00493 * marked as supported in the capabilities bitmap will have valid 00494 * values. 00495 * 00496 * @param slot_id Storage location ID. 00497 * @param details Pointer to firmware details struct to be populated. 00498 * @return Returns ERR_NONE on accept, and signals the event handler with 00499 * either DONE or ERROR when complete. 00500 * Returns ERR_INVALID_PARAMETER on reject, and no signal is sent. 00501 */ 00502 arm_uc_error_t ARM_UC_PAL_BlockDevice_GetFirmwareDetails( 00503 uint32_t slot_id, 00504 arm_uc_firmware_details_t *details) 00505 { 00506 arm_uc_error_t result = { .code = ERR_INVALID_PARAMETER }; 00507 00508 if (details) { 00509 UC_PAAL_TRACE("ARM_UC_PAL_BlockDevice_GetFirmwareDetails"); 00510 00511 /* find address of slot */ 00512 uint32_t slot_addr = ARM_UC_BLOCKDEVICE_INVALID_SIZE; 00513 uint32_t slot_size = ARM_UC_BLOCKDEVICE_INVALID_SIZE; 00514 result = pal_blockdevice_get_slot_addr_size(slot_id, &slot_addr, &slot_size); 00515 uint8_t buffer[pal_blockdevice_hdr_size]; 00516 00517 int status = arm_uc_blockdevice_read(buffer, 00518 slot_addr, 00519 pal_blockdevice_hdr_size); 00520 00521 if (status == ARM_UC_BLOCKDEVICE_SUCCESS) { 00522 result = arm_uc_parse_external_header_v2(buffer, details); 00523 00524 if (result.error == ERR_NONE) { 00525 /* signal done */ 00526 pal_blockdevice_signal_internal(ARM_UC_PAAL_EVENT_GET_FIRMWARE_DETAILS_DONE); 00527 } else { 00528 UC_PAAL_ERR_MSG("arm_uc_parse_external_header_v2 failed"); 00529 } 00530 } else { 00531 UC_PAAL_ERR_MSG("arm_uc_blockdevice_read failed"); 00532 } 00533 } 00534 00535 return result; 00536 } 00537 00538 #endif // #if defined(ARM_UC_FEATURE_PAL_BLOCKDEVICE)
Generated on Tue Jul 12 2022 20:20:57 by
