Skip to content

Commit

Permalink
[FL-2269] Core2 OTA (flipperdevices#1144)
Browse files Browse the repository at this point in the history
* C2OTA: wip
* Update Cube to 1.13.3
* Fixed prio
* Functional Core2 updater
* Removed hardware CRC usage; code cleanup & linter fixes
* Moved hardcoded stack params to copro.mk
* Fixing CI bundling of core2 fw
* Removed last traces of hardcoded radio stack
* OB processing draft
* Python scripts cleanup
* Support for comments in ob data
* Sacrificed SD card icon in favor of faster update. Waiting for Storage fix
* Additional handling for OB mismatched values
* Description for new furi_hal apis; spelling fixes
* Rework of OB write, WIP
* Properly restarting OB verification loop
* Split update_task_workers.c
* Checking OBs after enabling post-update mode
* Moved OB verification before flashing
* Removed ob.data for custom stacks
* Fixed progress calculation for OB
* Removed unnecessary OB mask cast

Co-authored-by: Aleksandr Kutuzov <[email protected]>
  • Loading branch information
hedger and skotopes authored Apr 27, 2022
1 parent 81aeda8 commit 7ce305f
Show file tree
Hide file tree
Showing 41 changed files with 1,623 additions and 296 deletions.
14 changes: 7 additions & 7 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -121,11 +121,11 @@ jobs:
- name: 'Bundle core2 firmware'
if: ${{ !github.event.pull_request.head.repo.fork }}
run: |
test -d core2_firmware && rm -rf core2_firmware || true
mkdir core2_firmware
./scripts/assets.py copro lib/STM32CubeWB core2_firmware STM32WB5x
tar czpf artifacts/flipper-z-any-core2_firmware-${{steps.names.outputs.suffix}}.tgz core2_firmware
uses: ./.github/actions/docker
with:
run: |
make -C assets copro_bundle
tar czpf artifacts/flipper-z-any-core2_firmware-${{steps.names.outputs.suffix}}.tgz -C assets core2_firmware
- name: 'Upload artifacts to update server'
if: ${{ !github.event.pull_request.head.repo.fork }}
Expand Down Expand Up @@ -213,8 +213,8 @@ jobs:
with:
run: |
set -e
make -C assets clean
make -C assets
make assets_rebuild assets_manifest
git diff --quiet || ( echo "Assets recompilation required."; exit 255 )
- name: 'Build the firmware in docker'
uses: ./.github/actions/docker
Expand Down
17 changes: 11 additions & 6 deletions Makefile
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
PROJECT_ROOT := $(abspath $(dir $(abspath $(firstword $(MAKEFILE_LIST)))))

include $(PROJECT_ROOT)/make/git.mk

COPRO_DIR := $(PROJECT_ROOT)/lib/STM32CubeWB/Projects/STM32WB_Copro_Wireless_Binaries/STM32WB5x
include $(PROJECT_ROOT)/assets/copro.mk

PROJECT_SOURCE_DIRECTORIES := \
$(PROJECT_ROOT)/applications \
Expand Down Expand Up @@ -97,7 +96,13 @@ updater_package_bin: firmware_all updater

.PHONY: updater_package
updater_package: firmware_all updater assets_manifest
@$(PROJECT_ROOT)/scripts/dist.py copy -t $(TARGET) -p firmware updater -s $(DIST_SUFFIX) -r $(PROJECT_ROOT)/assets/resources --bundlever "$(VERSION_STRING)"
@$(PROJECT_ROOT)/scripts/dist.py copy \
-t $(TARGET) -p firmware updater \
-s $(DIST_SUFFIX) -r $(PROJECT_ROOT)/assets/resources \
--bundlever "$(VERSION_STRING)" \
--radio $(COPRO_STACK_BIN_PATH) \
--radiotype $(COPRO_STACK_TYPE) \
--obdata $(PROJECT_ROOT)/scripts/ob.data

.PHONY: assets_manifest
assets_manifest:
Expand All @@ -109,7 +114,7 @@ assets_rebuild:

.PHONY: flash_radio
flash_radio:
@$(PROJECT_ROOT)/scripts/flash.py core2radio 0x080D7000 $(COPRO_DIR)/stm32wb5x_BLE_Stack_light_fw.bin
@$(PROJECT_ROOT)/scripts/flash.py core2radio $(COPRO_STACK_BIN_PATH) --addr=$(COPRO_STACK_ADDR)
@$(PROJECT_ROOT)/scripts/ob.py set

.PHONY: flash_radio_fus
Expand All @@ -125,8 +130,8 @@ flash_radio_fus:

.PHONY: flash_radio_fus_please_i_m_not_going_to_complain
flash_radio_fus_please_i_m_not_going_to_complain:
@$(PROJECT_ROOT)/scripts/flash.py core2fus 0x080EC000 --statement=AGREE_TO_LOSE_FLIPPER_FEATURES_THAT_USE_CRYPTO_ENCLAVE $(COPRO_DIR)/stm32wb5x_FUS_fw_for_fus_0_5_3.bin
@$(PROJECT_ROOT)/scripts/flash.py core2fus 0x080EC000 --statement=AGREE_TO_LOSE_FLIPPER_FEATURES_THAT_USE_CRYPTO_ENCLAVE $(COPRO_DIR)/stm32wb5x_FUS_fw.bin
@$(PROJECT_ROOT)/scripts/flash.py core2fus 0x080EC000 --statement=AGREE_TO_LOSE_FLIPPER_FEATURES_THAT_USE_CRYPTO_ENCLAVE $(COPRO_FIRMWARE_DIR)/stm32wb5x_FUS_fw_for_fus_0_5_3.bin
@$(PROJECT_ROOT)/scripts/flash.py core2fus 0x080EC000 --statement=AGREE_TO_LOSE_FLIPPER_FEATURES_THAT_USE_CRYPTO_ENCLAVE $(COPRO_FIRMWARE_DIR)/stm32wb5x_FUS_fw.bin
@$(PROJECT_ROOT)/scripts/ob.py set

.PHONY: lint
Expand Down
2 changes: 1 addition & 1 deletion applications/bt/bt_cli.c
Original file line number Diff line number Diff line change
Expand Up @@ -148,7 +148,7 @@ static void bt_cli_command_packet_rx(Cli* cli, string_t args, void* context) {
static void bt_cli_scan_callback(GapAddress address, void* context) {
furi_assert(context);
osMessageQueueId_t queue = context;
osMessageQueuePut(queue, &address, NULL, 250);
osMessageQueuePut(queue, &address, 0, 250);
}

static void bt_cli_command_scan(Cli* cli, string_t args, void* context) {
Expand Down
7 changes: 7 additions & 0 deletions applications/bt/bt_service/bt.c
Original file line number Diff line number Diff line change
Expand Up @@ -319,6 +319,13 @@ static void bt_change_profile(Bt* bt, BtMessage* message) {
int32_t bt_srv() {
Bt* bt = bt_alloc();

if(furi_hal_rtc_get_boot_mode() != FuriHalRtcBootModeNormal) {
FURI_LOG_W(TAG, "Skipped BT init: device in special startup mode");
ble_glue_wait_for_c2_start(FURI_HAL_BT_C2_START_TIMEOUT);
furi_record_create("bt", bt);
return 0;
}

// Read keys
if(!bt_keys_storage_load(bt)) {
FURI_LOG_W(TAG, "Failed to load bonding keys");
Expand Down
13 changes: 3 additions & 10 deletions applications/updater/scenes/updater_scene_main.c
Original file line number Diff line number Diff line change
Expand Up @@ -36,9 +36,9 @@ void updater_scene_main_on_enter(void* context) {
* will be missing from UI, however, /ext will be fully operational. So, until it's fixed, this
* should remain commented out. */
// If (somehow) we started after SD card is mounted, initiate update immediately
//if(storage_sd_status(updater->storage) == FSE_OK) {
// view_dispatcher_send_custom_event(updater->view_dispatcher, UpdaterCustomEventStartUpdate);
//}
if(storage_sd_status(updater->storage) == FSE_OK) {
view_dispatcher_send_custom_event(updater->view_dispatcher, UpdaterCustomEventStartUpdate);
}

updater_main_set_view_dispatcher(main_view, updater->view_dispatcher);
view_dispatcher_switch_to_view(updater->view_dispatcher, UpdaterViewMain);
Expand All @@ -64,13 +64,6 @@ bool updater_scene_main_on_event(void* context, SceneManagerEvent event) {
} else if(event.type == SceneManagerEventTypeCustom) {
switch(event.event) {
case UpdaterCustomEventStartUpdate:
if(!update_task_is_running(updater->update_task) &&
update_task_init(updater->update_task)) {
update_task_start(updater->update_task);
}
consumed = true;
break;

case UpdaterCustomEventRetryUpdate:
if(!update_task_is_running(updater->update_task) &&
(update_task_get_state(updater->update_task)->stage != UpdateTaskStageCompleted))
Expand Down
23 changes: 13 additions & 10 deletions applications/updater/util/update_task.c
Original file line number Diff line number Diff line change
Expand Up @@ -15,13 +15,18 @@ static const char* update_task_stage_descr[] = {
[UpdateTaskStageValidateDFUImage] = "Checking DFU file",
[UpdateTaskStageFlashWrite] = "Writing flash",
[UpdateTaskStageFlashValidate] = "Validating",
[UpdateTaskStageRadioImageValidate] = "Checking radio image",
[UpdateTaskStageRadioErase] = "Removing radio stack",
[UpdateTaskStageRadioWrite] = "Writing radio stack",
[UpdateTaskStageRadioCommit] = "Applying radio stack",
[UpdateTaskStageRadioInstall] = "Installing radio stack",
[UpdateTaskStageRadioBusy] = "Core2 is updating",
[UpdateTaskStageOBValidation] = "Validating opt. bytes",
[UpdateTaskStageLfsBackup] = "Backing up LFS",
[UpdateTaskStageLfsRestore] = "Restoring LFS",
[UpdateTaskStageResourcesUpdate] = "Updating resources",
[UpdateTaskStageCompleted] = "Completed!",
[UpdateTaskStageError] = "Error",
[UpdateTaskStageOBError] = "OB error, pls report",
};

static void update_task_set_status(UpdateTask* update_task, const char* status) {
Expand All @@ -37,7 +42,10 @@ static void update_task_set_status(UpdateTask* update_task, const char* status)

void update_task_set_progress(UpdateTask* update_task, UpdateTaskStage stage, uint8_t progress) {
if(stage != UpdateTaskStageProgress) {
update_task->state.stage = stage;
// do not override more specific error states
if((update_task->state.stage < UpdateTaskStageError) || (stage < UpdateTaskStageError)) {
update_task->state.stage = stage;
}
update_task->state.current_stage_idx++;
update_task_set_status(update_task, NULL);
}
Expand All @@ -53,7 +61,7 @@ void update_task_set_progress(UpdateTask* update_task, UpdateTaskStage stage, ui
progress,
update_task->state.current_stage_idx,
update_task->state.total_stages,
update_task->state.stage == UpdateTaskStageError,
update_task->state.stage >= UpdateTaskStageError,
update_task->status_change_cb_state);
}
}
Expand Down Expand Up @@ -116,6 +124,7 @@ UpdateTask* update_task_alloc() {
update_task->storage = furi_record_open("storage");
update_task->file = storage_file_alloc(update_task->storage);
update_task->status_change_cb = NULL;
string_init(update_task->update_path);

FuriThread* thread = update_task->thread = furi_thread_alloc();

Expand Down Expand Up @@ -152,12 +161,6 @@ void update_task_free(UpdateTask* update_task) {
free(update_task);
}

bool update_task_init(UpdateTask* update_task) {
furi_assert(update_task);
string_init(update_task->update_path);
return true;
}

bool update_task_parse_manifest(UpdateTask* update_task) {
furi_assert(update_task);
update_task_set_progress(update_task, UpdateTaskStageReadManifest, 0);
Expand Down Expand Up @@ -224,4 +227,4 @@ UpdateTaskState const* update_task_get_state(UpdateTask* update_task) {
UpdateManifest const* update_task_get_manifest(UpdateTask* update_task) {
furi_assert(update_task);
return update_task->manifest;
}
}
9 changes: 6 additions & 3 deletions applications/updater/util/update_task.h
Original file line number Diff line number Diff line change
Expand Up @@ -19,13 +19,18 @@ typedef enum {
UpdateTaskStageValidateDFUImage,
UpdateTaskStageFlashWrite,
UpdateTaskStageFlashValidate,
UpdateTaskStageRadioImageValidate,
UpdateTaskStageRadioErase,
UpdateTaskStageRadioWrite,
UpdateTaskStageRadioCommit,
UpdateTaskStageRadioInstall,
UpdateTaskStageRadioBusy,
UpdateTaskStageOBValidation,
UpdateTaskStageLfsBackup,
UpdateTaskStageLfsRestore,
UpdateTaskStageResourcesUpdate,
UpdateTaskStageCompleted,
UpdateTaskStageError,
UpdateTaskStageOBError
} UpdateTaskStage;

typedef struct {
Expand All @@ -50,8 +55,6 @@ UpdateTask* update_task_alloc();

void update_task_free(UpdateTask* update_task);

bool update_task_init(UpdateTask* update_task);

void update_task_set_progress_cb(UpdateTask* update_task, updateProgressCb cb, void* state);

bool update_task_start(UpdateTask* update_task);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,99 +9,17 @@
#include <update_util/lfs_backup.h>
#include <update_util/update_operation.h>
#include <toolbox/tar/tar_archive.h>
#include <toolbox/crc32_calc.h>

#define TAG "UpdWorkerBackup"

#define CHECK_RESULT(x) \
if(!(x)) { \
break; \
}

#define STM_DFU_VENDOR_ID 0x0483
#define STM_DFU_PRODUCT_ID 0xDF11
/* Written into DFU file by build pipeline */
#define FLIPPER_ZERO_DFU_DEVICE_CODE 0xFFFF

#define EXT_PATH "/ext"

static const DfuValidationParams flipper_dfu_params = {
.device = FLIPPER_ZERO_DFU_DEVICE_CODE,
.product = STM_DFU_PRODUCT_ID,
.vendor = STM_DFU_VENDOR_ID,
};

static void update_task_dfu_progress(const uint8_t progress, void* context) {
UpdateTask* update_task = context;
update_task_set_progress(update_task, UpdateTaskStageProgress, progress);
}

static bool page_task_compare_flash(
const uint8_t i_page,
const uint8_t* update_block,
uint16_t update_block_len) {
const size_t page_addr = furi_hal_flash_get_base() + furi_hal_flash_get_page_size() * i_page;
return (memcmp(update_block, (void*)page_addr, update_block_len) == 0);
}

/* Verifies a flash operation address for fitting into writable memory
*/
static bool check_address_boundaries(const size_t address) {
const size_t min_allowed_address = furi_hal_flash_get_base();
const size_t max_allowed_address = (size_t)furi_hal_flash_get_free_end_address();
return ((address >= min_allowed_address) && (address < max_allowed_address));
}

int32_t update_task_worker_flash_writer(void* context) {
furi_assert(context);
UpdateTask* update_task = context;
bool success = false;
DfuUpdateTask page_task = {
.address_cb = &check_address_boundaries,
.progress_cb = &update_task_dfu_progress,
.task_cb = &furi_hal_flash_program_page,
.context = update_task,
};

update_task->state.current_stage_idx = 0;
update_task->state.total_stages = 4;

do {
CHECK_RESULT(update_task_parse_manifest(update_task));

if(!string_empty_p(update_task->manifest->firmware_dfu_image)) {
update_task_set_progress(update_task, UpdateTaskStageValidateDFUImage, 0);
CHECK_RESULT(
update_task_open_file(update_task, update_task->manifest->firmware_dfu_image));
CHECK_RESULT(
dfu_file_validate_crc(update_task->file, &update_task_dfu_progress, update_task));

const uint8_t valid_targets =
dfu_file_validate_headers(update_task->file, &flipper_dfu_params);
if(valid_targets == 0) {
break;
}

update_task_set_progress(update_task, UpdateTaskStageFlashWrite, 0);
CHECK_RESULT(dfu_file_process_targets(&page_task, update_task->file, valid_targets));

page_task.task_cb = &page_task_compare_flash;

update_task_set_progress(update_task, UpdateTaskStageFlashValidate, 0);
CHECK_RESULT(dfu_file_process_targets(&page_task, update_task->file, valid_targets));
}

update_task_set_progress(update_task, UpdateTaskStageCompleted, 100);

furi_hal_rtc_set_boot_mode(FuriHalRtcBootModePostUpdate);

success = true;
} while(false);

if(!success) {
update_task_set_progress(update_task, UpdateTaskStageError, update_task->state.progress);
}

return success ? UPDATE_TASK_NOERR : UPDATE_TASK_FAILED;
}

static bool update_task_pre_update(UpdateTask* update_task) {
bool success = false;
string_t backup_file_path;
Expand Down Expand Up @@ -143,7 +61,8 @@ static bool update_task_post_update(UpdateTask* update_task) {
string_t file_path;
string_init(file_path);

update_task->state.total_stages = 2;
// status text is too long, too few stages to bother with a counter
update_task->state.total_stages = 0;

do {
CHECK_RESULT(update_task_parse_manifest(update_task));
Expand Down Expand Up @@ -184,6 +103,7 @@ static bool update_task_post_update(UpdateTask* update_task) {
}
tar_archive_free(archive);
}
success = true;
} while(false);

string_clear(file_path);
Expand Down
Loading

0 comments on commit 7ce305f

Please sign in to comment.