leo hendrickson / Mbed OS example-Ethernet-mbed-Cloud-connect
Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers arm_uc_pal_sxos_extensions.c Source File

arm_uc_pal_sxos_extensions.c

00001 // ----------------------------------------------------------------------------
00002 // Copyright 2016-2017 ARM Ltd.
00003 //
00004 // SPDX-License-Identifier: Apache-2.0
00005 //
00006 // Licensed under the Apache License, Version 2.0 (the "License");
00007 // you may not use this file except in compliance with the License.
00008 // You may obtain a copy of the License at
00009 //
00010 //     http://www.apache.org/licenses/LICENSE-2.0
00011 //
00012 // Unless required by applicable law or agreed to in writing, software
00013 // distributed under the License is distributed on an "AS IS" BASIS,
00014 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
00015 // See the License for the specific language governing permissions and
00016 // limitations under the License.
00017 // ----------------------------------------------------------------------------
00018 
00019 #include "arm_uc_config.h"
00020 #if defined(ARM_UC_FEATURE_PAL_FILESYSTEM) && (ARM_UC_FEATURE_PAL_FILESYSTEM == 1)
00021 #if defined(__SXOS__)
00022 
00023 #include "update-client-pal-filesystem/arm_uc_pal_extensions.h"
00024 #include "update-client-metadata-header/arm_uc_metadata_header_v2.h"
00025 #include "arm_uc_pal_filesystem_utils.h"
00026 
00027 #include "pal.h"
00028 
00029 #include "mbed-trace/mbed_trace.h"
00030 #define TRACE_GROUP "update-client-extensions"
00031 
00032 #include <stdlib.h>
00033 #include <inttypes.h>
00034 #include <limits.h>
00035 #include <stdio.h>
00036 #include <unistd.h>
00037 
00038 #include <fota.h>
00039 #include <vfs.h>
00040 
00041 
00042 static void (*arm_ucex_sxos_callback)(uint32_t) = NULL;
00043 
00044 // Header filename of active image
00045 #define IMAGE_HEADER_FILENAME_ACTIVE    "header_active.bin"
00046 
00047 // Header filename for new image (during update process)
00048 #define IMAGE_HEADER_FILENAME_UPDATE    "header_update.bin"
00049 
00050 static FOTA_ENV_T fenv = {
00051     .packFname = FOTA_PACK_DEFAULT_FILENAME,
00052     .idxFname = FOTA_INDEX_DEFAULT_FILENAME,
00053 };
00054 static FOTA_CONTEXT_T *fota_ctx = NULL;
00055 
00056 
00057 arm_uc_error_t pal_ext_imageInitAPI(void (*callback)(uint32_t))
00058 {
00059     arm_uc_error_t result = { .code = ERR_NONE };
00060 
00061     arm_ucex_sxos_callback = callback;
00062 
00063     tr_debug("Initializing FOTA...");
00064     fota_ctx = (FOTA_CONTEXT_T *)malloc(fotaContextSize());
00065     if (fota_ctx) {
00066         if (fotaInit(fota_ctx, &fenv)) {
00067             if (FOTA_AREA_UPGRADED == fotaGetStatus(fota_ctx)) {
00068                 // FOTA upgrade successful -> Rename header file as active
00069                 tr_debug("FOTA succeeded. Updating new image header");
00070                 if (vfs_rename(IMAGE_HEADER_FILENAME_UPDATE, IMAGE_HEADER_FILENAME_ACTIVE) != 0) {
00071                     tr_error("Unable to rename update header as active!");
00072                 }
00073             }
00074             // Mark fota image as handled
00075             fotaInvalidate(fota_ctx);
00076 
00077             // Remove fota image from file system
00078             pal_fsUnlink(FOTA_PACK_DEFAULT_FILENAME);
00079         } else {
00080             tr_error("FOTA init failure!");
00081             free(fota_ctx);
00082             fota_ctx = NULL;
00083             result.code = ERR_NOT_READY;
00084         }
00085     } else {
00086         tr_error("Unable to allocate FOTA CTX!");
00087         result.code = ERR_NOT_READY;
00088     }
00089 
00090     tr_debug("Initializing FOTA... Result = %d", result.code);
00091     return result;
00092 }
00093 
00094 arm_uc_error_t pal_ext_imageGetActiveDetails(arm_uc_firmware_details_t *details)
00095 {
00096     arm_uc_error_t result = { .code = ERR_INVALID_PARAMETER };
00097 
00098     if (details) {
00099         palFileDescriptor_t fd;
00100         palStatus_t status = pal_fsFopen(IMAGE_HEADER_FILENAME_ACTIVE, PAL_FS_FLAG_READONLY, &fd);
00101         if (PAL_SUCCESS == status) {
00102             uint8_t read_buffer[ARM_UC_EXTERNAL_HEADER_SIZE_V2];
00103             size_t bytes_read;
00104             status = pal_fsFread(&fd, &read_buffer, sizeof(read_buffer), &bytes_read);
00105             if (PAL_SUCCESS == status) {
00106                 /* read out header magic */
00107                 uint32_t headerMagic = arm_uc_parse_uint32(&read_buffer[0]);
00108 
00109                 /* read out header magic */
00110                 uint32_t headerVersion = arm_uc_parse_uint32(&read_buffer[4]);
00111 
00112                 /* choose version to decode */
00113                 if ((headerMagic == ARM_UC_INTERNAL_HEADER_MAGIC_V2) &&
00114                     (headerVersion == ARM_UC_INTERNAL_HEADER_VERSION_V2) &&
00115                     (bytes_read == ARM_UC_INTERNAL_HEADER_SIZE_V2)) {
00116                     result = arm_uc_parse_internal_header_v2(read_buffer, details);
00117                 } else if ((headerMagic == ARM_UC_EXTERNAL_HEADER_MAGIC_V2) &&
00118                            (headerVersion == ARM_UC_EXTERNAL_HEADER_VERSION_V2) &&
00119                            (bytes_read == ARM_UC_EXTERNAL_HEADER_SIZE_V2)) {
00120                     result = arm_uc_parse_external_header_v2(read_buffer, details);
00121                 } else {
00122                     /* invalid header format */
00123                     tr_error("Unrecognized firmware header: magic = 0x%" PRIx32 ", version = 0x%" PRIx32 ", size = %" PRIu32 ,
00124                         headerMagic, headerVersion, bytes_read);
00125                     result.code = ERR_INVALID_PARAMETER;
00126                 }
00127             }
00128             pal_fsFclose(&fd);
00129         } else {
00130             // XXX TODO: Need to implement version query before any update has been processed.
00131             //           In this version info is fetched only from header file which is created
00132             //           during update process.
00133             tr_warn("No image header");
00134         }
00135 
00136         if (PAL_SUCCESS != status || ERR_NONE != result.code) {
00137             memset(details, 0, sizeof(arm_uc_firmware_details_t));
00138         }
00139 
00140         if (arm_ucex_sxos_callback) {
00141             arm_ucex_sxos_callback(ARM_UC_PAAL_EVENT_GET_ACTIVE_FIRMWARE_DETAILS_DONE);
00142         }
00143     }
00144 
00145     return result;
00146 }
00147 
00148 arm_uc_error_t pal_ext_installerGetDetails(arm_uc_installer_details_t *details)
00149 {
00150     arm_uc_error_t result = { .code = ERR_INVALID_PARAMETER };
00151 
00152     if (details) {
00153         /* dummy implementation, return 0 */
00154         memset(details, 0, sizeof(arm_uc_installer_details_t));
00155 
00156         result.code = ERR_NONE;
00157 
00158         if (arm_ucex_sxos_callback) {
00159             arm_ucex_sxos_callback(ARM_UC_PAAL_EVENT_GET_INSTALLER_DETAILS_DONE);
00160         }
00161     }
00162 
00163     return result;
00164 }
00165 
00166 arm_uc_error_t pal_ext_imageActivate(uint32_t location)
00167 {
00168     arm_uc_error_t err = { .code = ERR_INVALID_PARAMETER };
00169     palStatus_t rc = PAL_ERR_GENERIC_FAILURE ;
00170 
00171     char image_path_buf[PAL_MAX_FILE_AND_FOLDER_LENGTH];
00172     char header_path_buf[PAL_MAX_FILE_AND_FOLDER_LENGTH];
00173 
00174     tr_info("Activating FOTA image...");
00175 
00176     err = arm_uc_pal_filesystem_get_path((palImageId_t)location, FIRMWARE_IMAGE_ITEM_DATA,
00177                                          image_path_buf, PAL_MAX_FILE_AND_FOLDER_LENGTH);
00178     if (err.code == ERR_NONE) {
00179         err = arm_uc_pal_filesystem_get_path((palImageId_t)location, FIRMWARE_IMAGE_ITEM_HEADER,
00180                                              header_path_buf, PAL_MAX_FILE_AND_FOLDER_LENGTH);
00181         if (err.code == ERR_NONE) {
00182             // Mark old file as invalid
00183             fotaInvalidate(fota_ctx);
00184 
00185             // SX OS expects FOTA image to be names as FOTA_PACK_DEFAULT_FILENAME
00186             if (vfs_rename(image_path_buf, FOTA_PACK_DEFAULT_FILENAME) == 0) {
00187                 if (fotaDownloadFinished(fota_ctx)) {
00188                     // Copy header as candidate for new image
00189                     if (vfs_rename(header_path_buf, IMAGE_HEADER_FILENAME_UPDATE) == 0) {
00190                         rc = PAL_SUCCESS;
00191                     } else {
00192                         tr_error("Unable to rename FOTA header!");
00193                     }
00194                 } else {
00195                     tr_error("FOTA image validation failed!");
00196                     fotaInvalidate(fota_ctx);
00197                 }
00198             } else {
00199                 tr_error("Unable to rename FOTA image!");
00200             }
00201         } else {
00202             tr_error("Unable to find image header!");
00203         }
00204     } else {
00205         tr_error("Unable to find image!");
00206     }
00207 
00208     if (arm_ucex_sxos_callback) {
00209         uint32_t event = (rc == PAL_SUCCESS && err.code == ERR_NONE ? ARM_UC_PAAL_EVENT_ACTIVATE_DONE : ARM_UC_PAAL_EVENT_ACTIVATE_ERROR);
00210         arm_ucex_sxos_callback(event);
00211     }
00212 
00213     if (rc != PAL_SUCCESS) {
00214         err.code = ERR_INVALID_PARAMETER;
00215     } else {
00216         err.code = ERR_NONE;
00217     }
00218 
00219     tr_info("Activating FOTA image... Done. rc = %d, err = %d", rc, err.code);
00220     return err;
00221 }
00222 
00223 #endif /* __SXOS__ */
00224 #endif /* ARM_UC_FEATURE_PAL_FILESYSTEM */