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_linux_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 #include "arm_uc_config.h" 00020 #if defined(ARM_UC_FEATURE_PAL_LINUX) && (ARM_UC_FEATURE_PAL_LINUX == 1) 00021 #if defined(TARGET_IS_PC_LINUX) 00022 #define _FILE_OFFSET_BITS 64 00023 00024 #include "update-client-pal-linux/arm_uc_pal_linux_implementation_internal.h" 00025 #include "update-client-pal-linux/arm_uc_pal_linux_implementation.h" 00026 #include "update-client-paal/arm_uc_paal_update_api.h" 00027 #include "update-client-pal-linux/arm_uc_pal_linux_ext.h" 00028 00029 #include "update-client-metadata-header/arm_uc_metadata_header_v2.h" 00030 00031 #define __STDC_FORMAT_MACROS 00032 #include <inttypes.h> 00033 #include <stdio.h> 00034 #include <errno.h> 00035 #include <pthread.h> 00036 #include <stdlib.h> 00037 #include <sys/stat.h> 00038 #include <sys/wait.h> 00039 00040 extern linux_worker_thread_info_t linux_worker_thread; 00041 00042 /* worker struct, must be accessible externally */ 00043 arm_ucp_worker_config_t arm_uc_worker_parameters = { 0 }; 00044 00045 static FILE *arm_uc_firmware_descriptor = NULL; 00046 00047 static arm_uc_error_t spawn_thread(void *(*start_routine)(void *), void *arg) 00048 { 00049 arm_uc_error_t result = {ERR_NONE}; 00050 00051 /* Get the thread mutex. This prevents another thread from being spawned until this one completes. 00052 There should only ever be one thread at a time, since they are spawned via a single-threaded 00053 state machine, but this guarantees that there will only be one. */ 00054 int status = pthread_mutex_trylock(&linux_worker_thread.mutex); 00055 if (status == EBUSY) { 00056 ARM_UC_SET_ERROR(result, ERR_NOT_READY); 00057 } else if (status != 0) { 00058 uint32_t code = (TWO_CC('P', 'T') << 16) | (status & 0xFFFF); 00059 ARM_UC_SET_ERROR(result, code); 00060 } 00061 /* Create "detached thread" attribute only once */ 00062 if (result.error == ERR_NONE && linux_worker_thread.attr_initialized == 0) { 00063 if ((status = pthread_attr_init(&linux_worker_thread.attr)) != 0) { 00064 result.error = ERR_INVALID_PARAMETER; 00065 pthread_mutex_unlock(&linux_worker_thread.mutex); 00066 } else { 00067 if ((status = pthread_attr_setdetachstate(&linux_worker_thread.attr, PTHREAD_CREATE_DETACHED)) != 0) { 00068 result.error = ERR_INVALID_PARAMETER; 00069 pthread_mutex_unlock(&linux_worker_thread.mutex); 00070 } else { 00071 linux_worker_thread.attr_initialized = 1; 00072 } 00073 } 00074 } 00075 if (result.error == ERR_NONE) { 00076 /* create a detached thread to execute the supplied routine */ 00077 int status = pthread_create(&linux_worker_thread.thread, 00078 &linux_worker_thread.attr, 00079 start_routine, 00080 arg); 00081 00082 /* check if thread was created successfully */ 00083 if (status != 0) { 00084 result.code = ERR_INVALID_PARAMETER; 00085 pthread_mutex_unlock(&linux_worker_thread.mutex); 00086 } 00087 } 00088 return result; 00089 } 00090 00091 /** 00092 * @brief Initialize the underlying storage and set the callback handler. 00093 * 00094 * @param callback Function pointer to event handler. 00095 * @return Returns ERR_NONE on accept, and signals the event handler with 00096 * either DONE or ERROR when complete. 00097 * Returns ERR_INVALID_PARAMETER on reject, and no signal is sent. 00098 */ 00099 arm_uc_error_t ARM_UC_PAL_Linux_Initialize(ARM_UC_PAAL_UPDATE_SignalEvent_t callback) 00100 { 00101 arm_uc_error_t result = { .code = ERR_INVALID_PARAMETER }; 00102 00103 if (callback) { 00104 arm_uc_pal_linux_internal_set_callback(callback); 00105 00106 /* create folder for headers if it does not already exist */ 00107 errno = 0; 00108 int status = mkdir(ARM_UC_HEADER_FOLDER_PATH, 0700); 00109 00110 if ((status == 0) || (errno == EEXIST)) { 00111 /* create folder for firmwares if it does not already exist */ 00112 errno = 0; 00113 status = mkdir(ARM_UC_FIRMWARE_FOLDER_PATH, 0700); 00114 00115 if ((status == 0) || (errno == EEXIST)) { 00116 /* set return code on success */ 00117 result.code = ERR_NONE; 00118 } 00119 } 00120 00121 /* signal completion or perform extended preparation */ 00122 if (result.error == ERR_NONE) { 00123 /* set explicit ERR_NONE upon success */ 00124 result.code = ERR_NONE; 00125 00126 if (arm_uc_worker_parameters.initialize) { 00127 /* use extended prepare, invoke script from worker thread */ 00128 00129 /* create a second thread which executes worker_parameters_prepare */ 00130 result = spawn_thread(arm_uc_pal_linux_extended_post_worker, 00131 arm_uc_worker_parameters.initialize); 00132 } else { 00133 /* call event handler */ 00134 arm_uc_pal_linux_signal_callback(ARM_UC_PAAL_EVENT_INITIALIZE_DONE, false); 00135 } 00136 } 00137 00138 } 00139 00140 return result; 00141 } 00142 00143 /** 00144 * @brief Get maximum number of supported storage locations. 00145 * 00146 * @return Number of storage locations. 00147 */ 00148 uint32_t ARM_UC_PAL_Linux_GetMaxID(void) 00149 { 00150 return 1; 00151 } 00152 00153 /** 00154 * @brief Prepare the storage layer for a new firmware image. 00155 * @details The storage location is set up to receive an image with 00156 * the details passed in the details struct. 00157 * 00158 * @param location Storage location ID. 00159 * @param details Pointer to a struct with firmware details. 00160 * @param buffer Temporary buffer for formatting and storing metadata. 00161 * @return Returns ERR_NONE on accept, and signals the event handler with 00162 * either DONE or ERROR when complete. 00163 * Returns ERR_INVALID_PARAMETER on reject, and no signal is sent. 00164 */ 00165 arm_uc_error_t ARM_UC_PAL_Linux_Prepare(uint32_t location, 00166 const arm_uc_firmware_details_t *details, 00167 arm_uc_buffer_t *buffer) 00168 { 00169 arm_uc_error_t result = { .code = ERR_INVALID_PARAMETER }; 00170 00171 if (details && buffer) { 00172 UC_PAAL_TRACE("details size: %" PRIu64, details->size); 00173 00174 /* write header */ 00175 result = arm_uc_pal_linux_internal_write_header(&location, details); 00176 00177 /* allocate space for firmware */ 00178 if (result.error == ERR_NONE) { 00179 char file_path[ARM_UC_MAXIMUM_FILE_AND_PATH_LENGTH] = { 0 }; 00180 00181 /* construct header file path */ 00182 result = arm_uc_pal_linux_internal_file_path(file_path, 00183 ARM_UC_MAXIMUM_FILE_AND_PATH_LENGTH, 00184 ARM_UC_FIRMWARE_FOLDER_PATH, 00185 "firmware", 00186 &location); 00187 00188 UC_PAAL_TRACE("file path: %s", file_path); 00189 00190 if (result.error == ERR_NONE) { 00191 /* open file */ 00192 errno = 0; 00193 FILE *descriptor = fopen(file_path, "wb"); 00194 00195 if (descriptor != NULL) { 00196 /* allocate space by writing empty file */ 00197 memset(buffer->ptr, 0, buffer->size_max); 00198 buffer->size = buffer->size_max; 00199 00200 uint64_t index = 0; 00201 /* 00202 * writing of full file is not enabled by default now. Few drawbacks of writing before download: 00203 * -kernel watchdog issue due some file IO problem with a huge write (around 4GB) 00204 * -wear of the MCC device for unnecessary physical writes (there is max number of writes that can be done before physical cells of memory break) 00205 * -increased time of update process. specially with huge files this will be many minutes of extra time spend to MCC write. 00206 */ 00207 #ifdef WRITE_FULL_PHYSICAL_FILE 00208 uint64_t writeSize = details->size; 00209 #else 00210 uint64_t writeSize = 1; 00211 #endif 00212 while (index < writeSize) { 00213 // calculate write size to handle overspill 00214 size_t actual_size = details->size - index; 00215 00216 if (actual_size > buffer->size) { 00217 actual_size = buffer->size; 00218 } 00219 00220 /* write buffer */ 00221 size_t xfer_size = fwrite(buffer->ptr, 00222 sizeof(uint8_t), 00223 actual_size, 00224 descriptor); 00225 00226 /* break out if write failed */ 00227 if (xfer_size == actual_size) { 00228 index += actual_size; 00229 } else { 00230 result.code = PAAL_ERR_FIRMWARE_TOO_LARGE; 00231 break; 00232 } 00233 } 00234 00235 /* close file after write */ 00236 int status = fclose(descriptor); 00237 00238 if (status == EOF) { 00239 UC_PAAL_ERR_MSG("failed to allocate space for firmware"); 00240 result.code = ERR_INVALID_PARAMETER; 00241 } 00242 } else { 00243 UC_PAAL_ERR_MSG("failed to open file: %s", strerror(errno)); 00244 } 00245 } else { 00246 UC_PAAL_ERR_MSG("file name and path too long"); 00247 } 00248 } else { 00249 UC_PAAL_ERR_MSG("could not write header"); 00250 } 00251 00252 /* signal completion or perform extended preparation */ 00253 if (result.error == ERR_NONE) { 00254 /* set explicit ERR_NONE upon success */ 00255 result.code = ERR_NONE; 00256 00257 if (arm_uc_worker_parameters.prepare) { 00258 /* use extended prepare, invoke script from worker thread */ 00259 /* export location */ 00260 arm_uc_pal_linux_internal_set_location(&location); 00261 00262 /* create a second thread which executes worker_parameters_prepare */ 00263 result = spawn_thread(arm_uc_pal_linux_extended_post_worker, 00264 arm_uc_worker_parameters.prepare); 00265 } else { 00266 /* call event handler */ 00267 arm_uc_pal_linux_signal_callback(ARM_UC_PAAL_EVENT_PREPARE_DONE, false); 00268 } 00269 } 00270 } 00271 00272 return result; 00273 } 00274 00275 /** 00276 * @brief Write a fragment to the indicated storage location. 00277 * @details The storage location must have been allocated using the Prepare 00278 * call. The call is expected to write the entire fragment before 00279 * signaling completion. 00280 * 00281 * @param location Storage location ID. 00282 * @param offset Offset in bytes to where the fragment should be written. 00283 * @param buffer Pointer to buffer struct with fragment. 00284 * @return Returns ERR_NONE on accept, and signals the event handler with 00285 * either DONE or ERROR when complete. 00286 * Returns ERR_INVALID_PARAMETER on reject, and no signal is sent. 00287 */ 00288 arm_uc_error_t ARM_UC_PAL_Linux_Write(uint32_t location, 00289 uint32_t offset, 00290 const arm_uc_buffer_t *buffer) 00291 { 00292 arm_uc_error_t result = { .code = ERR_INVALID_PARAMETER }; 00293 00294 if (buffer) { 00295 /* reverse default error code */ 00296 result.code = ERR_NONE; 00297 00298 /* open file if descriptor is not set */ 00299 if (arm_uc_firmware_descriptor == NULL) { 00300 char file_path[ARM_UC_MAXIMUM_FILE_AND_PATH_LENGTH] = { 0 }; 00301 00302 /* construct firmware file path */ 00303 result = arm_uc_pal_linux_internal_file_path(file_path, 00304 ARM_UC_MAXIMUM_FILE_AND_PATH_LENGTH, 00305 ARM_UC_FIRMWARE_FOLDER_PATH, 00306 "firmware", 00307 &location); 00308 00309 if (result.error == ERR_NONE) { 00310 /* open file */ 00311 if (arm_uc_worker_parameters.write) { 00312 /* in extended write, each fragment is stored in its own file */ 00313 arm_uc_firmware_descriptor = fopen(file_path, "w+b"); 00314 00315 /* export offset before resetting it */ 00316 arm_uc_pal_linux_internal_set_offset(offset); 00317 offset = 0; 00318 } else { 00319 /* in normal write, each fragment is added to an existing file */ 00320 arm_uc_firmware_descriptor = fopen(file_path, "r+b"); 00321 } 00322 } else { 00323 UC_PAAL_ERR_MSG("firmware file name and path too long"); 00324 } 00325 } 00326 00327 /* continue if file is open */ 00328 if (arm_uc_firmware_descriptor != NULL) { 00329 /* set write position */ 00330 int status = fseeko(arm_uc_firmware_descriptor, 00331 offset, 00332 SEEK_SET); 00333 00334 /* continue if position is set */ 00335 if (status == 0) { 00336 /* write buffer */ 00337 size_t xfer_size = fwrite(buffer->ptr, 00338 sizeof(uint8_t), 00339 buffer->size, 00340 arm_uc_firmware_descriptor); 00341 00342 /* set error code if write failed */ 00343 if (xfer_size != buffer->size) { 00344 UC_PAAL_ERR_MSG("failed to write firmware"); 00345 result.code = ERR_INVALID_PARAMETER; 00346 } 00347 00348 /* if using extended write */ 00349 if (arm_uc_worker_parameters.write) { 00350 /* close file after write */ 00351 int status = fclose(arm_uc_firmware_descriptor); 00352 arm_uc_firmware_descriptor = NULL; 00353 00354 if (status == EOF) { 00355 UC_PAAL_ERR_MSG("failed to close firmware file"); 00356 result.code = ERR_INVALID_PARAMETER; 00357 } 00358 } 00359 } else { 00360 UC_PAAL_ERR_MSG("failed to seek in firmware"); 00361 result.code = ERR_INVALID_PARAMETER; 00362 } 00363 } 00364 00365 /* signal completion or perform extended write */ 00366 if (result.error == ERR_NONE) { 00367 /* set explicit ERR_NONE */ 00368 result.code = ERR_NONE; 00369 00370 if (arm_uc_worker_parameters.write) { 00371 /* use extended write, invoke script from worker thread */ 00372 /* export location */ 00373 arm_uc_pal_linux_internal_set_location(&location); 00374 00375 /* create a second thread which executes worker_parameters_write */ 00376 result = spawn_thread(arm_uc_pal_linux_extended_post_worker, 00377 arm_uc_worker_parameters.write); 00378 } else { 00379 /* call event handler */ 00380 arm_uc_pal_linux_signal_callback(ARM_UC_PAAL_EVENT_WRITE_DONE, false); 00381 } 00382 } 00383 } 00384 00385 return result; 00386 } 00387 00388 /** 00389 * @brief Close storage location for writing and flush pending data. 00390 * 00391 * @param location 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_Linux_Finalize(uint32_t location) 00397 { 00398 arm_uc_error_t result = { .code = ERR_NONE }; 00399 00400 /* only close firmware file if descriptor is not NULL */ 00401 if (arm_uc_firmware_descriptor != NULL) { 00402 /* close file */ 00403 int status = fclose(arm_uc_firmware_descriptor); 00404 arm_uc_firmware_descriptor = NULL; 00405 00406 if (status == EOF) { 00407 UC_PAAL_ERR_MSG("failed to close firmware file"); 00408 result.code = ERR_INVALID_PARAMETER; 00409 } 00410 } 00411 00412 /* signal completion or perform extended finalization */ 00413 if (result.error == ERR_NONE) { 00414 /* explicitly set code to ERR_NONE */ 00415 result.code = ERR_NONE; 00416 00417 /* use extended finalize, invoke script from worker thread */ 00418 if (arm_uc_worker_parameters.finalize) { 00419 /* export location */ 00420 arm_uc_pal_linux_internal_set_location(&location); 00421 00422 /* create a second thread which executes worker_parameters_finalize */ 00423 result = spawn_thread(arm_uc_pal_linux_extended_post_worker, 00424 arm_uc_worker_parameters.finalize); 00425 } else { 00426 /* call event handler */ 00427 arm_uc_pal_linux_signal_callback(ARM_UC_PAAL_EVENT_FINALIZE_DONE, false); 00428 } 00429 } 00430 00431 return result; 00432 } 00433 00434 /** 00435 * @brief Read a fragment from the indicated storage location. 00436 * @details The function will read until the buffer is full or the end of 00437 * the storage location has been reached. The actual amount of 00438 * bytes read is set in the buffer struct. 00439 * 00440 * @param location Storage location ID. 00441 * @param offset Offset in bytes to read from. 00442 * @param buffer Pointer to buffer struct to store fragment. buffer->size 00443 * contains the intended read size. 00444 * @return Returns ERR_NONE on accept, and signals the event handler with 00445 * either DONE or ERROR when complete. 00446 * Returns ERR_INVALID_PARAMETER on reject, and no signal is sent. 00447 * buffer->size contains actual bytes read on return. 00448 */ 00449 arm_uc_error_t ARM_UC_PAL_Linux_Read(uint32_t location, 00450 uint32_t offset, 00451 arm_uc_buffer_t *buffer) 00452 { 00453 arm_uc_error_t result = { .code = ERR_INVALID_PARAMETER }; 00454 00455 if (buffer) { 00456 /* use extended finalize, invoke script from worker thread */ 00457 if (arm_uc_worker_parameters.read) { 00458 /* export location, offset and buffer */ 00459 arm_uc_pal_linux_internal_set_location(&location); 00460 arm_uc_pal_linux_internal_set_offset(offset); 00461 arm_uc_pal_linux_internal_set_buffer(buffer); 00462 00463 /* create a second thread which executes worker_parameters_read */ 00464 result = spawn_thread(arm_uc_pal_linux_extended_pre_worker, 00465 arm_uc_worker_parameters.read); 00466 } else { 00467 /* normal read */ 00468 char file_path[ARM_UC_MAXIMUM_FILE_AND_PATH_LENGTH] = { 0 }; 00469 00470 /* construct firmware file path */ 00471 result = arm_uc_pal_linux_internal_file_path(file_path, 00472 ARM_UC_MAXIMUM_FILE_AND_PATH_LENGTH, 00473 ARM_UC_FIRMWARE_FOLDER_PATH, 00474 "firmware", 00475 &location); 00476 00477 /* file path is valid */ 00478 if (result.error == ERR_NONE) { 00479 result = arm_uc_pal_linux_internal_read(file_path, offset, buffer); 00480 00481 /* signal completion */ 00482 if (result.error == ERR_NONE) { 00483 /* call event handler */ 00484 arm_uc_pal_linux_signal_callback(ARM_UC_PAAL_EVENT_READ_DONE, false); 00485 } 00486 } 00487 } 00488 } 00489 00490 return result; 00491 } 00492 00493 /** 00494 * @brief Set the firmware image in the slot to be the new active image. 00495 * @details This call is responsible for initiating the process for 00496 * applying a new/different image. Depending on the platform this 00497 * could be: 00498 * * An empty call, if the installer can deduce which slot to 00499 * choose from based on the firmware details. 00500 * * Setting a flag to indicate which slot to use next. 00501 * * Decompressing/decrypting/installing the firmware image on 00502 * top of another. 00503 * 00504 * @param location Storage location ID. 00505 * @return Returns ERR_NONE on accept, and signals the event handler with 00506 * either DONE or ERROR when complete. 00507 * Returns ERR_INVALID_PARAMETER on reject, and no signal is sent. 00508 */ 00509 arm_uc_error_t ARM_UC_PAL_Linux_Activate(uint32_t location) 00510 { 00511 arm_uc_error_t result = { .code = ERR_INVALID_PARAMETER }; 00512 00513 /* read firmware details from location */ 00514 arm_uc_firmware_details_t details = { 0 }; 00515 result = arm_uc_pal_linux_internal_read_header(&location, &details); 00516 00517 if (result.error == ERR_NONE) { 00518 UC_PAAL_TRACE("version: %" PRIu64, details.version); 00519 UC_PAAL_TRACE("size: %"PRIu64, details.size); 00520 00521 /* write details to active location */ 00522 result = arm_uc_pal_linux_internal_write_header(NULL, &details); 00523 00524 if (result.error == ERR_NONE) { 00525 /* explicitly set code to ERR_NONE */ 00526 result.code = ERR_NONE; 00527 00528 /* use extended activate, invoke script from worker thread */ 00529 if (arm_uc_worker_parameters.activate) { 00530 /* export location */ 00531 arm_uc_pal_linux_internal_set_location(&location); 00532 00533 /* create a second thread which executes worker_parameters_read */ 00534 result = spawn_thread(arm_uc_pal_linux_extended_post_worker, 00535 arm_uc_worker_parameters.activate); 00536 } else { 00537 arm_uc_pal_linux_signal_callback(ARM_UC_PAAL_EVENT_ACTIVATE_DONE, false); 00538 } 00539 } 00540 } 00541 00542 return result; 00543 } 00544 00545 /** 00546 * @brief Get firmware details for the actively running firmware. 00547 * @details This call populates the passed details struct with information 00548 * about the currently active firmware image. Only the fields 00549 * marked as supported in the capabilities bitmap will have valid 00550 * values. 00551 * 00552 * @param details Pointer to firmware details struct to be populated. 00553 * @return Returns ERR_NONE on accept, and signals the event handler with 00554 * either DONE or ERROR when complete. 00555 * Returns ERR_INVALID_PARAMETER on reject, and no signal is sent. 00556 */ 00557 arm_uc_error_t ARM_UC_PAL_Linux_GetActiveFirmwareDetails(arm_uc_firmware_details_t *details) 00558 { 00559 arm_uc_error_t result = { .code = ERR_INVALID_PARAMETER }; 00560 00561 if (details) { 00562 /* use extended get firmware details, invoke script from worker thread */ 00563 if (arm_uc_worker_parameters.active_details) { 00564 /* export details */ 00565 arm_uc_pal_linux_internal_set_details(details); 00566 00567 /* create a second thread which executes worker_parameters_read */ 00568 result = spawn_thread(arm_uc_pal_linux_extended_pre_worker, 00569 arm_uc_worker_parameters.active_details); 00570 00571 } else { 00572 /* normal read */ 00573 result = arm_uc_pal_linux_internal_read_header(NULL, details); 00574 00575 if (result.error == ERR_NONE) { 00576 UC_PAAL_TRACE("version: %" PRIu64, details->version); 00577 UC_PAAL_TRACE("size: %"PRIu64, details->size); 00578 00579 if (result.error == ERR_NONE) { 00580 arm_uc_pal_linux_signal_callback(ARM_UC_PAAL_EVENT_GET_ACTIVE_FIRMWARE_DETAILS_DONE, false); 00581 } 00582 } 00583 } 00584 } 00585 00586 return result; 00587 } 00588 00589 /** 00590 * @brief Get firmware details for the firmware image in the slot passed. 00591 * @details This call populates the passed details struct with information 00592 * about the firmware image in the slot passed. Only the fields 00593 * marked as supported in the capabilities bitmap will have valid 00594 * values. 00595 * 00596 * @param details Pointer to firmware details struct to be populated. 00597 * @return Returns ERR_NONE on accept, and signals the event handler with 00598 * either DONE or ERROR when complete. 00599 * Returns ERR_INVALID_PARAMETER on reject, and no signal is sent. 00600 */ 00601 arm_uc_error_t ARM_UC_PAL_Linux_GetFirmwareDetails(uint32_t location, 00602 arm_uc_firmware_details_t *details) 00603 { 00604 arm_uc_error_t result = { .code = ERR_INVALID_PARAMETER }; 00605 00606 if (details) { 00607 /* use extended get firmware details, invoke script from worker thread */ 00608 if (arm_uc_worker_parameters.details) { 00609 /* export location and details */ 00610 arm_uc_pal_linux_internal_set_location(&location); 00611 arm_uc_pal_linux_internal_set_details(details); 00612 00613 /* create a second thread which executes worker_parameters_read */ 00614 result = spawn_thread(arm_uc_pal_linux_extended_pre_worker, 00615 arm_uc_worker_parameters.details); 00616 } else { 00617 /* normal read */ 00618 result = arm_uc_pal_linux_internal_read_header(&location, details); 00619 00620 if (result.error == ERR_NONE) { 00621 UC_PAAL_TRACE("version: %" PRIu64, details->version); 00622 UC_PAAL_TRACE("size: %"PRIu64, details->size); 00623 00624 arm_uc_pal_linux_signal_callback(ARM_UC_PAAL_EVENT_GET_FIRMWARE_DETAILS_DONE, false); 00625 } 00626 } 00627 } 00628 00629 return result; 00630 } 00631 00632 /** 00633 * @brief Get details for the component responsible for installation. 00634 * @details This call populates the passed details struct with information 00635 * about the local installer. Only the fields marked as supported 00636 * in the capabilities bitmap will have valid values. The 00637 * installer could be the bootloader, a recovery image, or some 00638 * other component responsible for applying the new firmware 00639 * image. 00640 * 00641 * @param details Pointer to installer details struct to be populated. 00642 * @return Returns ERR_NONE on accept, and signals the event handler with 00643 * either DONE or ERROR when complete. 00644 * Returns ERR_INVALID_PARAMETER on reject, and no signal is sent. 00645 */ 00646 arm_uc_error_t ARM_UC_PAL_Linux_GetInstallerDetails(arm_uc_installer_details_t *details) 00647 { 00648 arm_uc_error_t result = { .code = ERR_INVALID_PARAMETER }; 00649 00650 if (details) { 00651 /* use extended installer details, invoke script from worker thread */ 00652 if (arm_uc_worker_parameters.installer) { 00653 /* export installer details */ 00654 arm_uc_pal_linux_internal_set_installer(details); 00655 00656 /* create a second thread which executes worker_parameters_read */ 00657 result = spawn_thread(arm_uc_pal_linux_extended_pre_worker, 00658 arm_uc_worker_parameters.installer); 00659 } else { 00660 /* normal read */ 00661 result = arm_uc_pal_linux_internal_read_installer(details); 00662 00663 if (result.error == ERR_NONE) { 00664 arm_uc_pal_linux_signal_callback(ARM_UC_PAAL_EVENT_GET_INSTALLER_DETAILS_DONE, false); 00665 } 00666 } 00667 } 00668 00669 return result; 00670 } 00671 00672 /** 00673 * @brief Write a manifest to a file. 00674 * @param location Storage location ID. 00675 * @param buffer Buffer that contains the manifest. 00676 * @return Returns ERR_NONE if the manifest was written. 00677 * Returns ERR_INVALID_PARAMETER on error. 00678 */ 00679 arm_uc_error_t ARM_UC_PAL_Linux_WriteManifest(uint32_t location, const arm_uc_buffer_t *buffer) 00680 { 00681 return arm_uc_pal_linux_internal_write_manifest(&location, buffer); 00682 } 00683 00684 #endif /* TARGET_IS_PC_LINUX */ 00685 #endif /* ARM_UC_FEATURE_PAL_LINUX */
Generated on Tue Jul 12 2022 20:20:57 by
