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