From b56ad45da35a01ca0f785e72a10e2f2ad94ddc34 Mon Sep 17 00:00:00 2001 From: Rahix <rahix@rahix.de> Date: Sun, 18 Aug 2019 20:56:16 +0200 Subject: [PATCH] feat(epicardium): Write default menu script When no `menu.py` is found, Epicardium will create one with the contents of `preload/menu.py`. Signed-off-by: Rahix <rahix@rahix.de> --- epicardium/modules/lifecycle.c | 76 +++++++++++++++++++++++++++++++++- 1 file changed, 74 insertions(+), 2 deletions(-) diff --git a/epicardium/modules/lifecycle.c b/epicardium/modules/lifecycle.c index 13ba9704..85968154 100644 --- a/epicardium/modules/lifecycle.c +++ b/epicardium/modules/lifecycle.c @@ -46,6 +46,9 @@ static volatile struct load_info async_load = { .type = PL_INVALID, }; +/* Whether to write the menu script before attempting to load. */ +static volatile bool write_menu = false; + /* Helpers {{{ */ /* @@ -181,6 +184,52 @@ static int load_async(char *name, bool reset) return 0; } +/* + * Epicardium contains an embedded default menu script which it writes to + * external flash if none is found there. This way, you won't make your card10 + * unusable by accidentally removing the menu script. + * + * You can find the sources for the menu-script in `preload/menu.py`. + */ + +/* + * Embed the menu.py script in the Epicardium binary. + */ +__asm(".section \".rodata\"\n" + "_menu_script_start:\n" + ".incbin \"../preload/menu.py\"\n" + "_menu_script_end:\n" + ".previous\n"); + +extern const uint8_t _menu_script_start; +extern const uint8_t _menu_script_end; + +static int write_default_menu(void) +{ + const size_t length = + (uintptr_t)&_menu_script_end - (uintptr_t)&_menu_script_start; + int ret; + + LOG_INFO("lifecycle", "Writing default menu ..."); + + int fd = epic_file_open("menu.py", "w"); + if (fd < 0) { + return fd; + } + + ret = epic_file_write(fd, &_menu_script_start, length); + if (ret < 0) { + return ret; + } + + ret = epic_file_close(fd); + if (ret < 0) { + return ret; + } + + return 0; +} + /* * Go back to the menu. */ @@ -196,9 +245,20 @@ static void load_menu(bool reset) int ret = load_async("menu.py", reset); if (ret < 0) { - /* TODO: Write default menu */ LOG_WARN("lifecycle", "No menu script found."); - load_async(PYINTERPRETER, reset); + + /* The lifecycle task will perform the write */ + write_menu = true; + + async_load.type = PL_PYTHON_SCRIPT; + async_load.do_reset = reset; + strncpy((char *)async_load.name, + "menu.py", + sizeof(async_load.name)); + + if (lifecycle_task != NULL) { + xTaskNotifyGive(lifecycle_task); + } } xSemaphoreGive(core1_mutex); @@ -308,6 +368,18 @@ void vLifecycleTask(void *pvParameters) continue; } + if (write_menu) { + write_menu = false; + int ret = write_default_menu(); + if (ret < 0) { + LOG_ERR("lifecycle", + "Failed to write default menu: %d", + ret); + load_async(PYINTERPRETER, ""); + ulTaskNotifyTake(pdTRUE, 0); + } + } + do_load((struct load_info *)&async_load); xSemaphoreGive(core1_mutex); -- GitLab