[syslinux] [PATCH 10/19] ldlinux: Loading a config file should cause re-initialisation

Paulo Alcantara pcacjr at zytor.com
Sat Mar 24 09:20:25 PDT 2012


Hi Matt,

On Fri, Mar 23, 2012 at 06:02:44PM +0000, Matt Fleming wrote:
> From: Matt Fleming <matt.fleming at intel.com>
> 
> There are a number of initialisation steps that need to be performed
> *every* time a config file is loaded. Reload ldlinux.c32 so that we
> can re-initialise the environment whenever a new config file is
> loaded. This involves unloading all the modules that have been loaded
> since ldlinux.c32. Luckily the list of loaded modules is sorted by
> load order, which means it's trivial to "pop" them from the front of
> the list.
> 
> Signed-off-by: Matt Fleming <matt.fleming at intel.com>
> ---
>  com32/elflink/ldlinux/execute.c   |   14 +++++++---
>  com32/elflink/ldlinux/ldlinux.c   |    6 ++++-
>  com32/include/linux/list.h        |   13 ++++++++++
>  com32/include/sys/module.h        |    6 ++++
>  com32/lib/sys/module/elf_module.c |    4 +-
>  core/elflink/config.c             |   41 -------------------------------
>  core/elflink/load_env32.c         |   48 +++++++++++++++++++++++++++++++++++-
>  7 files changed, 82 insertions(+), 50 deletions(-)
>  delete mode 100644 core/elflink/config.c
> 
> diff --git a/com32/elflink/ldlinux/execute.c b/com32/elflink/ldlinux/execute.c
> index 2b265a1..c01d63f 100644
> --- a/com32/elflink/ldlinux/execute.c
> +++ b/com32/elflink/ldlinux/execute.c
> @@ -19,6 +19,7 @@
>  #include <sys/exec.h>
>  #include "core.h"
>  #include "menu.h"
> +#include "fs.h"
>  
>  /* Must match enum kernel_type */
>  const char *const kernel_types[] = {
> @@ -74,8 +75,10 @@ void execute(const char *cmdline, enum kernel_type type)
>  		/* It might be a type specifier */
>  		enum kernel_type type = KT_NONE;
>  		for (pp = kernel_types; *pp; pp++, type++) {
> -			if (!strcmp(kernel + 1, *pp))
> -				execute(p, type);	/* Strip the type specifier and retry */
> +			if (!strcmp(kernel + 1, *pp)) {
> +				/* Strip the type specifier and retry */
> +				execute(p, type);
> +			}
>  		}
>  	}
>  
> @@ -88,9 +91,12 @@ void execute(const char *cmdline, enum kernel_type type)
>  		* the assembly runkernel.inc any more */
>  		new_linux_kernel(kernel, cmdline);
>  	} else if (type == KT_CONFIG) {
> +		char *argv[] = { "ldlinux.c32", NULL };
> +
>  		/* kernel contains the config file name */
> -		char *spawn_load_param[2] = { args, NULL };
> -		spawn_load(kernel, 1, spawn_load_param);
> +		realpath(ConfigName, kernel, FILENAME_MAX);
> +
> +		start_ldlinux("ldlinux.c32", 1, argv);
>  	} else {
>  		/* process the image need int 22 support */
>  		if (type == KT_LOCALBOOT) {
> diff --git a/com32/elflink/ldlinux/ldlinux.c b/com32/elflink/ldlinux/ldlinux.c
> index 03e2f60..6c306ad 100644
> --- a/com32/elflink/ldlinux/ldlinux.c
> +++ b/com32/elflink/ldlinux/ldlinux.c
> @@ -118,10 +118,14 @@ int main(int argc, char **argv)
>  	com32sys_t ireg, oreg;
>  	uint8_t *adv;
>  	int count = 0;
> +	char *config_argv[2] = { NULL, NULL };
>  
>  	openconsole(&dev_rawcon_r, &dev_ansiserial_w);
>  
> -	parse_configs(NULL);
> +	if (ConfigName[0])
> +		config_argv[0] = ConfigName;
> +
> +	parse_configs(config_argv);
>  
>  	__syslinux_init();
>  	adv = syslinux_getadv(ADV_BOOTONCE, &count);
> diff --git a/com32/include/linux/list.h b/com32/include/linux/list.h
> index 3b92e25..afe8980 100644
> --- a/com32/include/linux/list.h
> +++ b/com32/include/linux/list.h
> @@ -338,6 +338,19 @@ static inline void list_splice_init(struct list_head *list,
>  	     pos = list_entry(pos->member.next, typeof(*pos), member))
>  
>  /**
> + * list_for_each_entry_safe - iterate over list of given type safe against removal of list entry
> +* @pos:        the type * to use as a loop cursor.
> +* @n:          another type * to use as temporary storage
> +* @head:       the head for your list.
> +* @member:     the name of the list_struct within the struct.
> +*/
> +#define list_for_each_entry_safe(pos, n, head, member)                  \
> +	for (pos = list_entry((head)->next, typeof(*pos), member),      \
> +		n = list_entry(pos->member.next, typeof(*pos), member); \
> +             &pos->member != (head);					\
> +             pos = n, n = list_entry(n->member.next, typeof(*n), member))
> +
> +/**
>   * list_for_each_entry_reverse - iterate backwards over list of given type.
>   * @pos:	the type * to use as a loop cursor.
>   * @head:	the head for your list.
> diff --git a/com32/include/sys/module.h b/com32/include/sys/module.h
> index d10eae9..a9ddb60 100644
> --- a/com32/include/sys/module.h
> +++ b/com32/include/sys/module.h
> @@ -199,6 +199,12 @@ extern struct list_head modules_head;
>  #define for_each_module(m)	list_for_each_entry(m, &modules_head, list)
>  
>  /**
> + * for_each_module - iterator loop through the list of loaded modules safe against removal.
> + */
> +#define for_each_module_safe(m, n)				\
> +	list_for_each_entry_safe(m, n, &modules_head, list)
> +
> +/**
>   * modules_init - initialize the module subsystem.
>   *
>   * This function must be called before any module operation is to be performed.
> diff --git a/com32/lib/sys/module/elf_module.c b/com32/lib/sys/module/elf_module.c
> index ffdcd52..6b4d548 100644
> --- a/com32/lib/sys/module/elf_module.c
> +++ b/com32/lib/sys/module/elf_module.c
> @@ -5,7 +5,7 @@
>   *      Author: Stefan Bucur <stefanb at zytor.com>
>   */
>  
> -
> +#include <errno.h>
>  #include <stdlib.h>
>  #include <string.h>
>  #include <stdio.h>
> @@ -475,7 +475,7 @@ int module_load(struct elf_module *module) {
>  	// Do not allow duplicate modules
>  	if (module_find(module->name) != NULL) {
>  		DBG_PRINT("Module %s is already loaded.\n", module->name);
> -		return -1;
> +		return EEXIST;
>  	}
>  
>  	// Get a mapping/copy of the ELF file in memory
> diff --git a/core/elflink/config.c b/core/elflink/config.c
> deleted file mode 100644
> index b27aa82..0000000
> --- a/core/elflink/config.c
> +++ /dev/null
> @@ -1,41 +0,0 @@
> -/* ----------------------------------------------------------------------- *
> - *
> - *   Copyright 2007-2008 H. Peter Anvin - All Rights Reserved
> - *
> - *   Permission is hereby granted, free of charge, to any person
> - *   obtaining a copy of this software and associated documentation
> - *   files (the "Software"), to deal in the Software without
> - *   restriction, including without limitation the rights to use,
> - *   copy, modify, merge, publish, distribute, sublicense, and/or
> - *   sell copies of the Software, and to permit persons to whom
> - *   the Software is furnished to do so, subject to the following
> - *   conditions:
> - *
> - *   The above copyright notice and this permission notice shall
> - *   be included in all copies or substantial portions of the Software.
> - *
> - *   THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
> - *   EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
> - *   OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
> - *   NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
> - *   HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
> - *   WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
> - *   FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
> - *   OTHER DEALINGS IN THE SOFTWARE.
> - *
> - * ----------------------------------------------------------------------- */
> -
> -#include <syslinux/config.h>
> -#include <klibc/compiler.h>
> -#include <com32.h>
> -
> -const char *__syslinux_config_file;
> -
> -void __constructor __syslinux_get_config_file_name(void)
> -{
> -    static com32sys_t reg;
> -
> -    reg.eax.w[0] = 0x000e;
> -    __intcall(0x22, &reg, &reg);
> -    __syslinux_config_file = MK_PTR(reg.es, reg.ebx.w[0]);
> -}
> diff --git a/core/elflink/load_env32.c b/core/elflink/load_env32.c
> index 7ffe185..75f5629 100644
> --- a/core/elflink/load_env32.c
> +++ b/core/elflink/load_env32.c
> @@ -71,6 +71,50 @@ static void call_constr(void)
>  		(*p) ();
>  }
>  
> +int start_ldlinux(char **argv)
> +{
> +	int rv;
> +
> +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;
> +			}
> +		}
> +
> +		for_each_module_safe(mod, m) {
> +			if (mod == begin)
> +				break;
> +
> +			if (mod != begin)
> +				module_unload(mod);
> +		}
> +
> +		/*
> +		 * Finally unload LDLINUX.
> +		 *
> +		 * We'll reload it when we jump to 'again' which will
> +		 * cause all the initialsation steps to be executed

s/initialsation/initialisation

> +		 * again.
> +		 */
> +		module_unload(begin);
> +		goto again;
> +	}
> +
> +	return rv;
> +}
> +
>  /* note to self: do _*NOT*_ use static key word on this function */
>  void load_env32(com32sys_t * regs)
>  {
> @@ -97,7 +141,7 @@ void load_env32(com32sys_t * regs)
>  
>  	init_module_subsystem(&core_module);
>  
> -	spawn_load(LDLINUX, 1, argv);
> +	start_ldlinux(argv);
>  
>  	/*
>  	 * If we failed to load LDLINUX it could be because our
> @@ -112,7 +156,7 @@ void load_env32(com32sys_t * regs)
>  	fp = &__file_info[fd];
>  
>  	if (!search_config(&fp->i.fd, search_directories, filenames))
> -		spawn_load(LDLINUX, 1, argv);
> +		start_ldlinux(argv);
>  }
>  
>  int create_args_and_load(char *cmdline)
> -- 
> 1.7.4.4
> 
> _______________________________________________
> Syslinux mailing list
> Submissions to Syslinux at zytor.com
> Unsubscribe or set options at:
> http://www.zytor.com/mailman/listinfo/syslinux
> Please do not send private replies to mailing list traffic.

Reviewed-by: Paulo Alcantara <pcacjr at zytor.com>

-- 
-Paulo



More information about the Syslinux mailing list