From b451fa91def8a4020986e58da4675ad8c51f8774 Mon Sep 17 00:00:00 2001 From: MX <10697207+xMasterX@users.noreply.github.com> Date: Mon, 10 Jul 2023 16:52:12 +0300 Subject: [PATCH] Update wifi marauder app --- .../wifi_marauder_scene_console_output.c | 5 + .../scenes/wifi_marauder_scene_flasher.c | 172 ++++++++++++++++-- .../scenes/wifi_marauder_scene_start.c | 1 - .../wifi_marauder_app.c | 1 + .../wifi_marauder_app.h | 2 +- .../wifi_marauder_app_i.h | 17 ++ .../wifi_marauder_custom_event.h | 3 +- .../wifi_marauder_flasher.c | 113 ++++++++---- .../wifi_marauder_flasher.h | 7 + 9 files changed, 264 insertions(+), 57 deletions(-) diff --git a/applications/external/wifi_marauder_companion/scenes/wifi_marauder_scene_console_output.c b/applications/external/wifi_marauder_companion/scenes/wifi_marauder_scene_console_output.c index 236fe4eff..9e1719d08 100644 --- a/applications/external/wifi_marauder_companion/scenes/wifi_marauder_scene_console_output.c +++ b/applications/external/wifi_marauder_companion/scenes/wifi_marauder_scene_console_output.c @@ -182,6 +182,11 @@ bool wifi_marauder_scene_console_output_on_event(void* context, SceneManagerEven consumed = true; } else if(event.type == SceneManagerEventTypeTick) { consumed = true; + } else { + if(app->flash_worker_busy) { + // ignore button presses while flashing + consumed = true; + } } return consumed; diff --git a/applications/external/wifi_marauder_companion/scenes/wifi_marauder_scene_flasher.c b/applications/external/wifi_marauder_companion/scenes/wifi_marauder_scene_flasher.c index 79682879d..8fe91bbba 100644 --- a/applications/external/wifi_marauder_companion/scenes/wifi_marauder_scene_flasher.c +++ b/applications/external/wifi_marauder_companion/scenes/wifi_marauder_scene_flasher.c @@ -1,9 +1,14 @@ #include "../wifi_marauder_app_i.h" +#include "../wifi_marauder_flasher.h" enum SubmenuIndex { + SubmenuIndexS3Mode, SubmenuIndexBoot, SubmenuIndexPart, + SubmenuIndexNvs, + SubmenuIndexBootApp0, SubmenuIndexApp, + SubmenuIndexCustom, SubmenuIndexFlash, }; @@ -20,16 +25,30 @@ static void wifi_marauder_scene_flasher_callback(void* context, uint32_t index) // TODO refactor switch(index) { + case SubmenuIndexS3Mode: + // toggle S3 mode + app->selected_flash_options[SelectedFlashS3Mode] = !app->selected_flash_options[SelectedFlashS3Mode]; + view_dispatcher_send_custom_event(app->view_dispatcher, WifiMarauderEventRefreshSubmenu); + break; case SubmenuIndexBoot: - if(dialog_file_browser_show( - app->dialogs, selected_filepath, predefined_filepath, &browser_options)) { - strncpy( - app->bin_file_path_boot, - furi_string_get_cstr(selected_filepath), - sizeof(app->bin_file_path_boot)); + app->selected_flash_options[SelectedFlashBoot] = !app->selected_flash_options[SelectedFlashBoot]; + if (app->selected_flash_options[SelectedFlashBoot]) { + if(dialog_file_browser_show( + app->dialogs, selected_filepath, predefined_filepath, &browser_options)) { + strncpy( + app->bin_file_path_boot, + furi_string_get_cstr(selected_filepath), + sizeof(app->bin_file_path_boot)); + } } + if (app->bin_file_path_boot[0] == '\0') { + // if user didn't select a file, leave unselected + app->selected_flash_options[SelectedFlashBoot] = false; + } + view_dispatcher_send_custom_event(app->view_dispatcher, WifiMarauderEventRefreshSubmenu); break; case SubmenuIndexPart: + app->selected_flash_options[SelectedFlashPart] = !app->selected_flash_options[SelectedFlashPart]; if(dialog_file_browser_show( app->dialogs, selected_filepath, predefined_filepath, &browser_options)) { strncpy( @@ -37,8 +56,44 @@ static void wifi_marauder_scene_flasher_callback(void* context, uint32_t index) furi_string_get_cstr(selected_filepath), sizeof(app->bin_file_path_part)); } + if (app->bin_file_path_part[0] == '\0') { + // if user didn't select a file, leave unselected + app->selected_flash_options[SelectedFlashPart] = false; + } + view_dispatcher_send_custom_event(app->view_dispatcher, WifiMarauderEventRefreshSubmenu); + break; + case SubmenuIndexNvs: + app->selected_flash_options[SelectedFlashNvs] = !app->selected_flash_options[SelectedFlashNvs]; + if(dialog_file_browser_show( + app->dialogs, selected_filepath, predefined_filepath, &browser_options)) { + strncpy( + app->bin_file_path_nvs, + furi_string_get_cstr(selected_filepath), + sizeof(app->bin_file_path_nvs)); + } + if (app->bin_file_path_nvs[0] == '\0') { + // if user didn't select a file, leave unselected + app->selected_flash_options[SelectedFlashNvs] = false; + } + view_dispatcher_send_custom_event(app->view_dispatcher, WifiMarauderEventRefreshSubmenu); + break; + case SubmenuIndexBootApp0: + app->selected_flash_options[SelectedFlashBootApp0] = !app->selected_flash_options[SelectedFlashBootApp0]; + if(dialog_file_browser_show( + app->dialogs, selected_filepath, predefined_filepath, &browser_options)) { + strncpy( + app->bin_file_path_boot_app0, + furi_string_get_cstr(selected_filepath), + sizeof(app->bin_file_path_boot_app0)); + } + if (app->bin_file_path_boot_app0[0] == '\0') { + // if user didn't select a file, leave unselected + app->selected_flash_options[SelectedFlashBootApp0] = false; + } + view_dispatcher_send_custom_event(app->view_dispatcher, WifiMarauderEventRefreshSubmenu); break; case SubmenuIndexApp: + app->selected_flash_options[SelectedFlashApp] = !app->selected_flash_options[SelectedFlashApp]; if(dialog_file_browser_show( app->dialogs, selected_filepath, predefined_filepath, &browser_options)) { strncpy( @@ -46,10 +101,39 @@ static void wifi_marauder_scene_flasher_callback(void* context, uint32_t index) furi_string_get_cstr(selected_filepath), sizeof(app->bin_file_path_app)); } + if (app->bin_file_path_app[0] == '\0') { + // if user didn't select a file, leave unselected + app->selected_flash_options[SelectedFlashApp] = false; + } + view_dispatcher_send_custom_event(app->view_dispatcher, WifiMarauderEventRefreshSubmenu); + break; + case SubmenuIndexCustom: + app->selected_flash_options[SelectedFlashCustom] = !app->selected_flash_options[SelectedFlashCustom]; + if(dialog_file_browser_show( + app->dialogs, selected_filepath, predefined_filepath, &browser_options)) { + strncpy( + app->bin_file_path_custom, + furi_string_get_cstr(selected_filepath), + sizeof(app->bin_file_path_custom)); + } + if (app->bin_file_path_custom[0] == '\0') { + // if user didn't select a file, leave unselected + app->selected_flash_options[SelectedFlashCustom] = false; + } + view_dispatcher_send_custom_event(app->view_dispatcher, WifiMarauderEventRefreshSubmenu); break; case SubmenuIndexFlash: - // TODO error checking - scene_manager_next_scene(app->scene_manager, WifiMarauderSceneConsoleOutput); + // count how many options are selected + app->num_selected_flash_options = 0; + for (bool* option = &app->selected_flash_options[SelectedFlashBoot]; option < &app->selected_flash_options[NUM_FLASH_OPTIONS]; ++option) { + if (*option) { + ++app->num_selected_flash_options; + } + } + if (app->num_selected_flash_options) { + // only start next scene if at least one option is selected + scene_manager_next_scene(app->scene_manager, WifiMarauderSceneConsoleOutput); + } break; } @@ -57,31 +141,83 @@ static void wifi_marauder_scene_flasher_callback(void* context, uint32_t index) furi_string_free(predefined_filepath); } -void wifi_marauder_scene_flasher_on_enter(void* context) { - WifiMarauderApp* app = context; - +#define STR_SELECT "[x]" +#define STR_UNSELECT "[ ]" +#define STR_BOOT "Bootloader (" TOSTRING(ESP_ADDR_BOOT) ")" +#define STR_BOOT_S3 "Bootloader (" TOSTRING(ESP_ADDR_BOOT_S3) ")" +#define STR_PART "Part Table (" TOSTRING(ESP_ADDR_PART) ")" +#define STR_NVS "NVS (" TOSTRING(ESP_ADDR_NVS) ")" +#define STR_BOOT_APP0 "boot_app0 (" TOSTRING(ESP_ADDR_BOOT_APP0) ")" +#define STR_APP "Firmware (" TOSTRING(ESP_ADDR_APP) ")" +#define STR_CUSTOM "Custom" +#define STR_FLASH_S3 "[>] FLASH (ESP32-S3)" +#define STR_FLASH "[>] FLASH" +static void _refresh_submenu(WifiMarauderApp* app) { Submenu* submenu = app->submenu; + submenu_reset(app->submenu); + submenu_set_header(submenu, "Browse for files to flash"); submenu_add_item( - submenu, "Bootloader", SubmenuIndexBoot, wifi_marauder_scene_flasher_callback, app); + submenu, app->selected_flash_options[SelectedFlashS3Mode] ? "[x] Using ESP32-S3" : "[ ] Check if using S3", SubmenuIndexS3Mode, wifi_marauder_scene_flasher_callback, app); + const char* strSelectBootloader = STR_UNSELECT " " STR_BOOT; + if (app->selected_flash_options[SelectedFlashS3Mode]) { + if (app->selected_flash_options[SelectedFlashBoot]) { + strSelectBootloader = STR_SELECT " " STR_BOOT_S3; + } else { + strSelectBootloader = STR_UNSELECT " " STR_BOOT_S3; + } + } else { + if (app->selected_flash_options[SelectedFlashBoot]) { + strSelectBootloader = STR_SELECT " " STR_BOOT; + } else { + strSelectBootloader = STR_UNSELECT " " STR_BOOT; + } + } submenu_add_item( - submenu, "Partition Table", SubmenuIndexPart, wifi_marauder_scene_flasher_callback, app); + submenu, strSelectBootloader, SubmenuIndexBoot, wifi_marauder_scene_flasher_callback, app); submenu_add_item( - submenu, "Application", SubmenuIndexApp, wifi_marauder_scene_flasher_callback, app); + submenu, app->selected_flash_options[SelectedFlashPart] ? STR_SELECT " " STR_PART : STR_UNSELECT " " STR_PART, SubmenuIndexPart, wifi_marauder_scene_flasher_callback, app); submenu_add_item( - submenu, "[>] FLASH", SubmenuIndexFlash, wifi_marauder_scene_flasher_callback, app); + submenu, app->selected_flash_options[SelectedFlashNvs] ? STR_SELECT " " STR_NVS : STR_UNSELECT " " STR_NVS, SubmenuIndexNvs, wifi_marauder_scene_flasher_callback, app); + submenu_add_item( + submenu, app->selected_flash_options[SelectedFlashBootApp0] ? STR_SELECT " " STR_BOOT_APP0 : STR_UNSELECT " " STR_BOOT_APP0, SubmenuIndexBootApp0, wifi_marauder_scene_flasher_callback, app); + submenu_add_item( + submenu, app->selected_flash_options[SelectedFlashApp] ? STR_SELECT " " STR_APP : STR_UNSELECT " " STR_APP, SubmenuIndexApp, wifi_marauder_scene_flasher_callback, app); + // TODO: custom addr + //submenu_add_item( + // submenu, app->selected_flash_options[SelectedFlashCustom] ? STR_SELECT " " STR_CUSTOM : STR_UNSELECT " " STR_CUSTOM, SubmenuIndexCustom, wifi_marauder_scene_flasher_callback, app); + submenu_add_item( + submenu, app->selected_flash_options[SelectedFlashS3Mode] ? STR_FLASH_S3 : STR_FLASH, SubmenuIndexFlash, wifi_marauder_scene_flasher_callback, app); submenu_set_selected_item( submenu, scene_manager_get_scene_state(app->scene_manager, WifiMarauderSceneFlasher)); view_dispatcher_switch_to_view(app->view_dispatcher, WifiMarauderAppViewSubmenu); } +void wifi_marauder_scene_flasher_on_enter(void* context) { + WifiMarauderApp* app = context; + + memset(app->selected_flash_options, 0, sizeof(app->selected_flash_options)); + app->bin_file_path_boot[0] = '\0'; + app->bin_file_path_part[0] = '\0'; + app->bin_file_path_nvs[0] = '\0'; + app->bin_file_path_boot_app0[0] = '\0'; + app->bin_file_path_app[0] = '\0'; + app->bin_file_path_custom[0] = '\0'; + + _refresh_submenu(app); +} + bool wifi_marauder_scene_flasher_on_event(void* context, SceneManagerEvent event) { - //WifiMarauderApp* app = context; - UNUSED(context); - UNUSED(event); + WifiMarauderApp* app = context; bool consumed = false; + if (event.type == SceneManagerEventTypeCustom) { + if (event.event == WifiMarauderEventRefreshSubmenu) { + _refresh_submenu(app); + consumed = true; + } + } return consumed; } diff --git a/applications/external/wifi_marauder_companion/scenes/wifi_marauder_scene_start.c b/applications/external/wifi_marauder_companion/scenes/wifi_marauder_scene_start.c index 06dcd7fd7..97b26fc7f 100644 --- a/applications/external/wifi_marauder_companion/scenes/wifi_marauder_scene_start.c +++ b/applications/external/wifi_marauder_companion/scenes/wifi_marauder_scene_start.c @@ -243,7 +243,6 @@ void wifi_marauder_scene_start_on_enter(void* context) { } bool wifi_marauder_scene_start_on_event(void* context, SceneManagerEvent event) { - UNUSED(context); WifiMarauderApp* app = context; bool consumed = false; diff --git a/applications/external/wifi_marauder_companion/wifi_marauder_app.c b/applications/external/wifi_marauder_companion/wifi_marauder_app.c index 91fcb2372..c27a941ad 100644 --- a/applications/external/wifi_marauder_companion/wifi_marauder_app.c +++ b/applications/external/wifi_marauder_companion/wifi_marauder_app.c @@ -87,6 +87,7 @@ WifiMarauderApp* wifi_marauder_app_alloc() { app->view_dispatcher, WifiMarauderAppViewSubmenu, submenu_get_view(app->submenu)); app->flash_mode = false; + app->flash_worker_busy = false; scene_manager_next_scene(app->scene_manager, WifiMarauderSceneStart); diff --git a/applications/external/wifi_marauder_companion/wifi_marauder_app.h b/applications/external/wifi_marauder_companion/wifi_marauder_app.h index b6664fdab..187a0aaaa 100644 --- a/applications/external/wifi_marauder_companion/wifi_marauder_app.h +++ b/applications/external/wifi_marauder_companion/wifi_marauder_app.h @@ -4,7 +4,7 @@ extern "C" { #endif -#define WIFI_MARAUDER_APP_VERSION "v0.5.0" +#define WIFI_MARAUDER_APP_VERSION "v0.5.1" typedef struct WifiMarauderApp WifiMarauderApp; diff --git a/applications/external/wifi_marauder_companion/wifi_marauder_app_i.h b/applications/external/wifi_marauder_companion/wifi_marauder_app_i.h index cd248648a..a5c4818f0 100644 --- a/applications/external/wifi_marauder_companion/wifi_marauder_app_i.h +++ b/applications/external/wifi_marauder_companion/wifi_marauder_app_i.h @@ -48,6 +48,17 @@ typedef enum WifiMarauderUserInputType { WifiMarauderUserInputTypeFileName } WifiMarauderUserInputType; +typedef enum SelectedFlashOptions { + SelectedFlashS3Mode, + SelectedFlashBoot, + SelectedFlashPart, + SelectedFlashNvs, + SelectedFlashBootApp0, + SelectedFlashApp, + SelectedFlashCustom, + NUM_FLASH_OPTIONS +} SelectedFlashOptions; + struct WifiMarauderApp { Gui* gui; ViewDispatcher* view_dispatcher; @@ -115,10 +126,16 @@ struct WifiMarauderApp { char special_case_input_dst_addr[20]; // For flashing - TODO: put into its own struct? + bool selected_flash_options[NUM_FLASH_OPTIONS]; + int num_selected_flash_options; char bin_file_path_boot[100]; char bin_file_path_part[100]; + char bin_file_path_nvs[100]; + char bin_file_path_boot_app0[100]; char bin_file_path_app[100]; + char bin_file_path_custom[100]; FuriThread* flash_worker; + bool flash_worker_busy; bool flash_mode; }; diff --git a/applications/external/wifi_marauder_companion/wifi_marauder_custom_event.h b/applications/external/wifi_marauder_companion/wifi_marauder_custom_event.h index 8f020b754..ff03f31dd 100644 --- a/applications/external/wifi_marauder_companion/wifi_marauder_custom_event.h +++ b/applications/external/wifi_marauder_companion/wifi_marauder_custom_event.h @@ -10,5 +10,6 @@ typedef enum { WifiMarauderEventStartLogViewer, WifiMarauderEventStartScriptSelect, WifiMarauderEventStartSniffPmkidOptions, - WifiMarauderEventStartFlasher + WifiMarauderEventStartFlasher, + WifiMarauderEventRefreshSubmenu } WifiMarauderCustomEvent; diff --git a/applications/external/wifi_marauder_companion/wifi_marauder_flasher.c b/applications/external/wifi_marauder_companion/wifi_marauder_flasher.c index 8d30c1539..63820be0b 100644 --- a/applications/external/wifi_marauder_companion/wifi_marauder_flasher.c +++ b/applications/external/wifi_marauder_companion/wifi_marauder_flasher.c @@ -18,6 +18,8 @@ static esp_loader_error_t _flash_file(WifiMarauderApp* app, char* filepath, uint static uint8_t payload[1024]; File* bin_file = storage_file_alloc(app->storage); + char user_msg[256]; + // open file if(!storage_file_open(bin_file, filepath, FSAM_READ, FSOM_OPEN_EXISTING)) { storage_file_close(bin_file); @@ -28,48 +30,34 @@ static esp_loader_error_t _flash_file(WifiMarauderApp* app, char* filepath, uint uint64_t size = storage_file_size(bin_file); - /* - // TODO packet drops with higher BR? - err = esp_loader_change_transmission_rate(230400); - if (err != ESP_LOADER_SUCCESS) { - char err_msg[256]; - snprintf( - err_msg, - sizeof(err_msg), - "Cannot change transmission rate. Error: %u\n", - err); - storage_file_close(bin_file); - storage_file_free(bin_file); - loader_port_debug_print(err_msg); - return; - } - - furi_hal_uart_set_br(FuriHalUartIdUSART1, 230400); - // TODO remember to change BR back! - */ - loader_port_debug_print("Erasing flash...this may take a while\n"); err = esp_loader_flash_start(addr, size, sizeof(payload)); if(err != ESP_LOADER_SUCCESS) { storage_file_close(bin_file); storage_file_free(bin_file); - char err_msg[256]; - snprintf(err_msg, sizeof(err_msg), "Erasing flash failed with error %d\n", err); - loader_port_debug_print(err_msg); + snprintf(user_msg, sizeof(user_msg), "Erasing flash failed with error %d\n", err); + loader_port_debug_print(user_msg); return err; } loader_port_debug_print("Start programming\n"); + uint64_t last_updated = size; while(size > 0) { + if ((last_updated - size) > 50000) { + // inform user every 50k bytes + // TODO: draw a progress bar next update + snprintf(user_msg, sizeof(user_msg), "%llu bytes left.\n", size); + loader_port_debug_print(user_msg); + last_updated = size; + } size_t to_read = MIN(size, sizeof(payload)); uint16_t num_bytes = storage_file_read(bin_file, payload, to_read); err = esp_loader_flash_write(payload, num_bytes); if(err != ESP_LOADER_SUCCESS) { - char err_msg[256]; - snprintf(err_msg, sizeof(err_msg), "Packet could not be written! Error: %u\n", err); + snprintf(user_msg, sizeof(user_msg), "Packet could not be written! Error: %u\n", err); storage_file_close(bin_file); storage_file_free(bin_file); - loader_port_debug_print(err_msg); + loader_port_debug_print(user_msg); return err; } @@ -86,10 +74,49 @@ static esp_loader_error_t _flash_file(WifiMarauderApp* app, char* filepath, uint return ESP_LOADER_SUCCESS; } +typedef struct { + SelectedFlashOptions selected; + const char* description; + char* path; + uint32_t addr; +} FlashItem; + +static void _flash_all_files(WifiMarauderApp* app) { + esp_loader_error_t err; + const int num_steps = app->num_selected_flash_options; + + #define NUM_FLASH_ITEMS 6 + FlashItem items[NUM_FLASH_ITEMS] = { + { SelectedFlashBoot, "bootloader", app->bin_file_path_boot, app->selected_flash_options[SelectedFlashS3Mode] ? ESP_ADDR_BOOT_S3 : ESP_ADDR_BOOT }, + { SelectedFlashPart, "partition table", app->bin_file_path_part, ESP_ADDR_PART }, + { SelectedFlashNvs, "NVS", app->bin_file_path_nvs, ESP_ADDR_NVS }, + { SelectedFlashBootApp0, "boot_app0", app->bin_file_path_boot_app0, ESP_ADDR_BOOT_APP0 }, + { SelectedFlashApp, "firmware", app->bin_file_path_app, ESP_ADDR_APP }, + { SelectedFlashCustom, "custom data", app->bin_file_path_custom, 0x0 }, + /* if you add more entries, update NUM_FLASH_ITEMS above! */ + }; + + char user_msg[256]; + + int current_step = 1; + for (FlashItem* item = &items[0]; item < &items[NUM_FLASH_ITEMS]; ++item) { + if(app->selected_flash_options[item->selected]) { + snprintf(user_msg, sizeof(user_msg), "Flashing %s (%d/%d) to address 0x%lx\n", item->description, current_step++, num_steps, item->addr); + loader_port_debug_print(user_msg); + err = _flash_file(app, item->path, item->addr); + if(err) { + break; + } + } + } +} + static int32_t wifi_marauder_flash_bin(void* context) { WifiMarauderApp* app = (void*)context; esp_loader_error_t err; + app->flash_worker_busy = true; + // alloc global objects flash_rx_stream = furi_stream_buffer_alloc(RX_BUF_SIZE, 1); timer = furi_timer_alloc(_timer_callback, FuriTimerTypePeriodic, app); @@ -103,22 +130,36 @@ static int32_t wifi_marauder_flash_bin(void* context) { loader_port_debug_print(err_msg); } + #if 0 // still getting packet drops with this + // higher BR + if(!err) { + loader_port_debug_print("Increasing speed for faster flash\n"); + err = esp_loader_change_transmission_rate(230400); + if (err != ESP_LOADER_SUCCESS) { + char err_msg[256]; + snprintf( + err_msg, + sizeof(err_msg), + "Cannot change transmission rate. Error: %u\n", + err); + loader_port_debug_print(err_msg); + } + furi_hal_uart_set_br(FuriHalUartIdUSART1, 230400); + } + #endif + if(!err) { loader_port_debug_print("Connected\n"); - loader_port_debug_print("Flashing bootloader (1/3)\n"); - err = _flash_file(app, app->bin_file_path_boot, 0x1000); - } - if(!err) { - loader_port_debug_print("Flashing partition table (2/3)\n"); - err = _flash_file(app, app->bin_file_path_part, 0x8000); - } - if(!err) { - loader_port_debug_print("Flashing app (3/3)\n"); - err = _flash_file(app, app->bin_file_path_app, 0x10000); + _flash_all_files(app); + #if 0 + loader_port_debug_print("Restoring transmission rate\n"); + furi_hal_uart_set_br(FuriHalUartIdUSART1, 115200); + #endif loader_port_debug_print("Done flashing. Please reset the board manually.\n"); } // done + app->flash_worker_busy = false; // cleanup furi_stream_buffer_free(flash_rx_stream); diff --git a/applications/external/wifi_marauder_companion/wifi_marauder_flasher.h b/applications/external/wifi_marauder_companion/wifi_marauder_flasher.h index 796e258e5..3688ed09f 100644 --- a/applications/external/wifi_marauder_companion/wifi_marauder_flasher.h +++ b/applications/external/wifi_marauder_companion/wifi_marauder_flasher.h @@ -5,6 +5,13 @@ #define SERIAL_FLASHER_INTERFACE_UART /* TODO why is application.fam not passing this via cdefines */ #include "esp_loader_io.h" +#define ESP_ADDR_BOOT_S3 0x0 +#define ESP_ADDR_BOOT 0x1000 +#define ESP_ADDR_PART 0x8000 +#define ESP_ADDR_NVS 0x9000 +#define ESP_ADDR_BOOT_APP0 0xE000 +#define ESP_ADDR_APP 0x10000 + void wifi_marauder_flash_start_thread(WifiMarauderApp* app); void wifi_marauder_flash_stop_thread(WifiMarauderApp* app); void wifi_marauder_flash_handle_rx_data_cb(uint8_t* buf, size_t len, void* context); \ No newline at end of file