From 32ad2427ecda042a5eff93bae3773496ba5f44c1 Mon Sep 17 00:00:00 2001 From: Matt Fleming Date: Thu, 2 Aug 2012 09:26:54 +0100 Subject: [PATCH] ldlinux: Return to command prompt after loading COM32 The old COM32 loading code would drop the user at a command prompt once execution returned from the COM32 amodule. We need to replicate this because most callers of execute() don't expect it to return. This bug was noticed when loading a COM32 module from vesamenu.c32. Once execution returned from the COM32 module the display became garbled because no code exists to reinitialise the screen for VGA. Signed-off-by: Matt Fleming --- com32/elflink/ldlinux/config.h | 2 ++ com32/elflink/ldlinux/execute.c | 10 +++++++ com32/elflink/ldlinux/ldlinux.c | 61 +++++++++++++++++++++-------------------- com32/include/sys/module.h | 8 ++++++ com32/lib/sys/module/common.c | 24 ++++++++++++++++ core/elflink/load_env32.c | 19 ++----------- 6 files changed, 79 insertions(+), 45 deletions(-) diff --git a/com32/elflink/ldlinux/config.h b/com32/elflink/ldlinux/config.h index 4583202..ea4736e 100644 --- a/com32/elflink/ldlinux/config.h +++ b/com32/elflink/ldlinux/config.h @@ -47,4 +47,6 @@ extern int new_linux_kernel(char *okernel, char *ocmdline); extern void pm_load_high(com32sys_t *regs); +extern void ldlinux_enter_command(bool prompt); + #endif /* __CONFIG_H__ */ diff --git a/com32/elflink/ldlinux/execute.c b/com32/elflink/ldlinux/execute.c index 77d268c..e7969c2 100644 --- a/com32/elflink/ldlinux/execute.c +++ b/com32/elflink/ldlinux/execute.c @@ -18,6 +18,7 @@ #include #include #include +#include #include "core.h" #include "menu.h" #include "fs.h" @@ -93,6 +94,15 @@ void execute(const char *cmdline, uint32_t type) if (type == IMAGE_TYPE_COM32) { /* new entry for elf format c32 */ create_args_and_load((char *)cmdline); + + /* + * The old COM32 module code would run the module then + * drop the user back at the command prompt, + * irrespective of how the COM32 module was loaded, + * e.g. from vesamenu.c32. + */ + unload_modules_since("ldlinux.c32"); + ldlinux_enter_command(!noescape); } else if (type == IMAGE_TYPE_CONFIG) { char *argv[] = { "ldlinux.c32", NULL }; diff --git a/com32/elflink/ldlinux/ldlinux.c b/com32/elflink/ldlinux/ldlinux.c index 073f111..ade161f 100644 --- a/com32/elflink/ldlinux/ldlinux.c +++ b/com32/elflink/ldlinux/ldlinux.c @@ -222,6 +222,35 @@ static void enter_cmdline(void) } } +void ldlinux_enter_command(bool prompt) +{ + const char *cmdline = default_cmd; + + if (prompt) + goto cmdline; +auto_boot: + /* + * Auto boot + */ + if (defaultlevel || noescape) { + if (defaultlevel) { + load_kernel(cmdline); /* Shouldn't return */ + } else { + printf("No DEFAULT or UI configuration directive found!\n"); + + if (noescape) + kaboom(); + } + } + +cmdline: + /* Only returns if the user pressed enter or input timed out */ + enter_cmdline(); + + cmdline = ontimeoutlen ? ontimeout : default_cmd; + + goto auto_boot; +} int main(int argc __unused, char **argv __unused) { const void *adv; @@ -249,7 +278,7 @@ int main(int argc __unused, char **argv __unused) cmdline = dst = malloc(count + 1); if (!dst) { printf("Failed to allocate memory for ADV\n"); - goto cmdline; + ldlinux_enter_command(true); } for (i = 0; i < count; i++) @@ -261,37 +290,11 @@ int main(int argc __unused, char **argv __unused) syslinux_adv_write(); load_kernel(cmdline); /* Shouldn't return */ - goto cmdline; + ldlinux_enter_command(true); } /* TODO: Check KbdFlags? */ - if (forceprompt) - goto cmdline; - - cmdline = default_cmd; -auto_boot: - /* - * Auto boot - */ - if (defaultlevel || noescape) { - if (defaultlevel) { - load_kernel(cmdline); /* Shouldn't return */ - } else { - printf("No DEFAULT or UI configuration directive found!\n"); - - if (noescape) - kaboom(); - } - } - -cmdline: - /* Only returns if the user pressed enter or input timed out */ - enter_cmdline(); - - cmdline = ontimeoutlen ? ontimeout : default_cmd; - - goto auto_boot; - + ldlinux_enter_command(forceprompt); return 0; } diff --git a/com32/include/sys/module.h b/com32/include/sys/module.h index eabc9e0..095eb97 100644 --- a/com32/include/sys/module.h +++ b/com32/include/sys/module.h @@ -138,6 +138,14 @@ struct module_dep { }; +/** + * Unload all modules that have been loaded since @name. + * + * Returns the struct elf_module * for @name or %NULL if no modules + * have been loaded since @name. + */ +extern struct elf_module *unload_modules_since(const char *name); + #ifdef DYNAMIC_MODULE diff --git a/com32/lib/sys/module/common.c b/com32/lib/sys/module/common.c index 002b733..b120bc7 100644 --- a/com32/lib/sys/module/common.c +++ b/com32/lib/sys/module/common.c @@ -422,6 +422,30 @@ int module_unload(struct elf_module *module) { return _module_unload(module); } +struct elf_module *unload_modules_since(const char *name) { + struct elf_module *m, *mod, *begin = NULL; + + for_each_module(mod) { + if (!strcmp(mod->name, name)) { + begin = mod; + break; + } + } + + if (!begin) + return begin; + + for_each_module_safe(mod, m) { + if (mod == begin) + break; + + if (mod != begin) + module_unload(mod); + } + + return begin; +} + static Elf32_Sym *module_find_symbol_sysv(const char *name, struct elf_module *module) { unsigned long h = elf_hash((const unsigned char*)name); Elf32_Word *cr_word = module->hash_table; diff --git a/core/elflink/load_env32.c b/core/elflink/load_env32.c index b15cdbb..8e124a0 100644 --- a/core/elflink/load_env32.c +++ b/core/elflink/load_env32.c @@ -66,28 +66,15 @@ int start_ldlinux(char **argv) again: rv = spawn_load(LDLINUX, 1, argv); if (rv == EEXIST) { - struct elf_module *m, *mod, *begin = NULL; - /* * If a COM32 module calls execute() we may need to * unload all the modules loaded since ldlinux.c32, * and restart initialisation. This is especially * important for config files. */ - for_each_module(mod) { - if (!strcmp(mod->name, LDLINUX)) { - begin = mod; - break; - } - } + struct elf_module *ldlinux; - for_each_module_safe(mod, m) { - if (mod == begin) - break; - - if (mod != begin) - module_unload(mod); - } + ldlinux = unload_modules_since(LDLINUX); /* * Finally unload LDLINUX. @@ -96,7 +83,7 @@ again: * cause all the initialsation steps to be executed * again. */ - module_unload(begin); + module_unload(ldlinux); goto again; } -- 2.7.4