diff --git a/scenes/seader_scene_credential_info.c b/scenes/seader_scene_credential_info.c index 980672b..0f6a97b 100644 --- a/scenes/seader_scene_credential_info.c +++ b/scenes/seader_scene_credential_info.c @@ -19,10 +19,11 @@ void seader_scene_credential_info_on_enter(void* context) { PluginWiegand* plugin = seader->plugin_wiegand; Widget* widget = seader->widget; - FuriString* type_str = furi_string_alloc(); - FuriString* bitlength_str = furi_string_alloc(); - FuriString* credential_str = furi_string_alloc(); - FuriString* sio_str = furi_string_alloc(); + // Use reusable strings instead of allocating new ones + FuriString* type_str = seader->temp_string1; + FuriString* bitlength_str = seader->temp_string2; + FuriString* credential_str = seader->temp_string3; + FuriString* sio_str = seader->temp_string4; furi_string_set(credential_str, ""); furi_string_set(bitlength_str, ""); @@ -86,10 +87,7 @@ void seader_scene_credential_info_on_enter(void* context) { widget, 64, 48, AlignCenter, AlignCenter, FontSecondary, furi_string_get_cstr(sio_str)); } - furi_string_free(bitlength_str); - furi_string_free(type_str); - furi_string_free(credential_str); - furi_string_free(sio_str); + // No need to free strings as they are reused from seader struct view_dispatcher_switch_to_view(seader->view_dispatcher, SeaderViewWidget); } diff --git a/scenes/seader_scene_formats.c b/scenes/seader_scene_formats.c index f79ebc7..a2f0508 100644 --- a/scenes/seader_scene_formats.c +++ b/scenes/seader_scene_formats.c @@ -10,14 +10,16 @@ void seader_scene_formats_on_enter(void* context) { furi_string_reset(str); if(plugin) { - FuriString* description = furi_string_alloc(); + // Use reusable string instead of allocating new one + FuriString* description = seader->temp_string1; + furi_string_reset(description); size_t format_count = plugin->count(credential->bit_length, credential->credential); for(size_t i = 0; i < format_count; i++) { plugin->description(credential->bit_length, credential->credential, i, description); furi_string_cat_printf(str, "%s\n", furi_string_get_cstr(description)); } - furi_string_free(description); + // No need to free description as it's reused from seader struct } text_box_set_font(seader->text_box, TextBoxFontHex); diff --git a/scenes/seader_scene_read_card_success.c b/scenes/seader_scene_read_card_success.c index 2fcd5d4..e93692d 100644 --- a/scenes/seader_scene_read_card_success.c +++ b/scenes/seader_scene_read_card_success.c @@ -19,10 +19,11 @@ void seader_scene_read_card_success_on_enter(void* context) { PluginWiegand* plugin = seader->plugin_wiegand; Widget* widget = seader->widget; - FuriString* type_str = furi_string_alloc(); - FuriString* bitlength_str = furi_string_alloc(); - FuriString* credential_str = furi_string_alloc(); - FuriString* sio_str = furi_string_alloc(); + // Use reusable strings instead of allocating new ones + FuriString* type_str = seader->temp_string1; + FuriString* bitlength_str = seader->temp_string2; + FuriString* credential_str = seader->temp_string3; + FuriString* sio_str = seader->temp_string4; dolphin_deed(DolphinDeedNfcReadSuccess); @@ -100,10 +101,7 @@ void seader_scene_read_card_success_on_enter(void* context) { widget, 64, 48, AlignCenter, AlignCenter, FontSecondary, furi_string_get_cstr(sio_str)); } - furi_string_free(credential_str); - furi_string_free(bitlength_str); - furi_string_free(type_str); - furi_string_free(sio_str); + // No need to free strings as they are reused from seader struct view_dispatcher_switch_to_view(seader->view_dispatcher, SeaderViewWidget); } diff --git a/scenes/seader_scene_sam_info.c b/scenes/seader_scene_sam_info.c index c7f5249..2463497 100644 --- a/scenes/seader_scene_sam_info.c +++ b/scenes/seader_scene_sam_info.c @@ -15,7 +15,8 @@ void seader_scene_sam_info_on_enter(void* context) { SeaderWorker* seader_worker = seader->worker; Widget* widget = seader->widget; - FuriString* fw_str = furi_string_alloc(); + // Use reusable string instead of allocating new one + FuriString* fw_str = seader->temp_string1; furi_string_cat_printf( fw_str, "FW %d.%d", seader_worker->sam_version[0], seader_worker->sam_version[1]); @@ -26,7 +27,7 @@ void seader_scene_sam_info_on_enter(void* context) { widget_add_string_element( widget, 64, 5, AlignCenter, AlignCenter, FontSecondary, furi_string_get_cstr(fw_str)); - furi_string_free(fw_str); + // No need to free fw_str as it's reused from seader struct view_dispatcher_switch_to_view(seader->view_dispatcher, SeaderViewWidget); } diff --git a/scenes/seader_scene_sam_present.c b/scenes/seader_scene_sam_present.c index 2183da1..8938baf 100644 --- a/scenes/seader_scene_sam_present.c +++ b/scenes/seader_scene_sam_present.c @@ -53,7 +53,8 @@ void seader_scene_sam_present_on_update(void* context) { seader); } if(seader_worker->sam_version[0] != 0 && seader_worker->sam_version[1] != 0) { - FuriString* fw_str = furi_string_alloc(); + // Use reusable string instead of allocating new one + FuriString* fw_str = seader->temp_string1; furi_string_cat_printf( fw_str, "FW %d.%d", seader_worker->sam_version[0], seader_worker->sam_version[1]); submenu_add_item( @@ -62,7 +63,7 @@ void seader_scene_sam_present_on_update(void* context) { SubmenuIndexFwVersion, seader_scene_sam_present_submenu_callback, seader); - furi_string_free(fw_str); + // No need to free fw_str as it's reused from seader struct fwChecks = 0; } diff --git a/scenes/seader_scene_save_name.c b/scenes/seader_scene_save_name.c index 4e871a8..2be78fb 100644 --- a/scenes/seader_scene_save_name.c +++ b/scenes/seader_scene_save_name.c @@ -32,7 +32,8 @@ void seader_scene_save_name_on_enter(void* context) { SEADER_CRED_NAME_MAX_LEN, cred_name_empty); - FuriString* folder_path = furi_string_alloc(); + // Use reusable string instead of allocating new one + FuriString* folder_path = seader->temp_string1; if(furi_string_end_with(seader->credential->load_path, SEADER_APP_EXTENSION)) { path_extract_dirname(furi_string_get_cstr(seader->credential->load_path), folder_path); } else { @@ -45,7 +46,7 @@ void seader_scene_save_name_on_enter(void* context) { view_dispatcher_switch_to_view(seader->view_dispatcher, SeaderViewTextInput); - furi_string_free(folder_path); + // No need to free folder_path as it's reused from seader struct } bool seader_scene_save_name_on_event(void* context, SceneManagerEvent event) { diff --git a/seader.c b/seader.c index 217b1b2..b3c4bc8 100644 --- a/seader.c +++ b/seader.c @@ -90,6 +90,12 @@ Seader* seader_alloc() { view_dispatcher_add_view( seader->view_dispatcher, SeaderViewWidget, widget_get_view(seader->widget)); + // Allocate reusable strings for scene optimization + seader->temp_string1 = furi_string_alloc(); + seader->temp_string2 = furi_string_alloc(); + seader->temp_string3 = furi_string_alloc(); + seader->temp_string4 = furi_string_alloc(); + seader->plugin_manager = plugin_manager_alloc(PLUGIN_APP_ID, PLUGIN_API_VERSION, firmware_api_interface); @@ -157,6 +163,12 @@ void seader_free(Seader* seader) { view_dispatcher_remove_view(seader->view_dispatcher, SeaderViewWidget); widget_free(seader->widget); + // Free reusable strings + furi_string_free(seader->temp_string1); + furi_string_free(seader->temp_string2); + furi_string_free(seader->temp_string3); + furi_string_free(seader->temp_string4); + // Worker seader_worker_stop(seader->worker); seader_worker_free(seader->worker); diff --git a/seader_credential.c b/seader_credential.c index 52f6076..b214a0b 100644 --- a/seader_credential.c +++ b/seader_credential.c @@ -14,6 +14,41 @@ static const char* seader_file_header = "Flipper Seader Credential"; static const uint32_t seader_file_version = 1; extern const uint8_t picopass_iclass_key[]; +// Static const arrays to optimize stack usage - moved from functions to reduce stack allocation +static const uint8_t seader_manuf_block[16] = + {0xDF, 0xC6, 0x9C, 0x05, 0x80, 0x08, 0x04, 0x00, 0x00, 0x00, 0x73, 0x65, 0x61, 0x64, 0x65, 0x72}; + +static const uint8_t seader_sector0_trailer[16] = + {0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0x78, 0x77, 0x88, 0xc1, 0x89, 0xec, 0xa9, 0x7f, 0x8c, 0x2a}; + +static const uint8_t seader_sector1_trailer[16] = + {0x48, 0x49, 0x44, 0x20, 0x49, 0x53, 0x78, 0x77, 0x88, 0xaa, 0x20, 0x47, 0x52, 0x45, 0x41, 0x54}; + +static const uint8_t seader_section_trailer[16] = + {0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x07, 0x80, 0x69, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; + +static const uint8_t seader_mad_block[16] = + {0x1b, 0x01, 0x4d, 0x48, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; + +static const uint8_t seader_empty_block[16] = + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; + +// Picopass constants +static const uint8_t seader_picopass_fake_csn[PICOPASS_BLOCK_LEN] = + {0x7a, 0xf5, 0x31, 0x13, 0xfe, 0xff, 0x12, 0xe0}; + +static const uint8_t seader_picopass_cfg[PICOPASS_BLOCK_LEN] = + {0x12, 0xff, 0xff, 0xff, 0x7f, 0x1f, 0xff, 0x3c}; + +static const uint8_t seader_picopass_epurse[PICOPASS_BLOCK_LEN] = + {0xff, 0xff, 0xff, 0xff, 0xe3, 0xff, 0xff, 0xff}; + +static const uint8_t seader_picopass_aia[PICOPASS_BLOCK_LEN] = + {0xFF, 0xff, 0xff, 0xff, 0xFF, 0xFf, 0xff, 0xFF}; + +static const uint8_t seader_picopass_zero[PICOPASS_BLOCK_LEN] = + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; + SeaderCredential* seader_credential_alloc() { SeaderCredential* seader_dev = malloc(sizeof(SeaderCredential)); seader_dev->credential = 0; @@ -112,92 +147,6 @@ bool seader_credential_save_mfc(SeaderCredential* cred, const char* name) { uint8_t uid[4] = {0xDF, 0xC6, 0x9C, 0x05}; uint8_t atqa[2] = {0x00, 0x04}; uint8_t sak = 0x08; - uint8_t manuf_block[16] = { - 0xDF, - 0xC6, - 0x9C, - 0x05, - 0x80, - 0x08, - 0x04, - 0x00, - 0x00, - 0x00, - 0x73, - 0x65, - 0x61, - 0x64, - 0x65, - 0x72}; - uint8_t sector0_trailer[16] = { - 0xa0, - 0xa1, - 0xa2, - 0xa3, - 0xa4, - 0xa5, - 0x78, - 0x77, - 0x88, - 0xc1, - 0x89, - 0xec, - 0xa9, - 0x7f, - 0x8c, - 0x2a}; - uint8_t sector1_trailer[16] = { - 0x48, - 0x49, - 0x44, - 0x20, - 0x49, - 0x53, - 0x78, - 0x77, - 0x88, - 0xaa, - 0x20, - 0x47, - 0x52, - 0x45, - 0x41, - 0x54}; - uint8_t section_trailer[16] = { - 0xff, - 0xff, - 0xff, - 0xff, - 0xff, - 0xff, - 0xff, - 0x07, - 0x80, - 0x69, - 0xff, - 0xff, - 0xff, - 0xff, - 0xff, - 0xff}; - uint8_t mad_block[16] = { - 0x1b, - 0x01, - 0x4d, - 0x48, - 0x00, - 0x00, - 0x00, - 0x00, - 0x00, - 0x00, - 0x00, - 0x00, - 0x00, - 0x00, - 0x00, - 0x00}; - uint8_t empty_block[16] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; uint8_t pacs_block[16] = {0x02, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; bool saved = false; @@ -251,13 +200,19 @@ bool seader_credential_save_mfc(SeaderCredential* cred, const char* name) { switch(i) { case 0: if(!flipper_format_write_hex( - file, furi_string_get_cstr(temp_str), manuf_block, sizeof(manuf_block))) { + file, + furi_string_get_cstr(temp_str), + seader_manuf_block, + sizeof(seader_manuf_block))) { block_saved = false; } break; case 1: if(!flipper_format_write_hex( - file, furi_string_get_cstr(temp_str), mad_block, sizeof(mad_block))) { + file, + furi_string_get_cstr(temp_str), + seader_mad_block, + sizeof(seader_mad_block))) { block_saved = false; } break; @@ -265,8 +220,8 @@ bool seader_credential_save_mfc(SeaderCredential* cred, const char* name) { if(!flipper_format_write_hex( file, furi_string_get_cstr(temp_str), - sector0_trailer, - sizeof(sector0_trailer))) { + seader_sector0_trailer, + sizeof(seader_sector0_trailer))) { block_saved = false; } break; @@ -280,8 +235,8 @@ bool seader_credential_save_mfc(SeaderCredential* cred, const char* name) { if(!flipper_format_write_hex( file, furi_string_get_cstr(temp_str), - sector1_trailer, - sizeof(sector1_trailer))) { + seader_sector1_trailer, + sizeof(seader_sector1_trailer))) { block_saved = false; } break; @@ -303,14 +258,17 @@ bool seader_credential_save_mfc(SeaderCredential* cred, const char* name) { if(!flipper_format_write_hex( file, furi_string_get_cstr(temp_str), - section_trailer, - sizeof(section_trailer))) { + seader_section_trailer, + sizeof(seader_section_trailer))) { block_saved = false; } break; default: if(!flipper_format_write_hex( - file, furi_string_get_cstr(temp_str), empty_block, sizeof(empty_block))) { + file, + furi_string_get_cstr(temp_str), + seader_empty_block, + sizeof(seader_empty_block))) { block_saved = false; } break; @@ -381,12 +339,7 @@ bool seader_credential_save_agnostic(SeaderCredential* cred, const char* name) { } bool seader_credential_save_picopass(SeaderCredential* cred, const char* name) { - uint8_t zero[PICOPASS_BLOCK_LEN] = {0}; - uint8_t fake_csn[PICOPASS_BLOCK_LEN] = {0x7a, 0xf5, 0x31, 0x13, 0xfe, 0xff, 0x12, 0xe0}; - uint8_t cfg[PICOPASS_BLOCK_LEN] = {0x12, 0xff, 0xff, 0xff, 0x7f, 0x1f, 0xff, 0x3c}; - uint8_t epurse[PICOPASS_BLOCK_LEN] = {0xff, 0xff, 0xff, 0xff, 0xe3, 0xff, 0xff, 0xff}; uint8_t debit_key[PICOPASS_BLOCK_LEN] = {0xe3, 0xf3, 0x07, 0x84, 0x4a, 0x0b, 0x62, 0x04}; - uint8_t aia[PICOPASS_BLOCK_LEN] = {0xFF, 0xff, 0xff, 0xff, 0xFF, 0xFf, 0xff, 0xFF}; uint8_t pacs_cfg[PICOPASS_BLOCK_LEN] = {0x03, 0x03, 0x03, 0x03, 0x00, 0x03, 0xe0, 0x14}; bool saved = false; @@ -416,10 +369,13 @@ bool seader_credential_save_picopass(SeaderCredential* cred, const char* name) { furi_string_printf(temp_str, "Block %d", i); switch(i) { case CSN_INDEX: - if(memcmp(cred->diversifier, zero, PICOPASS_BLOCK_LEN) == 0) { + if(memcmp(cred->diversifier, seader_picopass_zero, PICOPASS_BLOCK_LEN) == 0) { // when doing a downgrade from a non-picopass, we need to use a fake csn if(!flipper_format_write_hex( - file, furi_string_get_cstr(temp_str), fake_csn, sizeof(fake_csn))) { + file, + furi_string_get_cstr(temp_str), + seader_picopass_fake_csn, + sizeof(seader_picopass_fake_csn))) { block_saved = false; } } else { @@ -434,7 +390,10 @@ bool seader_credential_save_picopass(SeaderCredential* cred, const char* name) { break; case EPURSE_INDEX: if(!flipper_format_write_hex( - file, furi_string_get_cstr(temp_str), epurse, PICOPASS_BLOCK_LEN)) { + file, + furi_string_get_cstr(temp_str), + seader_picopass_epurse, + PICOPASS_BLOCK_LEN)) { block_saved = false; } break; @@ -446,13 +405,19 @@ bool seader_credential_save_picopass(SeaderCredential* cred, const char* name) { break; case AIA_INDEX: if(!flipper_format_write_hex( - file, furi_string_get_cstr(temp_str), aia, PICOPASS_BLOCK_LEN)) { + file, + furi_string_get_cstr(temp_str), + seader_picopass_aia, + PICOPASS_BLOCK_LEN)) { block_saved = false; } break; case CFG_INDEX: if(!flipper_format_write_hex( - file, furi_string_get_cstr(temp_str), cfg, sizeof(cfg))) { + file, + furi_string_get_cstr(temp_str), + seader_picopass_cfg, + sizeof(seader_picopass_cfg))) { block_saved = false; } break; @@ -492,14 +457,20 @@ bool seader_credential_save_picopass(SeaderCredential* cred, const char* name) { } } else { if(!flipper_format_write_hex( - file, furi_string_get_cstr(temp_str), zero, sizeof(zero))) { + file, + furi_string_get_cstr(temp_str), + seader_picopass_zero, + sizeof(seader_picopass_zero))) { block_saved = false; } } break; default: if(!flipper_format_write_hex( - file, furi_string_get_cstr(temp_str), zero, sizeof(zero))) { + file, + furi_string_get_cstr(temp_str), + seader_picopass_zero, + sizeof(seader_picopass_zero))) { block_saved = false; } break; diff --git a/seader_i.h b/seader_i.h index 52fb739..d6305b8 100644 --- a/seader_i.h +++ b/seader_i.h @@ -111,6 +111,12 @@ struct Seader { char text_store[SEADER_TEXT_STORE_SIZE + 1]; FuriString* text_box_store; + // Reusable strings to optimize scene string allocations + FuriString* temp_string1; + FuriString* temp_string2; + FuriString* temp_string3; + FuriString* temp_string4; + // Common Views Submenu* submenu; Popup* popup;