From 8a6c499e1b21e8079ada1d352ea0f8b76e7626a1 Mon Sep 17 00:00:00 2001 From: Willy-JL <49810075+Willy-JL@users.noreply.github.com> Date: Mon, 12 Aug 2024 01:15:33 +0200 Subject: [PATCH] Migrate files and load MNTM settings on SD insert I don't fully like how I made this work, bu I don't see a better way without restructuring a lot of things and losing behavior compatibility --- applications/services/storage/storage.c | 25 +++++++++ furi/flipper.c | 68 ++++++++++++++++++------- furi/flipper.h | 4 ++ lib/momentum/namespoof.c | 12 +++++ 4 files changed, 91 insertions(+), 18 deletions(-) diff --git a/applications/services/storage/storage.c b/applications/services/storage/storage.c index fd49b459f..a681932b9 100644 --- a/applications/services/storage/storage.c +++ b/applications/services/storage/storage.c @@ -56,6 +56,25 @@ Storage* storage_app_alloc(void) { return app; } +#ifndef FURI_RAM_EXEC +#include +#include + +static int32_t sd_mount_handler(void* context) { + Storage* app = context; + StorageEvent event = {.type = StorageEventTypeCardMount}; + + // Needs to happen before other services load their settings + flipper_mount_callback(&event, NULL); + + // Everything else + furi_pubsub_publish(app->pubsub, &event); + + furi_record_close(RECORD_STORAGE); + return 0; +} +#endif + void storage_tick(Storage* app) { for(uint8_t i = 0; i < STORAGE_COUNT; i++) { StorageApi api = app->storage[i].api; @@ -86,8 +105,14 @@ void storage_tick(Storage* app) { if(app->storage[ST_EXT].status == StorageStatusOK) { FURI_LOG_I(TAG, "SD card mount"); +#ifndef FURI_RAM_EXEC + // Can't use pubsub for migration and can't lockup storage thread, + // see more explanation in flipper_mount_callback() + run_parallel(sd_mount_handler, app, 3 * 1024); +#else StorageEvent event = {.type = StorageEventTypeCardMount}; furi_pubsub_publish(app->pubsub, &event); +#endif } else { FURI_LOG_I(TAG, "SD card mount error"); StorageEvent event = {.type = StorageEventTypeCardMountError}; diff --git a/furi/flipper.c b/furi/flipper.c index 4cf8ab91b..0d96eeeb5 100644 --- a/furi/flipper.c +++ b/furi/flipper.c @@ -114,6 +114,34 @@ void flipper_migrate_files() { furi_record_close(RECORD_STORAGE); } + +// Cannot use pubsub to schedule on SD insert like other services because +// we want migration to happen before others load settings and new pubsub +// subscriptions are put first in callback list so migration would be last +// Also we cannot block the pubsub by loading files as it means storage +// service is deadlocked processing pubsub and cannot process file operations +// So instead storage runs this function in background thread and then +// dispatches the pubsub event to everyone else +void flipper_mount_callback(const void* message, void* context) { + UNUSED(context); + const StorageEvent* event = message; + + if(event->type == StorageEventTypeCardMount) { + // Migrate locations before other services load on SD insert + flipper_migrate_files(); + + // TODO: Need to restart services that already applied previous name + namespoof_init(); + + // TODO: If new SD doesn't contain all current settings IDs, values + // from previous SD are kept for these settings + momentum_settings_load(); + + // TODO: Could lock kernel on free to avoid GUI using assets while being free'd + asset_packs_free(); + asset_packs_init(); + } +} #endif void flipper_start_service(const FlipperInternalApplication* service) { @@ -146,25 +174,29 @@ void flipper_init(void) { #ifndef FURI_RAM_EXEC if(furi_hal_is_normal_boot()) { // Wait for storage record - furi_record_open(RECORD_STORAGE); + Storage* storage = furi_record_open(RECORD_STORAGE); + if(storage_sd_status(storage) != FSE_OK) { + FURI_LOG_D(TAG, "SD Card not ready, skipping early init"); + // Init on SD insert done by storage using flipper_mount_callback() + } else { + canvas_draw_icon(canvas, 39, 43, &I_dir_10px); + canvas_commit(canvas); + flipper_migrate_files(); + + canvas_draw_icon(canvas, 59, 42, &I_Apps_10px); + canvas_commit(canvas); + namespoof_init(); + + canvas_draw_icon(canvas, 79, 44, &I_Rpc_active_7x8); + canvas_commit(canvas); + momentum_settings_load(); + + furi_hal_light_sequence("rgb RB"); + canvas_draw_icon(canvas, 99, 44, &I_Hidden_window_9x8); + canvas_commit(canvas); + asset_packs_init(); + } furi_record_close(RECORD_STORAGE); - - canvas_draw_icon(canvas, 39, 43, &I_dir_10px); - canvas_commit(canvas); - flipper_migrate_files(); - - canvas_draw_icon(canvas, 59, 42, &I_Apps_10px); - canvas_commit(canvas); - namespoof_init(); - - canvas_draw_icon(canvas, 79, 44, &I_Rpc_active_7x8); - canvas_commit(canvas); - momentum_settings_load(); - - furi_hal_light_sequence("rgb RB"); - canvas_draw_icon(canvas, 99, 44, &I_Hidden_window_9x8); - canvas_commit(canvas); - asset_packs_init(); } else { FURI_LOG_I(TAG, "Special boot, skipping optional components"); } diff --git a/furi/flipper.h b/furi/flipper.h index 674cccf88..fe561f5ae 100644 --- a/furi/flipper.h +++ b/furi/flipper.h @@ -1,3 +1,7 @@ #pragma once void flipper_init(void); + +#ifndef FURI_RAM_EXEC +void flipper_mount_callback(const void* message, void* context); +#endif diff --git a/lib/momentum/namespoof.c b/lib/momentum/namespoof.c index 74e87c7bb..b2aa61399 100644 --- a/lib/momentum/namespoof.c +++ b/lib/momentum/namespoof.c @@ -10,6 +10,9 @@ void namespoof_init(void) { Storage* storage = furi_record_open(RECORD_STORAGE); FlipperFormat* file = flipper_format_file_alloc(storage); + const char* prev_custom_name = version_get_custom_name(NULL); + bool applied_new_name = false; + do { uint32_t version; if(!flipper_format_file_open_existing(file, NAMESPOOF_PATH)) break; @@ -20,8 +23,17 @@ void namespoof_init(void) { if(!flipper_format_read_string(file, "Name", str)) break; version_set_custom_name(NULL, strdup(furi_string_get_cstr(str))); furi_hal_version_set_name(NULL); + applied_new_name = true; } while(false); + if(prev_custom_name) { + if(!applied_new_name) { + version_set_custom_name(NULL, NULL); + furi_hal_version_init(); + } + free((void*)prev_custom_name); + } + flipper_format_free(file); furi_record_close(RECORD_STORAGE); furi_string_free(str);