mirror of
https://github.com/DarkFlippers/unleashed-firmware
synced 2024-11-10 06:54:19 +00:00
[FL-3377] Update error code descriptions (#2875)
* updater: added update error code descriptions * updater: separate ram/flash messages * updater: extra pre-update checks * updater: fixed string comparison * updater: Additional logging Co-authored-by: あく <alleteam@gmail.com>
This commit is contained in:
parent
af64ae0e40
commit
f2324e4d1c
8 changed files with 238 additions and 36 deletions
|
@ -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);
|
||||
|
|
|
@ -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 |
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -28,7 +28,8 @@ typedef enum {
|
|||
UpdatePrepareResultManifestInvalid,
|
||||
UpdatePrepareResultStageMissing,
|
||||
UpdatePrepareResultStageIntegrityError,
|
||||
UpdatePrepareResultManifestPointerError,
|
||||
UpdatePrepareResultManifestPointerCreateError,
|
||||
UpdatePrepareResultManifestPointerCheckError,
|
||||
UpdatePrepareResultTargetMismatch,
|
||||
UpdatePrepareResultOutdatedManifestVersion,
|
||||
UpdatePrepareResultIntFull,
|
||||
|
|
Loading…
Reference in a new issue