diff --git a/applications/bt/bt_cli.c b/applications/bt/bt_cli.c index 122eedf9..1c9b198b 100644 --- a/applications/bt/bt_cli.c +++ b/applications/bt/bt_cli.c @@ -68,7 +68,7 @@ static void bt_cli_command_carrier_rx(Cli* cli, string_t args, void* context) { while(!cli_cmd_interrupt_received(cli)) { osDelay(250); - printf("RSSI: %6.1f dB\r", furi_hal_bt_get_rssi()); + printf("RSSI: %6.1f dB\r", (double)furi_hal_bt_get_rssi()); fflush(stdout); } @@ -140,11 +140,9 @@ static void bt_cli_command_packet_rx(Cli* cli, string_t args, void* context) { printf("Press CTRL+C to stop\r\n"); furi_hal_bt_start_packet_rx(channel, datarate); - float rssi_raw = 0; while(!cli_cmd_interrupt_received(cli)) { osDelay(250); - rssi_raw = furi_hal_bt_get_rssi(); - printf("RSSI: %03.1f dB\r", rssi_raw); + printf("RSSI: %03.1f dB\r", (double)furi_hal_bt_get_rssi()); fflush(stdout); } uint16_t packets_received = furi_hal_bt_stop_packet_test(); diff --git a/applications/bt/bt_debug_app/views/bt_test.c b/applications/bt/bt_debug_app/views/bt_test.c index ac10e0a8..70f57c12 100755 --- a/applications/bt/bt_debug_app/views/bt_test.c +++ b/applications/bt/bt_debug_app/views/bt_test.c @@ -99,7 +99,7 @@ static void bt_test_draw_callback(Canvas* canvas, void* _model) { canvas_draw_str(canvas, 6, 60, model->message); if(model->state == BtTestStateStarted) { if(model->rssi != 0.0f) { - snprintf(info_str, sizeof(info_str), "RSSI:%3.1f dB", model->rssi); + snprintf(info_str, sizeof(info_str), "RSSI:%3.1f dB", (double)model->rssi); canvas_draw_str_aligned(canvas, 124, 60, AlignRight, AlignBottom, info_str); } } else if(model->state == BtTestStateStopped) { diff --git a/applications/desktop/animations/animation_manager.c b/applications/desktop/animations/animation_manager.c index f8e93716..75d45ef7 100644 --- a/applications/desktop/animations/animation_manager.c +++ b/applications/desktop/animations/animation_manager.c @@ -1,6 +1,7 @@ #include #include #include +#include #include #include #include @@ -391,7 +392,7 @@ static StorageAnimation* } } - uint32_t lucky_number = random() % whole_weight; + uint32_t lucky_number = furi_hal_random_get() % whole_weight; uint32_t weight = 0; StorageAnimation* selected = NULL; diff --git a/applications/desktop/animations/views/bubble_animation_view.c b/applications/desktop/animations/views/bubble_animation_view.c index 9b60d45c..380664c8 100644 --- a/applications/desktop/animations/views/bubble_animation_view.c +++ b/applications/desktop/animations/views/bubble_animation_view.c @@ -100,7 +100,8 @@ static const FrameBubble* return NULL; } - uint8_t index = random() % (active ? model->active_bubbles : model->passive_bubbles); + uint8_t index = + furi_hal_random_get() % (active ? model->active_bubbles : model->passive_bubbles); const BubbleAnimation* animation = model->current; for(int i = 0; i < animation->frame_bubble_sequences_count; ++i) { diff --git a/applications/infrared/helpers/infrared_parser.cpp b/applications/infrared/helpers/infrared_parser.cpp index 12a93924..d85a7269 100644 --- a/applications/infrared/helpers/infrared_parser.cpp +++ b/applications/infrared/helpers/infrared_parser.cpp @@ -145,7 +145,7 @@ bool infrared_parser_is_raw_signal_valid( frequency); result = false; } else if((duty_cycle <= 0) || (duty_cycle > 1)) { - FURI_LOG_E(TAG, "Duty cycle is out of range (0 - 1): %f", duty_cycle); + FURI_LOG_E(TAG, "Duty cycle is out of range (0 - 1): %f", (double)duty_cycle); result = false; } else if((timings_cnt <= 0) || (timings_cnt > MAX_TIMINGS_AMOUNT)) { FURI_LOG_E( diff --git a/applications/lfrfid_debug/view_modules/lfrfid_view_tune_vm.cpp b/applications/lfrfid_debug/view_modules/lfrfid_view_tune_vm.cpp index 3039517e..5c244b92 100644 --- a/applications/lfrfid_debug/view_modules/lfrfid_view_tune_vm.cpp +++ b/applications/lfrfid_debug/view_modules/lfrfid_view_tune_vm.cpp @@ -29,6 +29,8 @@ void LfRfidViewTuneVM::view_draw_callback(Canvas* canvas, void* _model) { constexpr uint8_t buffer_size = 128; char buffer[buffer_size + 1]; + double freq = ((float)SystemCoreClock / ((float)model->ARR + 1)); + double duty = ((float)model->CCR + 1) / ((float)model->ARR + 1) * 100.0f; snprintf( buffer, buffer_size, @@ -38,10 +40,10 @@ void LfRfidViewTuneVM::view_draw_callback(Canvas* canvas, void* _model) { "duty = %.4f", model->pos == 0 ? ">" : "", model->ARR, - (float)SystemCoreClock / ((float)model->ARR + 1), + freq, model->pos == 1 ? ">" : "", model->CCR, - ((float)model->CCR + 1) / ((float)model->ARR + 1) * 100.0f); + duty); elements_multiline_text_aligned(canvas, 2, 2, AlignLeft, AlignTop, buffer); } diff --git a/applications/rpc/rpc_system.c b/applications/rpc/rpc_system.c index 9ce7e34a..45ae2e5a 100644 --- a/applications/rpc/rpc_system.c +++ b/applications/rpc/rpc_system.c @@ -275,15 +275,22 @@ static void rpc_system_system_update_request_process(const PB_Main* request, voi RpcSession* session = (RpcSession*)context; furi_assert(session); - bool update_prepare_result = - update_operation_prepare(request->content.system_update_request.update_manifest) == - UpdatePrepareResultOK; + UpdatePrepareResult update_prepare_result = + update_operation_prepare(request->content.system_update_request.update_manifest); + /* RPC enum does not have such entry; setting to closest one */ + if(update_prepare_result == UpdatePrepareResultOutdatedManifestVersion) { + update_prepare_result = UpdatePrepareResultManifestInvalid; + } PB_Main* response = malloc(sizeof(PB_Main)); response->command_id = request->command_id; response->has_next = false; - response->command_status = update_prepare_result ? PB_CommandStatus_OK : - PB_CommandStatus_ERROR_INVALID_PARAMETERS; + response->command_status = (update_prepare_result == UpdatePrepareResultOK) ? + PB_CommandStatus_OK : + PB_CommandStatus_ERROR_INVALID_PARAMETERS; + response->which_content = PB_Main_system_update_response_tag; + response->content.system_update_response.code = + (PB_System_UpdateResponse_UpdateResultCode)update_prepare_result; rpc_send_and_release(session, response); free(response); } diff --git a/applications/subghz/subghz_cli.c b/applications/subghz/subghz_cli.c index d22b86f2..f919e1cf 100644 --- a/applications/subghz/subghz_cli.c +++ b/applications/subghz/subghz_cli.c @@ -94,7 +94,7 @@ void subghz_cli_command_rx_carrier(Cli* cli, string_t args, void* context) { while(!cli_cmd_interrupt_received(cli)) { osDelay(250); - printf("RSSI: %03.1fdbm\r", furi_hal_subghz_get_rssi()); + printf("RSSI: %03.1fdbm\r", (double)furi_hal_subghz_get_rssi()); fflush(stdout); } diff --git a/applications/unit_tests/test_index.c b/applications/unit_tests/test_index.c index 4045c8e2..a1acbed4 100644 --- a/applications/unit_tests/test_index.c +++ b/applications/unit_tests/test_index.c @@ -70,7 +70,7 @@ void unit_tests_cli(Cli* cli, string_t args, void* context) { cycle_counter = (furi_hal_get_tick() - cycle_counter); - FURI_LOG_I(TAG, "Consumed: %0.2fs", (float)cycle_counter / 1000); + FURI_LOG_I(TAG, "Consumed: %u us", cycle_counter); if(test_result == 0) { furi_hal_delay_ms(200); /* wait for tested services and apps to deallocate */ diff --git a/applications/updater/cli/updater_cli.c b/applications/updater/cli/updater_cli.c index dfc7fbce..fb2edeb9 100644 --- a/applications/updater/cli/updater_cli.c +++ b/applications/updater/cli/updater_cli.c @@ -52,7 +52,7 @@ static void updater_cli_restore(string_t args) { static void updater_cli_help(string_t args) { UNUSED(args); printf("Commands:\r\n" - "\tinstall /ext/update/PACKAGE/update.fuf - verify & apply update package\r\n" + "\tinstall /ext/path/to/update.fuf - verify & apply update package\r\n" "\tbackup /ext/path/to/backup.tar - create internal storage backup\r\n" "\trestore /ext/path/to/backup.tar - restore internal storage backup\r\n"); } diff --git a/applications/updater/util/update_task.c b/applications/updater/util/update_task.c index 373f680a..1238bdb0 100644 --- a/applications/updater/util/update_task.c +++ b/applications/updater/util/update_task.c @@ -260,16 +260,18 @@ bool update_task_parse_manifest(UpdateTask* update_task) { string_init(manifest_path); do { - update_task_set_progress(update_task, UpdateTaskStageProgress, 10); - if(!update_operation_get_current_package_path( - update_task->storage, update_task->update_path)) { + update_task_set_progress(update_task, UpdateTaskStageProgress, 13); + if(!furi_hal_version_do_i_belong_here()) { break; } - path_concat( - string_get_cstr(update_task->update_path), - UPDATE_MANIFEST_DEFAULT_NAME, - manifest_path); + update_task_set_progress(update_task, UpdateTaskStageProgress, 20); + if(!update_operation_get_current_package_manifest_path( + update_task->storage, manifest_path)) { + break; + } + + path_extract_dirname(string_get_cstr(manifest_path), update_task->update_path); update_task_set_progress(update_task, UpdateTaskStageProgress, 30); UpdateManifest* manifest = update_task->manifest; @@ -277,6 +279,16 @@ bool update_task_parse_manifest(UpdateTask* update_task) { break; } + update_task_set_progress(update_task, UpdateTaskStageProgress, 40); + if(manifest->manifest_version < UPDATE_OPERATION_MIN_MANIFEST_VERSION) { + break; + } + + update_task_set_progress(update_task, UpdateTaskStageProgress, 50); + if(manifest->target != furi_hal_version_get_hw_target()) { + break; + } + update_task->state.groups = update_task_get_task_groups(update_task); for(size_t stage_counter = 0; stage_counter < COUNT_OF(update_task_stage_progress); ++stage_counter) { @@ -286,13 +298,13 @@ bool update_task_parse_manifest(UpdateTask* update_task) { } } - update_task_set_progress(update_task, UpdateTaskStageProgress, 50); + update_task_set_progress(update_task, UpdateTaskStageProgress, 60); if((update_task->state.groups & UpdateTaskStageGroupFirmware) && !update_task_check_file_exists(update_task, manifest->firmware_dfu_image)) { break; } - update_task_set_progress(update_task, UpdateTaskStageProgress, 70); + update_task_set_progress(update_task, UpdateTaskStageProgress, 80); if((update_task->state.groups & UpdateTaskStageGroupRadio) && (!update_task_check_file_exists(update_task, manifest->radio_image) || (manifest->radio_version.version.type == 0))) { diff --git a/applications/updater/util/update_task_worker_backup.c b/applications/updater/util/update_task_worker_backup.c index 485fdd48..011510ed 100644 --- a/applications/updater/util/update_task_worker_backup.c +++ b/applications/updater/util/update_task_worker_backup.c @@ -63,7 +63,6 @@ static bool update_task_post_update(UpdateTask* update_task) { TarArchive* archive = tar_archive_alloc(update_task->storage); do { - CHECK_RESULT(update_task_parse_manifest(update_task)); path_concat( string_get_cstr(update_task->update_path), LFS_BACKUP_DEFAULT_FILENAME, file_path); @@ -114,7 +113,7 @@ int32_t update_task_worker_backup_restore(void* context) { return UPDATE_TASK_NOERR; } - if(!update_operation_get_current_package_path(update_task->storage, update_task->update_path)) { + if(!update_task_parse_manifest(update_task)) { return UPDATE_TASK_FAILED; } diff --git a/assets/compiled/flipper.pb.h b/assets/compiled/flipper.pb.h index 88548bea..3199090d 100644 --- a/assets/compiled/flipper.pb.h +++ b/assets/compiled/flipper.pb.h @@ -103,6 +103,7 @@ typedef struct _PB_Main { PB_Storage_BackupRestoreRequest storage_backup_restore_request; PB_System_PowerInfoRequest system_power_info_request; PB_System_PowerInfoResponse system_power_info_response; + PB_System_UpdateResponse system_update_response; } content; } PB_Main; @@ -171,6 +172,7 @@ extern "C" { #define PB_Main_storage_backup_restore_request_tag 43 #define PB_Main_system_power_info_request_tag 44 #define PB_Main_system_power_info_response_tag 45 +#define PB_Main_system_update_response_tag 46 /* Struct field encoding specification for nanopb */ #define PB_Empty_FIELDLIST(X, a) \ @@ -228,7 +230,8 @@ X(a, STATIC, ONEOF, MSG_W_CB, (content,system_update_request,content.system X(a, STATIC, ONEOF, MSG_W_CB, (content,storage_backup_create_request,content.storage_backup_create_request), 42) \ X(a, STATIC, ONEOF, MSG_W_CB, (content,storage_backup_restore_request,content.storage_backup_restore_request), 43) \ X(a, STATIC, ONEOF, MSG_W_CB, (content,system_power_info_request,content.system_power_info_request), 44) \ -X(a, STATIC, ONEOF, MSG_W_CB, (content,system_power_info_response,content.system_power_info_response), 45) +X(a, STATIC, ONEOF, MSG_W_CB, (content,system_power_info_response,content.system_power_info_response), 45) \ +X(a, STATIC, ONEOF, MSG_W_CB, (content,system_update_response,content.system_update_response), 46) #define PB_Main_CALLBACK NULL #define PB_Main_DEFAULT NULL #define PB_Main_content_empty_MSGTYPE PB_Empty @@ -273,6 +276,7 @@ X(a, STATIC, ONEOF, MSG_W_CB, (content,system_power_info_response,content.s #define PB_Main_content_storage_backup_restore_request_MSGTYPE PB_Storage_BackupRestoreRequest #define PB_Main_content_system_power_info_request_MSGTYPE PB_System_PowerInfoRequest #define PB_Main_content_system_power_info_response_MSGTYPE PB_System_PowerInfoResponse +#define PB_Main_content_system_update_response_MSGTYPE PB_System_UpdateResponse extern const pb_msgdesc_t PB_Empty_msg; extern const pb_msgdesc_t PB_StopSession_msg; diff --git a/assets/compiled/protobuf_version.h b/assets/compiled/protobuf_version.h index 0459d120..6b401411 100644 --- a/assets/compiled/protobuf_version.h +++ b/assets/compiled/protobuf_version.h @@ -1,3 +1,3 @@ #pragma once #define PROTOBUF_MAJOR_VERSION 0 -#define PROTOBUF_MINOR_VERSION 6 +#define PROTOBUF_MINOR_VERSION 7 diff --git a/assets/compiled/system.pb.c b/assets/compiled/system.pb.c index 45ab3a01..e05ff90e 100644 --- a/assets/compiled/system.pb.c +++ b/assets/compiled/system.pb.c @@ -48,6 +48,9 @@ PB_BIND(PB_System_ProtobufVersionResponse, PB_System_ProtobufVersionResponse, AU PB_BIND(PB_System_UpdateRequest, PB_System_UpdateRequest, AUTO) +PB_BIND(PB_System_UpdateResponse, PB_System_UpdateResponse, AUTO) + + PB_BIND(PB_System_PowerInfoRequest, PB_System_PowerInfoRequest, AUTO) @@ -56,3 +59,4 @@ PB_BIND(PB_System_PowerInfoResponse, PB_System_PowerInfoResponse, AUTO) + diff --git a/assets/compiled/system.pb.h b/assets/compiled/system.pb.h index 978219ae..aef2c75b 100644 --- a/assets/compiled/system.pb.h +++ b/assets/compiled/system.pb.h @@ -16,6 +16,17 @@ typedef enum _PB_System_RebootRequest_RebootMode { PB_System_RebootRequest_RebootMode_UPDATE = 2 } PB_System_RebootRequest_RebootMode; +typedef enum _PB_System_UpdateResponse_UpdateResultCode { + PB_System_UpdateResponse_UpdateResultCode_OK = 0, + PB_System_UpdateResponse_UpdateResultCode_ManifestPathInvalid = 1, + PB_System_UpdateResponse_UpdateResultCode_ManifestFolderNotFound = 2, + PB_System_UpdateResponse_UpdateResultCode_ManifestInvalid = 3, + PB_System_UpdateResponse_UpdateResultCode_StageMissing = 4, + PB_System_UpdateResponse_UpdateResultCode_StageIntegrityError = 5, + PB_System_UpdateResponse_UpdateResultCode_ManifestPointerError = 6, + PB_System_UpdateResponse_UpdateResultCode_TargetMismatch = 7 +} PB_System_UpdateResponse_UpdateResultCode; + /* Struct definitions */ typedef struct _PB_System_DeviceInfoRequest { char dummy_field; @@ -84,6 +95,10 @@ typedef struct _PB_System_RebootRequest { PB_System_RebootRequest_RebootMode mode; } PB_System_RebootRequest; +typedef struct _PB_System_UpdateResponse { + PB_System_UpdateResponse_UpdateResultCode code; +} PB_System_UpdateResponse; + typedef struct _PB_System_GetDateTimeResponse { bool has_datetime; PB_System_DateTime datetime; @@ -100,6 +115,10 @@ typedef struct _PB_System_SetDateTimeRequest { #define _PB_System_RebootRequest_RebootMode_MAX PB_System_RebootRequest_RebootMode_UPDATE #define _PB_System_RebootRequest_RebootMode_ARRAYSIZE ((PB_System_RebootRequest_RebootMode)(PB_System_RebootRequest_RebootMode_UPDATE+1)) +#define _PB_System_UpdateResponse_UpdateResultCode_MIN PB_System_UpdateResponse_UpdateResultCode_OK +#define _PB_System_UpdateResponse_UpdateResultCode_MAX PB_System_UpdateResponse_UpdateResultCode_TargetMismatch +#define _PB_System_UpdateResponse_UpdateResultCode_ARRAYSIZE ((PB_System_UpdateResponse_UpdateResultCode)(PB_System_UpdateResponse_UpdateResultCode_TargetMismatch+1)) + #ifdef __cplusplus extern "C" { @@ -120,6 +139,7 @@ extern "C" { #define PB_System_ProtobufVersionRequest_init_default {0} #define PB_System_ProtobufVersionResponse_init_default {0, 0} #define PB_System_UpdateRequest_init_default {NULL} +#define PB_System_UpdateResponse_init_default {_PB_System_UpdateResponse_UpdateResultCode_MIN} #define PB_System_PowerInfoRequest_init_default {0} #define PB_System_PowerInfoResponse_init_default {NULL, NULL} #define PB_System_PingRequest_init_zero {NULL} @@ -136,6 +156,7 @@ extern "C" { #define PB_System_ProtobufVersionRequest_init_zero {0} #define PB_System_ProtobufVersionResponse_init_zero {0, 0} #define PB_System_UpdateRequest_init_zero {NULL} +#define PB_System_UpdateResponse_init_zero {_PB_System_UpdateResponse_UpdateResultCode_MIN} #define PB_System_PowerInfoRequest_init_zero {0} #define PB_System_PowerInfoResponse_init_zero {NULL, NULL} @@ -157,6 +178,7 @@ extern "C" { #define PB_System_ProtobufVersionResponse_major_tag 1 #define PB_System_ProtobufVersionResponse_minor_tag 2 #define PB_System_RebootRequest_mode_tag 1 +#define PB_System_UpdateResponse_code_tag 1 #define PB_System_GetDateTimeResponse_datetime_tag 1 #define PB_System_SetDateTimeRequest_datetime_tag 1 @@ -241,6 +263,11 @@ X(a, POINTER, SINGULAR, STRING, update_manifest, 1) #define PB_System_UpdateRequest_CALLBACK NULL #define PB_System_UpdateRequest_DEFAULT NULL +#define PB_System_UpdateResponse_FIELDLIST(X, a) \ +X(a, STATIC, SINGULAR, UENUM, code, 1) +#define PB_System_UpdateResponse_CALLBACK NULL +#define PB_System_UpdateResponse_DEFAULT NULL + #define PB_System_PowerInfoRequest_FIELDLIST(X, a) \ #define PB_System_PowerInfoRequest_CALLBACK NULL @@ -266,6 +293,7 @@ extern const pb_msgdesc_t PB_System_PlayAudiovisualAlertRequest_msg; extern const pb_msgdesc_t PB_System_ProtobufVersionRequest_msg; extern const pb_msgdesc_t PB_System_ProtobufVersionResponse_msg; extern const pb_msgdesc_t PB_System_UpdateRequest_msg; +extern const pb_msgdesc_t PB_System_UpdateResponse_msg; extern const pb_msgdesc_t PB_System_PowerInfoRequest_msg; extern const pb_msgdesc_t PB_System_PowerInfoResponse_msg; @@ -284,6 +312,7 @@ extern const pb_msgdesc_t PB_System_PowerInfoResponse_msg; #define PB_System_ProtobufVersionRequest_fields &PB_System_ProtobufVersionRequest_msg #define PB_System_ProtobufVersionResponse_fields &PB_System_ProtobufVersionResponse_msg #define PB_System_UpdateRequest_fields &PB_System_UpdateRequest_msg +#define PB_System_UpdateResponse_fields &PB_System_UpdateResponse_msg #define PB_System_PowerInfoRequest_fields &PB_System_PowerInfoRequest_msg #define PB_System_PowerInfoResponse_fields &PB_System_PowerInfoResponse_msg @@ -304,6 +333,7 @@ extern const pb_msgdesc_t PB_System_PowerInfoResponse_msg; #define PB_System_ProtobufVersionResponse_size 12 #define PB_System_RebootRequest_size 2 #define PB_System_SetDateTimeRequest_size 24 +#define PB_System_UpdateResponse_size 2 #ifdef __cplusplus } /* extern "C" */ diff --git a/assets/protobuf b/assets/protobuf index 0ad90705..ffa62429 160000 --- a/assets/protobuf +++ b/assets/protobuf @@ -1 +1 @@ -Subproject commit 0ad90705b9434b6f8fb2c4b605069f0d56d8cc70 +Subproject commit ffa62429f3c678537e0e883a3a8c3ae5f1398ed4 diff --git a/core/furi/memmgr_heap.c b/core/furi/memmgr_heap.c index 665fe2e1..618d7e74 100644 --- a/core/furi/memmgr_heap.c +++ b/core/furi/memmgr_heap.c @@ -37,6 +37,7 @@ #include "memmgr_heap.h" #include "check.h" #include +#include #include #include #include diff --git a/firmware/targets/f7/Src/main.c b/firmware/targets/f7/Src/main.c index 2c28265f..3de1c6ca 100644 --- a/firmware/targets/f7/Src/main.c +++ b/firmware/targets/f7/Src/main.c @@ -48,7 +48,7 @@ int main() { flipper_boot_update_exec(); // if things go nice, we shouldn't reach this point. // But if we do, abandon to avoid bootloops - update_operation_disarm(); + furi_hal_rtc_set_boot_mode(FuriHalRtcBootModeNormal); furi_hal_power_reset(); } else { furi_hal_light_sequence("rgb G"); diff --git a/firmware/targets/f7/Src/update.c b/firmware/targets/f7/Src/update.c index f4a434b1..a91972e9 100644 --- a/firmware/targets/f7/Src/update.c +++ b/firmware/targets/f7/Src/update.c @@ -11,9 +11,10 @@ #include #include -static FATFS* pfs = NULL; +#define FS_ROOT_PATH "/" +#define UPDATE_POINTER_FILE_PATH FS_ROOT_PATH UPDATE_MANIFEST_POINTER_FILE_NAME -static const char FS_ROOT_PATH[] = "/"; +static FATFS* pfs = NULL; #define CHECK_FRESULT(result) \ { \ @@ -100,41 +101,34 @@ static bool flipper_update_load_stage(const string_t work_dir, UpdateManifest* m return false; } -static bool flipper_update_get_work_directory(string_t out_dir) { - const uint32_t update_index = furi_hal_rtc_get_register(FuriHalRtcRegisterUpdateFolderFSIndex); - if(update_index == UPDATE_OPERATION_ROOT_DIR_PACKAGE_MAGIC) { - string_set(out_dir, UPDATE_DIR_DEFAULT_REL_PATH); - return true; - } - - DIR dir; - UINT entry_idx = 0; - FILINFO fno; - CHECK_FRESULT(f_opendir(&dir, UPDATE_DIR_DEFAULT_REL_PATH)); - string_set(out_dir, UPDATE_DIR_DEFAULT_REL_PATH); - - while(f_readdir(&dir, &fno) == FR_OK) { - entry_idx++; - if(fno.fname[0] == '\0') { - return false; - } - if(entry_idx == update_index) { - path_append(out_dir, fno.fname); - return true; - } - } - - string_reset(out_dir); - return false; -} - -static UpdateManifest* flipper_update_process_manifest(const string_t work_dir) { +static bool flipper_update_get_manifest_path(string_t out_path) { FIL file; FILINFO stat; + uint16_t size_read = 0; + char manifest_name_buf[UPDATE_OPERATION_MAX_MANIFEST_PATH_LEN] = {0}; - string_t manifest_path; - string_init_set(manifest_path, work_dir); - path_append(manifest_path, UPDATE_MANIFEST_DEFAULT_NAME); + string_reset(out_path); + CHECK_FRESULT(f_stat(UPDATE_POINTER_FILE_PATH, &stat)); + CHECK_FRESULT(f_open(&file, UPDATE_POINTER_FILE_PATH, FA_OPEN_EXISTING | FA_READ)); + do { + if(f_read(&file, manifest_name_buf, UPDATE_OPERATION_MAX_MANIFEST_PATH_LEN, &size_read) != + FR_OK) { + break; + } + + if((size_read == 0) || (size_read == UPDATE_OPERATION_MAX_MANIFEST_PATH_LEN)) { + break; + } + string_set_str(out_path, manifest_name_buf); + string_right(out_path, strlen("/ext")); + } while(0); + f_close(&file); + return !string_empty_p(out_path); +} + +static UpdateManifest* flipper_update_process_manifest(const string_t manifest_path) { + FIL file; + FILINFO stat; CHECK_FRESULT(f_stat(string_get_cstr(manifest_path), &stat)); CHECK_FRESULT(f_open(&file, string_get_cstr(manifest_path), FA_OPEN_EXISTING | FA_READ)); @@ -164,7 +158,7 @@ static UpdateManifest* flipper_update_process_manifest(const string_t work_dir) } } while(false); - string_clear(manifest_path); + f_close(&file); free(manifest_data); return manifest; } @@ -174,22 +168,25 @@ void flipper_boot_update_exec() { return; } - string_t work_dir; + string_t work_dir, manifest_path; string_init(work_dir); + string_init(manifest_path); do { - if(!flipper_update_get_work_directory(work_dir)) { + if(!flipper_update_get_manifest_path(manifest_path)) { break; } - UpdateManifest* manifest = flipper_update_process_manifest(work_dir); + UpdateManifest* manifest = flipper_update_process_manifest(manifest_path); if(!manifest) { break; } + path_extract_dirname(string_get_cstr(manifest_path), work_dir); if(!flipper_update_load_stage(work_dir, manifest)) { update_manifest_free(manifest); } } while(false); + string_clear(manifest_path); string_clear(work_dir); free(pfs); } diff --git a/firmware/targets/f7/furi_hal/furi_hal_random.c b/firmware/targets/f7/furi_hal/furi_hal_random.c index 0f282fac..cd019c0d 100644 --- a/firmware/targets/f7/furi_hal/furi_hal_random.c +++ b/firmware/targets/f7/furi_hal/furi_hal_random.c @@ -7,6 +7,8 @@ #include +#define TAG "FuriHalRandom" + uint32_t furi_hal_random_get() { while(LL_HSEM_1StepLock(HSEM, CFG_HW_RNG_SEMID)) ; @@ -51,9 +53,13 @@ void furi_hal_random_fill_buf(uint8_t* buf, uint32_t len) { } void srand(unsigned seed) { - UNUSED(seed); // FIXME! + UNUSED(seed); } int rand() { return (furi_hal_random_get() & RAND_MAX); } + +long random() { + return (furi_hal_random_get() & RAND_MAX); +} diff --git a/firmware/targets/f7/furi_hal/furi_hal_subghz.c b/firmware/targets/f7/furi_hal/furi_hal_subghz.c index c5b5043b..7f40a152 100644 --- a/firmware/targets/f7/furi_hal/furi_hal_subghz.c +++ b/firmware/targets/f7/furi_hal/furi_hal_subghz.c @@ -972,9 +972,9 @@ void furi_hal_subghz_stop_async_tx() { FURI_LOG_D( TAG, "Async TX Radio stats: on %0.0fus, off %0.0fus, DutyCycle: %0.0f%%", - (float)furi_hal_subghz_async_tx.duty_high, - (float)furi_hal_subghz_async_tx.duty_low, - duty_cycle); + (double)furi_hal_subghz_async_tx.duty_high, + (double)furi_hal_subghz_async_tx.duty_low, + (double)duty_cycle); furi_hal_subghz_state = SubGhzStateIdle; } diff --git a/firmware/targets/f7/stm32wb55xx_flash.ld b/firmware/targets/f7/stm32wb55xx_flash.ld index f742ecc1..1d0e916b 100644 --- a/firmware/targets/f7/stm32wb55xx_flash.ld +++ b/firmware/targets/f7/stm32wb55xx_flash.ld @@ -135,6 +135,7 @@ SECTIONS _sdata = .; /* create a global symbol at data start */ *(.data) /* .data sections */ *(.data*) /* .data* sections */ + *(*_DRIVER_CONTEXT) . = ALIGN(4); _edata = .; /* define a global symbol at data end */ @@ -158,7 +159,7 @@ SECTIONS } >RAM1 /* User_heap_stack section, used to check that there is enough RAM left */ - ._user_heap_stack : + ._user_heap_stack(NOLOAD): { . = ALIGN(8); __heap_start__ = .; @@ -173,7 +174,7 @@ SECTIONS { __free_flash_start__ = .; . = ORIGIN(FLASH) + LENGTH(FLASH); - } >FLASH + } >FLASH /* Remove information from the standard libraries */ /DISCARD/ : diff --git a/firmware/targets/f7/target.mk b/firmware/targets/f7/target.mk index d96dd5e6..8e58a71c 100644 --- a/firmware/targets/f7/target.mk +++ b/firmware/targets/f7/target.mk @@ -19,9 +19,9 @@ endif MCU_FLAGS = -mcpu=cortex-m4 -mthumb -mfpu=fpv4-sp-d16 -mfloat-abi=hard # Warnings configuration -CFLAGS += -Wall -Wextra -Wredundant-decls +CFLAGS += -Wall -Wextra -Wredundant-decls -Wdouble-promotion -CFLAGS += $(MCU_FLAGS) -DSTM32WB55xx -fdata-sections -ffunction-sections +CFLAGS += $(MCU_FLAGS) -DSTM32WB55xx -fdata-sections -ffunction-sections -fsingle-precision-constant LDFLAGS += $(MCU_FLAGS) -specs=nosys.specs -specs=nano.specs CPPFLAGS += -fno-rtti -fno-use-cxa-atexit -fno-exceptions diff --git a/lib/flipper_format/flipper_format_stream.c b/lib/flipper_format/flipper_format_stream.c index 93b788a3..bd700849 100644 --- a/lib/flipper_format/flipper_format_stream.c +++ b/lib/flipper_format/flipper_format_stream.c @@ -276,7 +276,7 @@ bool flipper_format_stream_write_value_line(Stream* stream, FlipperStreamWriteDa #ifndef FLIPPER_STREAM_LITE case FlipperStreamValueFloat: { const float* data = write_data->data; - string_printf(value, "%f", data[i]); + string_printf(value, "%f", (double)data[i]); }; break; #endif case FlipperStreamValueInt32: { diff --git a/lib/lib.mk b/lib/lib.mk index 1470c89f..cb58fade 100644 --- a/lib/lib.mk +++ b/lib/lib.mk @@ -4,7 +4,7 @@ LIB_DIR = $(PROJECT_ROOT)/lib CFLAGS += -I$(LIB_DIR) # Mlib containers -CFLAGS += -I$(LIB_DIR)/mlib +CFLAGS += -I$(LIB_DIR)/mlib -D'M_MEMORY_FULL(x)=abort()' # U8G2 display library U8G2_DIR = $(LIB_DIR)/u8g2 diff --git a/lib/subghz/subghz_tx_rx_worker.c b/lib/subghz/subghz_tx_rx_worker.c index aad28b88..863aaa31 100644 --- a/lib/subghz/subghz_tx_rx_worker.c +++ b/lib/subghz/subghz_tx_rx_worker.c @@ -83,7 +83,10 @@ bool subghz_tx_rx_worker_rx(SubGhzTxRxWorker* instance, uint8_t* data, uint8_t* if(furi_hal_subghz_rx_pipe_not_empty()) { FURI_LOG_I( - TAG, "RSSI: %03.1fdbm LQI: %d", furi_hal_subghz_get_rssi(), furi_hal_subghz_get_lqi()); + TAG, + "RSSI: %03.1fdbm LQI: %d", + (double)furi_hal_subghz_get_rssi(), + furi_hal_subghz_get_lqi()); if(furi_hal_subghz_is_rx_data_crc_valid()) { furi_hal_subghz_read_packet(data, size); ret = true; diff --git a/lib/update_util/update_manifest.c b/lib/update_util/update_manifest.c index 555d7cfb..2fe0a1ef 100644 --- a/lib/update_util/update_manifest.c +++ b/lib/update_util/update_manifest.c @@ -26,6 +26,7 @@ UpdateManifest* update_manifest_alloc() { string_init(update_manifest->staged_loader_file); string_init(update_manifest->resource_bundle); update_manifest->target = 0; + update_manifest->manifest_version = 0; memset(update_manifest->ob_reference.bytes, 0, FURI_HAL_FLASH_OB_RAW_SIZE_BYTES); memset(update_manifest->ob_compare_mask.bytes, 0, FURI_HAL_FLASH_OB_RAW_SIZE_BYTES); memset(update_manifest->ob_write_mask.bytes, 0, FURI_HAL_FLASH_OB_RAW_SIZE_BYTES); @@ -49,12 +50,11 @@ static bool furi_assert(flipper_file); string_t filetype; - uint32_t version = 0; // TODO: compare filetype? string_init(filetype); update_manifest->valid = - flipper_format_read_header(flipper_file, filetype, &version) && + flipper_format_read_header(flipper_file, filetype, &update_manifest->manifest_version) && flipper_format_read_string(flipper_file, MANIFEST_KEY_INFO, update_manifest->version) && flipper_format_read_uint32( flipper_file, MANIFEST_KEY_TARGET, &update_manifest->target, 1) && @@ -68,7 +68,7 @@ static bool string_clear(filetype); if(update_manifest->valid) { - /* Optional fields - we can have dfu, radio, or both */ + /* Optional fields - we can have dfu, radio, resources, or any combination */ flipper_format_read_string( flipper_file, MANIFEST_KEY_DFU_FILE, update_manifest->firmware_dfu_image); flipper_format_read_string( @@ -131,8 +131,7 @@ static bool ob_data_check_masked_values_valid( const FuriHalFlashRawOptionByteData* mask) { bool valid = true; for(size_t idx = 0; valid && (idx < FURI_HAL_FLASH_OB_TOTAL_VALUES); ++idx) { - valid &= (data->obs[idx]. dword & mask->obs[idx].dword) == - data->obs[idx].dword; + valid &= (data->obs[idx].dword & mask->obs[idx].dword) == data->obs[idx].dword; } return valid; } diff --git a/lib/update_util/update_manifest.h b/lib/update_util/update_manifest.h index 2893be5a..2b1e6857 100644 --- a/lib/update_util/update_manifest.h +++ b/lib/update_util/update_manifest.h @@ -12,6 +12,7 @@ extern "C" { /* Paths don't include /ext -- because at startup SD card is mounted as root */ #define UPDATE_DIR_DEFAULT_REL_PATH "/update" #define UPDATE_MANIFEST_DEFAULT_NAME "update.fuf" +#define UPDATE_MANIFEST_POINTER_FILE_NAME ".fupdate" typedef union { uint8_t raw[6]; @@ -27,6 +28,7 @@ typedef union { _Static_assert(sizeof(UpdateManifestRadioVersion) == 6, "UpdateManifestRadioVersion size error"); typedef struct { + uint32_t manifest_version; string_t version; uint32_t target; string_t staged_loader_file; diff --git a/lib/update_util/update_operation.c b/lib/update_util/update_operation.c index c9a7cd18..142dcaaa 100644 --- a/lib/update_util/update_operation.c +++ b/lib/update_util/update_operation.c @@ -12,7 +12,6 @@ #define UPDATE_ROOT_DIR "/ext" UPDATE_DIR_DEFAULT_REL_PATH #define UPDATE_PREFIX "/ext" UPDATE_DIR_DEFAULT_REL_PATH "/" #define UPDATE_SUFFIX "/" UPDATE_MANIFEST_DEFAULT_NAME -#define MAX_DIR_NAME_LEN 250 static const char* update_prepare_result_descr[] = { [UpdatePrepareResultOK] = "OK", @@ -21,6 +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", + [UpdatePrepareResultOutdatedManifestVersion] = "Update package is too old", }; const char* update_operation_describe_preparation_result(const UpdatePrepareResult value) { @@ -31,65 +32,7 @@ const char* update_operation_describe_preparation_result(const UpdatePrepareResu } } -bool update_operation_get_package_dir_name(const char* full_path, string_t out_manifest_dir) { - bool path_ok = false; - string_t full_path_str; - string_init_set(full_path_str, full_path); - string_reset(out_manifest_dir); - bool start_end_ok = string_start_with_str_p(full_path_str, UPDATE_PREFIX) && - string_end_with_str_p(full_path_str, UPDATE_SUFFIX); - int16_t dir_name_len = - strlen(full_path) - strlen(UPDATE_PREFIX) - strlen(UPDATE_MANIFEST_DEFAULT_NAME) - 1; - if(dir_name_len == -1) { - path_ok = true; - } else if(start_end_ok && (dir_name_len > 0)) { - string_set_n(out_manifest_dir, full_path_str, strlen(UPDATE_PREFIX), dir_name_len); - path_ok = true; - if(string_search_char(out_manifest_dir, '/') != STRING_FAILURE) { - string_reset(out_manifest_dir); - path_ok = false; - } - } - string_clear(full_path_str); - return path_ok; -} - -int32_t update_operation_get_package_index(Storage* storage, const char* update_package_dir) { - furi_assert(storage); - furi_assert(update_package_dir); - - if(strlen(update_package_dir) == 0) { - return UPDATE_OPERATION_ROOT_DIR_PACKAGE_MAGIC; - } - - bool found = false; - int32_t index = 0; - File* dir = storage_file_alloc(storage); - FileInfo fi = {0}; - char* name_buffer = malloc(MAX_DIR_NAME_LEN); - do { - if(!storage_dir_open(dir, UPDATE_ROOT_DIR)) { - break; - } - - while(storage_dir_read(dir, &fi, name_buffer, MAX_DIR_NAME_LEN)) { - index++; - if(strcmp(name_buffer, update_package_dir)) { - continue; - } else { - found = true; - break; - } - } - } while(false); - - free(name_buffer); - storage_file_free(dir); - - return found ? index : -1; -} - -bool update_operation_get_current_package_path(Storage* storage, string_t out_path) { +static bool update_operation_get_current_package_path_rtc(Storage* storage, string_t out_path) { const uint32_t update_index = furi_hal_rtc_get_register(FuriHalRtcRegisterUpdateFolderFSIndex); string_set_str(out_path, UPDATE_ROOT_DIR); if(update_index == UPDATE_OPERATION_ROOT_DIR_PACKAGE_MAGIC) { @@ -100,13 +43,13 @@ bool update_operation_get_current_package_path(Storage* storage, string_t out_pa uint32_t iter_index = 0; File* dir = storage_file_alloc(storage); FileInfo fi = {0}; - char* name_buffer = malloc(MAX_DIR_NAME_LEN); + char* name_buffer = malloc(UPDATE_OPERATION_MAX_MANIFEST_PATH_LEN); do { if(!storage_dir_open(dir, UPDATE_ROOT_DIR)) { break; } - while(storage_dir_read(dir, &fi, name_buffer, MAX_DIR_NAME_LEN)) { + while(storage_dir_read(dir, &fi, name_buffer, UPDATE_OPERATION_MAX_MANIFEST_PATH_LEN)) { if(++iter_index == update_index) { found = true; path_append(out_path, name_buffer); @@ -124,79 +67,148 @@ bool update_operation_get_current_package_path(Storage* storage, string_t out_pa return found; } +#define UPDATE_FILE_POINTER_FN "/ext/" UPDATE_MANIFEST_POINTER_FILE_NAME +#define UPDATE_MANIFEST_MAX_PATH_LEN 256u + +bool update_operation_get_current_package_manifest_path(Storage* storage, string_t out_path) { + string_reset(out_path); + if(storage_common_stat(storage, UPDATE_FILE_POINTER_FN, NULL) == FSE_OK) { + char* manifest_name_buffer = malloc(UPDATE_MANIFEST_MAX_PATH_LEN); + File* upd_file = NULL; + do { + upd_file = storage_file_alloc(storage); + if(!storage_file_open( + upd_file, UPDATE_FILE_POINTER_FN, FSAM_READ, FSOM_OPEN_EXISTING)) { + break; + } + uint16_t bytes_read = + storage_file_read(upd_file, manifest_name_buffer, UPDATE_MANIFEST_MAX_PATH_LEN); + if((bytes_read == 0) || (bytes_read == UPDATE_MANIFEST_MAX_PATH_LEN)) { + break; + } + if(storage_common_stat(storage, manifest_name_buffer, NULL) != FSE_OK) { + break; + } + string_set_str(out_path, manifest_name_buffer); + } while(0); + free(manifest_name_buffer); + storage_file_free(upd_file); + } else { + /* legacy, will be deprecated */ + string_t rtcpath; + string_init(rtcpath); + do { + if(!update_operation_get_current_package_path_rtc(storage, rtcpath)) { + break; + } + path_concat(string_get_cstr(rtcpath), UPDATE_MANIFEST_DEFAULT_NAME, out_path); + } while(0); + string_clear(rtcpath); + } + return !string_empty_p(out_path); +} + +static bool update_operation_persist_manifest_path(Storage* storage, const char* manifest_path) { + const uint16_t manifest_path_len = strlen(manifest_path); + furi_check(manifest_path && manifest_path_len); + bool success = false; + File* file = storage_file_alloc(storage); + do { + if(manifest_path_len >= UPDATE_OPERATION_MAX_MANIFEST_PATH_LEN) { + break; + } + + if(!storage_file_open(file, UPDATE_FILE_POINTER_FN, FSAM_WRITE, FSOM_CREATE_ALWAYS)) { + break; + } + + if(storage_file_write(file, manifest_path, manifest_path_len) != manifest_path_len) { + break; + } + + success = true; + } while(0); + storage_file_free(file); + return success; +} + UpdatePrepareResult update_operation_prepare(const char* manifest_file_path) { - string_t update_folder; - string_init(update_folder); - if(!update_operation_get_package_dir_name(manifest_file_path, update_folder)) { - string_clear(update_folder); - return UpdatePrepareResultManifestPathInvalid; - } - + UpdatePrepareResult result = UpdatePrepareResultManifestFolderNotFound; Storage* storage = furi_record_open("storage"); - int32_t update_index = - update_operation_get_package_index(storage, string_get_cstr(update_folder)); - string_clear(update_folder); - - if(update_index < 0) { - furi_record_close("storage"); - return UpdatePrepareResultManifestFolderNotFound; - } - - string_t update_dir_path; - string_init(update_dir_path); - path_extract_dirname(manifest_file_path, update_dir_path); - - UpdatePrepareResult result = UpdatePrepareResultManifestInvalid; UpdateManifest* manifest = update_manifest_alloc(); - if(update_manifest_init(manifest, manifest_file_path)) { - result = UpdatePrepareResultStageMissing; - File* file = storage_file_alloc(storage); + File* file = storage_file_alloc(storage); + + string_t stage_path; + string_init(stage_path); + do { + if(storage_common_stat(storage, manifest_file_path, NULL) != FSE_OK) { + break; + } + + if(!update_manifest_init(manifest, manifest_file_path)) { + result = UpdatePrepareResultManifestInvalid; + break; + } + + if(manifest->manifest_version < UPDATE_OPERATION_MIN_MANIFEST_VERSION) { + result = UpdatePrepareResultOutdatedManifestVersion; + break; + } + + if(furi_hal_version_get_hw_target() != manifest->target) { + result = UpdatePrepareResultTargetMismatch; + break; + } - string_t stage_path; - string_init(stage_path); path_extract_dirname(manifest_file_path, stage_path); path_append(stage_path, string_get_cstr(manifest->staged_loader_file)); - uint32_t crc = 0; - do { - if(!storage_file_open( - file, string_get_cstr(stage_path), FSAM_READ, FSOM_OPEN_EXISTING)) { - break; - } - - result = UpdatePrepareResultStageIntegrityError; - crc = crc32_calc_file(file, NULL, NULL); - } while(false); - - string_clear(stage_path); - storage_file_free(file); - - if(crc == manifest->staged_loader_crc) { - furi_hal_rtc_set_boot_mode(FuriHalRtcBootModePreUpdate); - update_operation_persist_package_index(update_index); - result = UpdatePrepareResultOK; + if(!storage_file_open(file, string_get_cstr(stage_path), FSAM_READ, FSOM_OPEN_EXISTING)) { + result = UpdatePrepareResultStageMissing; + break; } - } - furi_record_close("storage"); + + uint32_t crc = crc32_calc_file(file, NULL, NULL); + if(crc != manifest->staged_loader_crc) { + result = UpdatePrepareResultStageIntegrityError; + break; + } + + if(!update_operation_persist_manifest_path(storage, manifest_file_path)) { + result = UpdatePrepareResultManifestPointerError; + break; + } + + result = UpdatePrepareResultOK; + furi_hal_rtc_set_boot_mode(FuriHalRtcBootModePreUpdate); + } while(false); + + string_clear(stage_path); + storage_file_free(file); + update_manifest_free(manifest); + furi_record_close("storage"); return result; } bool update_operation_is_armed() { FuriHalRtcBootMode boot_mode = furi_hal_rtc_get_boot_mode(); + const uint32_t rtc_upd_index = + furi_hal_rtc_get_register(FuriHalRtcRegisterUpdateFolderFSIndex); + Storage* storage = furi_record_open("storage"); + const bool upd_fn_ptr_exists = + (storage_common_stat(storage, UPDATE_FILE_POINTER_FN, NULL) == FSE_OK); + furi_record_close("storage"); return (boot_mode >= FuriHalRtcBootModePreUpdate) && (boot_mode <= FuriHalRtcBootModePostUpdate) && - (furi_hal_rtc_get_register(FuriHalRtcRegisterUpdateFolderFSIndex) > 0); + ((rtc_upd_index != INT_MAX) || upd_fn_ptr_exists); } void update_operation_disarm() { furi_hal_rtc_set_boot_mode(FuriHalRtcBootModeNormal); - furi_hal_rtc_set_register( - FuriHalRtcRegisterUpdateFolderFSIndex, INT_MAX); -} - -void update_operation_persist_package_index(int32_t index) { - furi_check(index >= 0); - furi_hal_rtc_set_register(FuriHalRtcRegisterUpdateFolderFSIndex, index); -} + furi_hal_rtc_set_register(FuriHalRtcRegisterUpdateFolderFSIndex, INT_MAX); + Storage* storage = furi_record_open("storage"); + storage_simply_remove(storage, UPDATE_FILE_POINTER_FN); + furi_record_close("storage"); +} \ No newline at end of file diff --git a/lib/update_util/update_operation.h b/lib/update_util/update_operation.h index c11f2754..39d58028 100644 --- a/lib/update_util/update_operation.h +++ b/lib/update_util/update_operation.h @@ -9,6 +9,8 @@ extern "C" { #endif #define UPDATE_OPERATION_ROOT_DIR_PACKAGE_MAGIC 0 +#define UPDATE_OPERATION_MAX_MANIFEST_PATH_LEN 255u +#define UPDATE_OPERATION_MIN_MANIFEST_VERSION 2 /* * Checks if supplied full manifest path is valid @@ -19,6 +21,7 @@ extern "C" { */ bool update_operation_get_package_dir_name(const char* full_path, string_t out_manifest_dir); +/* When updating this enum, also update assets/protobuf/system.proto */ typedef enum { UpdatePrepareResultOK, UpdatePrepareResultManifestPathInvalid, @@ -26,6 +29,9 @@ typedef enum { UpdatePrepareResultManifestInvalid, UpdatePrepareResultStageMissing, UpdatePrepareResultStageIntegrityError, + UpdatePrepareResultManifestPointerError, + UpdatePrepareResultTargetMismatch, + UpdatePrepareResultOutdatedManifestVersion, } UpdatePrepareResult; const char* update_operation_describe_preparation_result(const UpdatePrepareResult value); @@ -37,27 +43,13 @@ const char* update_operation_describe_preparation_result(const UpdatePrepareResu */ UpdatePrepareResult update_operation_prepare(const char* manifest_file_path); -/* - * Gets update package index to pass in RTC registers - * @param storage Storage API - * @param update_package_dir Package directory name - * @return int32_t <=0 - error, >0 - update index value - */ -int32_t update_operation_get_package_index(Storage* storage, const char* update_package_dir); - /* * Gets filesystem path for current update package * @param storage Storage API - * @param out_path Path to directory with manifest & related files. Must be initialized + * @param out_path Path to manifest. Must be initialized * @return true if path was restored successfully */ -bool update_operation_get_current_package_path(Storage* storage, string_t out_path); - -/* - * Stores given update index in RTC registers - * @param index Value to store - */ -void update_operation_persist_package_index(int32_t index); +bool update_operation_get_current_package_manifest_path(Storage* storage, string_t out_path); /* * Checks if an update operation step is pending after reset diff --git a/scripts/update.py b/scripts/update.py index 3e8daab0..4769565c 100755 --- a/scripts/update.py +++ b/scripts/update.py @@ -13,6 +13,7 @@ import math class Main(App): + UPDATE_MANIFEST_VERSION = 2 UPDATE_MANIFEST_NAME = "update.fuf" # No compression, plain tar @@ -93,7 +94,9 @@ class Main(App): ) file = FlipperFormatFile() - file.setHeader("Flipper firmware upgrade configuration", 1) + file.setHeader( + "Flipper firmware upgrade configuration", self.UPDATE_MANIFEST_VERSION + ) file.writeKey("Info", self.args.version) file.writeKey("Target", self.args.target[1:]) # dirty 'f' strip file.writeKey("Loader", stage_basename) @@ -102,7 +105,7 @@ class Main(App): file.writeKey("Firmware", dfu_basename) file.writeKey("Radio", radiobin_basename or "") file.writeKey("Radio address", self.int2ffhex(radio_addr)) - file.writeKey("Radio version", self.int2ffhex(radio_version)) + file.writeKey("Radio version", self.int2ffhex(radio_version, 12)) if radiobin_basename: file.writeKey("Radio CRC", self.int2ffhex(self.crc(self.args.radiobin))) else: @@ -149,11 +152,10 @@ class Main(App): return " ".join(f"{b:02X}" for b in value) @staticmethod - def int2ffhex(value: int): - n_hex_bytes = 4 + def int2ffhex(value: int, n_hex_syms=8): if value: - n_hex_bytes = math.ceil(math.ceil(math.log2(value)) / 8) * 2 - fmtstr = f"%0{n_hex_bytes}X" + n_hex_syms = math.ceil(math.ceil(math.log2(value)) / 8) * 2 + fmtstr = f"%0{n_hex_syms}X" hexstr = fmtstr % value return " ".join(list(Main.batch(hexstr, 2))[::-1])