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 update_client_hub_state_machine.c Source File

update_client_hub_state_machine.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_state_machine.h"
00020 #include "update_client_hub_error_handler.h"
00021 #include "update-client-hub/update_client_hub.h"
00022 
00023 #include "update-client-common/arm_uc_common.h"
00024 #include "update-client-firmware-manager/arm_uc_firmware_manager.h"
00025 #include "update-client-manifest-manager/update-client-manifest-manager.h"
00026 #include "update-client-source-manager/arm_uc_source_manager.h"
00027 #include "update-client-control-center/arm_uc_control_center.h"
00028 #include "update-client-control-center/arm_uc_pre_shared_key.h"
00029 
00030 #include "mbedtls/aes.h"
00031 
00032 #include "pal.h"
00033 
00034 #include <inttypes.h>
00035 
00036 /*****************************************************************************/
00037 /* Global variables                                                          */
00038 /*****************************************************************************/
00039 
00040 // state of the hub state machine
00041 static arm_uc_hub_state_t arm_uc_hub_state = ARM_UC_HUB_STATE_UNINITIALIZED;
00042 
00043 // the call back function registered by the user to signal end of intilisation
00044 static void (*arm_uc_hub_init_cb)(int32_t) = NULL;
00045 
00046 // The hub uses a double buffer system to speed up firmware download and storage
00047 #define BUFFER_SIZE_MAX (ARM_UC_BUFFER_SIZE / 2) //  define size of the double buffers
00048 static uint8_t message[BUFFER_SIZE_MAX];
00049 static arm_uc_buffer_t front_buffer = {
00050     .size_max = BUFFER_SIZE_MAX,
00051     .size = 0,
00052     .ptr = message
00053 };
00054 
00055 static uint8_t message2[BUFFER_SIZE_MAX];
00056 static arm_uc_buffer_t back_buffer = {
00057     .size_max = BUFFER_SIZE_MAX,
00058     .size = 0,
00059     .ptr = message2
00060 };
00061 
00062 // version (timestamp) of the current running application
00063 static arm_uc_firmware_details_t arm_uc_active_details = { 0 };
00064 static bool arm_uc_active_details_available = false;
00065 
00066 // bootloader information
00067 static arm_uc_installer_details_t arm_uc_installer_details = { 0 };
00068 
00069 // variable to keep track of the offset into the firmware image during download
00070 static uint32_t firmware_offset = 0;
00071 
00072 // variable to store the firmware config during firmware manager setup
00073 // Initialisation with an enum silences a compiler warning for ARM ("188-D: enumerated type mixed with another type").
00074 static ARM_UCFM_Setup_t arm_uc_hub_firmware_config = { UCFM_MODE_UNINIT };
00075 
00076 // buffer to store the decoded firmware key
00077 #define PLAIN_FIRMWARE_KEY_SIZE 16
00078 static uint8_t plainFirmwareKey[PLAIN_FIRMWARE_KEY_SIZE];
00079 static arm_uc_buffer_t arm_uc_hub_plain_key = {
00080     .size_max = PLAIN_FIRMWARE_KEY_SIZE,
00081     .size     = PLAIN_FIRMWARE_KEY_SIZE,
00082     .ptr      = plainFirmwareKey
00083 };
00084 
00085 static arm_uc_mmContext_t manifestManagerContext = { 0 };
00086 static arm_uc_mmContext_t* pManifestManagerContext = &manifestManagerContext;
00087 static manifest_firmware_info_t fwinfo = { 0 };
00088 
00089 // buffer to store a uri struct
00090 #define URI_STRING_LEN 256
00091 uint8_t uri_buffer[URI_STRING_LEN] = {0};
00092 
00093 static arm_uc_uri_t uri = {
00094     .size_max = sizeof(uri_buffer),
00095     .size     = 0,
00096     .ptr      = uri_buffer,
00097     .port     = 0,
00098     .scheme   = URI_SCHEME_NONE,
00099     .host     = NULL,
00100     .path     = NULL,
00101 };
00102 
00103 /*****************************************************************************/
00104 /* Debug                                                                     */
00105 /*****************************************************************************/
00106 
00107 #if ARM_UC_HUB_TRACE_ENABLE
00108 static void arm_uc_hub_debug_output()
00109 {
00110     printf("Manifest timestamp: %" PRIu64 "\r\n", fwinfo.timestamp);
00111 
00112     if (uri.scheme == URI_SCHEME_HTTP)
00113     {
00114         printf("Firmware URL http://%s:%" PRIu16 "%s\r\n",
00115             uri.host, uri.port, uri.path);
00116     }
00117 
00118     printf("Firmware size: %" PRIu32 "\r\n",fwinfo.size);
00119 
00120     printf("Firmware hash (%" PRIu32 "): ", fwinfo.hash.size);
00121     for (unsigned i = 0; i < fwinfo.hash.size; i++)
00122     {
00123         printf("%02" PRIx8, fwinfo.hash.ptr[i]);
00124     }
00125     printf("\r\n");
00126 
00127     if (fwinfo.cipherMode == ARM_UC_MM_CIPHERMODE_PSK)
00128     {
00129         printf("PSK ID: ");
00130         for (unsigned i = 0; i < fwinfo.psk.keyID.size; i++)
00131         {
00132             printf("%02" PRIx8, *(fwinfo.psk.keyID.ptr+i));
00133         }
00134         printf("\r\n");
00135 
00136         printf("cipherKey(16): ");
00137         for (unsigned i = 0; i < 16; i++)
00138         {
00139             printf("%02" PRIx8, *(fwinfo.psk.cipherKey.ptr+i));
00140         }
00141         printf("\r\n");
00142 
00143         printf("Decrypted Firmware Symmetric Key(16): ");
00144         for (unsigned i = 0; i < 16; i++)
00145         {
00146             printf("%02" PRIx8, arm_uc_hub_plain_key.ptr[i]);
00147         }
00148         printf("\r\n");
00149 
00150         printf("fwinfo.initVector\r\n");
00151         for (unsigned i = 0; i < 16; i++)
00152         {
00153             printf("%02" PRIx8, *(fwinfo.initVector.ptr+i));
00154         }
00155         printf("\r\n");
00156     }
00157 
00158     printf("Storage location: %" PRIu32 "\r\n",
00159            arm_uc_hub_firmware_config.package_id);
00160 }
00161 #endif
00162 
00163 /*****************************************************************************/
00164 /* State machine                                                             */
00165 /*****************************************************************************/
00166 
00167 /* Short hand for simple error handling code */
00168 #define HANDLE_ERROR(retval, msg, ...)                  \
00169     if (retval.error != ERR_NONE)                       \
00170     {                                                   \
00171         UC_HUB_ERR_MSG(msg " error code %s",            \
00172                        ##__VA_ARGS__,                   \
00173                        ARM_UC_err2Str(retval));         \
00174         new_state = ARM_UC_HUB_STATE_IDLE;              \
00175         break;                                          \
00176     }
00177 
00178 arm_uc_hub_state_t ARM_UC_HUB_getState()
00179 {
00180     return arm_uc_hub_state;
00181 }
00182 
00183 void ARM_UC_HUB_setInitializationCallback(void (*callback)(int32_t))
00184 {
00185     arm_uc_hub_init_cb = callback;
00186 }
00187 
00188 /**
00189  * @brief Return the active firmware details or NULL if they're not yet available.
00190  */
00191 arm_uc_firmware_details_t* ARM_UC_HUB_getActiveFirmwareDetails(void)
00192 {
00193     return arm_uc_active_details_available ? &arm_uc_active_details : NULL;
00194 }
00195 
00196 void ARM_UC_HUB_setState(arm_uc_hub_state_t new_state)
00197 {
00198     arm_uc_error_t retval;
00199 
00200     /* Loop until state is unchanged.
00201        First loop is mandatory regardless of current state.
00202     */
00203     do
00204     {
00205         /* store new stage */
00206         arm_uc_hub_state = new_state;
00207 
00208         switch (arm_uc_hub_state)
00209         {
00210             /*****************************************************************/
00211             /* Initialization                                                */
00212             /*****************************************************************/
00213             case ARM_UC_HUB_STATE_INITIALIZED:
00214                 UC_HUB_TRACE("ARM_UC_HUB_STATE_INITIALIZED");
00215 
00216                 /* signal that the Hub is initialized */
00217                 if (arm_uc_hub_init_cb)
00218                 {
00219                     arm_uc_hub_init_cb(ARM_UC_INIT_DONE);
00220                 }
00221 
00222                 /* report the active firmware hash to the Cloud in parallel
00223                    with the main user application.
00224                 */
00225                 arm_uc_active_details_available = false;
00226                 new_state = ARM_UC_HUB_STATE_GET_ACTIVE_FIRMWARE_DETAILS;
00227                 break;
00228 
00229             case ARM_UC_HUB_STATE_INITIALIZING:
00230                 UC_HUB_TRACE("ARM_UC_HUB_STATE_INITIALIZING");
00231                 break;
00232 
00233             /*****************************************************************/
00234             /* Report current firmware hash                                  */
00235             /*****************************************************************/
00236             case ARM_UC_HUB_STATE_GET_ACTIVE_FIRMWARE_DETAILS:
00237                 UC_HUB_TRACE("ARM_UC_HUB_STATE_GET_ACTIVE_FIRMWARE_DETAILS");
00238 
00239                 retval = ARM_UC_FirmwareManager.GetActiveFirmwareDetails(&arm_uc_active_details);
00240                 HANDLE_ERROR(retval, "Firmware manager GetActiveFirmwareDetails failed");
00241                 break;
00242 
00243             case ARM_UC_HUB_STATE_REPORT_ACTIVE_HASH:
00244                 UC_HUB_TRACE("ARM_UC_HUB_STATE_REPORT_ACTIVE_HASH");
00245 
00246                 /* copy hash to buffer */
00247                 memcpy(front_buffer.ptr,
00248                        arm_uc_active_details.hash,
00249                        ARM_UC_SHA256_SIZE);
00250 
00251                 front_buffer.size = ARM_UC_SHA256_SIZE;
00252 
00253                 /* send hash to update service */
00254                 ARM_UC_ControlCenter_ReportName(&front_buffer);
00255 
00256                 /* signal to the API that the firmware details are now available */
00257                 arm_uc_active_details_available = true;
00258 
00259                 new_state = ARM_UC_HUB_STATE_REPORT_ACTIVE_VERSION;
00260                 break;
00261 
00262             /*****************************************************************/
00263             /* Report current firmware version                               */
00264             /*****************************************************************/
00265             case ARM_UC_HUB_STATE_REPORT_ACTIVE_VERSION:
00266                 UC_HUB_TRACE("ARM_UC_HUB_STATE_REPORT_ACTIVE_VERSION");
00267 
00268                 UC_HUB_TRACE("Active version: %" PRIu64,
00269                              arm_uc_active_details.version);
00270 
00271                 /* send timestamp to update service */
00272                 ARM_UC_ControlCenter_ReportVersion(arm_uc_active_details.version);
00273 
00274                 new_state = ARM_UC_HUB_STATE_GET_INSTALLER_DETAILS;
00275                 break;
00276 
00277             /*****************************************************************/
00278             /* Report bootloader information                                 */
00279             /*****************************************************************/
00280             case ARM_UC_HUB_STATE_GET_INSTALLER_DETAILS:
00281                 UC_HUB_TRACE("ARM_UC_HUB_STATE_GET_INSTALLER_DETAILS");
00282 
00283                 retval = ARM_UC_FirmwareManager.GetInstallerDetails(&arm_uc_installer_details);
00284                 HANDLE_ERROR(retval, "Firmware manager GetInstallerDetails failed");
00285                 break;
00286 
00287             case ARM_UC_HUB_STATE_REPORT_INSTALLER_DETAILS:
00288             {
00289                 UC_HUB_TRACE("ARM_UC_HUB_STATE_REPORT_INSTALLER_DETAILS");
00290 
00291 #if 0
00292                 printf("bootloader: ");
00293                 for (uint32_t index = 0; index < 20; index++)
00294                 {
00295                     printf("%02X", arm_uc_installer_details.arm_hash[index]);
00296                 }
00297                 printf("\r\n");
00298 
00299                 printf("layout: %" PRIu32 "\r\n", arm_uc_installer_details.layout);
00300 #endif
00301 
00302                 /* report installer details to mbed cloud */
00303                 arm_uc_buffer_t bootloader_hash = {
00304                     .size_max = ARM_UC_SHA256_SIZE,
00305                     .size = ARM_UC_SHA256_SIZE,
00306                     .ptr = (arm_uc_installer_details.arm_hash)
00307                 };
00308                 ARM_UC_ControlCenter_ReportBootloaderHash(&bootloader_hash);
00309 
00310                 bootloader_hash.ptr = (arm_uc_installer_details.oem_hash);
00311                 ARM_UC_ControlCenter_ReportOEMBootloaderHash(&bootloader_hash);
00312 
00313                 /* set new state */
00314                 new_state = ARM_UC_HUB_STATE_IDLE;
00315                 break;
00316             }
00317 
00318             /*****************************************************************/
00319             /* Idle                                                          */
00320             /*****************************************************************/
00321             case ARM_UC_HUB_STATE_IDLE:
00322                 UC_HUB_TRACE("ARM_UC_MONITOR_STATE_IDLE");
00323 
00324                 /* signal monitor that device has entered IDLE state */
00325                 ARM_UC_ControlCenter_ReportState(ARM_UC_MONITOR_STATE_IDLE);
00326                 break;
00327 
00328             /*****************************************************************/
00329             /* Download manifest                                             */
00330             /*****************************************************************/
00331             case ARM_UC_HUB_STATE_NOTIFIED:
00332                 UC_HUB_TRACE("ARM_UC_HUB_STATE_NOTIFIED");
00333 
00334                 /* notification received of a new manifest, hence go get said manifest */
00335                 retval = ARM_UC_SourceManager.GetManifest(&front_buffer, 0);
00336                 HANDLE_ERROR(retval, "Source manager GetManifest failed");
00337                 break;
00338 
00339             case ARM_UC_HUB_STATE_MANIFEST_FETCHED:
00340                 UC_HUB_TRACE("ARM_UC_HUB_STATE_MANIFEST_FETCHED");
00341 
00342                 /* Save the manifest for later */
00343                 memcpy(&fwinfo.manifestBuffer, front_buffer.ptr,
00344                     ARM_UC_util_min(sizeof(fwinfo.manifestBuffer), front_buffer.size));
00345                 /* Save the manifest size for later */
00346                 fwinfo.manifestSize = front_buffer.size;
00347                 /* insert the manifest we just fetched into manifest manager */
00348                 retval = ARM_UC_mmInsert(&pManifestManagerContext, &front_buffer, &back_buffer,  NULL);
00349                 if (retval.code != MFST_ERR_PENDING)
00350                 {
00351                     HANDLE_ERROR(retval, "Manifest manager Insert failed")
00352                 }
00353                 break;
00354 
00355             /*****************************************************************/
00356             /* Rollback protection                                           */
00357             /*****************************************************************/
00358             case ARM_UC_HUB_STATE_MANIFEST_COMPLETE:
00359                 UC_HUB_TRACE("ARM_UC_HUB_STATE_MANIFEST_COMPLETE");
00360 
00361                 /* get the firmware info out of the manifest we just inserted
00362                    into the manifest manager
00363                 */
00364                 retval = ARM_UC_mmFetchFirmwareInfo(&pManifestManagerContext,
00365                                                     &fwinfo,
00366                                                     NULL);
00367                 if (retval.code != MFST_ERR_PENDING)
00368                 {
00369                     HANDLE_ERROR(retval, "Manifest manager fetch info failed")
00370                 }
00371                 break;
00372 
00373             case ARM_UC_HUB_STATE_CHECK_VERSION:
00374                 UC_HUB_TRACE("ARM_UC_HUB_STATE_CHECK_VERSION");
00375 
00376                 /* only continue if timestamp is newer than active version */
00377                 if (fwinfo.timestamp > arm_uc_active_details.version)
00378                 {
00379                     /* set new state */
00380                     new_state = ARM_UC_HUB_STATE_PREPARE_FIRMWARE_SETUP;
00381                 }
00382                 else
00383                 {
00384                     UC_HUB_ERR_MSG("version: %" PRIu64 " <= %" PRIu64,
00385                                 fwinfo.timestamp,
00386                                 arm_uc_active_details.version);
00387 
00388                     /* signal warning through external handler */
00389                     ARM_UC_HUB_ErrorHandler(HUB_ERR_ROLLBACK_PROTECTION,
00390                                             ARM_UC_HUB_STATE_CHECK_VERSION);
00391 
00392                     /* set new state */
00393                     new_state = ARM_UC_HUB_STATE_IDLE;
00394                 }
00395                 break;
00396 
00397             /*****************************************************************/
00398             /* Parse manifest                                                */
00399             /*****************************************************************/
00400             case ARM_UC_HUB_STATE_PREPARE_FIRMWARE_SETUP:
00401                 UC_HUB_TRACE("ARM_UC_HUB_STATE_PREPARE_FIRMWARE_SETUP");
00402 
00403                 /* store pointer to hash */
00404                 arm_uc_hub_firmware_config.hash = &fwinfo.hash;
00405 
00406                 /* parse the url string into a arm_uc_uri_t struct */
00407                 retval = arm_uc_str2uri(fwinfo.uri.ptr,
00408                                         fwinfo.uri.size,
00409                                         &uri);
00410 
00411                 /* URI-based errors are propagated to monitor */
00412                 if (retval.error != ERR_NONE)
00413                 {
00414                     /* make sure that the URI string is always 0-terminated */
00415                     fwinfo.uri.ptr[fwinfo.uri.size_max - 1] = '\0';
00416                     UC_HUB_ERR_MSG("Unable to parse URI string %s", fwinfo.uri.ptr);
00417 
00418                     /* signal warning through external handler */
00419                     ARM_UC_HUB_ErrorHandler(SOMA_ERR_INVALID_PARAMETER,
00420                                             ARM_UC_HUB_STATE_PREPARE_FIRMWARE_SETUP);
00421 
00422                     /* set new state */
00423                     new_state = ARM_UC_HUB_STATE_IDLE;
00424                     break;
00425                 }
00426 
00427                 /* store firmware size */
00428                 arm_uc_hub_firmware_config.package_size = fwinfo.size;
00429 
00430                 /* read cryptography mode to determine if firmware is encrypted */
00431                 switch(fwinfo.cipherMode)
00432                 {
00433                     case ARM_UC_MM_CIPHERMODE_NONE:
00434                         arm_uc_hub_firmware_config.mode = UCFM_MODE_NONE_SHA_256;
00435                         break;
00436 
00437                     case ARM_UC_MM_CIPHERMODE_PSK:
00438                         {
00439                             /* Get pre-shared-key from the Control Center */
00440                             /* TODO: this call should be asynchronous */
00441                             const uint8_t* arm_uc_pre_shared_key = NULL;
00442                             retval = ARM_UC_PreSharedKey_GetKey(&arm_uc_pre_shared_key, 128);
00443                             HANDLE_ERROR(retval, "Unable to get PSK");
00444 
00445                             /* Decode the firmware key to be used to decode the firmware */
00446                             UC_HUB_TRACE("Decoding firmware AES key...");
00447                             mbedtls_aes_context ctx;
00448                             mbedtls_aes_init(&ctx);
00449                             mbedtls_aes_setkey_dec(&ctx, arm_uc_pre_shared_key, 128);
00450                             mbedtls_aes_crypt_ecb(&ctx, MBEDTLS_AES_DECRYPT, fwinfo.psk.cipherKey.ptr, arm_uc_hub_plain_key.ptr);
00451 
00452                             arm_uc_hub_firmware_config.mode = UCFM_MODE_AES_CTR_128_SHA_256;
00453                             arm_uc_hub_firmware_config.key  = &arm_uc_hub_plain_key;
00454                             arm_uc_hub_firmware_config.iv   = &fwinfo.initVector;
00455                         }
00456                         break;
00457 
00458                     case ARM_UC_MM_CIPHERMODE_CERT_CIPHERKEY:
00459                     case ARM_UC_MM_CIPHERMODE_CERT_KEYTABLE:
00460                     default:
00461                         retval.code = MFST_ERR_CRYPTO_MODE;
00462                         HANDLE_ERROR(retval, "Unsupported AES Key distribution mode...");
00463                         break;
00464                 }
00465 
00466                 /* check if storage ID has been set */
00467                 if (fwinfo.strgId.size == 0 || fwinfo.strgId.ptr == NULL)
00468                 {
00469                     /* no storage ID set, use default value 0 */
00470                     arm_uc_hub_firmware_config.package_id = 0;
00471                 }
00472                 else
00473                 {
00474                     /* check if storage ID is "default" */
00475                     uint32_t location = arm_uc_strnstrn(fwinfo.strgId.ptr,
00476                                                         fwinfo.strgId.size,
00477                                                         (const uint8_t*) "default",
00478                                                         7);
00479 
00480                     if (location != UINT32_MAX)
00481                     {
00482                         arm_uc_hub_firmware_config.package_id = 0;
00483                     }
00484                     else
00485                     {
00486                         /* parse storage ID */
00487                         bool success = false;
00488                         arm_uc_hub_firmware_config.package_id =
00489                             arm_uc_str2uint32(fwinfo.strgId.ptr,
00490                                               fwinfo.strgId.size,
00491                                               &success);
00492                     }
00493                 }
00494 
00495 #if ARM_UC_HUB_TRACE_ENABLE
00496                 arm_uc_hub_debug_output();
00497 #endif
00498 
00499                 /* Set new state */
00500                 new_state = ARM_UC_HUB_STATE_REQUEST_DOWNLOAD_AUTHORIZATION;
00501                 break;
00502 
00503             /*****************************************************************/
00504             /* Download authorization                                        */
00505             /*****************************************************************/
00506             case ARM_UC_HUB_STATE_REQUEST_DOWNLOAD_AUTHORIZATION:
00507                 UC_HUB_TRACE("ARM_UC_HUB_STATE_REQUEST_DOWNLOAD_AUTHORIZATION");
00508 
00509                 /* Signal control center */
00510                 ARM_UC_ControlCenter_GetAuthorization(ARM_UCCC_REQUEST_DOWNLOAD);
00511 
00512                 /* Set new state */
00513                 new_state = ARM_UC_HUB_STATE_WAIT_FOR_DOWNLOAD_AUTHORIZATION;
00514                 break;
00515 
00516             case ARM_UC_HUB_STATE_WAIT_FOR_DOWNLOAD_AUTHORIZATION:
00517                 UC_HUB_TRACE("ARM_UC_HUB_STATE_WAIT_FOR_DOWNLOAD_AUTHORIZATION");
00518                 break;
00519 
00520             case ARM_UC_HUB_STATE_DOWNLOAD_AUTHORIZED:
00521                 UC_HUB_TRACE("ARM_UC_HUB_STATE_DOWNLOAD_AUTHORIZED");
00522 
00523                 /* Set new state */
00524                 new_state = ARM_UC_HUB_STATE_SETUP_FIRMWARE;
00525                 break;
00526 
00527             /*****************************************************************/
00528             /* Download firmware                                             */
00529             /*****************************************************************/
00530 
00531             /* The firmware is downloaded in fragments. While one fragment is
00532                written to storage, the next fragment is being downloaded.
00533 
00534                In the ARM_UC_HUB_STATE_FETCH_FIRST_FRAGMENT state, the first
00535                fragment is being downloaded. Once completed, the first fragment
00536                will be in the front_buffer and both the network stack and
00537                storage stack will be idle.
00538 
00539                In the ARM_UC_HUB_STATE_STORE_AND_DOWNLOAD state, the front and
00540                back buffers are swapped. The front buffer is being used for
00541                downloading the next fragment while the back buffer is being
00542                written to storage.
00543 
00544                ARM_UC_FirmwareManager.Write and
00545                ARM_UC_SourceManager.GetFirmwareFragment will both finish
00546                asynchronously generating two events:
00547                ARM_UC_SM_EVENT_FIRMWARE and UCFM_EVENT_UPDATE_DONE.
00548 
00549                If the ARM_UC_SM_EVENT_FIRMWARE event is generated first, the
00550                system enters the ARM_UC_HUB_STATE_WAIT_FOR_STORAGE state.
00551                If the UCFM_EVENT_UPDATE_DONE event is generated first, the
00552                system enters the ARM_UC_HUB_STATE_WAIT_FOR_NETWORK state.
00553                The second generated event will move the system back to the
00554                ARM_UC_HUB_STATE_STORE_AND_DOWNLOAD state.
00555 
00556                The download will stop once the fragment offset is larger than
00557                the firmware size written in the manifest. This moves the system
00558                to the ARM_UC_HUB_STATE_STORE_LAST_FRAGMENT state.
00559 
00560                Once the last fragment is written, the newly written firmware
00561                committed in the ARM_UC_HUB_STATE_FINALIZE_STORAGE state.
00562             */
00563             case ARM_UC_HUB_STATE_SETUP_FIRMWARE:
00564                 {
00565                     UC_HUB_TRACE("ARM_UC_HUB_STATE_SETUP_FIRMWARE");
00566 
00567                     /* store the firmware info in the manifest_firmware_info_t struct */
00568                     arm_uc_firmware_details_t arm_uc_hub_firmware_details = { 0 };
00569 
00570                     /* use manifest timestamp as firmware header version */
00571                     arm_uc_hub_firmware_details.version = fwinfo.timestamp;
00572                     arm_uc_hub_firmware_details.size    = fwinfo.size;
00573 
00574                     /* copy hash */
00575                     memcpy(arm_uc_hub_firmware_details.hash,
00576                         fwinfo.hash.ptr,
00577                         ARM_UC_SHA256_SIZE);
00578 
00579     #if 0
00580                     memcpy(arm_uc_hub_firmware_details.campaign,
00581                         configuration.campaign,
00582                         ARM_UC_GUID_SIZE);
00583     #endif
00584 
00585                     /* setup the firmware manager to get ready for firmware storage */
00586                     retval = ARM_UC_FirmwareManager.Prepare(&arm_uc_hub_firmware_config,
00587                                                             &arm_uc_hub_firmware_details,
00588                                                             &front_buffer);
00589                     HANDLE_ERROR(retval, "ARM_UC_FirmwareManager Setup failed")
00590                 }
00591                 break;
00592 
00593             case ARM_UC_HUB_STATE_FETCH_FIRST_FRAGMENT:
00594                 UC_HUB_TRACE("ARM_UC_HUB_STATE_FETCH_FIRST_FRAGMENT");
00595 
00596                 /* set state to downloading when trying to fetch the first chunk of firmware */
00597                 UC_HUB_TRACE("Setting Monitor State: ARM_UC_MONITOR_STATE_DOWNLOADING");
00598                 ARM_UC_ControlCenter_ReportState(ARM_UC_MONITOR_STATE_DOWNLOADING);
00599 
00600                 /* reset download values */
00601                 front_buffer.size = 0;
00602                 back_buffer.size = 0;
00603                 firmware_offset = 0;
00604 
00605                 /* Check firmware size before entering the download state machine.
00606                    An empty firmware is used for erasing a slot.
00607                 */
00608                 if (firmware_offset < fwinfo.size)
00609                 {
00610                     /* get first firmware fragment */
00611                     UC_HUB_TRACE("Getting next chunk at offset %" PRIu32,
00612                                  firmware_offset);
00613                     retval = ARM_UC_SourceManager.GetFirmwareFragment(&uri,
00614                                                                       &front_buffer,
00615                                                                       firmware_offset);
00616                     HANDLE_ERROR(retval, "GetFirmwareFragment failed")
00617                 }
00618                 else
00619                 {
00620                     /* No download is necessary, send next state to monitor service
00621                        and close storage slot.
00622                     */
00623                     UC_HUB_TRACE("Firmware empty, skip download phase and finalize");
00624                     UC_HUB_TRACE("Setting Monitor State: ARM_UC_MONITOR_STATE_DOWNLOADED");
00625                     ARM_UC_ControlCenter_ReportState(ARM_UC_MONITOR_STATE_DOWNLOADED);
00626                     new_state = ARM_UC_HUB_STATE_FINALIZE_STORAGE;
00627                 }
00628                 break;
00629 
00630             case ARM_UC_HUB_STATE_STORE_AND_DOWNLOAD:
00631                 UC_HUB_TRACE("ARM_UC_HUB_STATE_STORE_AND_DOWNLOAD");
00632 
00633                 /* swap the front and back buffers
00634                    the back buffer contained just downloaded firmware chunk
00635                    the front buffer can now be cleared and used to download new chunk
00636                 */
00637                 {
00638                     arm_uc_buffer_t temp_buf_ptr = front_buffer;
00639                     front_buffer = back_buffer;
00640                     back_buffer = temp_buf_ptr;
00641                 }
00642 
00643                 UC_HUB_TRACE("Fragment: %" PRIu32 " %" PRIu32, firmware_offset, back_buffer.size);
00644 
00645                 /* increase offset by the amount that we just downloaded */
00646                 firmware_offset += back_buffer.size;
00647 
00648                 /* store the downloaded chunk in the back buffer */
00649                 if (back_buffer.size > 0)
00650                 {
00651                     retval = ARM_UC_FirmwareManager.Write(&back_buffer);
00652                     HANDLE_ERROR(retval, "ARM_UC_FirmwareManager Update failed")
00653                 }
00654 
00655                 /* go fetch a new chunk using the front buffer if more are expected */
00656                 if (firmware_offset < fwinfo.size)
00657                 {
00658                     front_buffer.size = 0;
00659                     UC_HUB_TRACE("Getting next chunk at offset: %" PRIu32, firmware_offset);
00660                     retval = ARM_UC_SourceManager.GetFirmwareFragment(&uri, &front_buffer, firmware_offset);
00661                     HANDLE_ERROR(retval, "GetFirmwareFragment failed")
00662                 }
00663                 else
00664                 {
00665                     UC_HUB_TRACE("Store last fragment");
00666                     new_state = ARM_UC_HUB_STATE_STORE_LAST_FRAGMENT;
00667                 }
00668 
00669                 /* report progress */
00670                 ARM_UC_ControlCenter_ReportProgress(firmware_offset, fwinfo.size);
00671                 break;
00672 
00673             case ARM_UC_HUB_STATE_WAIT_FOR_STORAGE:
00674                 UC_HUB_TRACE("ARM_UC_HUB_STATE_WAIT_FOR_STORAGE");
00675                 break;
00676 
00677             case ARM_UC_HUB_STATE_WAIT_FOR_NETWORK:
00678                 UC_HUB_TRACE("ARM_UC_HUB_STATE_WAIT_FOR_NETWORK");
00679                 break;
00680 
00681             case ARM_UC_HUB_STATE_STORE_LAST_FRAGMENT:
00682                 UC_HUB_TRACE("ARM_UC_HUB_STATE_STORE_LAST_FRAGMENT");
00683 
00684                 /* set state to downloaded when the full size of the firmware
00685                    have been fetched.
00686                 */
00687                 UC_HUB_TRACE("Setting Monitor State: ARM_UC_MONITOR_STATE_DOWNLOADED");
00688                 ARM_UC_ControlCenter_ReportState(ARM_UC_MONITOR_STATE_DOWNLOADED);
00689                 break;
00690 
00691             case ARM_UC_HUB_STATE_FINALIZE_STORAGE:
00692                 UC_HUB_TRACE("ARM_UC_HUB_STATE_FINALIZE_STORAGE");
00693 
00694                 retval = ARM_UC_FirmwareManager.Finalize(&front_buffer, &back_buffer);
00695                 HANDLE_ERROR(retval, "ARM_UC_FirmwareManager Finalize failed")
00696                 break;
00697 
00698             /*****************************************************************/
00699             /* Install authorization                                         */
00700             /*****************************************************************/
00701             case ARM_UC_HUB_STATE_STORAGE_FINALIZED:
00702                 UC_HUB_TRACE("ARM_UC_HUB_STATE_STORAGE_FINALIZED");
00703 
00704                 /* Signal control center */
00705                 ARM_UC_ControlCenter_GetAuthorization(ARM_UCCC_REQUEST_INSTALL);
00706 
00707                 /* Set new state */
00708                 new_state = ARM_UC_HUB_STATE_WAIT_FOR_INSTALL_AUTHORIZATION;
00709                 break;
00710 
00711             case ARM_UC_HUB_STATE_WAIT_FOR_INSTALL_AUTHORIZATION:
00712                 UC_HUB_TRACE("ARM_UC_HUB_STATE_WAIT_FOR_INSTALL_AUTHORIZATION");
00713                 break;
00714 
00715             case ARM_UC_HUB_STATE_INSTALL_AUTHORIZED:
00716                 UC_HUB_TRACE("ARM_UC_HUB_STATE_INSTALL_AUTHORIZED");
00717 
00718                 UC_HUB_TRACE("Setting Monitor State: ARM_UC_MONITOR_STATE_UPDATING");
00719                 ARM_UC_ControlCenter_ReportState(ARM_UC_MONITOR_STATE_UPDATING);
00720 
00721 /* TODO: set timeout on ReportState before relying on callback to progress state machine */
00722                 new_state = ARM_UC_HUB_STATE_ACTIVATE_FIRMWARE;
00723                 break;
00724 
00725             case ARM_UC_HUB_STATE_ACTIVATE_FIRMWARE:
00726                 UC_HUB_TRACE("ARM_UC_HUB_STATE_ACTIVATE_FIRMWARE");
00727 
00728                 /* Firmware verification passes, activate firmware image.
00729                 */
00730                 ARM_UC_FirmwareManager.Activate(arm_uc_hub_firmware_config.package_id);
00731                 break;
00732 
00733             case ARM_UC_HUB_STATE_REBOOT:
00734                 UC_HUB_TRACE("ARM_UC_HUB_STATE_REBOOT");
00735 
00736                 /* Firmware activated, now reboot the system to apply
00737                    the new image.
00738                 */
00739                 pal_osReboot();
00740 
00741                 /* Reboot not implemented on this platform.
00742                    Report new firmware hash and continue operation.
00743                 */
00744                 new_state = ARM_UC_HUB_STATE_GET_ACTIVE_FIRMWARE_DETAILS;
00745                 break;
00746 
00747             /*****************************************************************/
00748             /* Error                                                         */
00749             /*****************************************************************/
00750             case ARM_UC_HUB_STATE_ERROR_FIRMWARE_MANAGER:
00751                 UC_HUB_TRACE("ARM_UC_HUB_STATE_ERROR_FIRMWARE_MANAGER");
00752                 new_state = ARM_UC_HUB_STATE_IDLE;
00753                 break;
00754 
00755             case ARM_UC_HUB_STATE_ERROR_MANIFEST_MANAGER:
00756                 UC_HUB_TRACE("ARM_UC_HUB_STATE_ERROR_MANIFEST_MANAGER");
00757                 new_state = ARM_UC_HUB_STATE_IDLE;
00758                 break;
00759 
00760             case ARM_UC_HUB_STATE_ERROR_SOURCE_MANAGER:
00761                 UC_HUB_TRACE("ARM_UC_HUB_STATE_ERROR_SOURCE_MANAGER");
00762                 new_state = ARM_UC_HUB_STATE_IDLE;
00763                 break;
00764 
00765             case ARM_UC_HUB_STATE_ERROR_CONTROL_CENTER:
00766                 UC_HUB_TRACE("ARM_UC_HUB_STATE_ERROR_CONTROL_CENTER");
00767                 new_state = ARM_UC_HUB_STATE_IDLE;
00768                 break;
00769 
00770             case ARM_UC_HUB_STATE_WAIT_FOR_ERROR_ACK:
00771                 UC_HUB_TRACE("ARM_UC_HUB_STATE_WAIT_FOR_ERROR_ACK");
00772                 /* Don't change state. The only place where this state is set is in
00773                    update_client_hub_error_handler.c, right after reporting the update
00774                    result, so we wait for a "report done" event (ARM_UCCC_EVENT_MONITOR_SEND_DONE
00775                    in arm_uc_hub_event_handlers.c). The handler for this particular
00776                    event will then set the state to 'idle' */
00777                 break;
00778 
00779             default:
00780                 new_state = ARM_UC_HUB_STATE_IDLE;
00781                 break;
00782         }
00783     }
00784     while (arm_uc_hub_state != new_state);
00785 }
00786