diff --git a/applications/main/fap_loader/fap_loader_app.c b/applications/main/fap_loader/fap_loader_app.c index fb0a300e7..d2f6b1f41 100644 --- a/applications/main/fap_loader/fap_loader_app.c +++ b/applications/main/fap_loader/fap_loader_app.c @@ -70,6 +70,7 @@ static bool fap_loader_run_selected_app(FapLoader* loader) { do { file_selected = true; loader->app = flipper_application_alloc(loader->storage, &hashtable_api_interface); + size_t start = furi_get_tick(); FURI_LOG_I(TAG, "FAP Loader is loading %s", furi_string_get_cstr(loader->fap_path)); @@ -99,6 +100,7 @@ static bool fap_loader_run_selected_app(FapLoader* loader) { break; } + FURI_LOG_I(TAG, "Loaded in %ums", (size_t)(furi_get_tick() - start)); FURI_LOG_I(TAG, "FAP Loader is staring app"); FuriThread* thread = flipper_application_spawn(loader->app, NULL); diff --git a/applications/plugins/snake_game/snake_game.c b/applications/plugins/snake_game/snake_game.c index 2aad952f0..74ce8d389 100644 --- a/applications/plugins/snake_game/snake_game.c +++ b/applications/plugins/snake_game/snake_game.c @@ -61,12 +61,32 @@ typedef struct { InputEvent input; } SnakeEvent; -static const NotificationSequence sequence_short_vibro_and_sound = { +const NotificationSequence sequence_fail = { &message_vibro_on, - &message_note_c5, + + &message_note_ds4, + &message_delay_10, + &message_sound_off, + &message_delay_10, + + &message_note_ds4, + &message_delay_10, + &message_sound_off, + &message_delay_10, + + &message_note_ds4, + &message_delay_10, + &message_sound_off, + &message_delay_10, + + &message_vibro_off, + NULL, +}; + +const NotificationSequence sequence_eat = { + &message_note_c7, &message_delay_50, &message_sound_off, - &message_vibro_off, NULL, }; @@ -95,12 +115,6 @@ static void snake_game_render_callback(Canvas* const canvas, void* ctx) { canvas_draw_box(canvas, p.x, p.y, 4, 4); } - // Show score on the game field - if(snake_state->state != GameStateGameOver) { - char buffer2[6]; - snprintf(buffer2, sizeof(buffer2), "%u", snake_state->len - 7); - canvas_draw_str_aligned(canvas, 124, 10, AlignRight, AlignBottom, buffer2); - } // Game Over banner if(snake_state->state == GameStateGameOver) { // Screen is 128x64 px @@ -247,7 +261,8 @@ static void snake_game_move_snake(SnakeState* const snake_state, Point const nex snake_state->points[0] = next_step; } -static void snake_game_process_game_step(SnakeState* const snake_state, NotificationApp* notify) { +static void + snake_game_process_game_step(SnakeState* const snake_state, NotificationApp* notification) { if(snake_state->state == GameStateGameOver) { return; } @@ -266,6 +281,7 @@ static void snake_game_process_game_step(SnakeState* const snake_state, Notifica return; } else if(snake_state->state == GameStateLastChance) { snake_state->state = GameStateGameOver; + notification_message_block(notification, &sequence_fail); return; } } else { @@ -277,17 +293,16 @@ static void snake_game_process_game_step(SnakeState* const snake_state, Notifica crush = snake_game_collision_with_tail(snake_state, next_step); if(crush) { snake_state->state = GameStateGameOver; + notification_message_block(notification, &sequence_fail); return; } bool eatFruit = (next_step.x == snake_state->fruit.x) && (next_step.y == snake_state->fruit.y); if(eatFruit) { - notification_message(notify, &sequence_short_vibro_and_sound); - //notification_message(notify, &sequence_blink_white_100); - snake_state->len++; if(snake_state->len >= MAX_SNAKE_LEN) { snake_state->state = GameStateGameOver; + notification_message_block(notification, &sequence_fail); return; } } @@ -296,6 +311,7 @@ static void snake_game_process_game_step(SnakeState* const snake_state, Notifica if(eatFruit) { snake_state->fruit = snake_game_get_new_fruit(snake_state); + notification_message(notification, &sequence_eat); } } @@ -327,9 +343,10 @@ int32_t snake_game_app(void* p) { // Open GUI and register view_port Gui* gui = furi_record_open(RECORD_GUI); gui_add_view_port(gui, view_port, GuiLayerFullscreen); - NotificationApp* notification = furi_record_open(RECORD_NOTIFICATION); + notification_message_block(notification, &sequence_display_backlight_enforce_on); + SnakeEvent event; for(bool processing = true; processing;) { FuriStatus event_status = furi_message_queue_get(event_queue, &event, 100); @@ -374,6 +391,9 @@ int32_t snake_game_app(void* p) { release_mutex(&state_mutex, snake_state); } + // Wait for all notifications to be played and return backlight to normal state + notification_message_block(notification, &sequence_display_backlight_enforce_auto); + furi_timer_free(timer); view_port_enabled_set(view_port, false); gui_remove_view_port(gui, view_port); diff --git a/furi/core/thread.c b/furi/core/thread.c index 3ebca807e..508146f63 100644 --- a/furi/core/thread.c +++ b/furi/core/thread.c @@ -103,6 +103,7 @@ static void furi_thread_body(void* context) { furi_assert(pvTaskGetThreadLocalStoragePointer(NULL, 0) != NULL); vTaskSetThreadLocalStoragePointer(NULL, 0, NULL); + thread->task_handle = NULL; vTaskDelete(NULL); furi_thread_catch(); } @@ -211,13 +212,8 @@ bool furi_thread_join(FuriThread* thread) { furi_check(furi_thread_get_current() != thread); - // Check if thread was started - if(thread->task_handle == NULL) { - return false; - } - // Wait for thread to stop - while(eTaskGetState(thread->task_handle) != eDeleted) { + while(thread->task_handle) { furi_delay_ms(10); } diff --git a/lib/flipper_application/elf/elf_file.c b/lib/flipper_application/elf/elf_file.c index b66e27d9a..c70af067e 100644 --- a/lib/flipper_application/elf/elf_file.c +++ b/lib/flipper_application/elf/elf_file.c @@ -57,8 +57,23 @@ static ELFSection* elf_file_get_section(ELFFile* elf, const char* name) { return ELFSectionDict_get(elf->sections, name); } -static void elf_file_put_section(ELFFile* elf, const char* name, ELFSection* section) { - ELFSectionDict_set_at(elf->sections, strdup(name), *section); +static ELFSection* elf_file_get_or_put_section(ELFFile* elf, const char* name) { + ELFSection* section_p = elf_file_get_section(elf, name); + if(!section_p) { + ELFSectionDict_set_at( + elf->sections, + strdup(name), + (ELFSection){ + .data = NULL, + .sec_idx = 0, + .size = 0, + .rel_count = 0, + .rel_offset = 0, + }); + section_p = elf_file_get_section(elf, name); + } + + return section_p; } static bool elf_read_string_from_offset(ELFFile* elf, off_t offset, FuriString* name) { @@ -320,12 +335,12 @@ static bool elf_relocate_symbol(ELFFile* elf, Elf32_Addr relAddr, int type, Elf3 return true; } -static bool elf_relocate(ELFFile* elf, Elf32_Shdr* h, ELFSection* s) { +static bool elf_relocate(ELFFile* elf, ELFSection* s) { if(s->data) { Elf32_Rel rel; - size_t relEntries = h->sh_size / sizeof(rel); + size_t relEntries = s->rel_count; size_t relCount; - (void)storage_file_seek(elf->fd, h->sh_offset, true); + (void)storage_file_seek(elf->fd, s->rel_offset, true); FURI_LOG_D(TAG, " Offset Info Type Name"); int relocate_result = true; @@ -395,14 +410,6 @@ static bool elf_relocate(ELFFile* elf, Elf32_Shdr* h, ELFSection* s) { return false; } -/**************************************************************************************************/ -/********************************************* MISC ***********************************************/ -/**************************************************************************************************/ - -static bool cstr_prefix(const char* prefix, const char* string) { - return strncmp(prefix, string, strlen(prefix)) == 0; -} - /**************************************************************************************************/ /************************************ Internal FAP interfaces *************************************/ /**************************************************************************************************/ @@ -445,6 +452,31 @@ static bool elf_load_debug_link(ELFFile* elf, Elf32_Shdr* section_header) { section_header->sh_size; } +static bool 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; + } + + section->data = aligned_malloc(section_header->sh_size, section_header->sh_addralign); + section->size = section_header->sh_size; + + if(section_header->sh_type == SHT_NOBITS) { + // BSS section, no data to load + return true; + } + + 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; + } + + FURI_LOG_D(TAG, "0x%X", section->data); + return true; +} + static SectionType elf_preload_section( ELFFile* elf, size_t section_idx, @@ -453,73 +485,63 @@ static SectionType elf_preload_section( FlipperApplicationManifest* manifest) { const char* name = furi_string_get_cstr(name_string); - const struct { - const char* prefix; - SectionType type; - } lookup_sections[] = { - {".text", SectionTypeData}, - {".rodata", SectionTypeData}, - {".data", SectionTypeData}, - {".bss", SectionTypeData}, - {".preinit_array", SectionTypeData}, - {".init_array", SectionTypeData}, - {".fini_array", SectionTypeData}, - {".rel.text", SectionTypeRelData}, - {".rel.rodata", SectionTypeRelData}, - {".rel.data", SectionTypeRelData}, - {".rel.preinit_array", SectionTypeRelData}, - {".rel.init_array", SectionTypeRelData}, - {".rel.fini_array", SectionTypeRelData}, - }; + // Load allocable section + if(section_header->sh_flags & SHF_ALLOC) { + ELFSection* section_p = elf_file_get_or_put_section(elf, name); + section_p->sec_idx = section_idx; - for(size_t i = 0; i < COUNT_OF(lookup_sections); i++) { - if(cstr_prefix(lookup_sections[i].prefix, name)) { - FURI_LOG_D(TAG, "Found section %s", lookup_sections[i].prefix); + if(section_header->sh_type == SHT_PREINIT_ARRAY) { + elf->preinit_array = section_p; + } else if(section_header->sh_type == SHT_INIT_ARRAY) { + elf->init_array = section_p; + } else if(section_header->sh_type == SHT_FINI_ARRAY) { + elf->fini_array = section_p; + } - if(lookup_sections[i].type == SectionTypeRelData) { - name = name + strlen(".rel"); - } - - ELFSection* section_p = elf_file_get_section(elf, name); - if(!section_p) { - ELFSection section = { - .data = NULL, - .sec_idx = 0, - .rel_sec_idx = 0, - .size = 0, - }; - - elf_file_put_section(elf, name, §ion); - section_p = elf_file_get_section(elf, name); - } - - if(lookup_sections[i].type == SectionTypeRelData) { - section_p->rel_sec_idx = section_idx; - } else { - section_p->sec_idx = section_idx; - } - - return lookup_sections[i].type; + if(!elf_load_section_data(elf, section_p, section_header)) { + FURI_LOG_E(TAG, "Error loading section '%s'", name); + return SectionTypeERROR; + } else { + return SectionTypeData; } } + // Load link info section + if(section_header->sh_flags & SHF_INFO_LINK) { + 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; + } + + // Load symbol table if(strcmp(name, ".symtab") == 0) { 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; - } else if(strcmp(name, ".strtab") == 0) { + } + + // 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; - } else if(strcmp(name, ".fapmeta") == 0) { + } + + // Load manifest section + if(strcmp(name, ".fapmeta") == 0) { FURI_LOG_D(TAG, "Found .fapmeta section"); if(elf_load_metadata(elf, section_header, manifest)) { return SectionTypeManifest; } else { return SectionTypeERROR; } - } else if(strcmp(name, ".gnu_debuglink") == 0) { + } + + // Load debug link section + if(strcmp(name, ".gnu_debuglink") == 0) { FURI_LOG_D(TAG, "Found .gnu_debuglink section"); if(elf_load_debug_link(elf, section_header)) { return SectionTypeDebugLink; @@ -531,61 +553,17 @@ static SectionType elf_preload_section( return SectionTypeUnused; } -static bool elf_load_section_data(ELFFile* elf, ELFSection* section) { - Elf32_Shdr section_header; - if(section->sec_idx == 0) { - FURI_LOG_D(TAG, "Section is not present"); - return true; - } - - if(!elf_read_section_header(elf, section->sec_idx, §ion_header)) { - return false; - } - - if(section_header.sh_size == 0) { - FURI_LOG_D(TAG, "No data for section"); - return true; - } - - section->data = aligned_malloc(section_header.sh_size, section_header.sh_addralign); - section->size = section_header.sh_size; - - if(section_header.sh_type == SHT_NOBITS) { - /* section is empty (.bss?) */ - /* no need to memset - allocator already did that */ - return true; - } - - 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; - } - - FURI_LOG_D(TAG, "0x%X", section->data); - return true; -} - static bool elf_relocate_section(ELFFile* elf, ELFSection* section) { - Elf32_Shdr section_header; - if(section->rel_sec_idx) { + if(section->rel_count) { FURI_LOG_D(TAG, "Relocating section"); - if(elf_read_section_header(elf, section->rel_sec_idx, §ion_header)) - return elf_relocate(elf, §ion_header, section); - else { - FURI_LOG_E(TAG, "Error reading section header"); - return false; - } + return elf_relocate(elf, section); } else { FURI_LOG_D(TAG, "No relocation index"); /* Not an error */ } return true; } -static void elf_file_call_section_list(ELFFile* elf, const char* name, bool reverse_order) { - ELFSection* section = elf_file_get_section(elf, name); - +static void elf_file_call_section_list(ELFSection* section, bool reverse_order) { if(section && section->size) { const uint32_t* start = section->data; const uint32_t* end = section->data + section->size; @@ -729,7 +707,6 @@ bool elf_file_load_section_table(ELFFile* elf, FlipperApplicationManifest* manif } furi_string_free(name); - FURI_LOG_D(TAG, "Load symbols done"); return IS_FLAGS_SET(loaded_sections, SectionTypeValid); } @@ -739,16 +716,6 @@ ELFFileLoadStatus elf_file_load_sections(ELFFile* elf) { ELFSectionDict_it_t it; AddressCache_init(elf->relocation_cache); - size_t start = furi_get_tick(); - - for(ELFSectionDict_it(it, elf->sections); !ELFSectionDict_end_p(it); ELFSectionDict_next(it)) { - ELFSectionDict_itref_t* itref = ELFSectionDict_ref(it); - FURI_LOG_D(TAG, "Loading section '%s'", itref->key); - if(!elf_load_section_data(elf, &itref->value)) { - FURI_LOG_E(TAG, "Error loading section '%s'", itref->key); - status = ELFFileLoadStatusUnspecifiedError; - } - } if(status == ELFFileLoadStatusSuccess) { for(ELFSectionDict_it(it, elf->sections); !ELFSectionDict_end_p(it); @@ -777,14 +744,13 @@ ELFFileLoadStatus elf_file_load_sections(ELFFile* elf) { FURI_LOG_D(TAG, "Relocation cache size: %u", AddressCache_size(elf->relocation_cache)); FURI_LOG_D(TAG, "Trampoline cache size: %u", AddressCache_size(elf->trampoline_cache)); AddressCache_clear(elf->relocation_cache); - FURI_LOG_I(TAG, "Loaded in %ums", (size_t)(furi_get_tick() - start)); return status; } void elf_file_pre_run(ELFFile* elf) { - elf_file_call_section_list(elf, ".preinit_array", false); - elf_file_call_section_list(elf, ".init_array", false); + elf_file_call_section_list(elf->preinit_array, false); + elf_file_call_section_list(elf->init_array, false); } int32_t elf_file_run(ELFFile* elf, void* args) { @@ -794,7 +760,7 @@ int32_t elf_file_run(ELFFile* elf, void* args) { } void elf_file_post_run(ELFFile* elf) { - elf_file_call_section_list(elf, ".fini_array", true); + elf_file_call_section_list(elf->fini_array, true); } const ElfApiInterface* elf_file_get_api_interface(ELFFile* elf_file) { diff --git a/lib/flipper_application/elf/elf_file_i.h b/lib/flipper_application/elf/elf_file_i.h index 1df075f06..9b38540b7 100644 --- a/lib/flipper_application/elf/elf_file_i.h +++ b/lib/flipper_application/elf/elf_file_i.h @@ -16,8 +16,10 @@ typedef int32_t(entry_t)(void*); typedef struct { void* data; uint16_t sec_idx; - uint16_t rel_sec_idx; Elf32_Word size; + + size_t rel_count; + Elf32_Off rel_offset; } ELFSection; DICT_DEF2(ELFSectionDict, const char*, M_CSTR_OPLIST, ELFSection, M_POD_OPLIST) @@ -39,6 +41,10 @@ struct ELFFile { File* fd; const ElfApiInterface* api_interface; ELFDebugLinkInfo debug_link_info; + + ELFSection* preinit_array; + ELFSection* init_array; + ELFSection* fini_array; }; #ifdef __cplusplus