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