From ecd324dd1cc1d25ccbdada9329cd1a573ea71bcb Mon Sep 17 00:00:00 2001 From: Astra <93453568+Astrrra@users.noreply.github.com> Date: Mon, 17 Jun 2024 22:18:53 +0900 Subject: [PATCH 1/4] [FL-3856] Don't crash on reading weird cards (#3717) * Don't crash on reading weird cards * mf plus: fix incorrect read fail event handler Co-authored-by: gornekich --- .../main/nfc/helpers/protocol_support/mf_plus/mf_plus.c | 3 +-- lib/nfc/protocols/mf_plus/mf_plus_i.c | 8 +++++++- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/applications/main/nfc/helpers/protocol_support/mf_plus/mf_plus.c b/applications/main/nfc/helpers/protocol_support/mf_plus/mf_plus.c index eebed2a8d..eb2299cb5 100644 --- a/applications/main/nfc/helpers/protocol_support/mf_plus/mf_plus.c +++ b/applications/main/nfc/helpers/protocol_support/mf_plus/mf_plus.c @@ -41,8 +41,7 @@ static NfcCommand nfc_scene_read_poller_callback_mf_plus(NfcGenericEvent event, view_dispatcher_send_custom_event(instance->view_dispatcher, NfcCustomEventPollerSuccess); command = NfcCommandStop; } else if(mf_plus_event->type == MfPlusPollerEventTypeReadFailed) { - view_dispatcher_send_custom_event(instance->view_dispatcher, NfcCustomEventPollerFailure); - command = NfcCommandStop; + command = NfcCommandReset; } return command; diff --git a/lib/nfc/protocols/mf_plus/mf_plus_i.c b/lib/nfc/protocols/mf_plus/mf_plus_i.c index d5fe5be82..13bf8c5d8 100644 --- a/lib/nfc/protocols/mf_plus/mf_plus_i.c +++ b/lib/nfc/protocols/mf_plus/mf_plus_i.c @@ -4,13 +4,15 @@ MF_PLUS_FFF_PICC_PREFIX " " \ "Version" +#define MF_PLUS_T1_TK_VALUE_LEN 7 + #define MF_PLUS_FFF_SECURITY_LEVEL_KEY "Security Level" #define MF_PLUS_FFF_CARD_TYPE_KEY "Card Type" #define MF_PLUS_FFF_MEMORY_SIZE_KEY "Memory Size" #define TAG "MfPlus" -const uint8_t mf_plus_ats_t1_tk_values[][7] = { +const uint8_t mf_plus_ats_t1_tk_values[][MF_PLUS_T1_TK_VALUE_LEN] = { {0xC1, 0x05, 0x2F, 0x2F, 0x00, 0x35, 0xC7}, // Mifare Plus S {0xC1, 0x05, 0x2F, 0x2F, 0x01, 0xBC, 0xD6}, // Mifare Plus X {0xC1, 0x05, 0x2F, 0x2F, 0x00, 0xF6, 0xD1}, // Mifare Plus SE @@ -97,6 +99,10 @@ MfPlusError MfPlusError error = MfPlusErrorProtocol; + if(simple_array_get_count(iso4_data->ats_data.t1_tk) != MF_PLUS_T1_TK_VALUE_LEN) { + return MfPlusErrorProtocol; + } + switch(iso4_data->iso14443_3a_data->sak) { case 0x08: if(memcmp( From 039faf02f1efaa02eb5fe8f4582a010ceca0345f Mon Sep 17 00:00:00 2001 From: MMX <10697207+xMasterX@users.noreply.github.com> Date: Mon, 17 Jun 2024 16:49:09 +0300 Subject: [PATCH 2/4] SubGHz: Princeton - Add check for wrong guard_time values and show guard time in UI (#3719) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: あく --- lib/subghz/protocols/princeton.c | 21 +++++++++++++++++++-- 1 file changed, 19 insertions(+), 2 deletions(-) diff --git a/lib/subghz/protocols/princeton.c b/lib/subghz/protocols/princeton.c index 59175de8f..888ea9645 100644 --- a/lib/subghz/protocols/princeton.c +++ b/lib/subghz/protocols/princeton.c @@ -14,6 +14,7 @@ #define TAG "SubGhzProtocolPrinceton" #define PRINCETON_GUARD_TIME_DEFALUT 30 //GUARD_TIME = PRINCETON_GUARD_TIME_DEFALUT * TE +// Guard Time value should be between 15 -> 72 otherwise default value will be used static const SubGhzBlockConst subghz_protocol_princeton_const = { .te_short = 390, @@ -172,6 +173,11 @@ SubGhzProtocolStatus if(!flipper_format_read_uint32( flipper_format, "Guard_time", (uint32_t*)&instance->guard_time, 1)) { instance->guard_time = PRINCETON_GUARD_TIME_DEFALUT; + } else { + // Guard Time value should be between 15 -> 72 otherwise default value will be used + if((instance->guard_time < 15) || (instance->guard_time > 72)) { + instance->guard_time = PRINCETON_GUARD_TIME_DEFALUT; + } } flipper_format_read_uint32( @@ -268,6 +274,10 @@ void subghz_protocol_decoder_princeton_feed(void* context, bool level, uint32_t instance->generic.data = instance->decoder.decode_data; instance->generic.data_count_bit = instance->decoder.decode_count_bit; instance->guard_time = roundf((float)duration / instance->te); + // Guard Time value should be between 15 -> 72 otherwise default value will be used + if((instance->guard_time < 15) || (instance->guard_time > 72)) { + instance->guard_time = PRINCETON_GUARD_TIME_DEFALUT; + } if(instance->base.callback) instance->base.callback(&instance->base, instance->base.context); @@ -369,7 +379,13 @@ SubGhzProtocolStatus if(!flipper_format_read_uint32( flipper_format, "Guard_time", (uint32_t*)&instance->guard_time, 1)) { instance->guard_time = PRINCETON_GUARD_TIME_DEFALUT; + } else { + // Guard Time value should be between 15 -> 72 otherwise default value will be used + if((instance->guard_time < 15) || (instance->guard_time > 72)) { + instance->guard_time = PRINCETON_GUARD_TIME_DEFALUT; + } } + } while(false); return ret; @@ -388,12 +404,13 @@ void subghz_protocol_decoder_princeton_get_string(void* context, FuriString* out "Key:0x%08lX\r\n" "Yek:0x%08lX\r\n" "Sn:0x%05lX Btn:%01X\r\n" - "Te:%luus\r\n", + "Te:%luus GT:Te*%lu\r\n", instance->generic.protocol_name, instance->generic.data_count_bit, (uint32_t)(instance->generic.data & 0xFFFFFF), data_rev, instance->generic.serial, instance->generic.btn, - instance->te); + instance->te, + instance->guard_time); } From 729db7fa98d60f34c805ca3cd3f957ad4fa7a66e Mon Sep 17 00:00:00 2001 From: gornekich Date: Mon, 17 Jun 2024 15:20:35 +0100 Subject: [PATCH 3/4] [FL-3857] NFC Ultralight Original write support (#3718) * mf ultralight: rename ultralight unknown to origin * nfc app: add write to origin support for origin ultralights * mf ultralight: add orig write support on lib level * targets: bump major API version --- .../mf_ultralight/mf_ultralight.c | 2 +- lib/nfc/helpers/nfc_data_generator.c | 2 +- lib/nfc/protocols/mf_ultralight/mf_ultralight.c | 10 ++++++---- lib/nfc/protocols/mf_ultralight/mf_ultralight.h | 2 +- .../mf_ultralight/mf_ultralight_poller.c | 17 +++++++---------- targets/f18/api_symbols.csv | 2 +- targets/f7/api_symbols.csv | 2 +- 7 files changed, 18 insertions(+), 19 deletions(-) diff --git a/applications/main/nfc/helpers/protocol_support/mf_ultralight/mf_ultralight.c b/applications/main/nfc/helpers/protocol_support/mf_ultralight/mf_ultralight.c index a3028905f..b55ba130e 100644 --- a/applications/main/nfc/helpers/protocol_support/mf_ultralight/mf_ultralight.c +++ b/applications/main/nfc/helpers/protocol_support/mf_ultralight/mf_ultralight.c @@ -192,7 +192,7 @@ static void nfc_scene_read_and_saved_menu_on_enter_mf_ultralight(NfcApp* instanc } else if( data->type == MfUltralightTypeNTAG213 || data->type == MfUltralightTypeNTAG215 || data->type == MfUltralightTypeNTAG216 || data->type == MfUltralightTypeUL11 || - data->type == MfUltralightTypeUL21) { + data->type == MfUltralightTypeUL21 || data->type == MfUltralightTypeOrigin) { submenu_add_item( submenu, "Write", diff --git a/lib/nfc/helpers/nfc_data_generator.c b/lib/nfc/helpers/nfc_data_generator.c index c10e8fd94..7914c1f7f 100644 --- a/lib/nfc/helpers/nfc_data_generator.c +++ b/lib/nfc/helpers/nfc_data_generator.c @@ -49,7 +49,7 @@ static void nfc_generate_mf_ul_orig(NfcDevice* nfc_device) { MfUltralightData* mfu_data = mf_ultralight_alloc(); nfc_generate_mf_ul_common(mfu_data); - mfu_data->type = MfUltralightTypeUnknown; + mfu_data->type = MfUltralightTypeOrigin; mfu_data->pages_total = 16; mfu_data->pages_read = 16; memset(&mfu_data->page[4], 0xff, sizeof(MfUltralightPage)); diff --git a/lib/nfc/protocols/mf_ultralight/mf_ultralight.c b/lib/nfc/protocols/mf_ultralight/mf_ultralight.c index 6300801ab..1f3481c17 100644 --- a/lib/nfc/protocols/mf_ultralight/mf_ultralight.c +++ b/lib/nfc/protocols/mf_ultralight/mf_ultralight.c @@ -26,7 +26,7 @@ typedef struct { static const uint32_t mf_ultralight_data_format_version = 2; static const MfUltralightFeatures mf_ultralight_features[MfUltralightTypeNum] = { - [MfUltralightTypeUnknown] = + [MfUltralightTypeOrigin] = { .device_name = "Mifare Ultralight", .total_pages = 16, @@ -215,7 +215,7 @@ static const char* mf_ultralight_get_device_name_by_type(MfUltralightType type, NfcDeviceNameType name_type) { if(name_type == NfcDeviceNameTypeShort && (type == MfUltralightTypeUL11 || type == MfUltralightTypeUL21)) { - type = MfUltralightTypeUnknown; + type = MfUltralightTypeOrigin; } return mf_ultralight_features[type].device_name; @@ -512,7 +512,7 @@ Iso14443_3aData* mf_ultralight_get_base_data(const MfUltralightData* data) { MfUltralightType mf_ultralight_get_type_by_version(MfUltralightVersion* version) { furi_check(version); - MfUltralightType type = MfUltralightTypeUnknown; + MfUltralightType type = MfUltralightTypeOrigin; if(version->storage_size == 0x0B || version->storage_size == 0x00) { type = MfUltralightTypeUL11; @@ -575,12 +575,14 @@ uint8_t mf_ultralight_get_write_end_page(MfUltralightType type) { furi_assert( type == MfUltralightTypeUL11 || type == MfUltralightTypeUL21 || type == MfUltralightTypeNTAG213 || type == MfUltralightTypeNTAG215 || - type == MfUltralightTypeNTAG216); + type == MfUltralightTypeNTAG216 || type == MfUltralightTypeOrigin); uint8_t end_page = mf_ultralight_get_config_page_num(type); if(type == MfUltralightTypeNTAG213 || type == MfUltralightTypeNTAG215 || type == MfUltralightTypeNTAG216) { end_page -= 1; + } else if(type == MfUltralightTypeOrigin) { + end_page = mf_ultralight_features[type].total_pages; } return end_page; diff --git a/lib/nfc/protocols/mf_ultralight/mf_ultralight.h b/lib/nfc/protocols/mf_ultralight/mf_ultralight.h index 6c6a83a17..582e9e0e2 100644 --- a/lib/nfc/protocols/mf_ultralight/mf_ultralight.h +++ b/lib/nfc/protocols/mf_ultralight/mf_ultralight.h @@ -48,7 +48,7 @@ typedef enum { } MfUltralightError; typedef enum { - MfUltralightTypeUnknown, + MfUltralightTypeOrigin, MfUltralightTypeNTAG203, MfUltralightTypeMfulC, MfUltralightTypeUL11, diff --git a/lib/nfc/protocols/mf_ultralight/mf_ultralight_poller.c b/lib/nfc/protocols/mf_ultralight/mf_ultralight_poller.c index bc4ebd515..52b445859 100644 --- a/lib/nfc/protocols/mf_ultralight/mf_ultralight_poller.c +++ b/lib/nfc/protocols/mf_ultralight/mf_ultralight_poller.c @@ -281,12 +281,7 @@ static NfcCommand mf_ultralight_poller_handler_check_ntag_203(MfUltralightPoller } else { FURI_LOG_D(TAG, "Original Ultralight detected"); iso14443_3a_poller_halt(instance->iso14443_3a_poller); - instance->data->type = MfUltralightTypeUnknown; - if(instance->mode == MfUltralightPollerModeWrite) { - instance->mfu_event.type = MfUltralightPollerEventTypeCardMismatch; - instance->callback(instance->general_event, instance->context); - next_state = MfUltralightPollerStateWriteFail; - } + instance->data->type = MfUltralightTypeOrigin; } instance->state = next_state; @@ -575,10 +570,12 @@ static NfcCommand mf_ultralight_poller_handler_request_write_data(MfUltralightPo break; } - if(!instance->auth_context.auth_success) { - FURI_LOG_D(TAG, "Unknown password"); - instance->mfu_event.type = MfUltralightPollerEventTypeCardLocked; - break; + if(mf_ultralight_support_feature(features, MfUltralightFeatureSupportPasswordAuth)) { + if(!instance->auth_context.auth_success) { + FURI_LOG_D(TAG, "Unknown password"); + instance->mfu_event.type = MfUltralightPollerEventTypeCardLocked; + break; + } } const MfUltralightPage staticlock_page = tag_data->page[2]; diff --git a/targets/f18/api_symbols.csv b/targets/f18/api_symbols.csv index 4b40107ce..99c153c04 100644 --- a/targets/f18/api_symbols.csv +++ b/targets/f18/api_symbols.csv @@ -1,5 +1,5 @@ entry,status,name,type,params -Version,+,65.0,, +Version,+,66.0,, Header,+,applications/services/bt/bt_service/bt.h,, Header,+,applications/services/bt/bt_service/bt_keys_storage.h,, Header,+,applications/services/cli/cli.h,, diff --git a/targets/f7/api_symbols.csv b/targets/f7/api_symbols.csv index d64571963..b59453823 100644 --- a/targets/f7/api_symbols.csv +++ b/targets/f7/api_symbols.csv @@ -1,5 +1,5 @@ entry,status,name,type,params -Version,+,65.0,, +Version,+,66.0,, Header,+,applications/drivers/subghz/cc1101_ext/cc1101_ext_interconnect.h,, Header,+,applications/services/bt/bt_service/bt.h,, Header,+,applications/services/bt/bt_service/bt_keys_storage.h,, From d8ef0991fbc3a31b9a64ae45df5fe03459ac5921 Mon Sep 17 00:00:00 2001 From: Sergei Gavrilov Date: Tue, 18 Jun 2024 01:40:47 +1000 Subject: [PATCH 4/4] ELF, Flipper application: do not crash on "out of memory" (#3664) * ELF, Flipper application: do not crash on "out of memory" * loader: better error messages * typo * fix position * Loader: QR code for common errors * NFC: error message * Loader: error descriptions --- applications/main/nfc/nfc_app.c | 9 +- applications/services/loader/loader.c | 216 ++++++++++++++---- applications/services/loader/loader_i.h | 12 + assets/icons/Loader/err_01.png | Bin 0 -> 394 bytes assets/icons/Loader/err_02.png | Bin 0 -> 397 bytes assets/icons/Loader/err_03.png | Bin 0 -> 385 bytes assets/icons/Loader/err_04.png | Bin 0 -> 385 bytes assets/icons/Loader/err_05.png | Bin 0 -> 393 bytes assets/icons/Loader/err_06.png | Bin 0 -> 398 bytes assets/icons/Loader/err_07.png | Bin 0 -> 401 bytes assets/icons/Loader/err_09.png | Bin 0 -> 394 bytes lib/flipper_application/elf/elf_file.c | 137 ++++++++--- lib/flipper_application/elf/elf_file.h | 11 +- lib/flipper_application/flipper_application.c | 57 ++--- lib/flipper_application/flipper_application.h | 3 +- 15 files changed, 324 insertions(+), 121 deletions(-) create mode 100644 assets/icons/Loader/err_01.png create mode 100644 assets/icons/Loader/err_02.png create mode 100644 assets/icons/Loader/err_03.png create mode 100644 assets/icons/Loader/err_04.png create mode 100644 assets/icons/Loader/err_05.png create mode 100644 assets/icons/Loader/err_06.png create mode 100644 assets/icons/Loader/err_07.png create mode 100644 assets/icons/Loader/err_09.png diff --git a/applications/main/nfc/nfc_app.c b/applications/main/nfc/nfc_app.c index d0557de2a..62a1206f1 100644 --- a/applications/main/nfc/nfc_app.c +++ b/applications/main/nfc/nfc_app.c @@ -464,13 +464,10 @@ static bool nfc_is_hal_ready(void) { // No connection to the chip, show an error screen DialogsApp* dialogs = furi_record_open(RECORD_DIALOGS); DialogMessage* message = dialog_message_alloc(); + dialog_message_set_header(message, "Error: NFC Chip Failed", 64, 0, AlignCenter, AlignTop); dialog_message_set_text( - message, - "Error!\nNFC chip failed to start\n\n\nSend a photo of this to:\nsupport@flipperzero.one", - 0, - 0, - AlignLeft, - AlignTop); + message, "Send error photo via\nsupport.flipper.net", 0, 63, AlignLeft, AlignBottom); + dialog_message_set_icon(message, &I_err_09, 128 - 25, 64 - 25); dialog_message_show(dialogs, message); dialog_message_free(message); furi_record_close(RECORD_DIALOGS); diff --git a/applications/services/loader/loader.c b/applications/services/loader/loader.c index d4a4d581a..de013381f 100644 --- a/applications/services/loader/loader.c +++ b/applications/services/loader/loader.c @@ -27,11 +27,11 @@ static const char* loader_find_external_application_by_name(const char* app_name // API -LoaderStatus - loader_start(Loader* loader, const char* name, const char* args, FuriString* error_message) { - furi_check(loader); - furi_check(name); - +static LoaderMessageLoaderStatusResult loader_start_internal( + Loader* loader, + const char* name, + const char* args, + FuriString* error_message) { LoaderMessage message; LoaderMessageLoaderStatusResult result; @@ -44,43 +44,126 @@ LoaderStatus furi_message_queue_put(loader->queue, &message, FuriWaitForever); api_lock_wait_unlock_and_free(message.api_lock); - return result.value; + return result; } -static void - loader_show_gui_error(LoaderStatus status, const char* name, FuriString* error_message) { - if(status == LoaderStatusErrorUnknownApp && +typedef struct { + const char* error; + const char* description; + const char* url; + const Icon* icon; +} LoaderError; + +static const LoaderError err_app_not_found = + {"App Not Found", "Update firmware or app", "err_01", &I_err_01}; +static const LoaderError err_invalid_flie = {"Invalid File", "Update the app", "err_02", &I_err_02}; +static const LoaderError err_invalid_manifest = + {"Invalid Manifest", "Update firmware or app", "err_03", &I_err_03}; +static const LoaderError err_missing_imports = + {"Missing Imports", "Update firmware", "err_04", &I_err_04}; +static const LoaderError err_hw_target_mismatch = + {"HW Target\nMismatch", "App not supported", "err_05", &I_err_05}; +static const LoaderError err_outdated_app = {"Outdated App", "Update the app", "err_06", &I_err_06}; +static const LoaderError err_outdated_firmware = + {"Outdated\nFirmware", "Update firmware", "err_07", &I_err_07}; + +static void loader_dialog_prepare_and_show(DialogsApp* dialogs, const LoaderError* err) { + FuriString* header = furi_string_alloc_printf("Error: %s", err->error); + FuriString* text = + furi_string_alloc_printf("%s\nLearn more:\nr.flipper.net/%s", err->description, err->url); + DialogMessage* message = dialog_message_alloc(); + + dialog_message_set_header(message, furi_string_get_cstr(header), 64, 0, AlignCenter, AlignTop); + dialog_message_set_text(message, furi_string_get_cstr(text), 0, 63, AlignLeft, AlignBottom); + dialog_message_set_icon(message, err->icon, 128 - 25, 64 - 25); + dialog_message_show(dialogs, message); + + dialog_message_free(message); + furi_string_free(header); + furi_string_free(text); +} + +static void loader_show_gui_error( + LoaderMessageLoaderStatusResult status, + const char* name, + FuriString* error_message) { + DialogsApp* dialogs = furi_record_open(RECORD_DIALOGS); + DialogMessage* message = dialog_message_alloc(); + + if(status.value == LoaderStatusErrorUnknownApp && loader_find_external_application_by_name(name) != NULL) { // Special case for external apps - DialogsApp* dialogs = furi_record_open(RECORD_DIALOGS); - DialogMessage* message = dialog_message_alloc(); dialog_message_set_header(message, "Update needed", 64, 3, AlignCenter, AlignTop); - dialog_message_set_buttons(message, NULL, NULL, NULL); dialog_message_set_icon(message, &I_WarningDolphinFlip_45x42, 83, 22); dialog_message_set_text( message, "Update firmware\nto run this app", 3, 26, AlignLeft, AlignTop); dialog_message_show(dialogs, message); - dialog_message_free(message); - furi_record_close(RECORD_DIALOGS); - } else if(status == LoaderStatusErrorUnknownApp || status == LoaderStatusErrorInternal) { + } else if(status.value == LoaderStatusErrorUnknownApp) { + loader_dialog_prepare_and_show(dialogs, &err_app_not_found); + } else if(status.value == LoaderStatusErrorInternal) { // TODO FL-3522: we have many places where we can emit a double start, ex: desktop, menu // so i prefer to not show LoaderStatusErrorAppStarted error message for now - DialogsApp* dialogs = furi_record_open(RECORD_DIALOGS); - DialogMessage* message = dialog_message_alloc(); - dialog_message_set_header(message, "Error", 64, 0, AlignCenter, AlignTop); - dialog_message_set_buttons(message, NULL, NULL, NULL); + switch(status.error) { + case LoaderStatusErrorInvalidFile: + loader_dialog_prepare_and_show(dialogs, &err_invalid_flie); + break; + case LoaderStatusErrorInvalidManifest: + loader_dialog_prepare_and_show(dialogs, &err_invalid_manifest); + break; + case LoaderStatusErrorMissingImports: + loader_dialog_prepare_and_show(dialogs, &err_missing_imports); + break; + case LoaderStatusErrorHWMismatch: + loader_dialog_prepare_and_show(dialogs, &err_hw_target_mismatch); + break; + case LoaderStatusErrorOutdatedApp: + loader_dialog_prepare_and_show(dialogs, &err_outdated_app); + break; + case LoaderStatusErrorOutdatedFirmware: + loader_dialog_prepare_and_show(dialogs, &err_outdated_firmware); + break; + case LoaderStatusErrorOutOfMemory: + dialog_message_set_header( + message, "Error: Out of Memory", 64, 0, AlignCenter, AlignTop); + dialog_message_set_text( + message, + "Not enough RAM to run the\napp. Please reboot the device", + 64, + 13, + AlignCenter, + AlignTop); + dialog_message_set_buttons(message, NULL, NULL, "Reboot"); + if(dialog_message_show(dialogs, message) == DialogMessageButtonRight) { + furi_hal_power_reset(); + } + break; + default: + // Generic error + dialog_message_set_header(message, "Error", 64, 0, AlignCenter, AlignTop); - furi_string_replace(error_message, "/ext/apps/", ""); - furi_string_replace(error_message, ", ", "\n"); - furi_string_replace(error_message, ": ", "\n"); + furi_string_replace(error_message, "/ext/apps/", ""); + furi_string_replace(error_message, ", ", "\n"); + furi_string_replace(error_message, ": ", "\n"); - dialog_message_set_text( - message, furi_string_get_cstr(error_message), 64, 35, AlignCenter, AlignCenter); - - dialog_message_show(dialogs, message); - dialog_message_free(message); - furi_record_close(RECORD_DIALOGS); + dialog_message_set_text( + message, furi_string_get_cstr(error_message), 64, 35, AlignCenter, AlignCenter); + dialog_message_show(dialogs, message); + break; + } } + + dialog_message_free(message); + furi_record_close(RECORD_DIALOGS); +} + +LoaderStatus + loader_start(Loader* loader, const char* name, const char* args, FuriString* error_message) { + furi_check(loader); + furi_check(name); + + LoaderMessageLoaderStatusResult result = + loader_start_internal(loader, name, args, error_message); + return result.value; } LoaderStatus loader_start_with_gui_error(Loader* loader, const char* name, const char* args) { @@ -88,10 +171,11 @@ LoaderStatus loader_start_with_gui_error(Loader* loader, const char* name, const furi_check(name); FuriString* error_message = furi_string_alloc(); - LoaderStatus status = loader_start(loader, name, args, error_message); - loader_show_gui_error(status, name, error_message); + LoaderMessageLoaderStatusResult result = + loader_start_internal(loader, name, args, error_message); + loader_show_gui_error(result, name, error_message); furi_string_free(error_message); - return status; + return result.value; } void loader_start_detached_with_gui_error(Loader* loader, const char* name, const char* args) { @@ -316,13 +400,46 @@ static LoaderStatus loader_make_success_status(FuriString* error_message) { return LoaderStatusOk; } -static LoaderStatus loader_start_external_app( +static LoaderStatusError + loader_status_error_from_preload_status(FlipperApplicationPreloadStatus status) { + switch(status) { + case FlipperApplicationPreloadStatusInvalidFile: + return LoaderStatusErrorInvalidFile; + case FlipperApplicationPreloadStatusNotEnoughMemory: + return LoaderStatusErrorOutOfMemory; + case FlipperApplicationPreloadStatusInvalidManifest: + return LoaderStatusErrorInvalidManifest; + case FlipperApplicationPreloadStatusApiTooOld: + return LoaderStatusErrorOutdatedApp; + case FlipperApplicationPreloadStatusApiTooNew: + return LoaderStatusErrorOutdatedFirmware; + case FlipperApplicationPreloadStatusTargetMismatch: + return LoaderStatusErrorHWMismatch; + default: + return LoaderStatusErrorUnknown; + } +} + +static LoaderStatusError + loader_status_error_from_load_status(FlipperApplicationLoadStatus status) { + switch(status) { + case FlipperApplicationLoadStatusMissingImports: + return LoaderStatusErrorMissingImports; + default: + return LoaderStatusErrorUnknown; + } +} + +static LoaderMessageLoaderStatusResult loader_start_external_app( Loader* loader, Storage* storage, const char* path, const char* args, FuriString* error_message) { - LoaderStatus status = loader_make_success_status(error_message); + LoaderMessageLoaderStatusResult result; + result.value = loader_make_success_status(error_message); + result.error = LoaderStatusErrorUnknown; + LoaderEvent event; event.type = LoaderEventTypeApplicationBeforeLoad; furi_pubsub_publish(loader->pubsub, &event); @@ -337,8 +454,9 @@ static LoaderStatus loader_start_external_app( flipper_application_preload(loader->app.fap, path); if(preload_res != FlipperApplicationPreloadStatusSuccess) { const char* err_msg = flipper_application_preload_status_to_string(preload_res); - status = loader_make_status_error( + result.value = loader_make_status_error( LoaderStatusErrorInternal, error_message, "Preload failed, %s: %s", path, err_msg); + result.error = loader_status_error_from_preload_status(preload_res); break; } @@ -346,15 +464,16 @@ static LoaderStatus loader_start_external_app( flipper_application_map_to_memory(loader->app.fap); if(load_status != FlipperApplicationLoadStatusSuccess) { const char* err_msg = flipper_application_load_status_to_string(load_status); - status = loader_make_status_error( + result.value = loader_make_status_error( LoaderStatusErrorInternal, error_message, "Load failed, %s: %s", path, err_msg); + result.error = loader_status_error_from_load_status(load_status); break; } FURI_LOG_I(TAG, "Loaded in %zums", (size_t)(furi_get_tick() - start)); if(flipper_application_is_plugin(loader->app.fap)) { - status = loader_make_status_error( + result.value = loader_make_status_error( LoaderStatusErrorInternal, error_message, "Plugin %s is not runnable", path); break; } @@ -376,14 +495,14 @@ static LoaderStatus loader_start_external_app( loader_start_app_thread(loader, FlipperInternalApplicationFlagDefault); } while(0); - if(status != LoaderStatusOk) { + if(result.value != LoaderStatusOk) { flipper_application_free(loader->app.fap); loader->app.fap = NULL; event.type = LoaderEventTypeApplicationLoadFailed; furi_pubsub_publish(loader->pubsub, &event); } - return status; + return result; } // process messages @@ -419,23 +538,26 @@ static bool loader_do_is_locked(Loader* loader) { return loader->app.thread != NULL; } -static LoaderStatus loader_do_start_by_name( +static LoaderMessageLoaderStatusResult loader_do_start_by_name( Loader* loader, const char* name, const char* args, FuriString* error_message) { - LoaderStatus status; + LoaderMessageLoaderStatusResult status; + status.value = loader_make_success_status(error_message); + status.error = LoaderStatusErrorUnknown; + do { // check lock if(loader_do_is_locked(loader)) { if(loader->app.thread == (FuriThread*)LOADER_MAGIC_THREAD_VALUE) { - status = loader_make_status_error( + status.value = loader_make_status_error( LoaderStatusErrorAppStarted, error_message, "Loader is locked"); } else { const char* current_thread_name = furi_thread_get_name(furi_thread_get_id(loader->app.thread)); - status = loader_make_status_error( + status.value = loader_make_status_error( LoaderStatusErrorAppStarted, error_message, "Loader is locked, please close the \"%s\" first", @@ -449,7 +571,7 @@ static LoaderStatus loader_do_start_by_name( const FlipperInternalApplication* app = loader_find_application_by_name(name); if(app) { loader_start_internal_app(loader, app, args); - status = loader_make_success_status(error_message); + status.value = loader_make_success_status(error_message); break; } } @@ -457,7 +579,7 @@ static LoaderStatus loader_do_start_by_name( // check Applications if(strcmp(name, LOADER_APPLICATIONS_NAME) == 0) { loader_do_applications_show(loader); - status = loader_make_success_status(error_message); + status.value = loader_make_success_status(error_message); break; } @@ -480,7 +602,7 @@ static LoaderStatus loader_do_start_by_name( furi_record_close(RECORD_STORAGE); } - status = loader_make_status_error( + status.value = loader_make_status_error( LoaderStatusErrorUnknownApp, error_message, "Application \"%s\" not found", name); } while(false); @@ -555,13 +677,13 @@ int32_t loader_srv(void* p) { if(furi_message_queue_get(loader->queue, &message, FuriWaitForever) == FuriStatusOk) { switch(message.type) { case LoaderMessageTypeStartByName: - message.status_value->value = loader_do_start_by_name( + *(message.status_value) = loader_do_start_by_name( loader, message.start.name, message.start.args, message.start.error_message); api_lock_unlock(message.api_lock); break; case LoaderMessageTypeStartByNameDetachedWithGuiError: { FuriString* error_message = furi_string_alloc(); - LoaderStatus status = loader_do_start_by_name( + LoaderMessageLoaderStatusResult status = loader_do_start_by_name( loader, message.start.name, message.start.args, error_message); loader_show_gui_error(status, message.start.name, error_message); if(message.start.name) free((void*)message.start.name); diff --git a/applications/services/loader/loader_i.h b/applications/services/loader/loader_i.h index daa5484d3..95c0c0006 100644 --- a/applications/services/loader/loader_i.h +++ b/applications/services/loader/loader_i.h @@ -39,8 +39,20 @@ typedef struct { FuriString* error_message; } LoaderMessageStartByName; +typedef enum { + LoaderStatusErrorUnknown, + LoaderStatusErrorInvalidFile, + LoaderStatusErrorInvalidManifest, + LoaderStatusErrorMissingImports, + LoaderStatusErrorHWMismatch, + LoaderStatusErrorOutdatedApp, + LoaderStatusErrorOutOfMemory, + LoaderStatusErrorOutdatedFirmware, +} LoaderStatusError; + typedef struct { LoaderStatus value; + LoaderStatusError error; } LoaderMessageLoaderStatusResult; typedef struct { diff --git a/assets/icons/Loader/err_01.png b/assets/icons/Loader/err_01.png new file mode 100644 index 0000000000000000000000000000000000000000..7ffdf761da64afe452664bd98020b59c06b81c32 GIT binary patch literal 394 zcmV;50d@X~P)P000>X1^@s6#OZ}&00009a7bBm000XU z000XU0RWnu7ytkO0drDELIAGL9O(c600d`2O+f$vv5yPz6*u0w3i%DJ+3sXE2} zaCwts8N!O#C7Qd&hb6O@kqI$KTynB9<;&N5vXz oxl;IYj>%kGMwd!Zm54L>0_ZZS)%egVs{jB107*qoM6N<$f(eYTbpQYW literal 0 HcmV?d00001 diff --git a/assets/icons/Loader/err_02.png b/assets/icons/Loader/err_02.png new file mode 100644 index 0000000000000000000000000000000000000000..e00b1cb3b813c7db4a956eb60055a6a23cdbaa5a GIT binary patch literal 397 zcmV;80doF{P)P000>X1^@s6#OZ}&00009a7bBm000XU z000XU0RWnu7ytkO0drDELIAGL9O(c600d`2O+f$vv5yPnVsr6kDZP_XZ!5wHr~f>NL&AyfAhJIk>Xi} z(-9Pz*?ts?z>L4yB4q*;O$ixb(QRl^MLhy30TB>|p+yX*M*v0k5mov`#ne`5^dT7BDwG!{tZUse~DtD4f%(>Ch{&KLK_=+7-g1+Qu$ z2+a6yf&bu0?J7$UoW-Rf7!#m0&H9#GaS66xs=b(*>sVqar5-MGcPU1dZ7cn&v4c3T zk^?gl*O$9YP?rD9QdM8&%@_gW904;glsBWVQNyTt6_;)WWx{9M{`B>Gk{=2cGgR!+ ryHu~jgD4a;?^W1VWLNe_GFvNO&F{9HrD6Vh00000NkvXXu0mjfdFh}U literal 0 HcmV?d00001 diff --git a/assets/icons/Loader/err_03.png b/assets/icons/Loader/err_03.png new file mode 100644 index 0000000000000000000000000000000000000000..bb28c29abef21a7debcf62a87a8ec97c6352a4e3 GIT binary patch literal 385 zcmV-{0e=38P)P000>X1^@s6#OZ}&00009a7bBm000XU z000XU0RWnu7ytkO0drDELIAGL9O(c600d`2O+f$vv5yPnnvJ5|Lv<&ijar*Hi8oc*;ZV? zQgAtk(Anuc<~-yX=P#9&?M4;UckK$z?W_N#PB2s#k%Glh%E*dW39bygqRf4CJmI~1 z6l!?o{c}{`tu=lbYn5P000>X1^@s6#OZ}&00009a7bBm000XU z000XU0RWnu7ytkO0drDELIAGL9O(c600d`2O+f$vv5yPe*f@S0@_S)|676o-3 zPBJKOR`Y0-fz|#Q52Z5TT;bkcT#zxvdR)Ru*O}1@}9}zb{;A=P$z)~ zrzse*)}Caq*_cvR*;Mt%H~=n)7qDjJ>Fndk#Z#M%ZT7A0eD_XMk9A9rKA17UPhOF&aofva`)4bXw|ma f#n}^4vxAa1fFPzbmwU<;00000NkvXXu0mjfV1J-q literal 0 HcmV?d00001 diff --git a/assets/icons/Loader/err_05.png b/assets/icons/Loader/err_05.png new file mode 100644 index 0000000000000000000000000000000000000000..c606f9a331a9a65719d80e01bdee913be9bfad14 GIT binary patch literal 393 zcmV;40e1e0P)P000>X1^@s6#OZ}&00009a7bBm000XU z000XU0RWnu7ytkO0drDELIAGL9O(c600d`2O+f$vv5yPh=bKZ4IyuKe*~ghvfQNbRxa8JuJW&enP)E@GQf9|uR#eWo zc7vE_TTv|LJhN2&jL%=v<(i@MwCYP000>X1^@s6#OZ}&00009a7bBm000XU z000XU0RWnu7ytkO0drDELIAGL9O(c600d`2O+f$vv5yP7R8|b_7W-k-Wh)Y~0Z#OMw!B0+Nh7ayUx?oG6HbI-7*Ernv5Q zNC&n!h1|H4AFf}>v!yY=5^v7wIISID#vf$`Wtdd1T;($*lk>XQrv# zuQIi4wa3c5i!*neuC3aioYYVekh;6N)sAluJ{_jJg|uP+_{PtIq-sp?Nq!0>LqU%n zaTie4(eWo-6(kY$9BWysY2(Z22wD1xL1)I7vBxA;&!=-4A1#uny5;QJ_R`D9#B*ol s^jqhom(DQFrJKigd>Ip&tJP000>X1^@s6#OZ}&00009a7bBm000XU z000XU0RWnu7ytkO0drDELIAGL9O(c600d`2O+f$vv5yP*U?OdwPuD;}xVwf5v<_`MD~o zZidqdN@2IJMhWcXTim3TfsD3{3@}X_BdVw?P-Z{@X^as$oUQ#IS&o1FdimP0o-B&G zlZBpn@4TV|jK;}-A_-|>Ql-o&vl^8*qub}vPYgO!-i(=H^}MP}d1=x3DuvXWy4%-p vRd5P000>X1^@s6#OZ}&00009a7bBm000XU z000XU0RWnu7ytkO0drDELIAGL9O(c600d`2O+f$vv5yPR~~+6TDJ_kD+IyV!7f=D z@MyrX;@U_p*>A7X&3lpE3PnikKm*qI>f)4NH_$fn=`s+zI#z3QYY;3vbH;9}Zed2J zS1($=+F5;az^Yd5%b1;6z#JHTL+@%s1?@nYEInH4PlM_>JU| literal 0 HcmV?d00001 diff --git a/lib/flipper_application/elf/elf_file.c b/lib/flipper_application/elf/elf_file.c index 398f25209..d0c4f52fb 100644 --- a/lib/flipper_application/elf/elf_file.c +++ b/lib/flipper_application/elf/elf_file.c @@ -435,7 +435,6 @@ static bool elf_relocate(ELFFile* elf, ELFSection* s) { /************************************ Internal FAP interfaces *************************************/ /**************************************************************************************************/ typedef enum { - SectionTypeERROR = 0, SectionTypeUnused = 1 << 0, SectionTypeData = 1 << 1, SectionTypeRelData = 1 << 2, @@ -443,8 +442,6 @@ typedef enum { SectionTypeStrTab = 1 << 4, SectionTypeDebugLink = 1 << 5, SectionTypeFastRelData = 1 << 6, - - SectionTypeValid = SectionTypeSymTab | SectionTypeStrTab, } SectionType; static bool elf_load_debug_link(ELFFile* elf, Elf32_Shdr* section_header) { @@ -460,37 +457,62 @@ static bool str_prefix(const char* str, const char* prefix) { return strncmp(prefix, str, strlen(prefix)) == 0; } -static bool elf_load_section_data(ELFFile* elf, ELFSection* section, Elf32_Shdr* section_header) { +typedef enum { + ELFLoadSectionResultSuccess, + ELFLoadSectionResultNoMemory, + ELFLoadSectionResultError, +} ELFLoadSectionResult; + +typedef struct { + SectionType type; + ELFLoadSectionResult result; +} SectionTypeInfo; + +static ELFLoadSectionResult + elf_load_section_data(ELFFile* elf, ELFSection* section, Elf32_Shdr* section_header) { if(section_header->sh_size == 0) { FURI_LOG_D(TAG, "No data for section"); - return true; + return ELFLoadSectionResultSuccess; + } + + size_t safe_size = section_header->sh_size + 1024; + + furi_kernel_lock(); + + if(memmgr_heap_get_max_free_block() < safe_size) { + furi_kernel_unlock(); + FURI_LOG_E(TAG, "Not enough memory to load section data"); + return ELFLoadSectionResultNoMemory; } section->data = aligned_malloc(section_header->sh_size, section_header->sh_addralign); section->size = section_header->sh_size; + furi_kernel_unlock(); + if(section_header->sh_type == SHT_NOBITS) { // BSS section, no data to load - return true; + return ELFLoadSectionResultSuccess; } if((!storage_file_seek(elf->fd, section_header->sh_offset, true)) || (storage_file_read(elf->fd, section->data, section_header->sh_size) != section_header->sh_size)) { FURI_LOG_E(TAG, " seek/read fail"); - return false; + return ELFLoadSectionResultError; } FURI_LOG_D(TAG, "0x%p", section->data); - return true; + return ELFLoadSectionResultSuccess; } -static SectionType elf_preload_section( +static SectionTypeInfo elf_preload_section( ELFFile* elf, size_t section_idx, Elf32_Shdr* section_header, FuriString* name_string) { const char* name = furi_string_get_cstr(name_string); + SectionTypeInfo info; #ifdef ELF_DEBUG_LOG // log section name, type and flags @@ -527,7 +549,10 @@ static SectionType elf_preload_section( if(str_prefix(name, ".ARM.") || str_prefix(name, ".rel.ARM.") || str_prefix(name, ".fast.rel.ARM.")) { FURI_LOG_D(TAG, "Ignoring ARM section"); - return SectionTypeUnused; + + info.type = SectionTypeUnused; + info.result = ELFLoadSectionResultSuccess; + return info; } // Load allocable section @@ -546,26 +571,32 @@ static SectionType elf_preload_section( elf->fini_array = section_p; } - if(!elf_load_section_data(elf, section_p, section_header)) { + info.type = SectionTypeData; + info.result = elf_load_section_data(elf, section_p, section_header); + + if(info.result != ELFLoadSectionResultSuccess) { FURI_LOG_E(TAG, "Error loading section '%s'", name); - return SectionTypeERROR; - } else { - return SectionTypeData; } + + return info; } // Load link info section if(section_header->sh_flags & SHF_INFO_LINK) { + info.type = SectionTypeRelData; + if(str_prefix(name, ".rel")) { name = name + strlen(".rel"); ELFSection* section_p = elf_file_get_or_put_section(elf, name); section_p->rel_count = section_header->sh_size / sizeof(Elf32_Rel); section_p->rel_offset = section_header->sh_offset; - return SectionTypeRelData; + info.result = ELFLoadSectionResultSuccess; } else { FURI_LOG_E(TAG, "Unknown link info section '%s'", name); - return SectionTypeERROR; + info.result = ELFLoadSectionResultError; } + + return info; } // Load fast rel section @@ -574,13 +605,16 @@ static SectionType elf_preload_section( ELFSection* section_p = elf_file_get_or_put_section(elf, name); section_p->fast_rel = malloc(sizeof(ELFSection)); - if(!elf_load_section_data(elf, section_p->fast_rel, section_header)) { + info.type = SectionTypeFastRelData; + info.result = elf_load_section_data(elf, section_p->fast_rel, section_header); + + if(info.result != ELFLoadSectionResultSuccess) { FURI_LOG_E(TAG, "Error loading section '%s'", name); - return SectionTypeERROR; + } else { + FURI_LOG_D(TAG, "Loaded fast rel section for '%s'", name); } - FURI_LOG_D(TAG, "Loaded fast rel section for '%s'", name); - return SectionTypeFastRelData; + return info; } // Load symbol table @@ -588,27 +622,39 @@ static SectionType elf_preload_section( FURI_LOG_D(TAG, "Found .symtab section"); elf->symbol_table = section_header->sh_offset; elf->symbol_count = section_header->sh_size / sizeof(Elf32_Sym); - return SectionTypeSymTab; + + info.type = SectionTypeSymTab; + info.result = ELFLoadSectionResultSuccess; + return info; } // Load string table if(strcmp(name, ".strtab") == 0) { FURI_LOG_D(TAG, "Found .strtab section"); elf->symbol_table_strings = section_header->sh_offset; - return SectionTypeStrTab; + + info.type = SectionTypeStrTab; + info.result = ELFLoadSectionResultSuccess; + return info; } // Load debug link section if(strcmp(name, ".gnu_debuglink") == 0) { FURI_LOG_D(TAG, "Found .gnu_debuglink section"); + info.type = SectionTypeDebugLink; + if(elf_load_debug_link(elf, section_header)) { - return SectionTypeDebugLink; + info.result = ELFLoadSectionResultSuccess; + return info; } else { - return SectionTypeERROR; + info.result = ELFLoadSectionResultError; + return info; } } - return SectionTypeUnused; + info.type = SectionTypeUnused; + info.result = ELFLoadSectionResultSuccess; + return info; } static Elf32_Addr elf_address_of_by_hash(ELFFile* elf, uint32_t hash) { @@ -836,35 +882,57 @@ bool elf_file_open(ELFFile* elf, const char* path) { return true; } -bool elf_file_load_section_table(ELFFile* elf) { - SectionType loaded_sections = SectionTypeERROR; +ElfLoadSectionTableResult elf_file_load_section_table(ELFFile* elf) { + SectionType loaded_sections = 0; FuriString* name = furi_string_alloc(); + ElfLoadSectionTableResult result = ElfLoadSectionTableResultSuccess; FURI_LOG_D(TAG, "Scan ELF indexs..."); - // TODO FL-3526: why we start from 1? + for(size_t section_idx = 1; section_idx < elf->sections_count; section_idx++) { Elf32_Shdr section_header; furi_string_reset(name); if(!elf_read_section(elf, section_idx, §ion_header, name)) { - loaded_sections = SectionTypeERROR; + loaded_sections = 0; break; } FURI_LOG_D( TAG, "Preloading data for section #%d %s", section_idx, furi_string_get_cstr(name)); - SectionType section_type = elf_preload_section(elf, section_idx, §ion_header, name); - loaded_sections |= section_type; + SectionTypeInfo section_type_info = + elf_preload_section(elf, section_idx, §ion_header, name); + loaded_sections |= section_type_info.type; - if(section_type == SectionTypeERROR) { - loaded_sections = SectionTypeERROR; + if(section_type_info.result != ELFLoadSectionResultSuccess) { + if(section_type_info.result == ELFLoadSectionResultNoMemory) { + FURI_LOG_E(TAG, "Not enough memory"); + result = ElfLoadSectionTableResultNoMemory; + } else if(section_type_info.result == ELFLoadSectionResultError) { + FURI_LOG_E(TAG, "Error loading section"); + result = ElfLoadSectionTableResultError; + } + + loaded_sections = 0; break; } } furi_string_free(name); - return IS_FLAGS_SET(loaded_sections, SectionTypeValid); + if(result != ElfLoadSectionTableResultSuccess) { + return result; + } else { + bool sections_valid = + IS_FLAGS_SET(loaded_sections, SectionTypeSymTab | SectionTypeStrTab) | + IS_FLAGS_SET(loaded_sections, SectionTypeFastRelData); + if(sections_valid) { + return ElfLoadSectionTableResultSuccess; + } else { + FURI_LOG_E(TAG, "No valid sections found"); + return ElfLoadSectionTableResultError; + } + } } ElfProcessSectionResult elf_process_section( @@ -877,7 +945,6 @@ ElfProcessSectionResult elf_process_section( Elf32_Shdr section_header; // find section - // TODO FL-3526: why we start from 1? for(size_t section_idx = 1; section_idx < elf->sections_count; section_idx++) { furi_string_reset(section_name); if(!elf_read_section(elf, section_idx, §ion_header, section_name)) { diff --git a/lib/flipper_application/elf/elf_file.h b/lib/flipper_application/elf/elf_file.h index 921b506bd..caeeb3848 100644 --- a/lib/flipper_application/elf/elf_file.h +++ b/lib/flipper_application/elf/elf_file.h @@ -33,7 +33,6 @@ typedef struct { typedef enum { ELFFileLoadStatusSuccess = 0, ELFFileLoadStatusUnspecifiedError, - ELFFileLoadStatusNoFreeMemory, ELFFileLoadStatusMissingImports, } ELFFileLoadStatus; @@ -43,6 +42,12 @@ typedef enum { ElfProcessSectionResultSuccess, } ElfProcessSectionResult; +typedef enum { + ElfLoadSectionTableResultError, + ElfLoadSectionTableResultNoMemory, + ElfLoadSectionTableResultSuccess, +} ElfLoadSectionTableResult; + typedef bool(ElfProcessSection)(File* file, size_t offset, size_t size, void* context); /** @@ -70,9 +75,9 @@ bool elf_file_open(ELFFile* elf_file, const char* path); /** * @brief Load ELF file section table (load stage #1) * @param elf_file - * @return bool + * @return ElfLoadSectionTableResult */ -bool elf_file_load_section_table(ELFFile* elf_file); +ElfLoadSectionTableResult elf_file_load_section_table(ELFFile* elf_file); /** * @brief Load and relocate ELF file sections (load stage #2) diff --git a/lib/flipper_application/flipper_application.c b/lib/flipper_application/flipper_application.c index a3509896f..376e9c9ea 100644 --- a/lib/flipper_application/flipper_application.c +++ b/lib/flipper_application/flipper_application.c @@ -161,8 +161,11 @@ static FlipperApplicationPreloadStatus // if we are loading full file if(load_full) { // load section table - if(!elf_file_load_section_table(app->elf)) { + ElfLoadSectionTableResult load_result = elf_file_load_section_table(app->elf); + if(load_result == ElfLoadSectionTableResultError) { return FlipperApplicationPreloadStatusInvalidFile; + } else if(load_result == ElfLoadSectionTableResultNoMemory) { + return FlipperApplicationPreloadStatusNotEnoughMemory; } // load assets section @@ -219,8 +222,6 @@ FlipperApplicationLoadStatus flipper_application_map_to_memory(FlipperApplicatio elf_file_init_debug_info(app->elf, &app->state); flipper_application_list_add_app(app); return FlipperApplicationLoadStatusSuccess; - case ELFFileLoadStatusNoFreeMemory: - return FlipperApplicationLoadStatusNoFreeMemory; case ELFFileLoadStatusMissingImports: return FlipperApplicationLoadStatusMissingImports; default: @@ -272,38 +273,38 @@ FuriThread* flipper_application_alloc_thread(FlipperApplication* app, const char return app->thread; } -static const char* preload_status_strings[] = { - [FlipperApplicationPreloadStatusSuccess] = "Success", - [FlipperApplicationPreloadStatusUnspecifiedError] = "Unknown error", - [FlipperApplicationPreloadStatusInvalidFile] = "Invalid file", - [FlipperApplicationPreloadStatusInvalidManifest] = "Invalid file manifest", - [FlipperApplicationPreloadStatusApiTooOld] = - "Update Application to use with this Firmware (ApiTooOld)", - [FlipperApplicationPreloadStatusApiTooNew] = - "Update Firmware to use with this Application (ApiTooNew)", - [FlipperApplicationPreloadStatusTargetMismatch] = "Hardware target mismatch", -}; - -static const char* load_status_strings[] = { - [FlipperApplicationLoadStatusSuccess] = "Success", - [FlipperApplicationLoadStatusUnspecifiedError] = "Unknown error", - [FlipperApplicationLoadStatusNoFreeMemory] = "Out of memory", - [FlipperApplicationLoadStatusMissingImports] = - "Update Firmware to use with this Application (MissingImports)", -}; - const char* flipper_application_preload_status_to_string(FlipperApplicationPreloadStatus status) { - if(status >= COUNT_OF(preload_status_strings) || preload_status_strings[status] == NULL) { - return "Unknown error"; + switch(status) { + case FlipperApplicationPreloadStatusSuccess: + return "Success"; + case FlipperApplicationPreloadStatusInvalidFile: + return "Invalid file"; + case FlipperApplicationPreloadStatusNotEnoughMemory: + return "Not enough memory"; + case FlipperApplicationPreloadStatusInvalidManifest: + return "Invalid file manifest"; + case FlipperApplicationPreloadStatusApiTooOld: + return "Update Application to use with this Firmware (ApiTooOld)"; + case FlipperApplicationPreloadStatusApiTooNew: + return "Update Firmware to use with this Application (ApiTooNew)"; + case FlipperApplicationPreloadStatusTargetMismatch: + return "Hardware target mismatch"; } - return preload_status_strings[status]; + + return "Unknown error"; } const char* flipper_application_load_status_to_string(FlipperApplicationLoadStatus status) { - if(status >= COUNT_OF(load_status_strings) || load_status_strings[status] == NULL) { + switch(status) { + case FlipperApplicationLoadStatusSuccess: + return "Success"; + case FlipperApplicationLoadStatusUnspecifiedError: return "Unknown error"; + case FlipperApplicationLoadStatusMissingImports: + return "Update Firmware to use with this Application (MissingImports)"; } - return load_status_strings[status]; + + return "Unknown error"; } const FlipperAppPluginDescriptor* diff --git a/lib/flipper_application/flipper_application.h b/lib/flipper_application/flipper_application.h index 3daca5bc0..71627bd4b 100644 --- a/lib/flipper_application/flipper_application.h +++ b/lib/flipper_application/flipper_application.h @@ -18,8 +18,8 @@ extern "C" { typedef enum { FlipperApplicationPreloadStatusSuccess = 0, - FlipperApplicationPreloadStatusUnspecifiedError, FlipperApplicationPreloadStatusInvalidFile, + FlipperApplicationPreloadStatusNotEnoughMemory, FlipperApplicationPreloadStatusInvalidManifest, FlipperApplicationPreloadStatusApiTooOld, FlipperApplicationPreloadStatusApiTooNew, @@ -29,7 +29,6 @@ typedef enum { typedef enum { FlipperApplicationLoadStatusSuccess = 0, FlipperApplicationLoadStatusUnspecifiedError, - FlipperApplicationLoadStatusNoFreeMemory, FlipperApplicationLoadStatusMissingImports, } FlipperApplicationLoadStatus;