Simulated product dispenser
Fork of mbed-cloud-workshop-connect-HTS221 by
arm_uc_pal_linux_implementation_internal.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 00023 #include "update-client-common/arm_uc_trace.h" 00024 #include "update-client-common/arm_uc_utilities.h" 00025 #include "update-client-common/arm_uc_metadata_header_v2.h" 00026 #include "update-client-common/arm_uc_scheduler.h" 00027 00028 #define __STDC_FORMAT_MACROS 00029 #include <inttypes.h> 00030 #include <stdio.h> 00031 #include <errno.h> 00032 #include <pthread.h> 00033 #include <stdlib.h> 00034 #include <sys/stat.h> 00035 #include <sys/wait.h> 00036 00037 /* pointer to external callback handler */ 00038 static ARM_UC_PAAL_UPDATE_SignalEvent_t arm_uc_pal_external_callback = NULL; 00039 00040 linux_worker_thread_info_t linux_worker_thread = {0, PTHREAD_MUTEX_INITIALIZER}; 00041 00042 // storage set aside for adding event_cb to the event queue 00043 static arm_uc_callback_t event_cb_storage = { 0 }; 00044 00045 void arm_uc_pal_linux_signal_callback(uint32_t event, bool from_thread) 00046 { 00047 if (arm_uc_pal_external_callback) 00048 { 00049 if (from_thread) { 00050 /* Run given callback in the update client's thread */ 00051 ARM_UC_PostCallback(&event_cb_storage, arm_uc_pal_external_callback, event); 00052 } else { 00053 arm_uc_pal_external_callback(event); 00054 } 00055 } 00056 if (from_thread) { 00057 /* The last thing that the thread does is call arm_uc_pal_linux_signal_callback(), 00058 * so unlock the thread mutex so that another thread can be created if needed */ 00059 pthread_mutex_unlock(&linux_worker_thread.mutex); 00060 } 00061 } 00062 00063 void arm_uc_pal_linux_internal_set_callback(ARM_UC_PAAL_UPDATE_SignalEvent_t callback) 00064 { 00065 arm_uc_pal_external_callback = callback; 00066 } 00067 00068 static uint32_t arm_uc_offset = 0; 00069 static arm_uc_buffer_t* arm_uc_buffer = NULL; 00070 static arm_uc_firmware_details_t* arm_uc_details = NULL; 00071 static arm_uc_installer_details_t* arm_uc_installer = NULL; 00072 static uint32_t* arm_uc_location = NULL; 00073 static uint32_t arm_uc_location_buffer = 0; 00074 00075 void arm_uc_pal_linux_internal_set_offset(uint32_t offset) 00076 { 00077 arm_uc_offset = offset; 00078 } 00079 00080 void arm_uc_pal_linux_internal_set_buffer(arm_uc_buffer_t* buffer) 00081 { 00082 arm_uc_buffer = buffer; 00083 } 00084 00085 void arm_uc_pal_linux_internal_set_details(arm_uc_firmware_details_t* details) 00086 { 00087 arm_uc_details = details; 00088 } 00089 00090 void arm_uc_pal_linux_internal_set_installer(arm_uc_installer_details_t* details) 00091 { 00092 arm_uc_installer = details; 00093 } 00094 00095 void arm_uc_pal_linux_internal_set_location(uint32_t* location) 00096 { 00097 if (location) 00098 { 00099 arm_uc_location_buffer = *location; 00100 arm_uc_location = &arm_uc_location_buffer; 00101 } 00102 else 00103 { 00104 arm_uc_location = NULL; 00105 } 00106 } 00107 00108 arm_uc_error_t arm_uc_pal_linux_internal_file_path(char* buffer, 00109 size_t buffer_length, 00110 const char* folder, 00111 const char* type, 00112 uint32_t* location) 00113 { 00114 arm_uc_error_t result = { .code = ERR_INVALID_PARAMETER }; 00115 00116 if (buffer && folder && type) 00117 { 00118 int actual_length = 0; 00119 00120 if (location) 00121 { 00122 /* construct file path using location */ 00123 actual_length = snprintf(buffer, buffer_length, 00124 "%s/%s_%" PRIu32 ".bin", folder, type, *location); 00125 } 00126 else 00127 { 00128 /* construct file path without location */ 00129 actual_length = snprintf(buffer, buffer_length, 00130 "%s/%s.bin", folder, type); 00131 } 00132 00133 /* check that the buffer is large enough */ 00134 if (actual_length < buffer_length) 00135 { 00136 result.code = ERR_NONE; 00137 } 00138 } 00139 00140 return result; 00141 } 00142 00143 static bool arm_uc_pal_linux_internal_command(arm_ucp_worker_t* parameters, 00144 char* command, 00145 size_t command_length) 00146 { 00147 /* default to failed */ 00148 bool valid = false; 00149 00150 if (parameters && command) 00151 { 00152 /* invert status */ 00153 valid = true; 00154 00155 int length = snprintf(command, 00156 command_length, 00157 "%s ", 00158 parameters->command); 00159 00160 /* initialize remaining */ 00161 int remaining = command_length - length; 00162 00163 /* add header parameter if requested */ 00164 if ((remaining > 0) && (parameters->header)) 00165 { 00166 char file_path[ARM_UC_MAXIMUM_FILE_AND_PATH_LENGTH] = { 0 }; 00167 00168 /* construct header file path */ 00169 arm_uc_error_t result = 00170 arm_uc_pal_linux_internal_file_path(file_path, 00171 sizeof(file_path), 00172 ARM_UC_HEADER_FOLDER_PATH, 00173 "header", 00174 arm_uc_location); 00175 00176 /* generated valid file path */ 00177 if (result.error == ERR_NONE) 00178 { 00179 /* add parameter to command line */ 00180 length += snprintf(&command[length], 00181 remaining, 00182 "-h %s ", 00183 file_path); 00184 } 00185 00186 /* update remaining */ 00187 remaining = ARM_UC_MAXIMUM_FILE_AND_PATH_LENGTH - length; 00188 00189 /* check validity */ 00190 valid = ((result.error == ERR_NONE) && (remaining > 0)); 00191 } 00192 00193 /* add firmware parameter if requested */ 00194 if ((valid) && (parameters->firmware)) 00195 { 00196 char file_path[ARM_UC_MAXIMUM_FILE_AND_PATH_LENGTH] = { 0 }; 00197 00198 /* construct firmware file path */ 00199 arm_uc_error_t result = 00200 arm_uc_pal_linux_internal_file_path(file_path, 00201 sizeof(file_path), 00202 ARM_UC_FIRMWARE_FOLDER_PATH, 00203 "firmware", 00204 arm_uc_location); 00205 00206 /* generated valid file path */ 00207 if (result.error == ERR_NONE) 00208 { 00209 /* add parameter to command line */ 00210 length += snprintf(&command[length], 00211 remaining, 00212 "-f %s ", 00213 file_path); 00214 } 00215 00216 /* update remaining */ 00217 remaining = ARM_UC_MAXIMUM_FILE_AND_PATH_LENGTH - length; 00218 00219 /* check validity */ 00220 valid = ((result.error == ERR_NONE) && (remaining > 0)); 00221 } 00222 00223 /* add location parameter if requested */ 00224 if ((valid) && (parameters->location)) 00225 { 00226 /* add parameter to command line */ 00227 length += snprintf(&command[length], 00228 remaining, 00229 "-l %" PRIu32 " ", 00230 *arm_uc_location); 00231 00232 /* update remaining */ 00233 remaining = ARM_UC_MAXIMUM_FILE_AND_PATH_LENGTH - length; 00234 00235 /* check validity */ 00236 valid = (remaining > 0); 00237 } 00238 00239 /* add offset parameter if requested */ 00240 if ((valid) && (parameters->offset)) 00241 { 00242 /* add parameter to command line */ 00243 length += snprintf(&command[length], 00244 remaining, 00245 "-o %" PRIu32 " ", 00246 arm_uc_offset); 00247 00248 /* update remaining */ 00249 remaining = ARM_UC_MAXIMUM_FILE_AND_PATH_LENGTH - length; 00250 00251 /* check validity */ 00252 valid = (remaining > 0); 00253 } 00254 00255 /* add size parameter if requested */ 00256 if ((valid) && (parameters->size)) 00257 { 00258 if (arm_uc_buffer) 00259 { 00260 /* add parameter to command line */ 00261 length += snprintf(&command[length], 00262 remaining, 00263 "-s %" PRIu32 " ", 00264 arm_uc_buffer->size_max); 00265 00266 /* update remaining */ 00267 remaining = ARM_UC_MAXIMUM_FILE_AND_PATH_LENGTH - length; 00268 00269 /* check validity */ 00270 valid = (remaining > 0); 00271 } 00272 else 00273 { 00274 valid = false; 00275 } 00276 } 00277 } 00278 00279 return valid; 00280 } 00281 00282 arm_uc_error_t arm_uc_pal_linux_internal_read(const char* file_path, 00283 uint32_t offset, 00284 arm_uc_buffer_t* buffer) 00285 { 00286 /* default to failure result */ 00287 arm_uc_error_t result = { .code = ERR_INVALID_PARAMETER }; 00288 00289 if (file_path && buffer) 00290 { 00291 /* open file */ 00292 errno = 0; 00293 FILE* descriptor = fopen(file_path, "rb"); 00294 00295 /* continue if file is open */ 00296 if (descriptor != NULL) 00297 { 00298 /* set read position */ 00299 int status = fseek(descriptor, offset, SEEK_SET); 00300 00301 /* continue if position is set */ 00302 if (status == 0) 00303 { 00304 /* read buffer */ 00305 errno = 0; 00306 size_t xfer_size = fread(buffer->ptr, 00307 sizeof(uint8_t), 00308 buffer->size, 00309 descriptor); 00310 00311 /* set buffer size if read succeeded */ 00312 status = ferror(descriptor); 00313 00314 if (status == 0) 00315 { 00316 buffer->size = xfer_size; 00317 00318 /* set successful result */ 00319 result.code = ERR_NONE; 00320 } 00321 else 00322 { 00323 /* set error code if read failed */ 00324 UC_PAAL_ERR_MSG("failed to read %s: %s", file_path, strerror(errno)); 00325 buffer->size = 0; 00326 } 00327 00328 /* close file after read */ 00329 fclose(descriptor); 00330 } 00331 else 00332 { 00333 UC_PAAL_ERR_MSG("failed to seek in: %s", file_path); 00334 } 00335 } 00336 else 00337 { 00338 UC_PAAL_ERR_MSG("failed to open %s: %s", file_path, strerror(errno)); 00339 } 00340 } 00341 00342 return result; 00343 } 00344 00345 arm_uc_error_t arm_uc_pal_linux_internal_read_header(uint32_t* location, 00346 arm_uc_firmware_details_t* details) 00347 { 00348 arm_uc_error_t result = { .code = ERR_INVALID_PARAMETER }; 00349 00350 if (details) 00351 { 00352 /* construct header file path */ 00353 char file_path[ARM_UC_MAXIMUM_FILE_AND_PATH_LENGTH] = { 0 }; 00354 00355 result = arm_uc_pal_linux_internal_file_path(file_path, 00356 ARM_UC_MAXIMUM_FILE_AND_PATH_LENGTH, 00357 ARM_UC_HEADER_FOLDER_PATH, 00358 "header", 00359 location); 00360 00361 /* file path is valid */ 00362 if (result.error == ERR_NONE) 00363 { 00364 /* allocate external header sized read buffer since it will be 00365 large enough to hold either an internal or external header. 00366 */ 00367 uint8_t read_buffer[ARM_UC_EXTERNAL_HEADER_SIZE_V2] = { 0 }; 00368 00369 arm_uc_buffer_t buffer = { 00370 .size_max = sizeof(read_buffer), 00371 .size = sizeof(read_buffer), 00372 .ptr = read_buffer 00373 }; 00374 00375 /* read metadata header */ 00376 result = arm_uc_pal_linux_internal_read(file_path, 0, &buffer); 00377 00378 /* check return code */ 00379 if (result.error == ERR_NONE) 00380 { 00381 UC_PAAL_TRACE("header bytes: %u", buffer.size); 00382 00383 /* read out header magic */ 00384 uint32_t headerMagic = arm_uc_parse_uint32(&read_buffer[0]); 00385 00386 /* read out header magic */ 00387 uint32_t headerVersion = arm_uc_parse_uint32(&read_buffer[4]); 00388 00389 /* choose version to decode */ 00390 if ((headerMagic == ARM_UC_INTERNAL_HEADER_MAGIC_V2) && 00391 (headerVersion == ARM_UC_INTERNAL_HEADER_VERSION_V2) && 00392 (buffer.size == ARM_UC_INTERNAL_HEADER_SIZE_V2)) 00393 { 00394 result = arm_uc_parse_internal_header_v2(read_buffer, details); 00395 } 00396 else if ((headerMagic == ARM_UC_EXTERNAL_HEADER_MAGIC_V2) && 00397 (headerVersion == ARM_UC_EXTERNAL_HEADER_VERSION_V2) && 00398 (buffer.size == ARM_UC_EXTERNAL_HEADER_SIZE_V2)) 00399 { 00400 result = arm_uc_parse_external_header_v2(read_buffer, details); 00401 } 00402 else 00403 { 00404 UC_PAAL_ERR_MSG("invalid header in slot %" PRIu32, location); 00405 00406 /* invalid header format */ 00407 result.code = ERR_INVALID_PARAMETER; 00408 } 00409 } 00410 else 00411 { 00412 /* unsuccessful read */ 00413 UC_PAAL_ERR_MSG("unable to read header in slot %" PRIX32, location); 00414 } 00415 } 00416 else 00417 { 00418 UC_PAAL_ERR_MSG("header file name and path too long"); 00419 } 00420 } 00421 00422 return result; 00423 } 00424 00425 arm_uc_error_t arm_uc_pal_linux_internal_read_installer(arm_uc_installer_details_t* details) 00426 { 00427 arm_uc_error_t result = { .code = ERR_INVALID_PARAMETER }; 00428 00429 if (details) 00430 { 00431 /* construct file path */ 00432 char file_path[ARM_UC_MAXIMUM_FILE_AND_PATH_LENGTH] = { 0 }; 00433 00434 result = arm_uc_pal_linux_internal_file_path(file_path, 00435 ARM_UC_MAXIMUM_FILE_AND_PATH_LENGTH, 00436 ARM_UC_INSTALLER_FOLDER_PATH, 00437 "installer", 00438 NULL); 00439 00440 /* file path is valid */ 00441 if (result.error == ERR_NONE) 00442 { 00443 uint8_t read_buffer[2 * sizeof(arm_uc_hash_t) + sizeof(uint32_t)] = { 0 }; 00444 00445 arm_uc_buffer_t buffer = { 00446 .size_max = sizeof(read_buffer), 00447 .size = 0, 00448 .ptr = read_buffer 00449 }; 00450 00451 /* read installer details */ 00452 result = arm_uc_pal_linux_internal_read(file_path, 0, &buffer); 00453 00454 UC_PAAL_TRACE("installer bytes: %u", buffer.size); 00455 00456 /* check return code */ 00457 if ((result.error == ERR_NONE) && 00458 (buffer.size == sizeof(read_buffer))) 00459 { 00460 memcpy(details->arm_hash, 00461 buffer.ptr, 00462 sizeof(arm_uc_hash_t)); 00463 00464 memcpy(details->oem_hash, 00465 &buffer.ptr[sizeof(arm_uc_hash_t)], 00466 sizeof(arm_uc_hash_t)); 00467 00468 details->layout = arm_uc_parse_uint32(&buffer.ptr[2 * sizeof(arm_uc_hash_t)]); 00469 } 00470 else 00471 { 00472 /* unsuccessful read */ 00473 UC_PAAL_ERR_MSG("unable to read installer details"); 00474 } 00475 } 00476 else 00477 { 00478 UC_PAAL_ERR_MSG("installer file name and path too long"); 00479 } 00480 } 00481 00482 return result; 00483 } 00484 00485 arm_uc_error_t arm_uc_pal_linux_internal_write_header(uint32_t* location, 00486 const arm_uc_firmware_details_t* details) 00487 { 00488 arm_uc_error_t result = { .code = ERR_INVALID_PARAMETER }; 00489 00490 if (details) 00491 { 00492 /* allocate external header sized buffer since it will be 00493 large enough to hold either an internal or external header. 00494 */ 00495 uint8_t temp_buffer[ARM_UC_EXTERNAL_HEADER_SIZE_V2] = { 0 }; 00496 00497 arm_uc_buffer_t buffer = { 00498 .size_max = sizeof(temp_buffer), 00499 .size = 0, 00500 .ptr = temp_buffer 00501 }; 00502 00503 /* encode firmware details in buffer */ 00504 #if ARM_UC_USE_EXTERNAL_HEADER 00505 result = arm_uc_create_external_header_v2(details, &buffer); 00506 #else 00507 result = arm_uc_create_internal_header_v2(details, &buffer); 00508 #endif 00509 00510 /* write header file */ 00511 if (result.error == ERR_NONE) 00512 { 00513 char file_path[ARM_UC_MAXIMUM_FILE_AND_PATH_LENGTH] = { 0 }; 00514 00515 /* construct header file path */ 00516 result = arm_uc_pal_linux_internal_file_path(file_path, 00517 ARM_UC_MAXIMUM_FILE_AND_PATH_LENGTH, 00518 ARM_UC_HEADER_FOLDER_PATH, 00519 "header", 00520 location); 00521 00522 if (result.error == ERR_NONE) 00523 { 00524 /* inverse result */ 00525 result.code = ERR_INVALID_PARAMETER; 00526 00527 /* open file and get file handler */ 00528 errno = 0; 00529 FILE* file = fopen(file_path, "wb"); 00530 00531 if (file != NULL) 00532 { 00533 /* write buffer to file */ 00534 size_t xfer_size = fwrite(buffer.ptr, 00535 sizeof(uint8_t), 00536 buffer.size, 00537 file); 00538 00539 UC_PAAL_TRACE("written: %u", xfer_size); 00540 00541 /* close file after write */ 00542 int status = fclose(file); 00543 00544 if ((xfer_size == buffer.size) && 00545 (status != EOF)) 00546 { 00547 /* set return code if write was successful */ 00548 result.code = ERR_NONE; 00549 } 00550 else 00551 { 00552 UC_PAAL_ERR_MSG("failed to write header"); 00553 } 00554 } 00555 else 00556 { 00557 UC_PAAL_ERR_MSG("file open failed: %s", strerror(errno)); 00558 } 00559 } 00560 else 00561 { 00562 UC_PAAL_ERR_MSG("header file name and path too long"); 00563 } 00564 } 00565 else 00566 { 00567 UC_PAAL_ERR_MSG("header too large for buffer"); 00568 } 00569 00570 } 00571 00572 return result; 00573 } 00574 00575 /** 00576 * @brief Function to run script in a worker thread before file operations. 00577 * 00578 * @param params Pointer to arm_ucp_worker_t struct. 00579 */ 00580 void* arm_uc_pal_linux_extended_pre_worker(void* params) 00581 { 00582 /* default to failure */ 00583 arm_uc_error_t result = { .code = ERR_INVALID_PARAMETER }; 00584 00585 /* get parameters */ 00586 arm_ucp_worker_t* parameters = (arm_ucp_worker_t*) params; 00587 00588 /* file path to script result */ 00589 char file_path[ARM_UC_MAXIMUM_FILE_AND_PATH_LENGTH] = { 0 }; 00590 00591 /* construct script command */ 00592 char command[ARM_UC_MAXIMUM_COMMAND_LENGTH] = { 0 }; 00593 00594 int error = 0; 00595 int valid = arm_uc_pal_linux_internal_command(parameters, 00596 command, 00597 ARM_UC_MAXIMUM_COMMAND_LENGTH); 00598 00599 /* command is valid */ 00600 if (valid) 00601 { 00602 UC_PAAL_TRACE("Extended pre-script command: %s", command); 00603 00604 /* execute script */ 00605 errno = 0; 00606 FILE* pipe = popen(command, "r"); 00607 00608 if (pipe) 00609 { 00610 /* read pipe */ 00611 size_t xfer_size = fread(file_path, 00612 sizeof(uint8_t), 00613 ARM_UC_MAXIMUM_FILE_AND_PATH_LENGTH, 00614 pipe); 00615 00616 /* trim non-printable characters */ 00617 for (size_t index = 0; index < xfer_size; index++) 00618 { 00619 /* space is the first printable character */ 00620 if (file_path[index] < ' ') 00621 { 00622 /* truncate string */ 00623 file_path[index] = '\0'; 00624 break; 00625 } 00626 } 00627 00628 int status = 0; 00629 00630 /* check fread error status */ 00631 status = ferror(pipe); 00632 if (status == 0) 00633 { 00634 /* Wait for child thread termination and check exit status */ 00635 status = pclose(pipe); 00636 00637 /* make sure child thread terminated correctly and scirpt exit status is 0 */ 00638 if (status != -1 && WIFEXITED(status)) 00639 { 00640 if (WEXITSTATUS(status) == 0) 00641 { 00642 /* switch from boolean result to arm_uc_error_t */ 00643 result.code = ERR_NONE; 00644 } 00645 else 00646 { 00647 UC_PAAL_ERR_MSG("Script exited with non-zero status %" PRId32, status); 00648 } 00649 } 00650 else 00651 { 00652 UC_PAAL_ERR_MSG("pipe terminated incorrectly %" PRId32, status); 00653 } 00654 } 00655 else 00656 { 00657 UC_PAAL_ERR_MSG("failed to read pipe: %" PRId32, status); 00658 } 00659 } 00660 else 00661 { 00662 UC_PAAL_ERR_MSG("failed to execute script: %" PRId32, errno); 00663 } 00664 } 00665 00666 /* file path is valid */ 00667 if (result.error == ERR_NONE) 00668 { 00669 /* invert status */ 00670 result.code = ERR_INVALID_PARAMETER; 00671 00672 extern arm_ucp_worker_config_t arm_uc_worker_parameters; 00673 00674 /* perform read operation */ 00675 if ((parameters == arm_uc_worker_parameters.read) && 00676 (arm_uc_buffer != NULL)) 00677 { 00678 result = arm_uc_pal_linux_internal_read(file_path, 0, arm_uc_buffer); 00679 00680 /* reset global buffer */ 00681 arm_uc_buffer = NULL; 00682 } 00683 00684 /* read details */ 00685 if ((parameters == arm_uc_worker_parameters.details) && 00686 (arm_uc_details != NULL)) 00687 { 00688 result = arm_uc_pal_linux_internal_read_header(arm_uc_location, 00689 arm_uc_details); 00690 00691 /* reset global details pointer */ 00692 arm_uc_details = NULL; 00693 } 00694 00695 /* read active details */ 00696 if ((parameters == arm_uc_worker_parameters.active_details) && 00697 (arm_uc_details != NULL)) 00698 { 00699 result = arm_uc_pal_linux_internal_read_header(NULL, 00700 arm_uc_details); 00701 00702 /* reset global details pointer */ 00703 arm_uc_details = NULL; 00704 } 00705 00706 /* read installer details */ 00707 if ((parameters == arm_uc_worker_parameters.installer) && 00708 (arm_uc_installer != NULL)) 00709 { 00710 result = arm_uc_pal_linux_internal_read_installer(arm_uc_installer); 00711 00712 /* reset global installer pointer */ 00713 arm_uc_installer = NULL; 00714 } 00715 } 00716 00717 if (result.error == ERR_NONE) 00718 { 00719 UC_PAAL_TRACE("pre-script complete"); 00720 00721 arm_uc_pal_linux_signal_callback(parameters->success_event, true); 00722 } 00723 else 00724 { 00725 UC_PAAL_ERR_MSG("pre-script failed"); 00726 00727 arm_uc_pal_linux_signal_callback(parameters->failure_event, true); 00728 } 00729 } 00730 00731 /** 00732 * @brief Function to run script in a worker thread before file operations. 00733 * 00734 * @param params Pointer to arm_ucp_worker_t struct. 00735 */ 00736 void* arm_uc_pal_linux_extended_post_worker(void* params) 00737 { 00738 /* get parameters */ 00739 arm_ucp_worker_t* parameters = (arm_ucp_worker_t*) params; 00740 00741 /* construct script command */ 00742 char command[ARM_UC_MAXIMUM_COMMAND_LENGTH] = { 0 }; 00743 00744 int error = 0; 00745 int32_t event = 0; 00746 int valid = arm_uc_pal_linux_internal_command(parameters, 00747 command, 00748 ARM_UC_MAXIMUM_COMMAND_LENGTH); 00749 00750 if (valid) 00751 { 00752 UC_PAAL_TRACE("Extended post-script command: %s", command); 00753 00754 /* execute script command */ 00755 error = system(command); 00756 error = WEXITSTATUS(error); 00757 00758 /* update valid flag */ 00759 valid = (error == 0); 00760 } 00761 00762 if (valid) 00763 { 00764 UC_PAAL_TRACE("post-script completed"); 00765 00766 event = parameters->success_event; 00767 00768 /* execute the post runner if it exists and the script succeeded */ 00769 if (parameters->post_runner) 00770 { 00771 event = parameters->post_runner(); 00772 UC_PAAL_TRACE("post runner returned event %" PRId32, event); 00773 } 00774 } 00775 else 00776 { 00777 UC_PAAL_ERR_MSG("post-script failed: %" PRId32, error); 00778 00779 event = parameters->failure_event; 00780 } 00781 00782 arm_uc_pal_linux_signal_callback(event, true); 00783 } 00784 00785 #endif
Generated on Tue Jul 12 2022 19:12:11 by 1.7.2