unleashed-firmware/applications/external/wifi_marauder_companion/wifi_marauder_flasher.c
2023-07-05 20:26:47 +03:00

200 lines
6.1 KiB
C

#include "wifi_marauder_flasher.h"
FuriStreamBuffer* flash_rx_stream; // TODO make safe
WifiMarauderApp* global_app; // TODO make safe
FuriTimer* timer; // TODO make
static uint32_t _remaining_time = 0;
static void _timer_callback(void* context) {
UNUSED(context);
if(_remaining_time > 0) {
_remaining_time--;
}
}
static esp_loader_error_t _flash_file(WifiMarauderApp* app, char* filepath, uint32_t addr) {
// TODO cleanup
esp_loader_error_t err;
static uint8_t payload[1024];
File* bin_file = storage_file_alloc(app->storage);
// open file
if(!storage_file_open(bin_file, filepath, FSAM_READ, FSOM_OPEN_EXISTING)) {
storage_file_close(bin_file);
storage_file_free(bin_file);
dialog_message_show_storage_error(app->dialogs, "Cannot open file");
return ESP_LOADER_ERROR_FAIL;
}
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);
return err;
}
loader_port_debug_print("Start programming\n");
while(size > 0) {
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);
storage_file_close(bin_file);
storage_file_free(bin_file);
loader_port_debug_print(err_msg);
return err;
}
size -= num_bytes;
}
loader_port_debug_print("Finished programming\n");
// TODO verify
storage_file_close(bin_file);
storage_file_free(bin_file);
return ESP_LOADER_SUCCESS;
}
static int32_t wifi_marauder_flash_bin(void* context) {
WifiMarauderApp* app = (void*)context;
esp_loader_error_t err;
// alloc global objects
flash_rx_stream = furi_stream_buffer_alloc(RX_BUF_SIZE, 1);
timer = furi_timer_alloc(_timer_callback, FuriTimerTypePeriodic, app);
loader_port_debug_print("Connecting\n");
esp_loader_connect_args_t connect_config = ESP_LOADER_CONNECT_DEFAULT();
err = esp_loader_connect(&connect_config);
if(err != ESP_LOADER_SUCCESS) {
char err_msg[256];
snprintf(err_msg, sizeof(err_msg), "Cannot connect to target. Error: %u\n", err);
loader_port_debug_print(err_msg);
}
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);
loader_port_debug_print("Done flashing. Please reset the board manually.\n");
}
// done
// cleanup
furi_stream_buffer_free(flash_rx_stream);
flash_rx_stream = NULL;
furi_timer_free(timer);
return 0;
}
void wifi_marauder_flash_start_thread(WifiMarauderApp* app) {
global_app = app;
app->flash_worker = furi_thread_alloc();
furi_thread_set_name(app->flash_worker, "WifiMarauderFlashWorker");
furi_thread_set_stack_size(app->flash_worker, 2048);
furi_thread_set_context(app->flash_worker, app);
furi_thread_set_callback(app->flash_worker, wifi_marauder_flash_bin);
furi_thread_start(app->flash_worker);
}
void wifi_marauder_flash_stop_thread(WifiMarauderApp* app) {
furi_thread_join(app->flash_worker);
furi_thread_free(app->flash_worker);
}
esp_loader_error_t loader_port_read(uint8_t* data, uint16_t size, uint32_t timeout) {
size_t read = furi_stream_buffer_receive(flash_rx_stream, data, size, pdMS_TO_TICKS(timeout));
if(read < size) {
return ESP_LOADER_ERROR_TIMEOUT;
} else {
return ESP_LOADER_SUCCESS;
}
}
esp_loader_error_t loader_port_write(const uint8_t* data, uint16_t size, uint32_t timeout) {
UNUSED(timeout);
wifi_marauder_uart_tx((uint8_t*)data, size);
return ESP_LOADER_SUCCESS;
}
void loader_port_enter_bootloader(void) {
// unimplemented
}
void loader_port_delay_ms(uint32_t ms) {
furi_delay_ms(ms);
}
void loader_port_start_timer(uint32_t ms) {
_remaining_time = ms;
furi_timer_start(timer, pdMS_TO_TICKS(1));
}
uint32_t loader_port_remaining_time(void) {
return _remaining_time;
}
extern void wifi_marauder_console_output_handle_rx_data_cb(
uint8_t* buf,
size_t len,
void* context); // TODO cleanup
void loader_port_debug_print(const char* str) {
if(global_app)
wifi_marauder_console_output_handle_rx_data_cb((uint8_t*)str, strlen(str), global_app);
}
void loader_port_spi_set_cs(uint32_t level) {
UNUSED(level);
// unimplemented
}
void wifi_marauder_flash_handle_rx_data_cb(uint8_t* buf, size_t len, void* context) {
UNUSED(context);
if(flash_rx_stream) {
furi_stream_buffer_send(flash_rx_stream, buf, len, 0);
} else {
// done flashing
if(global_app) wifi_marauder_console_output_handle_rx_data_cb(buf, len, global_app);
}
}