Mayank Gupta / Mbed OS pelion-example-frdm

Dependencies:   FXAS21002 FXOS8700Q

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers update_client_hub.c Source File

update_client_hub.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 "update-client-hub/update_client_hub.h"
00020 
00021 #include "update-client-common/arm_uc_common.h"
00022 #include "update-client-control-center/arm_uc_control_center.h"
00023 #include "update-client-control-center/arm_uc_pre_shared_key.h"
00024 #include "update-client-control-center/arm_uc_certificate.h"
00025 #include "update-client-source-manager/arm_uc_source_manager.h"
00026 #include "update-client-firmware-manager/arm_uc_firmware_manager.h"
00027 #include "update-client-manifest-manager/update-client-manifest-manager.h"
00028 
00029 #include "update_client_hub_state_machine.h"
00030 #include "update_client_hub_event_handlers.h"
00031 #include "update_client_hub_error_handler.h"
00032 
00033 #include "pal4life-device-identity/pal_device_identity.h"
00034 
00035 #define HANDLE_INIT_ERROR(retval, msg, ...)\
00036     if (retval.error != ERR_NONE)\
00037     {\
00038         ARM_UC_HUB_setState(ARM_UC_HUB_STATE_UNINITIALIZED);\
00039         UC_HUB_ERR_MSG(msg " error code %s", ##__VA_ARGS__, ARM_UC_err2Str(retval));\
00040         return retval;\
00041     }
00042 
00043 static const ARM_UPDATE_SOURCE **arm_uc_sources = NULL;
00044 static uint8_t arm_uc_sources_size = 0;
00045 extern arm_uc_mmContext_t *pManifestManagerContext;
00046 
00047 /**
00048  * @brief Handle any errors posted by the scheduler.
00049  * @details This explicitly runs *not* in interrupt context, the scheduler has a dedicated
00050  *            callback structure to ensure it can post at least this event.
00051  *          ARM_UC_HUB_ErrorHandler() will invoke the HUB callback that was set up.
00052  *          It is up to the external application to go about inducing a reset etc,
00053  *            if that is what it decides. Note that the HUB is no longer operable
00054  *            and the app should probably Uninitialize it and report an error.
00055  *            However, the HUB will attempt some cleanup after it returns.
00056  * @param an_event the type of the event causing the error callback.
00057  *        The only possible errors from the scheduler are currently:
00058  *            ARM_UC_EQ_ERR_POOL_EXHAUSTED
00059  *            ARM_UC_EQ_ERR_FAILED_TAKE
00060  *        These are passed on to the Hub error handler as an internal error,
00061  *          and the hub state is now considered unknown from this perspective.
00062  *          (An internal error is considered fatal by the hub.)
00063  */
00064 void UC_HUB_scheduler_error_handler(uint32_t an_event)
00065 {
00066     UC_HUB_ERR_MSG("scheduler error: %" PRIu32, an_event);
00067     ARM_UC_HUB_ErrorHandler(HUB_ERR_INTERNAL_ERROR, ARM_UC_HUB_getState());
00068 }
00069 
00070 /**
00071  * @brief Call initialiser of all components of the client.
00072  *        finish asynchronously, will invoke callback when initialization is done.
00073  * @param init_cb the callback to be invoked at the end of initialization.
00074  */
00075 arm_uc_error_t ARM_UC_HUB_Initialize(void (*init_cb)(uintptr_t))
00076 {
00077     arm_uc_error_t retval;
00078 
00079     if (ARM_UC_HUB_getState() != ARM_UC_HUB_STATE_UNINITIALIZED) {
00080         UC_HUB_ERR_MSG("Already Initialized/Initializing");
00081         return (arm_uc_error_t) { ERR_INVALID_STATE };
00082     }
00083     ARM_UC_HUB_setState(ARM_UC_HUB_STATE_INITIALIZING);
00084 
00085     ARM_UC_SchedulerInit();
00086     ARM_UC_HUB_setInitializationCallback(init_cb);
00087     ARM_UC_SetSchedulerErrorHandler(UC_HUB_scheduler_error_handler);
00088 
00089     /* Register event handler with Control Center. */
00090     retval = ARM_UC_ControlCenter_Initialize(ARM_UC_HUB_ControlCenterEventHandler);
00091     HANDLE_INIT_ERROR(retval, "Control Center init failed")
00092 
00093     /* Register event handler with Firmware Manager */
00094     retval = ARM_UC_FirmwareManager.Initialize(ARM_UC_HUB_FirmwareManagerEventHandler);
00095     HANDLE_INIT_ERROR(retval, "Firmware Manager init failed")
00096 
00097     /* Register event handler with Source Manager */
00098     retval = ARM_UC_SourceManager.Initialize(ARM_UC_HUB_SourceManagerEventHandler);
00099     HANDLE_INIT_ERROR(retval, "Source Manager init failed")
00100 
00101     for (uint8_t index = 0; index < arm_uc_sources_size; index++) {
00102         ARM_UC_SourceManager.AddSource(arm_uc_sources[index]);
00103     }
00104 
00105     /* Register event handler and add config store implementation to manifest
00106        manager.
00107     */
00108     retval = ARM_UC_mmInit(&pManifestManagerContext,
00109                            ARM_UC_HUB_ManifestManagerEventHandler,
00110                            NULL);
00111     HANDLE_INIT_ERROR(retval, "Manifest manager init failed")
00112 
00113     /* add hard coded certificates to the manifest manager */
00114     // retval = ARM_UC_mmStoreCertificate(CA_PATH, cert, CERT_SIZE);
00115     // if ((retval.error != ERR_NONE) && (retval.code != MFST_ERR_PENDING))
00116     // {
00117     //     HANDLE_INIT_ERROR(retval, "Manifest manager StoreCertificate failed")
00118     // }
00119 
00120     return (arm_uc_error_t) { ERR_NONE };
00121 }
00122 
00123 /**
00124  * @brief Process events in the event queue.
00125  */
00126 arm_uc_error_t ARM_UC_HUB_ProcessEvents()
00127 {
00128     ARM_UC_ProcessQueue();
00129 
00130     return (arm_uc_error_t) { ERR_NONE };
00131 }
00132 
00133 /**
00134  * @brief Register callback function for when callbacks are added to an empty queue.
00135  */
00136 arm_uc_error_t ARM_UC_HUB_AddNotificationHandler(void (*handler)(void))
00137 {
00138     ARM_UC_AddNotificationHandler(handler);
00139 
00140     return (arm_uc_error_t) { ERR_NONE };
00141 }
00142 
00143 /**
00144  * @brief Add source to the Update Client.
00145  */
00146 arm_uc_error_t ARM_UC_HUB_SetSources(const ARM_UPDATE_SOURCE *sources[],
00147                                      uint8_t size)
00148 {
00149     arm_uc_sources = sources;
00150     arm_uc_sources_size = size;
00151 
00152     return (arm_uc_error_t) { ERR_NONE };
00153 }
00154 
00155 /**
00156  * Set PAAL Update implementation
00157  */
00158 arm_uc_error_t ARM_UC_HUB_SetStorage(const ARM_UC_PAAL_UPDATE *implementation)
00159 {
00160     return ARM_UCP_SetPAALUpdate(implementation);
00161 }
00162 
00163 /**
00164  * @brief Add monitor to the control center.
00165  */
00166 arm_uc_error_t ARM_UC_HUB_AddMonitor(const ARM_UPDATE_MONITOR *monitor)
00167 {
00168     return ARM_UC_ControlCenter_AddMonitor(monitor);
00169 }
00170 
00171 /**
00172  * @brief Temporary error reporting function.
00173  */
00174 void ARM_UC_HUB_AddErrorCallback(void (*callback)(int32_t error))
00175 {
00176     ARM_UC_HUB_AddErrorCallbackInternal(callback);
00177 }
00178 
00179 /**
00180  * @brief Authorize request.
00181  */
00182 arm_uc_error_t ARM_UC_Authorize(arm_uc_request_t request)
00183 {
00184     return ARM_UC_ControlCenter_Authorize(request);
00185 }
00186 
00187 /**
00188  * @brief Set callback for receiving download progress.
00189  * @details User application call for setting callback handler.
00190  *          The callback function takes the progreess in percent as argument.
00191  *
00192  * @param callback Function pointer to the progress function.
00193  * @return Error code.
00194  */
00195 arm_uc_error_t ARM_UC_SetProgressHandler(void (*callback)(uint32_t progress, uint32_t total))
00196 {
00197     return ARM_UC_ControlCenter_SetProgressHandler(callback);
00198 }
00199 
00200 /**
00201  * @brief Set callback function for authorizing requests.
00202  * @details User application call for setting callback handler.
00203  *          The callback function takes an enum request and an authorization
00204  *          function pointer. To authorize the given request, the caller
00205  *          invokes the authorization function.
00206  *
00207  * @param callback Function pointer to the authorization function.
00208  * @return Error code.
00209  */
00210 arm_uc_error_t ARM_UC_SetAuthorizeHandler(void (*callback)(int32_t))
00211 {
00212     return ARM_UC_ControlCenter_SetAuthorityHandler(callback);
00213 }
00214 
00215 /**
00216  * @brief Override update authorization handler.
00217  * @details Force download and update to progress regardless of authorization
00218  *          handler. This function is used for unblocking an update in a buggy
00219  *          application.
00220  */
00221 void ARM_UC_OverrideAuthorization(void)
00222 {
00223     ARM_UC_ControlCenter_OverrideAuthorization();
00224 }
00225 
00226 #if defined(ARM_UC_FEATURE_MANIFEST_PUBKEY) && (ARM_UC_FEATURE_MANIFEST_PUBKEY == 1)
00227 /**
00228  * @brief Add certificate.
00229  * @details [long description]
00230  *
00231  * @param certificate Pointer to certiface being added.
00232  * @param certificate_length Certificate length.
00233  * @param fingerprint Pointer to the fingerprint of the certificate being added.
00234  * @param fingerprint_length Fingerprint length.
00235  * @return Error code.
00236  */
00237 arm_uc_error_t ARM_UC_AddCertificate(const uint8_t *certificate,
00238                                      uint16_t certificate_length,
00239                                      const uint8_t *fingerprint,
00240                                      uint16_t fingerprint_length,
00241                                      void (*callback)(arm_uc_error_t, const arm_uc_buffer_t *))
00242 {
00243     return ARM_UC_Certificate_Add(certificate,
00244                                   certificate_length,
00245                                   fingerprint,
00246                                   fingerprint_length,
00247                                   callback);
00248 }
00249 #endif /* ARM_UC_FEATURE_MANIFEST_PUBKEY */
00250 
00251 #if defined(ARM_UC_FEATURE_MANIFEST_PSK) && (ARM_UC_FEATURE_MANIFEST_PSK == 1)
00252 /**
00253  * @brief Set pointer to pre-shared-key with the given size.
00254  *
00255  * @param key Pointer to pre-shared-key.
00256  * @param bits Key size in bits.
00257  *
00258  * @return Error code.
00259  */
00260 arm_uc_error_t ARM_UC_AddPreSharedKey(const uint8_t *key, uint16_t bits)
00261 {
00262     return ARM_UC_PreSharedKey_SetSecret(key, bits);
00263 }
00264 #endif
00265 
00266 /**
00267  * @brief Function for setting the vendor ID.
00268  * @details The ID is copied to a 16 byte struct. Any data after the first
00269  *          16 bytes will be ignored.
00270  * @param id Pointer to ID.
00271  * @param length Length of ID.
00272  * @return Error code.
00273  */
00274 arm_uc_error_t ARM_UC_SetVendorId(const uint8_t *id, uint8_t length)
00275 {
00276     arm_uc_guid_t uuid = { 0 };
00277 
00278     if (id) {
00279         for (uint8_t index = 0;
00280                 (index < sizeof(arm_uc_guid_t) && (index < length));
00281                 index++) {
00282             ((uint8_t *) uuid)[index] = id[index];
00283         }
00284     }
00285 
00286     return pal_setVendorGuid(&uuid);
00287 }
00288 
00289 /**
00290  * @brief Function for setting the class ID.
00291  * @details The ID is copied to a 16 byte struct. Any data after the first
00292  *          16 bytes will be ignored.
00293  * @param id Pointer to ID.
00294  * @param length Length of ID.
00295  * @return Error code.
00296  */
00297 arm_uc_error_t ARM_UC_SetClassId(const uint8_t *id, uint8_t length)
00298 {
00299     arm_uc_guid_t uuid = { 0 };
00300 
00301     if (id) {
00302         for (uint8_t index = 0;
00303                 (index < sizeof(arm_uc_guid_t) && (index < length));
00304                 index++) {
00305             ((uint8_t *) uuid)[index] = id[index];
00306         }
00307     }
00308 
00309     return pal_setClassGuid(&uuid);
00310 }
00311 
00312 /**
00313  * @brief Function for setting the device ID.
00314  * @details The ID is copied to a 16 byte struct. Any data after the first
00315  *          16 bytes will be ignored.
00316  * @param id Pointer to ID.
00317  * @param length Length of ID.
00318  * @return Error code.
00319  */
00320 arm_uc_error_t ARM_UC_SetDeviceId(const uint8_t *id, uint8_t length)
00321 {
00322     arm_uc_guid_t uuid = { 0 };
00323 
00324     if (id) {
00325         for (uint8_t index = 0;
00326                 (index < sizeof(arm_uc_guid_t) && (index < length));
00327                 index++) {
00328             ((uint8_t *) uuid)[index] = id[index];
00329         }
00330     }
00331 
00332     return pal_setDeviceGuid(&uuid);
00333 }
00334 
00335 /**
00336  * @brief Function for reporting the vendor ID.
00337  * @details 16 bytes are copied into the supplied buffer.
00338  * @param id Pointer to storage for ID. MUST be at least 16 bytes long.
00339  * @param id_max the size of the ID buffer
00340  * @param id_size pointer to a variable to receive the size of the ID
00341  *                written into the buffer (always 16).
00342  * @return Error code.
00343  */
00344 arm_uc_error_t ARM_UC_GetVendorId(uint8_t *id,
00345                                   const size_t id_max,
00346                                   size_t *id_size)
00347 {
00348     arm_uc_guid_t guid = {0};
00349     arm_uc_error_t err = {ERR_NONE};
00350     if (id_max < sizeof(arm_uc_guid_t)) {
00351         err.code = ARM_UC_DI_ERR_SIZE;
00352     }
00353     if (err.error == ERR_NONE) {
00354         err = pal_getVendorGuid(&guid);
00355     }
00356     if (err.error == ERR_NONE) {
00357         memcpy(id, guid, sizeof(arm_uc_guid_t));
00358         if (id_size != NULL) {
00359             *id_size = sizeof(arm_uc_guid_t);
00360         }
00361     }
00362     return err;
00363 }
00364 
00365 /**
00366  * @brief Function for reporting the class ID.
00367  * @details 16 bytes are copied into the supplied buffer.
00368  * @param id Pointer to storage for ID. MUST be at least 16 bytes long.
00369  * @param id_max the size of the ID buffer
00370  * @param id_size pointer to a variable to receive the size of the ID
00371  *                written into the buffer (always 16).
00372  * @return Error code.
00373  */
00374 arm_uc_error_t ARM_UC_GetClassId(uint8_t *id,
00375                                  const size_t id_max,
00376                                  size_t *id_size)
00377 {
00378     arm_uc_guid_t guid = {0};
00379     arm_uc_error_t err = {ERR_NONE};
00380     if (id_max < sizeof(arm_uc_guid_t)) {
00381         err.code = ARM_UC_DI_ERR_SIZE;
00382     }
00383     if (err.error == ERR_NONE) {
00384         err = pal_getClassGuid(&guid);
00385     }
00386     if (err.error == ERR_NONE) {
00387         memcpy(id, guid, sizeof(arm_uc_guid_t));
00388         if (id_size != NULL) {
00389             *id_size = sizeof(arm_uc_guid_t);
00390         }
00391     }
00392     return err;
00393 }
00394 
00395 /**
00396  * @brief Function for reporting the device ID.
00397  * @details 16 bytes are copied into the supplied buffer.
00398  * @param id Pointer to storage for ID. MUST be at least 16 bytes long.
00399  * @param id_max the size of the ID buffer
00400  * @param id_size pointer to a variable to receive the size of the ID
00401  *                written into the buffer (always 16).
00402  * @return Error code.
00403  */
00404 arm_uc_error_t ARM_UC_GetDeviceId(uint8_t *id,
00405                                   const size_t id_max,
00406                                   size_t *id_size)
00407 {
00408     arm_uc_guid_t guid = {0};
00409     arm_uc_error_t err = {ERR_NONE};
00410     if (id_max < sizeof(arm_uc_guid_t)) {
00411         err.code = ARM_UC_DI_ERR_SIZE;
00412     }
00413     if (err.error == ERR_NONE) {
00414         err = pal_getDeviceGuid(&guid);
00415     }
00416     if (err.error == ERR_NONE) {
00417         memcpy(id, guid, sizeof(arm_uc_guid_t));
00418         if (id_size != NULL) {
00419             *id_size = sizeof(arm_uc_guid_t);
00420         }
00421     }
00422     return err;
00423 }
00424 
00425 arm_uc_error_t ARM_UC_HUB_Uninitialize(void)
00426 {
00427     if (ARM_UC_HUB_getState() <= ARM_UC_HUB_STATE_INITIALIZED) {
00428         UC_HUB_ERR_MSG("Update Client not initialized");
00429         return (arm_uc_error_t) { ERR_INVALID_STATE };
00430     }
00431 
00432     arm_uc_error_t err = ARM_UC_SourceManager.Uninitialize();
00433     ARM_UC_HUB_setState(ARM_UC_HUB_STATE_UNINITIALIZED);
00434     return err;
00435 }
00436 
00437 /**
00438  * @brief Return the details of the active firmware.
00439  * @param details Pointer to the firmware details structure.
00440  * @return ARM_UC_HUB_ERR_NOT_AVAILABLE if the active firmware details
00441  *         are not yet available, ERR_INVALID_PARAMETER if "details" is
00442  *         NULL or ERR_NONE for success.
00443  */
00444 arm_uc_error_t ARM_UC_API_GetActiveFirmwareDetails(arm_uc_firmware_details_t *details)
00445 {
00446     arm_uc_error_t err = {ARM_UC_HUB_ERR_NOT_AVAILABLE};
00447 
00448     if (details == NULL) {
00449         err.code = ERR_INVALID_PARAMETER;
00450     } else {
00451         arm_uc_firmware_details_t *hub_details = ARM_UC_HUB_getActiveFirmwareDetails();
00452         if (hub_details) {
00453             memcpy(details, hub_details, sizeof(arm_uc_firmware_details_t));
00454             err.code = ERR_NONE;
00455         }
00456     }
00457     return err;
00458 }
00459 
00460 /**
00461  * @brief Return whether or not the given state is a valid defined one.
00462  */
00463 bool ARM_UC_IsValidState(arm_uc_update_state_t an_update_state)
00464 {
00465     int val = (int)an_update_state;
00466     bool is_valid = ((val >= (int)ARM_UC_UPDATE_STATE_FIRST)
00467                      && (val <= (int)ARM_UC_UPDATE_STATE_LAST));
00468     if (!is_valid) UC_ERROR_ERR_MSG("Invalid UC HUB reported state");
00469     return is_valid;
00470 }
00471 
00472 /**
00473  * @brief Return whether or not the given result is a valid defined one.
00474  */
00475 bool ARM_UC_IsValidResult(arm_uc_update_result_t an_update_result)
00476 {
00477     bool is_valid = ((an_update_result >= ARM_UC_UPDATE_RESULT_UPDATE_FIRST)
00478                      && (an_update_result <= ARM_UC_UPDATE_RESULT_UPDATE_LAST))
00479                     || ((an_update_result >= ARM_UC_UPDATE_RESULT_FETCHER_FIRST)
00480                         && (an_update_result <= ARM_UC_UPDATE_RESULT_FETCHER_LAST))
00481                     || ((an_update_result >= ARM_UC_UPDATE_RESULT_WRITER_FIRST)
00482                         && (an_update_result <= ARM_UC_UPDATE_RESULT_WRITER_LAST))
00483                     || ((an_update_result >= ARM_UC_UPDATE_RESULT_PROCESSOR_FIRST)
00484                         && (an_update_result <= ARM_UC_UPDATE_RESULT_PROCESSOR_LAST))
00485                     || ((an_update_result >= ARM_UC_UPDATE_RESULT_MANIFEST_FIRST)
00486                         && (an_update_result <= ARM_UC_UPDATE_RESULT_MANIFEST_LAST));
00487     if (!is_valid) UC_ERROR_ERR_MSG("Invalid UC HUB reported state");
00488     return is_valid;
00489 }