diff options
author | Matt Fleming <matt.fleming@intel.com> | 2012-08-02 09:26:54 +0100 |
---|---|---|
committer | Matt Fleming <matt.fleming@intel.com> | 2012-08-02 09:26:54 +0100 |
commit | 32ad2427ecda042a5eff93bae3773496ba5f44c1 (patch) | |
tree | 28c2a6723175aa0c6670c8ccd3a725b032ce1727 | |
parent | 5c88d800a5d612ceb2339476c544f09410b5a454 (diff) | |
download | syslinux-32ad2427ecda042a5eff93bae3773496ba5f44c1.tar.gz syslinux-32ad2427ecda042a5eff93bae3773496ba5f44c1.tar.xz syslinux-32ad2427ecda042a5eff93bae3773496ba5f44c1.zip |
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 <matt.fleming@intel.com>
-rw-r--r-- | com32/elflink/ldlinux/config.h | 2 | ||||
-rw-r--r-- | com32/elflink/ldlinux/execute.c | 10 | ||||
-rw-r--r-- | com32/elflink/ldlinux/ldlinux.c | 61 | ||||
-rw-r--r-- | com32/include/sys/module.h | 8 | ||||
-rw-r--r-- | com32/lib/sys/module/common.c | 24 | ||||
-rw-r--r-- | 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 45832022..ea4736e6 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 77d268c8..e7969c2e 100644 --- a/com32/elflink/ldlinux/execute.c +++ b/com32/elflink/ldlinux/execute.c @@ -18,6 +18,7 @@ #include <com32.h> #include <sys/exec.h> #include <sys/io.h> +#include <sys/module.h> #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 073f1116..ade161f3 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 eabc9e0f..095eb974 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 002b733a..b120bc73 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 b15cdbbb..8e124a0e 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; } |