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