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_paal_classic_pal.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 #include "arm_uc_config.h" 00020 #if defined(ARM_UC_FEATURE_PAL_FILESYSTEM) && (ARM_UC_FEATURE_PAL_FILESYSTEM == 1) 00021 00022 #include "update-client-paal/arm_uc_paal_update_api.h" 00023 00024 #include "update-client-pal-filesystem/arm_uc_pal_extensions.h" 00025 #include "update-client-metadata-header/arm_uc_metadata_header_v2.h" 00026 #include "arm_uc_pal_filesystem_utils.h" 00027 00028 #include "pal.h" 00029 00030 #include "mbed-trace/mbed_trace.h" 00031 #define TRACE_GROUP "UCPI" 00032 00033 #include <stdio.h> 00034 00035 #define ARM_UC_FIRMWARE_FOLDER_NAME "firmware" 00036 00037 /* pointer to external callback handler */ 00038 static ARM_UC_PAAL_UPDATE_SignalEvent_t arm_uc_pal_external_callback = NULL; 00039 00040 static void arm_uc_pal_classic_signal_callback(uintptr_t event) 00041 { 00042 if (arm_uc_pal_external_callback) { 00043 arm_uc_pal_external_callback(event); 00044 } 00045 } 00046 00047 static void arm_uc_pal_classic_callback(palImageEvents_t event) 00048 { 00049 /* 00050 ARM_UC_PAAL_EVENT_INITIALIZE_DONE, 00051 ARM_UC_PAAL_EVENT_PREPARE_DONE, 00052 ARM_UC_PAAL_EVENT_WRITE_DONE, 00053 ARM_UC_PAAL_EVENT_FINALIZE_DONE, 00054 ARM_UC_PAAL_EVENT_READ_DONE, 00055 ARM_UC_PAAL_EVENT_ACTIVATE_DONE, 00056 ARM_UC_PAAL_EVENT_GET_ACTIVE_FIRMWARE_DETAILS_DONE, 00057 ARM_UC_PAAL_EVENT_GET_FIRMWARE_DETAILS_DONE, 00058 ARM_UC_PAAL_EVENT_GET_INSTALLER_DETAILS_DONE, 00059 ARM_UC_PAAL_EVENT_INITIALIZE_ERROR, 00060 ARM_UC_PAAL_EVENT_PREPARE_ERROR, 00061 ARM_UC_PAAL_EVENT_WRITE_ERROR, 00062 ARM_UC_PAAL_EVENT_FINALIZE_ERROR, 00063 ARM_UC_PAAL_EVENT_READ_ERROR, 00064 ARM_UC_PAAL_EVENT_ACTIVATE_ERROR, 00065 ARM_UC_PAAL_EVENT_GET_ACTIVE_FIRMWARE_DETAILS_ERROR, 00066 ARM_UC_PAAL_EVENT_GET_FIRMWARE_DETAILS_ERROR, 00067 ARM_UC_PAAL_EVENT_GET_INSTALLER_DETAILS_ERROR, 00068 */ 00069 tr_debug("arm_uc_pal_classic_callback"); 00070 00071 switch (event) { 00072 case PAL_IMAGE_EVENT_INIT: 00073 arm_uc_pal_classic_signal_callback(ARM_UC_PAAL_EVENT_INITIALIZE_DONE); 00074 break; 00075 case PAL_IMAGE_EVENT_PREPARE: 00076 arm_uc_pal_classic_signal_callback(ARM_UC_PAAL_EVENT_PREPARE_DONE); 00077 break; 00078 case PAL_IMAGE_EVENT_WRITE: 00079 arm_uc_pal_classic_signal_callback(ARM_UC_PAAL_EVENT_WRITE_DONE); 00080 break; 00081 case PAL_IMAGE_EVENT_FINALIZE: 00082 arm_uc_pal_classic_signal_callback(ARM_UC_PAAL_EVENT_FINALIZE_DONE); 00083 break; 00084 case PAL_IMAGE_EVENT_READTOBUFFER: 00085 arm_uc_pal_classic_signal_callback(ARM_UC_PAAL_EVENT_READ_DONE); 00086 break; 00087 case PAL_IMAGE_EVENT_ACTIVATE: 00088 arm_uc_pal_classic_signal_callback(ARM_UC_PAAL_EVENT_ACTIVATE_DONE); 00089 break; 00090 default: 00091 break; 00092 } 00093 } 00094 00095 /** 00096 * @brief Initialize the underlying storage and set the callback handler. 00097 * 00098 * @param callback Function pointer to event handler. 00099 * @return Returns ERR_NONE on accept, and signals the event handler with 00100 * either DONE or ERROR when complete. 00101 * Returns ERR_INVALID_PARAMETER on reject, and no signal is sent. 00102 */ 00103 arm_uc_error_t ARM_UC_Classic_PAL_Initialize(ARM_UC_PAAL_UPDATE_SignalEvent_t callback) 00104 { 00105 arm_uc_error_t result = { .code = ERR_INVALID_PARAMETER }; 00106 00107 if (callback) { 00108 palStatus_t status1 = pal_imageInitAPI(arm_uc_pal_classic_callback); 00109 arm_uc_error_t status2 = pal_ext_imageInitAPI(arm_uc_pal_classic_signal_callback); 00110 00111 if ((status1 == PAL_SUCCESS) && (status2.error == ERR_NONE)) { 00112 arm_uc_pal_external_callback = callback; 00113 arm_uc_pal_classic_signal_callback(ARM_UC_PAAL_EVENT_INITIALIZE_DONE); 00114 00115 result.code = ERR_NONE; 00116 } else { 00117 result.code = ERR_NOT_READY; 00118 } 00119 } 00120 00121 return result; 00122 } 00123 00124 /** 00125 * @brief Get a bitmap indicating supported features. 00126 * @details The bitmap is used in conjunction with the firmware and 00127 * installer details struct to indicate what fields are supported 00128 * and which values are valid. 00129 * 00130 * @return Capability bitmap. 00131 */ 00132 ARM_UC_PAAL_UPDATE_CAPABILITIES ARM_UC_Classic_PAL_GetCapabilities(void) 00133 { 00134 ARM_UC_PAAL_UPDATE_CAPABILITIES result = { 00135 .installer_arm_hash = 0, 00136 .installer_oem_hash = 0, 00137 .installer_layout = 0, 00138 .firmware_hash = 1, 00139 .firmware_hmac = 0, 00140 .firmware_campaign = 0, 00141 .firmware_version = 1, 00142 .firmware_size = 1 00143 }; 00144 00145 return result; 00146 } 00147 00148 /** 00149 * @brief Get maximum number of supported storage locations. 00150 * 00151 * @return Number of storage locations. 00152 */ 00153 uint32_t ARM_UC_Classic_PAL_GetMaxID(void) 00154 { 00155 return 1; 00156 } 00157 00158 /** 00159 * @brief Prepare the storage layer for a new firmware image. 00160 * @details The storage location is set up to receive an image with 00161 * the details passed in the details struct. 00162 * 00163 * @param location Storage location ID. 00164 * @param details Pointer to a struct with firmware details. 00165 * @param buffer Temporary buffer for formatting and storing metadata. 00166 * @return Returns ERR_NONE on accept, and signals the event handler with 00167 * either DONE or ERROR when complete. 00168 * Returns ERR_INVALID_PARAMETER on reject, and no signal is sent. 00169 */ 00170 arm_uc_error_t ARM_UC_Classic_PAL_Prepare(uint32_t location, 00171 const arm_uc_firmware_details_t *details, 00172 arm_uc_buffer_t *buffer) 00173 { 00174 arm_uc_error_t result = { .code = ERR_INVALID_PARAMETER }; 00175 00176 if (details && buffer) { 00177 /* encode firmware details in buffer */ 00178 arm_uc_error_t header_status = arm_uc_create_external_header_v2(details, 00179 buffer); 00180 00181 if (header_status.error == ERR_NONE) { 00182 /* format file name and path */ 00183 char file_path[PAL_MAX_FILE_AND_FOLDER_LENGTH] = { 0 }; 00184 00185 arm_uc_error_t rv = arm_uc_pal_filesystem_get_path(location, 00186 FIRMWARE_IMAGE_ITEM_HEADER, 00187 file_path, 00188 PAL_MAX_FILE_AND_FOLDER_LENGTH); 00189 00190 if (rv.code == ERR_NONE) { 00191 tr_debug("file_path: %s", file_path); 00192 00193 palFileDescriptor_t file = 0; 00194 00195 /* open file and get file handler */ 00196 palStatus_t status = pal_fsFopen(file_path, 00197 PAL_FS_FLAG_READWRITETRUNC, 00198 &file); 00199 00200 if (status == PAL_SUCCESS) { 00201 size_t xfer_size = 0; 00202 00203 /* write buffer to file */ 00204 status = pal_fsFwrite(&file, 00205 buffer->ptr, 00206 buffer->size, 00207 &xfer_size); 00208 00209 tr_debug("written: %lu", (unsigned long)xfer_size); 00210 00211 /* call event hadnler and set return code if write was successful */ 00212 if ((status == PAL_SUCCESS) && 00213 (xfer_size == buffer->size)) { 00214 result.code = ERR_NONE; 00215 00216 arm_uc_pal_classic_signal_callback(ARM_UC_PAAL_EVENT_PREPARE_DONE); 00217 } 00218 00219 /* close file after write */ 00220 status = pal_fsFclose(&file); 00221 00222 if (status != PAL_SUCCESS) { 00223 tr_error("pal_fsFclose failed: %" PRId32, status); 00224 } 00225 } else { 00226 tr_error("pal_fsFopen failed: %" PRId32, status); 00227 } 00228 } else { 00229 tr_error("file name and path too long"); 00230 } 00231 } else { 00232 tr_error("header too large for buffer"); 00233 } 00234 } 00235 00236 return result; 00237 } 00238 00239 /** 00240 * @brief Write a fragment to the indicated storage location. 00241 * @details The storage location must have been allocated using the Prepare 00242 * call. The call is expected to write the entire fragment before 00243 * signaling completion. 00244 * 00245 * @param location Storage location ID. 00246 * @param offset Offset in bytes to where the fragment should be written. 00247 * @param buffer Pointer to buffer struct with fragment. 00248 * @return Returns ERR_NONE on accept, and signals the event handler with 00249 * either DONE or ERROR when complete. 00250 * Returns ERR_INVALID_PARAMETER on reject, and no signal is sent. 00251 */ 00252 arm_uc_error_t ARM_UC_Classic_PAL_Write(uint32_t location, 00253 uint32_t offset, 00254 const arm_uc_buffer_t *buffer) 00255 { 00256 arm_uc_error_t result = { .code = ERR_INVALID_PARAMETER }; 00257 00258 if (buffer) { 00259 palStatus_t status = pal_imageWrite(location, 00260 offset, 00261 (palConstBuffer_t *) buffer); 00262 00263 if (status == PAL_SUCCESS) { 00264 result.code = ERR_NONE; 00265 } else { 00266 result.code = ERR_NOT_READY; 00267 } 00268 } 00269 00270 return result; 00271 } 00272 00273 /** 00274 * @brief Close storage location for writing and flush pending data. 00275 * 00276 * @param location Storage location ID. 00277 * @return Returns ERR_NONE on accept, and signals the event handler with 00278 * either DONE or ERROR when complete. 00279 * Returns ERR_INVALID_PARAMETER on reject, and no signal is sent. 00280 */ 00281 arm_uc_error_t ARM_UC_Classic_PAL_Finalize(uint32_t location) 00282 { 00283 arm_uc_error_t result = { .code = ERR_NOT_READY }; 00284 00285 palStatus_t status = pal_imageFinalize(location); 00286 00287 if (status == PAL_SUCCESS) { 00288 result.code = ERR_NONE; 00289 } 00290 00291 return result; 00292 } 00293 00294 /** 00295 * @brief Read a fragment from the indicated storage location. 00296 * @details The function will read until the buffer is full or the end of 00297 * the storage location has been reached. The actual amount of 00298 * bytes read is set in the buffer struct. 00299 * 00300 * @param location Storage location ID. 00301 * @param offset Offset in bytes to read from. 00302 * @param buffer Pointer to buffer struct to store fragment. buffer->size 00303 * contains the intended read size. 00304 * @return Returns ERR_NONE on accept, and signals the event handler with 00305 * either DONE or ERROR when complete. 00306 * Returns ERR_INVALID_PARAMETER on reject, and no signal is sent. 00307 * buffer->size contains actual bytes read on return. 00308 */ 00309 arm_uc_error_t ARM_UC_Classic_PAL_Read(uint32_t location, 00310 uint32_t offset, 00311 arm_uc_buffer_t *buffer) 00312 { 00313 arm_uc_error_t result = { .code = ERR_INVALID_PARAMETER }; 00314 00315 if (buffer) { 00316 palStatus_t status = pal_imageReadToBuffer(location, 00317 offset, 00318 (palBuffer_t *) buffer); 00319 00320 if (status == PAL_SUCCESS) { 00321 tr_debug("pal_imageReadToBuffer succeeded: %" PRIX32, buffer->size); 00322 result.code = ERR_NONE; 00323 } else { 00324 tr_error("pal_imageReadToBuffer failed"); 00325 result.code = ERR_NOT_READY; 00326 } 00327 } 00328 00329 return result; 00330 } 00331 00332 /** 00333 * @brief Set the firmware image in the slot to be the new active image. 00334 * @details This call is responsible for initiating the process for 00335 * applying a new/different image. Depending on the platform this 00336 * could be: 00337 * * An empty call, if the installer can deduce which slot to 00338 * choose from based on the firmware details. 00339 * * Setting a flag to indicate which slot to use next. 00340 * * Decompressing/decrypting/installing the firmware image on 00341 * top of another. 00342 * 00343 * @param location Storage location ID. 00344 * @return Returns ERR_NONE on accept, and signals the event handler with 00345 * either DONE or ERROR when complete. 00346 * Returns ERR_INVALID_PARAMETER on reject, and no signal is sent. 00347 */ 00348 arm_uc_error_t ARM_UC_Classic_PAL_Activate(uint32_t location) 00349 { 00350 arm_uc_error_t result = { .code = ERR_INVALID_PARAMETER }; 00351 00352 result = pal_ext_imageActivate(location); 00353 00354 return result; 00355 } 00356 00357 /** 00358 * @brief Get firmware details for the actively running firmware. 00359 * @details This call populates the passed details struct with information 00360 * about the currently active firmware image. Only the fields 00361 * marked as supported in the capabilities bitmap will have valid 00362 * values. 00363 * 00364 * @param details Pointer to firmware details struct to be populated. 00365 * @return Returns ERR_NONE on accept, and signals the event handler with 00366 * either DONE or ERROR when complete. 00367 * Returns ERR_INVALID_PARAMETER on reject, and no signal is sent. 00368 */ 00369 arm_uc_error_t ARM_UC_Classic_PAL_GetActiveFirmwareDetails(arm_uc_firmware_details_t *details) 00370 { 00371 arm_uc_error_t result = { .code = ERR_INVALID_PARAMETER }; 00372 00373 if (details) { 00374 result = pal_ext_imageGetActiveDetails(details); 00375 } 00376 00377 return result; 00378 } 00379 00380 /** 00381 * @brief Get firmware details for the firmware image in the slot passed. 00382 * @details This call populates the passed details struct with information 00383 * about the firmware image in the slot passed. Only the fields 00384 * marked as supported in the capabilities bitmap will have valid 00385 * values. 00386 * 00387 * @param details Pointer to firmware details struct to be populated. 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_Classic_PAL_GetFirmwareDetails(uint32_t location, 00393 arm_uc_firmware_details_t *details) 00394 { 00395 arm_uc_error_t result = { .code = ERR_INVALID_PARAMETER }; 00396 00397 if (details) { 00398 char file_path[PAL_MAX_FILE_AND_FOLDER_LENGTH + 1] = { 0 }; 00399 00400 arm_uc_error_t rv = arm_uc_pal_filesystem_get_path(location, 00401 FIRMWARE_IMAGE_ITEM_HEADER, 00402 file_path, 00403 PAL_MAX_FILE_AND_FOLDER_LENGTH); 00404 00405 if (rv.code == ERR_NONE) { 00406 palFileDescriptor_t file = 0; 00407 00408 /* open metadata header file if it exists */ 00409 palStatus_t pal_rc = pal_fsFopen(file_path, 00410 PAL_FS_FLAG_READONLY, 00411 &file); 00412 00413 if (pal_rc == PAL_SUCCESS) { 00414 size_t xfer_size = 0; 00415 00416 /* read metadata header */ 00417 uint8_t read_buffer[ARM_UC_EXTERNAL_HEADER_SIZE_V2] = { 0 }; 00418 00419 pal_rc = pal_fsFread(&file, 00420 read_buffer, 00421 ARM_UC_EXTERNAL_HEADER_SIZE_V2, 00422 &xfer_size); 00423 00424 /* check return code */ 00425 if ((pal_rc == PAL_SUCCESS) && 00426 (xfer_size == ARM_UC_EXTERNAL_HEADER_SIZE_V2)) { 00427 tr_debug("read bytes: %lu", (unsigned long)xfer_size); 00428 00429 /* read out header magic */ 00430 uint32_t headerMagic = arm_uc_parse_uint32(&read_buffer[0]); 00431 00432 /* read out header magic */ 00433 uint32_t headerVersion = arm_uc_parse_uint32(&read_buffer[4]); 00434 00435 /* choose version to decode */ 00436 if ((headerMagic == ARM_UC_EXTERNAL_HEADER_MAGIC_V2) && 00437 (headerVersion == ARM_UC_EXTERNAL_HEADER_VERSION_V2)) { 00438 result = arm_uc_parse_external_header_v2(read_buffer, details); 00439 00440 tr_debug("version: %" PRIu64, details->version); 00441 tr_debug("size: %"PRIu64, details->size); 00442 00443 if (result.error == ERR_NONE) { 00444 arm_uc_pal_classic_signal_callback(ARM_UC_PAAL_EVENT_GET_FIRMWARE_DETAILS_DONE); 00445 } 00446 } else { 00447 /* invalid header format */ 00448 tr_error("invalid header in slot %" PRIu32, location); 00449 } 00450 } else if (xfer_size != ARM_UC_EXTERNAL_HEADER_SIZE_V2) { 00451 /* invalid header format */ 00452 tr_error("invalid header in slot %" PRIu32, location); 00453 } else { 00454 /* unsuccessful read */ 00455 tr_error("pal_fsFread returned 0x%" PRIX32, (uint32_t) pal_rc); 00456 } 00457 00458 /* close file after use */ 00459 pal_rc = pal_fsFclose(&file); 00460 00461 if (pal_rc != PAL_SUCCESS) { 00462 tr_error("pal_fsFclose failed: %" PRId32, pal_rc); 00463 } 00464 } else { 00465 /* header file not present, slot is either invalid or unused. */ 00466 result.code = ERR_NOT_READY; 00467 } 00468 } 00469 } 00470 00471 return result; 00472 } 00473 00474 /** 00475 * @brief Get details for the component responsible for installation. 00476 * @details This call populates the passed details struct with information 00477 * about the local installer. Only the fields marked as supported 00478 * in the capabilities bitmap will have valid values. The 00479 * installer could be the bootloader, a recovery image, or some 00480 * other component responsible for applying the new firmware 00481 * image. 00482 * 00483 * @param details Pointer to installer details struct to be populated. 00484 * @return Returns ERR_NONE on accept, and signals the event handler with 00485 * either DONE or ERROR when complete. 00486 * Returns ERR_INVALID_PARAMETER on reject, and no signal is sent. 00487 */ 00488 arm_uc_error_t ARM_UC_Classic_PAL_GetInstallerDetails(arm_uc_installer_details_t *details) 00489 { 00490 arm_uc_error_t result = { .code = ERR_INVALID_PARAMETER }; 00491 00492 if (details) { 00493 result = pal_ext_installerGetDetails(details); 00494 } 00495 00496 return result; 00497 } 00498 00499 const ARM_UC_PAAL_UPDATE ARM_UCP_FILESYSTEM = { 00500 .Initialize = ARM_UC_Classic_PAL_Initialize, 00501 .GetCapabilities = ARM_UC_Classic_PAL_GetCapabilities, 00502 .GetMaxID = ARM_UC_Classic_PAL_GetMaxID, 00503 .Prepare = ARM_UC_Classic_PAL_Prepare, 00504 .Write = ARM_UC_Classic_PAL_Write, 00505 .Finalize = ARM_UC_Classic_PAL_Finalize, 00506 .Read = ARM_UC_Classic_PAL_Read, 00507 .Activate = ARM_UC_Classic_PAL_Activate, 00508 .GetActiveFirmwareDetails = ARM_UC_Classic_PAL_GetActiveFirmwareDetails, 00509 .GetFirmwareDetails = ARM_UC_Classic_PAL_GetFirmwareDetails, 00510 .GetInstallerDetails = ARM_UC_Classic_PAL_GetInstallerDetails 00511 }; 00512 00513 #endif /* ARM_UC_FEATURE_PAL_FILESYSTEM */
Generated on Tue Jul 12 2022 20:20:57 by
