Ver código fonte

ESP32 flasher: Add other flash options, support ESP32-S3, lockout exit button when flashing

0xchocolate 2 anos atrás
pai
commit
a2a5aa5971

+ 5 - 0
scenes/wifi_marauder_scene_console_output.c

@@ -182,6 +182,11 @@ bool wifi_marauder_scene_console_output_on_event(void* context, SceneManagerEven
         consumed = true;
         consumed = true;
     } else if(event.type == SceneManagerEventTypeTick) {
     } else if(event.type == SceneManagerEventTypeTick) {
         consumed = true;
         consumed = true;
+    } else {
+        if(app->flash_worker_busy) {
+            // ignore button presses while flashing
+            consumed = true;
+        }
     }
     }
 
 
     return consumed;
     return consumed;

+ 153 - 17
scenes/wifi_marauder_scene_flasher.c

@@ -1,9 +1,14 @@
 #include "../wifi_marauder_app_i.h"
 #include "../wifi_marauder_app_i.h"
+#include "../wifi_marauder_flasher.h"
 
 
 enum SubmenuIndex {
 enum SubmenuIndex {
+    SubmenuIndexS3Mode,
     SubmenuIndexBoot,
     SubmenuIndexBoot,
     SubmenuIndexPart,
     SubmenuIndexPart,
+    SubmenuIndexNvs,
+    SubmenuIndexBootApp0,
     SubmenuIndexApp,
     SubmenuIndexApp,
+    SubmenuIndexCustom,
     SubmenuIndexFlash,
     SubmenuIndexFlash,
 };
 };
 
 
@@ -20,25 +25,75 @@ static void wifi_marauder_scene_flasher_callback(void* context, uint32_t index)
 
 
     // TODO refactor
     // TODO refactor
     switch(index) {
     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:
     case SubmenuIndexBoot:
+        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(
         if(dialog_file_browser_show(
                app->dialogs, selected_filepath, predefined_filepath, &browser_options)) {
                app->dialogs, selected_filepath, predefined_filepath, &browser_options)) {
             strncpy(
             strncpy(
-                app->bin_file_path_boot,
+                app->bin_file_path_part,
                 furi_string_get_cstr(selected_filepath),
                 furi_string_get_cstr(selected_filepath),
-                sizeof(app->bin_file_path_boot));
+                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;
         break;
-    case SubmenuIndexPart:
+    case SubmenuIndexNvs:
+        app->selected_flash_options[SelectedFlashNvs] = !app->selected_flash_options[SelectedFlashNvs];
         if(dialog_file_browser_show(
         if(dialog_file_browser_show(
                app->dialogs, selected_filepath, predefined_filepath, &browser_options)) {
                app->dialogs, selected_filepath, predefined_filepath, &browser_options)) {
             strncpy(
             strncpy(
-                app->bin_file_path_part,
+                app->bin_file_path_nvs,
                 furi_string_get_cstr(selected_filepath),
                 furi_string_get_cstr(selected_filepath),
-                sizeof(app->bin_file_path_part));
+                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;
         break;
     case SubmenuIndexApp:
     case SubmenuIndexApp:
+        app->selected_flash_options[SelectedFlashApp] = !app->selected_flash_options[SelectedFlashApp];
         if(dialog_file_browser_show(
         if(dialog_file_browser_show(
                app->dialogs, selected_filepath, predefined_filepath, &browser_options)) {
                app->dialogs, selected_filepath, predefined_filepath, &browser_options)) {
             strncpy(
             strncpy(
@@ -46,10 +101,39 @@ static void wifi_marauder_scene_flasher_callback(void* context, uint32_t index)
                 furi_string_get_cstr(selected_filepath),
                 furi_string_get_cstr(selected_filepath),
                 sizeof(app->bin_file_path_app));
                 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;
         break;
     case SubmenuIndexFlash:
     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;
         break;
     }
     }
 
 
@@ -57,31 +141,83 @@ static void wifi_marauder_scene_flasher_callback(void* context, uint32_t index)
     furi_string_free(predefined_filepath);
     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* submenu = app->submenu;
 
 
+    submenu_reset(app->submenu);
+
     submenu_set_header(submenu, "Browse for files to flash");
     submenu_set_header(submenu, "Browse for files to flash");
     submenu_add_item(
     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, strSelectBootloader, SubmenuIndexBoot, wifi_marauder_scene_flasher_callback, app);
+    submenu_add_item(
+        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, app->selected_flash_options[SelectedFlashNvs] ? STR_SELECT " " STR_NVS : STR_UNSELECT " " STR_NVS, SubmenuIndexNvs, wifi_marauder_scene_flasher_callback, app);
     submenu_add_item(
     submenu_add_item(
-        submenu, "Partition Table", SubmenuIndexPart, wifi_marauder_scene_flasher_callback, app);
+        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_add_item(
-        submenu, "Application", SubmenuIndexApp, wifi_marauder_scene_flasher_callback, app);
+        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_add_item(
-        submenu, "[>] FLASH", SubmenuIndexFlash, wifi_marauder_scene_flasher_callback, app);
+        submenu, app->selected_flash_options[SelectedFlashS3Mode] ? STR_FLASH_S3 : STR_FLASH, SubmenuIndexFlash, wifi_marauder_scene_flasher_callback, app);
 
 
     submenu_set_selected_item(
     submenu_set_selected_item(
         submenu, scene_manager_get_scene_state(app->scene_manager, WifiMarauderSceneFlasher));
         submenu, scene_manager_get_scene_state(app->scene_manager, WifiMarauderSceneFlasher));
     view_dispatcher_switch_to_view(app->view_dispatcher, WifiMarauderAppViewSubmenu);
     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) {
 bool wifi_marauder_scene_flasher_on_event(void* context, SceneManagerEvent event) {
-    //WifiMarauderApp* app = context;
-    UNUSED(context);
-    UNUSED(event);
+    WifiMarauderApp* app = context;
     bool consumed = false;
     bool consumed = false;
+    if (event.type == SceneManagerEventTypeCustom) {
+        if (event.event == WifiMarauderEventRefreshSubmenu) {
+            _refresh_submenu(app);
+            consumed = true;
+        }
+    }
 
 
     return consumed;
     return consumed;
 }
 }

+ 0 - 1
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) {
 bool wifi_marauder_scene_start_on_event(void* context, SceneManagerEvent event) {
-    UNUSED(context);
     WifiMarauderApp* app = context;
     WifiMarauderApp* app = context;
     bool consumed = false;
     bool consumed = false;
 
 

+ 1 - 0
wifi_marauder_app.c

@@ -87,6 +87,7 @@ WifiMarauderApp* wifi_marauder_app_alloc() {
         app->view_dispatcher, WifiMarauderAppViewSubmenu, submenu_get_view(app->submenu));
         app->view_dispatcher, WifiMarauderAppViewSubmenu, submenu_get_view(app->submenu));
 
 
     app->flash_mode = false;
     app->flash_mode = false;
+    app->flash_worker_busy = false;
 
 
     scene_manager_next_scene(app->scene_manager, WifiMarauderSceneStart);
     scene_manager_next_scene(app->scene_manager, WifiMarauderSceneStart);
 
 

+ 1 - 1
wifi_marauder_app.h

@@ -4,7 +4,7 @@
 extern "C" {
 extern "C" {
 #endif
 #endif
 
 
-#define WIFI_MARAUDER_APP_VERSION "v0.5.0"
+#define WIFI_MARAUDER_APP_VERSION "v0.5.1"
 
 
 typedef struct WifiMarauderApp WifiMarauderApp;
 typedef struct WifiMarauderApp WifiMarauderApp;
 
 

+ 17 - 0
wifi_marauder_app_i.h

@@ -48,6 +48,17 @@ typedef enum WifiMarauderUserInputType {
     WifiMarauderUserInputTypeFileName
     WifiMarauderUserInputTypeFileName
 } WifiMarauderUserInputType;
 } WifiMarauderUserInputType;
 
 
+typedef enum SelectedFlashOptions {
+    SelectedFlashS3Mode,
+    SelectedFlashBoot,
+    SelectedFlashPart,
+    SelectedFlashNvs,
+    SelectedFlashBootApp0,
+    SelectedFlashApp,
+    SelectedFlashCustom,
+    NUM_FLASH_OPTIONS
+} SelectedFlashOptions;
+
 struct WifiMarauderApp {
 struct WifiMarauderApp {
     Gui* gui;
     Gui* gui;
     ViewDispatcher* view_dispatcher;
     ViewDispatcher* view_dispatcher;
@@ -115,10 +126,16 @@ struct WifiMarauderApp {
     char special_case_input_dst_addr[20];
     char special_case_input_dst_addr[20];
 
 
     // For flashing - TODO: put into its own struct?
     // 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_boot[100];
     char bin_file_path_part[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_app[100];
+    char bin_file_path_custom[100];
     FuriThread* flash_worker;
     FuriThread* flash_worker;
+    bool flash_worker_busy;
     bool flash_mode;
     bool flash_mode;
 };
 };
 
 

+ 2 - 1
wifi_marauder_custom_event.h

@@ -10,5 +10,6 @@ typedef enum {
     WifiMarauderEventStartLogViewer,
     WifiMarauderEventStartLogViewer,
     WifiMarauderEventStartScriptSelect,
     WifiMarauderEventStartScriptSelect,
     WifiMarauderEventStartSniffPmkidOptions,
     WifiMarauderEventStartSniffPmkidOptions,
-    WifiMarauderEventStartFlasher
+    WifiMarauderEventStartFlasher,
+    WifiMarauderEventRefreshSubmenu
 } WifiMarauderCustomEvent;
 } WifiMarauderCustomEvent;

+ 76 - 35
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];
     static uint8_t payload[1024];
     File* bin_file = storage_file_alloc(app->storage);
     File* bin_file = storage_file_alloc(app->storage);
 
 
+    char user_msg[256];
+
     // open file
     // open file
     if(!storage_file_open(bin_file, filepath, FSAM_READ, FSOM_OPEN_EXISTING)) {
     if(!storage_file_open(bin_file, filepath, FSAM_READ, FSOM_OPEN_EXISTING)) {
         storage_file_close(bin_file);
         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);
     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");
     loader_port_debug_print("Erasing flash...this may take a while\n");
     err = esp_loader_flash_start(addr, size, sizeof(payload));
     err = esp_loader_flash_start(addr, size, sizeof(payload));
     if(err != ESP_LOADER_SUCCESS) {
     if(err != ESP_LOADER_SUCCESS) {
         storage_file_close(bin_file);
         storage_file_close(bin_file);
         storage_file_free(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;
         return err;
     }
     }
 
 
     loader_port_debug_print("Start programming\n");
     loader_port_debug_print("Start programming\n");
+    uint64_t last_updated = size;
     while(size > 0) {
     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));
         size_t to_read = MIN(size, sizeof(payload));
         uint16_t num_bytes = storage_file_read(bin_file, payload, to_read);
         uint16_t num_bytes = storage_file_read(bin_file, payload, to_read);
         err = esp_loader_flash_write(payload, num_bytes);
         err = esp_loader_flash_write(payload, num_bytes);
         if(err != ESP_LOADER_SUCCESS) {
         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_close(bin_file);
             storage_file_free(bin_file);
             storage_file_free(bin_file);
-            loader_port_debug_print(err_msg);
+            loader_port_debug_print(user_msg);
             return err;
             return err;
         }
         }
 
 
@@ -86,10 +74,49 @@ static esp_loader_error_t _flash_file(WifiMarauderApp* app, char* filepath, uint
     return ESP_LOADER_SUCCESS;
     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) {
 static int32_t wifi_marauder_flash_bin(void* context) {
     WifiMarauderApp* app = (void*)context;
     WifiMarauderApp* app = (void*)context;
     esp_loader_error_t err;
     esp_loader_error_t err;
 
 
+    app->flash_worker_busy = true;
+
     // alloc global objects
     // alloc global objects
     flash_rx_stream = furi_stream_buffer_alloc(RX_BUF_SIZE, 1);
     flash_rx_stream = furi_stream_buffer_alloc(RX_BUF_SIZE, 1);
     timer = furi_timer_alloc(_timer_callback, FuriTimerTypePeriodic, app);
     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);
         loader_port_debug_print(err_msg);
     }
     }
 
 
+    #if 0 // still getting packet drops with this
+    // higher BR
     if(!err) {
     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);
+        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) {
     if(!err) {
-        loader_port_debug_print("Flashing app (3/3)\n");
-        err = _flash_file(app, app->bin_file_path_app, 0x10000);
+        loader_port_debug_print("Connected\n");
+        _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");
         loader_port_debug_print("Done flashing. Please reset the board manually.\n");
     }
     }
 
 
     // done
     // done
+    app->flash_worker_busy = false;
 
 
     // cleanup
     // cleanup
     furi_stream_buffer_free(flash_rx_stream);
     furi_stream_buffer_free(flash_rx_stream);

+ 7 - 0
wifi_marauder_flasher.h

@@ -5,6 +5,13 @@
 #define SERIAL_FLASHER_INTERFACE_UART /* TODO why is application.fam not passing this via cdefines */
 #define SERIAL_FLASHER_INTERFACE_UART /* TODO why is application.fam not passing this via cdefines */
 #include "esp_loader_io.h"
 #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_start_thread(WifiMarauderApp* app);
 void wifi_marauder_flash_stop_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);
 void wifi_marauder_flash_handle_rx_data_cb(uint8_t* buf, size_t len, void* context);