[syslinux:elflink] ldlinux: Return to command prompt after loading COM32
syslinux-bot for Matt Fleming
matt.fleming at intel.com
Tue Aug 14 09:21:07 PDT 2012
Commit-ID: 32ad2427ecda042a5eff93bae3773496ba5f44c1
Gitweb: http://www.syslinux.org/commit/32ad2427ecda042a5eff93bae3773496ba5f44c1
Author: Matt Fleming <matt.fleming at intel.com>
AuthorDate: Thu, 2 Aug 2012 09:26:54 +0100
Committer: Matt Fleming <matt.fleming at intel.com>
CommitDate: Thu, 2 Aug 2012 09:26:54 +0100
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 at intel.com>
---
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 <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 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;
}
More information about the Syslinux-commits
mailing list