Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

allow the bootloader to be flashed over DFU #1788

Merged
merged 1 commit into from
Jun 14, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions hal/inc/hal_dynalib_ota.h
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ DYNALIB_FN(6, hal_ota, HAL_FLASH_Update, int(const uint8_t*, uint32_t, uint32_t,
DYNALIB_FN(7, hal_ota, HAL_FLASH_End, hal_update_complete_t(hal_module_t*))
DYNALIB_FN(8, hal_ota, HAL_FLASH_OTA_Validate, int(hal_module_t*, bool, module_validation_flags_t, void*))
DYNALIB_FN(9, hal_ota, HAL_OTA_Add_System_Info, void(hal_system_info_t* info, bool create, void* reserved))
DYNALIB_FN(10, hal_ota, HAL_FLASH_ApplyPendingUpdate, hal_update_complete_t(hal_module_t*, bool, void*))
DYNALIB_END(hal_ota)

#endif /* HAL_DYNALIB_OTA_H */
Expand Down
7 changes: 7 additions & 0 deletions hal/inc/ota_flash_hal.h
Original file line number Diff line number Diff line change
Expand Up @@ -143,6 +143,13 @@ typedef enum {

hal_update_complete_t HAL_FLASH_End(hal_module_t* module);

/**
* @param module Optional pointer to a module that receives the module definition of the firmware that was flashed.
* @param dryRun when true, only test that the system has a pending update in memory. When false, the test is performed and the module
* applied if valid (or the bootloader instructed to apply it.)
*/
hal_update_complete_t HAL_FLASH_ApplyPendingUpdate(hal_module_t* module, bool dryRun, void* reserved);

uint32_t HAL_FLASH_ModuleAddress(uint32_t address);
uint32_t HAL_FLASH_ModuleLength(uint32_t address);
bool HAL_FLASH_VerifyCRC32(uint32_t address, uint32_t length);
Expand Down
2 changes: 1 addition & 1 deletion hal/src/core/ota_flash_hal.c
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ int HAL_FLASH_OTA_Validate(hal_module_t* mod, bool userDepsOptional, module_vali
return 0;
}

hal_update_complete_t HAL_FLASH_End(hal_module_t* reserved)
hal_update_complete_t HAL_FLASH_ApplyPendingUpdate(hal_module_t* module, bool dryRun, void* reserved)
{
FLASH_End();
return HAL_UPDATE_APPLIED_PENDING_RESTART;
Expand Down
6 changes: 5 additions & 1 deletion hal/src/gcc/ota_flash_hal.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,11 @@ int HAL_FLASH_OTA_Validate(hal_module_t* mod, bool userDepsOptional, module_vali
return HAL_UPDATE_APPLIED;
}


hal_update_complete_t HAL_FLASH_ApplyPendingUpdate(hal_module_t* module, bool dryRun, void* reserved)
{
HAL_FLASH_End(module);
return HAL_UPDATE_APPLIED_PENDING_RESTART;
}

/**
* Set the claim code for this device.
Expand Down
25 changes: 25 additions & 0 deletions hal/src/nRF52840/ota_flash_hal.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -450,6 +450,31 @@ hal_update_complete_t HAL_FLASH_End(hal_module_t* mod)
return result;
}

// Todo this code and much of the code here is duplicated between Gen2 and Gen3
// This should be factored out into directory shared by both platforms.
hal_update_complete_t HAL_FLASH_ApplyPendingUpdate(hal_module_t* module, bool dryRun, void* reserved)
{
uint8_t otaUpdateFlag = DCT_OTA_UPDATE_FLAG_CLEAR;
STATIC_ASSERT(sizeof(otaUpdateFlag)==DCT_OTA_UPDATE_FLAG_SIZE, "expected ota update flag size to be 1");
dct_read_app_data_copy(DCT_OTA_UPDATE_FLAG_OFFSET, &otaUpdateFlag, DCT_OTA_UPDATE_FLAG_SIZE);
hal_update_complete_t result = HAL_UPDATE_ERROR;
if (otaUpdateFlag==DCT_OTA_UPDATE_FLAG_SET) {
if (dryRun) {
// todo - we should probably check the module integrity too
// ideally this parameter would be passed to HAL_FLASH_End to avoid duplication of logic here.
result = HAL_UPDATE_APPLIED;
}
else {
// clear the flag
otaUpdateFlag = DCT_OTA_UPDATE_FLAG_CLEAR;
dct_write_app_data(&otaUpdateFlag, DCT_OTA_UPDATE_FLAG_OFFSET, DCT_OTA_UPDATE_FLAG_SIZE);
result = HAL_FLASH_End(module);
}
}
return result;
}


void HAL_FLASH_Read_ServerAddress(ServerAddress* server_addr)
{
bool udp = HAL_Feature_Get(FEATURE_CLOUD_UDP);
Expand Down
25 changes: 25 additions & 0 deletions hal/src/stm32f2xx/ota_flash_hal_stm32f2xx.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -340,6 +340,31 @@ hal_update_complete_t HAL_FLASH_End(hal_module_t* mod)
return result;
}

// Todo this code and much of the code here is duplicated between Gen2 and Gen3
// This should be factored out into directory shared by both platforms.
hal_update_complete_t HAL_FLASH_ApplyPendingUpdate(hal_module_t* module, bool dryRun, void* reserved)
{
uint8_t otaUpdateFlag = DCT_OTA_UPDATE_FLAG_CLEAR;
STATIC_ASSERT(sizeof(otaUpdateFlag)==DCT_OTA_UPDATE_FLAG_SIZE, "expected ota update flag size to be 1");
dct_read_app_data_copy(DCT_OTA_UPDATE_FLAG_OFFSET, &otaUpdateFlag, DCT_OTA_UPDATE_FLAG_SIZE);
hal_update_complete_t result = HAL_UPDATE_ERROR;
if (otaUpdateFlag==DCT_OTA_UPDATE_FLAG_SET) {
if (dryRun) {
// todo - we should probably check the module integrity too
// ideally this parameter would be passed to HAL_FLASH_End to avoid duplication of logic here.
result = HAL_UPDATE_APPLIED;
}
else {
// clear the flag
otaUpdateFlag = DCT_OTA_UPDATE_FLAG_CLEAR;
dct_write_app_data(&otaUpdateFlag, DCT_OTA_UPDATE_FLAG_OFFSET, DCT_OTA_UPDATE_FLAG_SIZE);
result = HAL_FLASH_End(module);
}
}
return result;
}


void copy_dct(void* target, uint16_t offset, uint16_t length) {
dct_read_app_data_copy(offset, target, length);
}
Expand Down
10 changes: 9 additions & 1 deletion platform/MCU/STM32F2xx/SPARK_Firmware_Driver/inc/dct.h
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,8 @@ typedef struct __attribute__((packed)) application_dct {
uint8_t device_private_key[1216]; // sufficient for 2048 bits
uint8_t device_public_key[384]; // sufficient for 2048 bits
static_ip_config_t ip_config;
uint8_t unused[96];
uint8_t unused[95]; //
uint8_t ota_update_flag; // should be 0xA5 to trigger an update from data stored in the update region
uint32_t feature_flags[1]; // Configurable feature flags (see HAL_Feature_Set()). Default uninitialized value is 0xffffffff
uint8_t country_code[4]; // WICED country code. Stored as bit-endian format: CH1/CH2/0/rev (max 255)
uint8_t claim_code[63]; // claim code. no terminating null.
Expand Down Expand Up @@ -111,6 +112,7 @@ typedef struct __attribute__((packed)) application_dct {
#define DCT_SERVER_PUBLIC_KEY_OFFSET (offsetof(application_dct_t, server_public_key))
#define DCT_SERVER_ADDRESS_OFFSET ((DCT_SERVER_PUBLIC_KEY_OFFSET)+384)
#define DCT_IP_CONFIG_OFFSET (offsetof(application_dct_t, ip_config))
#define DCT_OTA_UPDATE_FLAG_OFFSET (offsetof(application_dct_t, ota_update_flag))
#define DCT_FEATURE_FLAGS_OFFSET (offsetof(application_dct_t, feature_flags))
#define DCT_COUNTRY_CODE_OFFSET (offsetof(application_dct_t, country_code))
#define DCT_CLAIM_CODE_OFFSET (offsetof(application_dct_t, claim_code))
Expand Down Expand Up @@ -138,6 +140,7 @@ typedef struct __attribute__((packed)) application_dct {
#define DCT_DEVICE_PUBLIC_KEY_SIZE (sizeof(application_dct_t::device_public_key))
#define DCT_SERVER_PUBLIC_KEY_SIZE (sizeof(application_dct_t::server_public_key))
#define DCT_IP_CONFIG_SIZE (sizeof(application_dct_t::ip_config))
#define DCT_OTA_UPDATE_FLAG_SIZE (sizeof(application_dct_t::ota_update_flag))
#define DCT_FEATURE_FLAGS_SIZE (sizeof(application_dct_t::feature_flags))
#define DCT_COUNTRY_CODE_SIZE (sizeof(application_dct_t::country_code))
#define DCT_CLAIM_CODE_SIZE (sizeof(application_dct_t::claim_code))
Expand Down Expand Up @@ -171,6 +174,7 @@ STATIC_ASSERT_DCT_OFFSET(version, 32);
STATIC_ASSERT_DCT_OFFSET(device_private_key, 34);
STATIC_ASSERT_DCT_OFFSET(device_public_key, 1250 /*34+1216*/);
STATIC_ASSERT_DCT_OFFSET(ip_config, 1634 /* 1250 + 384 */);
STATIC_ASSERT_DCT_OFFSET(ota_update_flag, 1753);
STATIC_ASSERT_DCT_OFFSET(feature_flags, 1754 /* 1634 + 120 */);
STATIC_ASSERT_DCT_OFFSET(country_code, 1758 /* 1754 + 4 */);
STATIC_ASSERT_DCT_OFFSET(claim_code, 1762 /* 1758 + 4 */);
Expand Down Expand Up @@ -212,6 +216,10 @@ STATIC_ASSERT_FLAGS_OFFSET(FeaturesEnabled_SysFlag, 19);
STATIC_ASSERT_FLAGS_OFFSET(RCC_CSR_SysFlag, 20);
STATIC_ASSERT_FLAGS_OFFSET(reserved, 24);

#define DCT_OTA_UPDATE_FLAG_SET (0xA5)
#define DCT_OTA_UPDATE_FLAG_CLEAR (0XFF)


// Note: This function is deprecated, use dct_read_app_data_copy() or dct_read_app_data_lock() instead
const void* dct_read_app_data(uint32_t offset);

Expand Down
9 changes: 8 additions & 1 deletion platform/MCU/nRF52840/inc/dct.h
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,8 @@ typedef struct __attribute__((packed)) application_dct {
uint8_t device_private_key[1216]; // sufficient for 2048 bits
uint8_t device_public_key[384]; // sufficient for 2048 bits
static_ip_config_t ip_config;
uint8_t unused[96];
uint8_t unused[95];
uint8_t ota_update_flag; // should be 0xA5 to trigger an update from data stored in the update region
uint32_t feature_flags[1]; // Configurable feature flags (see HAL_Feature_Set()). Default uninitialized value is 0xffffffff
uint8_t country_code[4]; // WICED country code. Stored as bit-endian format: CH1/CH2/0/rev (max 255)
uint8_t claim_code[63]; // claim code. no terminating null.
Expand Down Expand Up @@ -118,6 +119,7 @@ typedef struct __attribute__((packed)) application_dct {
#define DCT_SERVER_PUBLIC_KEY_OFFSET (offsetof(application_dct_t, server_public_key))
#define DCT_SERVER_ADDRESS_OFFSET ((DCT_SERVER_PUBLIC_KEY_OFFSET)+384)
#define DCT_IP_CONFIG_OFFSET (offsetof(application_dct_t, ip_config))
#define DCT_OTA_UPDATE_FLAG_OFFSET (offsetof(application_dct_t, ota_update_flag))
#define DCT_FEATURE_FLAGS_OFFSET (offsetof(application_dct_t, feature_flags))
#define DCT_COUNTRY_CODE_OFFSET (offsetof(application_dct_t, country_code))
#define DCT_CLAIM_CODE_OFFSET (offsetof(application_dct_t, claim_code))
Expand Down Expand Up @@ -149,6 +151,7 @@ typedef struct __attribute__((packed)) application_dct {
#define DCT_DEVICE_PUBLIC_KEY_SIZE (sizeof(application_dct_t::device_public_key))
#define DCT_SERVER_PUBLIC_KEY_SIZE (sizeof(application_dct_t::server_public_key))
#define DCT_IP_CONFIG_SIZE (sizeof(application_dct_t::ip_config))
#define DCT_OTA_UPDATE_FLAG_SIZE (sizeof(application_dct_t::ota_update_flag))
#define DCT_FEATURE_FLAGS_SIZE (sizeof(application_dct_t::feature_flags))
#define DCT_COUNTRY_CODE_SIZE (sizeof(application_dct_t::country_code))
#define DCT_CLAIM_CODE_SIZE (sizeof(application_dct_t::claim_code))
Expand Down Expand Up @@ -178,6 +181,9 @@ typedef struct __attribute__((packed)) application_dct {
#define STATIC_ASSERT_DCT_OFFSET(field, expected) PARTICLE_STATIC_ASSERT( dct_##field, offsetof(application_dct_t, field)==expected)
#define STATIC_ASSERT_FLAGS_OFFSET(field, expected) PARTICLE_STATIC_ASSERT( dct_sysflag_##field, offsetof(platform_system_flags_t, field)==expected)

#define DCT_OTA_UPDATE_FLAG_SET (0xA5)
#define DCT_OTA_UPDATE_FLAG_CLEAR (0XFF)

/**
* Assert offsets. These ensure that the layout in flash isn't inadvertently changed.
*/
Expand All @@ -186,6 +192,7 @@ STATIC_ASSERT_DCT_OFFSET(version, 32);
STATIC_ASSERT_DCT_OFFSET(device_private_key, 34);
STATIC_ASSERT_DCT_OFFSET(device_public_key, 1250 /*34+1216*/);
STATIC_ASSERT_DCT_OFFSET(ip_config, 1634 /* 1250 + 384 */);
STATIC_ASSERT_DCT_OFFSET(ota_update_flag, 1753);
STATIC_ASSERT_DCT_OFFSET(feature_flags, 1754 /* 1634 + 120 */);
STATIC_ASSERT_DCT_OFFSET(country_code, 1758 /* 1754 + 4 */);
STATIC_ASSERT_DCT_OFFSET(claim_code, 1762 /* 1758 + 4 */);
Expand Down
8 changes: 7 additions & 1 deletion system/src/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -767,7 +767,13 @@ void app_setup_and_loop(void)
bool threaded = system_thread_get_state(NULL) != spark::feature::DISABLED &&
(system_mode()!=SAFE_MODE);

Network_Setup(threaded);
if (HAL_FLASH_ApplyPendingUpdate(nullptr /*module*/, false /*dryRun*/, nullptr /*reserved*/)==HAL_UPDATE_APPLIED_PENDING_RESTART) {
// the regular OTA update delays 100 milliseconds so maintaining the same behavior.
HAL_Delay_Milliseconds(100);
HAL_Core_System_Reset_Ex(RESET_REASON_UPDATE, 0, nullptr);
}

Network_Setup(threaded); // todo - why does this come before system thread initialization?

#if PLATFORM_THREADING
if (threaded)
Expand Down
4 changes: 2 additions & 2 deletions system/src/system_update.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -382,8 +382,8 @@ int Spark_Finish_Firmware_Update(FileTransfer::Descriptor& file, uint32_t flags,
if (file.store==FileTransfer::Store::FIRMWARE)
{
hal_update_complete_t result = HAL_FLASH_End(module ? (hal_module_t*)module : &mod);
system_notify_event(firmware_update, result!=HAL_UPDATE_ERROR ? firmware_update_complete : firmware_update_failed, &file);
res = (result == HAL_UPDATE_ERROR);
system_notify_event(firmware_update, result<=HAL_UPDATE_ERROR ? firmware_update_complete : firmware_update_failed, &file);
res = (result <= HAL_UPDATE_ERROR);

// always restart for now
if ((true || result==HAL_UPDATE_APPLIED_PENDING_RESTART) && !(flags & UpdateFlag::DONT_RESET))
Expand Down