Merge branch 'ofw-dev' into dev

This commit is contained in:
MX
2023-07-14 16:53:45 +03:00
10 changed files with 294 additions and 36 deletions
@@ -430,6 +430,20 @@ FS_Error storage_common_rename(Storage* storage, const char* old_path, const cha
break;
}
if(storage_dir_exists(storage, old_path)) {
FuriString* dir_path = furi_string_alloc_set_str(old_path);
if(!furi_string_end_with_str(dir_path, "/")) {
furi_string_cat_str(dir_path, "/");
}
const char* dir_path_s = furi_string_get_cstr(dir_path);
if(strncmp(new_path, dir_path_s, strlen(dir_path_s)) == 0) {
error = FSE_INVALID_NAME;
furi_string_free(dir_path);
break;
}
furi_string_free(dir_path);
}
if(storage_file_exists(storage, new_path)) {
storage_common_remove(storage, new_path);
}
+189 -3
View File
@@ -19,7 +19,7 @@ static const char* update_task_stage_descr[] = {
[UpdateTaskStageRadioErase] = "Uninstalling radio FW",
[UpdateTaskStageRadioWrite] = "Writing radio FW",
[UpdateTaskStageRadioInstall] = "Installing radio FW",
[UpdateTaskStageRadioBusy] = "Radio is updating",
[UpdateTaskStageRadioBusy] = "Core 2 busy",
[UpdateTaskStageOBValidation] = "Validating opt. bytes",
[UpdateTaskStageLfsBackup] = "Backing up LFS",
[UpdateTaskStageLfsRestore] = "Restoring LFS",
@@ -30,6 +30,191 @@ static const char* update_task_stage_descr[] = {
[UpdateTaskStageOBError] = "OB, report",
};
static const struct {
UpdateTaskStage stage;
uint8_t percent_min, percent_max;
const char* descr;
} update_task_error_detail[] = {
{
.stage = UpdateTaskStageReadManifest,
.percent_min = 0,
.percent_max = 13,
.descr = "Wrong Updater HW",
},
{
.stage = UpdateTaskStageReadManifest,
.percent_min = 14,
.percent_max = 20,
.descr = "Manifest pointer error",
},
{
.stage = UpdateTaskStageReadManifest,
.percent_min = 21,
.percent_max = 30,
.descr = "Manifest load error",
},
{
.stage = UpdateTaskStageReadManifest,
.percent_min = 31,
.percent_max = 40,
.descr = "Wrong package version",
},
{
.stage = UpdateTaskStageReadManifest,
.percent_min = 41,
.percent_max = 50,
.descr = "HW Target mismatch",
},
{
.stage = UpdateTaskStageReadManifest,
.percent_min = 51,
.percent_max = 60,
.descr = "No DFU file",
},
{
.stage = UpdateTaskStageReadManifest,
.percent_min = 61,
.percent_max = 80,
.descr = "No Radio file",
},
#ifndef FURI_RAM_EXEC
{
.stage = UpdateTaskStageLfsBackup,
.percent_min = 0,
.percent_max = 100,
.descr = "FS R/W error",
},
#else
{
.stage = UpdateTaskStageRadioImageValidate,
.percent_min = 0,
.percent_max = 98,
.descr = "FS Read error",
},
{
.stage = UpdateTaskStageRadioImageValidate,
.percent_min = 99,
.percent_max = 100,
.descr = "CRC mismatch",
},
{
.stage = UpdateTaskStageRadioErase,
.percent_min = 0,
.percent_max = 30,
.descr = "Stack remove: cmd error",
},
{
.stage = UpdateTaskStageRadioErase,
.percent_min = 31,
.percent_max = 100,
.descr = "Stack remove: wait failed",
},
{
.stage = UpdateTaskStageRadioWrite,
.percent_min = 0,
.percent_max = 100,
.descr = "Stack write: error",
},
{
.stage = UpdateTaskStageRadioInstall,
.percent_min = 0,
.percent_max = 10,
.descr = "Stack install: cmd error",
},
{
.stage = UpdateTaskStageRadioInstall,
.percent_min = 11,
.percent_max = 100,
.descr = "Stack install: wait failed",
},
{
.stage = UpdateTaskStageRadioBusy,
.percent_min = 0,
.percent_max = 10,
.descr = "Failed to start C2",
},
{
.stage = UpdateTaskStageRadioBusy,
.percent_min = 11,
.percent_max = 20,
.descr = "C2 FUS swich failed",
},
{
.stage = UpdateTaskStageRadioBusy,
.percent_min = 21,
.percent_max = 30,
.descr = "FUS operation failed",
},
{
.stage = UpdateTaskStageRadioBusy,
.percent_min = 31,
.percent_max = 100,
.descr = "C2 Stach switch failed",
},
{
.stage = UpdateTaskStageOBValidation,
.percent_min = 0,
.percent_max = 100,
.descr = "Uncorr. value mismatch",
},
{
.stage = UpdateTaskStageValidateDFUImage,
.percent_min = 0,
.percent_max = 1,
.descr = "Failed to open DFU file",
},
{
.stage = UpdateTaskStageValidateDFUImage,
.percent_min = 1,
.percent_max = 97,
.descr = "DFU file read error",
},
{
.stage = UpdateTaskStageValidateDFUImage,
.percent_min = 98,
.percent_max = 100,
.descr = "DFU file CRC mismatch",
},
{
.stage = UpdateTaskStageFlashWrite,
.percent_min = 0,
.percent_max = 100,
.descr = "Flash write error",
},
{
.stage = UpdateTaskStageFlashValidate,
.percent_min = 0,
.percent_max = 100,
.descr = "Flash compare error",
},
#endif
#ifndef FURI_RAM_EXEC
{
.stage = UpdateTaskStageLfsRestore,
.percent_min = 0,
.percent_max = 100,
.descr = "LFS I/O error",
},
{
.stage = UpdateTaskStageResourcesUpdate,
.percent_min = 0,
.percent_max = 100,
.descr = "SD card I/O error",
},
#endif
};
static const char* update_task_get_error_message(UpdateTaskStage stage, uint8_t percent) {
for(size_t i = 0; i < COUNT_OF(update_task_error_detail); i++) {
if(update_task_error_detail[i].stage == stage &&
percent >= update_task_error_detail[i].percent_min &&
percent <= update_task_error_detail[i].percent_max) {
return update_task_error_detail[i].descr;
}
}
return "Unknown error";
}
typedef struct {
UpdateTaskStageGroup group;
uint8_t weight;
@@ -111,8 +296,9 @@ void update_task_set_progress(UpdateTask* update_task, UpdateTaskStage stage, ui
if(stage >= UpdateTaskStageError) {
furi_string_printf(
update_task->state.status,
"%s #[%d-%d]",
update_task_stage_descr[stage],
"%s\n#[%d-%d]",
update_task_get_error_message(
update_task->state.stage, update_task->state.stage_progress),
update_task->state.stage,
update_task->state.stage_progress);
} else {
@@ -24,3 +24,8 @@ bool update_task_open_file(UpdateTask* update_task, FuriString* filename);
int32_t update_task_worker_flash_writer(void* context);
int32_t update_task_worker_backup_restore(void* context);
#define CHECK_RESULT(x) \
if(!(x)) { \
break; \
}
@@ -15,11 +15,6 @@
#define TAG "UpdWorkerBackup"
#define CHECK_RESULT(x) \
if(!(x)) { \
break; \
}
static bool update_task_pre_update(UpdateTask* update_task) {
bool success = false;
FuriString* backup_file_path;
@@ -13,11 +13,6 @@
#define TAG "UpdWorkerRAM"
#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 */
@@ -137,7 +132,7 @@ static bool update_task_write_stack_data(UpdateTask* update_task) {
}
static void update_task_wait_for_restart(UpdateTask* update_task) {
update_task_set_progress(update_task, UpdateTaskStageRadioBusy, 10);
update_task_set_progress(update_task, UpdateTaskStageRadioBusy, 70);
furi_delay_ms(C2_MODE_SWITCH_TIMEOUT);
furi_crash("C2 timeout");
}
@@ -153,12 +148,12 @@ static bool update_task_write_stack(UpdateTask* update_task) {
manifest->radio_crc);
CHECK_RESULT(update_task_write_stack_data(update_task));
update_task_set_progress(update_task, UpdateTaskStageRadioInstall, 0);
update_task_set_progress(update_task, UpdateTaskStageRadioInstall, 10);
CHECK_RESULT(
ble_glue_fus_stack_install(manifest->radio_address, 0) != BleGlueCommandResultError);
update_task_set_progress(update_task, UpdateTaskStageRadioInstall, 80);
update_task_set_progress(update_task, UpdateTaskStageProgress, 80);
CHECK_RESULT(ble_glue_fus_wait_operation() == BleGlueCommandResultOK);
update_task_set_progress(update_task, UpdateTaskStageRadioInstall, 100);
update_task_set_progress(update_task, UpdateTaskStageProgress, 100);
/* ...system will restart here. */
update_task_wait_for_restart(update_task);
} while(false);
@@ -170,9 +165,9 @@ static bool update_task_remove_stack(UpdateTask* update_task) {
FURI_LOG_W(TAG, "Removing stack");
update_task_set_progress(update_task, UpdateTaskStageRadioErase, 30);
CHECK_RESULT(ble_glue_fus_stack_delete() != BleGlueCommandResultError);
update_task_set_progress(update_task, UpdateTaskStageRadioErase, 80);
update_task_set_progress(update_task, UpdateTaskStageProgress, 80);
CHECK_RESULT(ble_glue_fus_wait_operation() == BleGlueCommandResultOK);
update_task_set_progress(update_task, UpdateTaskStageRadioErase, 100);
update_task_set_progress(update_task, UpdateTaskStageProgress, 100);
/* ...system will restart here. */
update_task_wait_for_restart(update_task);
} while(false);
@@ -180,6 +175,7 @@ static bool update_task_remove_stack(UpdateTask* update_task) {
}
static bool update_task_manage_radiostack(UpdateTask* update_task) {
update_task_set_progress(update_task, UpdateTaskStageRadioBusy, 10);
bool success = false;
do {
CHECK_RESULT(ble_glue_wait_for_c2_start(FURI_HAL_BT_C2_START_TIMEOUT));
@@ -208,15 +204,17 @@ static bool update_task_manage_radiostack(UpdateTask* update_task) {
/* Version or type mismatch. Let's boot to FUS and start updating. */
FURI_LOG_W(TAG, "Restarting to FUS");
furi_hal_rtc_set_flag(FuriHalRtcFlagC2Update);
update_task_set_progress(update_task, UpdateTaskStageProgress, 20);
CHECK_RESULT(furi_hal_bt_ensure_c2_mode(BleGlueC2ModeFUS));
/* ...system will restart here. */
update_task_wait_for_restart(update_task);
}
} else if(c2_state->mode == BleGlueC2ModeFUS) {
/* OK, we're in FUS mode. */
update_task_set_progress(update_task, UpdateTaskStageRadioBusy, 10);
FURI_LOG_W(TAG, "Waiting for FUS to settle");
ble_glue_fus_wait_operation();
update_task_set_progress(update_task, UpdateTaskStageProgress, 30);
CHECK_RESULT(ble_glue_fus_wait_operation() == BleGlueCommandResultOK);
if(stack_version_match) {
/* We can't check StackType with FUS, but partial version matches */
if(furi_hal_rtc_is_flag_set(FuriHalRtcFlagC2Update)) {
@@ -230,7 +228,7 @@ static bool update_task_manage_radiostack(UpdateTask* update_task) {
/* We might just had the stack installed.
* Let's start it up to check its version */
FURI_LOG_W(TAG, "Starting stack to check full version");
update_task_set_progress(update_task, UpdateTaskStageRadioBusy, 40);
update_task_set_progress(update_task, UpdateTaskStageProgress, 50);
CHECK_RESULT(furi_hal_bt_ensure_c2_mode(BleGlueC2ModeStack));
/* ...system will restart here. */
update_task_wait_for_restart(update_task);
@@ -81,16 +81,17 @@ static void updater_main_draw_callback(Canvas* canvas, void* _model) {
canvas_set_font(canvas, FontPrimary);
if(model->failed) {
canvas_draw_str_aligned(canvas, 42, 16, AlignLeft, AlignTop, "Update Failed!");
canvas_draw_icon(canvas, 2, 22, &I_Warning_30x23);
canvas_draw_str_aligned(canvas, 40, 9, AlignLeft, AlignTop, "Update Failed!");
canvas_set_font(canvas, FontSecondary);
canvas_draw_str_aligned(
canvas, 42, 32, AlignLeft, AlignTop, furi_string_get_cstr(model->status));
canvas_draw_icon(canvas, 7, 16, &I_Warning_30x23);
elements_multiline_text_aligned(
canvas, 75, 26, AlignCenter, AlignTop, furi_string_get_cstr(model->status));
canvas_draw_str_aligned(
canvas, 18, 51, AlignLeft, AlignTop, "to retry, hold to abort");
canvas_draw_icon(canvas, 7, 50, &I_Ok_btn_9x9);
canvas_draw_icon(canvas, 75, 51, &I_Pin_back_arrow_10x8);
canvas, 18, 55, AlignLeft, AlignTop, "to retry, hold to abort");
canvas_draw_icon(canvas, 7, 54, &I_Ok_btn_9x9);
canvas_draw_icon(canvas, 75, 55, &I_Pin_back_arrow_10x8);
} else {
canvas_draw_str_aligned(canvas, 55, 14, AlignLeft, AlignTop, "UPDATING");
canvas_set_font(canvas, FontSecondary);
@@ -0,0 +1,42 @@
REM Written by @dexv
DELAY 2000
GUI r
DELAY 500
STRING powershell
ENTER
DELAY 1000
STRING $url = "https://update.flipperzero.one/qFlipper/release/windows-amd64/portable"
ENTER
STRING $output = "$env:USERPROFILE\Documents\qFlipper.zip"
ENTER
STRING $destination = "$env:USERPROFILE\Documents\qFlipper"
ENTER
STRING $shortcutPath = "$env:USERPROFILE\Desktop\qFlipper.lnk"
ENTER
STRING $scriptPath = "$env:USERPROFILE\Documents\qFlipperInstall.ps1"
ENTER
STRING $driverPath = "$destination\STM32 Driver"
ENTER
STRING $installBat = "$driverPath\install.bat"
ENTER
STRING (New-Object System.Net.WebClient).DownloadFile($url, $output)
ENTER
STRING Expand-Archive -Path $output -DestinationPath $destination -Force
ENTER
STRING Set-Location -Path $destination
ENTER
STRING Start-Process -FilePath ".\qFlipper.exe"
ENTER
STRING Start-Process -Wait -FilePath "cmd.exe" -ArgumentList "/c $installBat"
ENTER
STRING $shell = New-Object -ComObject WScript.Shell
ENTER
STRING $shortcut = $shell.CreateShortcut($shortcutPath)
ENTER
STRING $shortcut.TargetPath = "$destination\qFlipper.exe"
ENTER
STRING $shortcut.Save()
ENTER
DELAY 500
STRING "powershell -ExecutionPolicy Bypass -File $scriptPath"
ENTER
+5 -2
View File
@@ -87,9 +87,12 @@ Even if something goes wrong, updater allows you to retry failed operations and
| Uninstalling radio FW | **4** | **0** | SHCI Delete command error |
| | | **80** | Error awaiting command status |
| Writing radio FW | **5** | **0-100** | Block read/write error |
| Installing radio FW | **6** | **0** | SHCI Install command error |
| Installing radio FW | **6** | **10** | SHCI Install command error |
| | | **80** | Error awaiting command status |
| Radio is updating | **7** | **10** | Error waiting for operation completion |
| Core2 is busy | **7** | **10** | Couldn't start C2 |
| | | **20** | Failed to switch C2 to FUS mode |
| | | **30** | Error in FUS operation |
| | | **50** | Failed to switch C2 to stack mode |
| Validating opt. bytes | **8** | **yy** | Option byte code |
| Checking DFU file | **9** | **0** | Error opening DFU file |
| | | **1-98** | Error reading DFU file |
+17 -4
View File
@@ -20,7 +20,8 @@ static const char* update_prepare_result_descr[] = {
[UpdatePrepareResultManifestInvalid] = "Invalid manifest data",
[UpdatePrepareResultStageMissing] = "Missing Stage2 loader",
[UpdatePrepareResultStageIntegrityError] = "Corrupted Stage2 loader",
[UpdatePrepareResultManifestPointerError] = "Failed to create update pointer file",
[UpdatePrepareResultManifestPointerCreateError] = "Failed to create update pointer file",
[UpdatePrepareResultManifestPointerCheckError] = "Update pointer file error (corrupted FS?)",
[UpdatePrepareResultTargetMismatch] = "Hardware target mismatch",
[UpdatePrepareResultOutdatedManifestVersion] = "Update package is too old",
[UpdatePrepareResultIntFull] = "Need more free space in internal storage",
@@ -142,8 +143,8 @@ UpdatePrepareResult update_operation_prepare(const char* manifest_file_path) {
File* file = storage_file_alloc(storage);
uint64_t free_int_space;
FuriString* stage_path;
stage_path = furi_string_alloc();
FuriString* stage_path = furi_string_alloc();
FuriString* manifest_path_check = furi_string_alloc();
do {
if((storage_common_fs_info(storage, STORAGE_INT_PATH_PREFIX, NULL, &free_int_space) !=
FSE_OK) ||
@@ -188,7 +189,18 @@ UpdatePrepareResult update_operation_prepare(const char* manifest_file_path) {
}
if(!update_operation_persist_manifest_path(storage, manifest_file_path)) {
result = UpdatePrepareResultManifestPointerError;
result = UpdatePrepareResultManifestPointerCreateError;
break;
}
if(!update_operation_get_current_package_manifest_path(storage, manifest_path_check) ||
(furi_string_cmpi_str(manifest_path_check, manifest_file_path) != 0)) {
FURI_LOG_E(
"update",
"Manifest pointer check failed: '%s' != '%s'",
furi_string_get_cstr(manifest_path_check),
manifest_file_path);
result = UpdatePrepareResultManifestPointerCheckError;
break;
}
@@ -197,6 +209,7 @@ UpdatePrepareResult update_operation_prepare(const char* manifest_file_path) {
} while(false);
furi_string_free(stage_path);
furi_string_free(manifest_path_check);
storage_file_free(file);
update_manifest_free(manifest);
+2 -1
View File
@@ -28,7 +28,8 @@ typedef enum {
UpdatePrepareResultManifestInvalid,
UpdatePrepareResultStageMissing,
UpdatePrepareResultStageIntegrityError,
UpdatePrepareResultManifestPointerError,
UpdatePrepareResultManifestPointerCreateError,
UpdatePrepareResultManifestPointerCheckError,
UpdatePrepareResultTargetMismatch,
UpdatePrepareResultOutdatedManifestVersion,
UpdatePrepareResultIntFull,