Simulated product dispenser

Dependencies:   HTS221

Fork of mbed-cloud-workshop-connect-HTS221 by Jim Carver

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers arm_uc_pal_linux_implementation_internal.c Source File

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