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