Matt Fleming
2012-Mar-23 18:02 UTC
[syslinux] [PATCH 00/19][elflink] Improve compatibility with 4.x
From: Matt Fleming <matt.fleming at intel.com> The following patch series is available at, git://git.zytor.com/users/mfleming/syslinux.git elflink All patches are against the 'elflink' branch. This series fixes a few serious bugs and some behavioural incompatibilities with the 4.x series. Matt Fleming (19): ldlinux: Initialise 'p' before using it. ldlinux: Parse kernel type for labels com32/menu: vesamenu.c32 and menu.c32 require multiple obj files core: Only adjust screen if we're in text mode core: Delete the aux segment core: Check for func key in getchar() ldlinux: Fix detection of function keys core: Shrink core/ldlinux.sys to be under 64K bytes elf: Support __constructor and __destructor ldlinux: Loading a config file should cause re-initialisation elflink: Don't use strcmp on a non-NUL terminated string com32: Delete execute.c and use the one from ldlinux ldlinux: chdir to the APPEND str when parsing a CONFIG directive ldlinux: Avoid initialised data memory corruption ldlinux: Make the default execute type KT_KERNEL ldlinux: Disable VGA graphics when loading a kernel ldlinux: Don't alloc initramfs unless initrd= is specified mk: Don't link against compiler's version of libgcc core: Abstract search_config() into search_dirs() com32/Makefile | 4 +- com32/elflink/ldlinux/Makefile | 5 +- com32/elflink/ldlinux/cli.c | 36 ++------------ com32/elflink/ldlinux/execute.c | 43 ++++++++-------- com32/elflink/ldlinux/ipappend.c | 58 --------------------- com32/elflink/ldlinux/kernel.c | 13 +++-- com32/elflink/ldlinux/ldlinux.c | 72 ++++++++++++++++----------- com32/elflink/ldlinux/readconfig.c | 8 +++- com32/include/linux/list.h | 13 +++++ com32/include/sys/exec.h | 23 --------- com32/include/sys/module.h | 38 ++++++-------- com32/lib/Makefile | 71 +++++++++++++++----------- com32/lib/elf32.ld | 10 +--- com32/lib/sys/module/common.c | 12 ++++- com32/lib/sys/module/elf_module.c | 97 +++++++++++++++++++++++++++--------- com32/lib/sys/module/exec.c | 87 ++------------------------------ com32/menu/Makefile | 6 +- com32/menu/execute.c | 69 ------------------------- core/Makefile | 2 +- core/comboot.inc | 6 ++- core/conio.c | 6 ++- core/elflink/config.c | 41 --------------- core/elflink/load_env32.c | 62 +++++++++++++++++++++-- core/font.c | 20 ++++--- core/fs/fs.c | 2 +- core/fs/iso9660/iso9660.c | 2 +- core/fs/lib/loadconfig.c | 2 +- core/fs/lib/searchconfig.c | 19 ++++--- core/graphics.c | 6 +-- core/include/core.h | 2 +- core/include/fs.h | 6 ++- core/init.inc | 2 +- core/layout.inc | 15 ------ core/syslinux.ld | 15 ------ mk/elf.mk | 3 +- mk/lib.mk | 2 +- 36 files changed, 350 insertions(+), 528 deletions(-) delete mode 100644 com32/elflink/ldlinux/ipappend.c delete mode 100644 com32/menu/execute.c delete mode 100644 core/elflink/config.c -- 1.7.4.4
Matt Fleming
2012-Mar-23 18:02 UTC
[syslinux] [PATCH 01/19] ldlinux: Initialise 'p' before using it.
From: Matt Fleming <matt.fleming at intel.com> Signed-off-by: Matt Fleming <matt.fleming at intel.com> --- com32/elflink/ldlinux/ldlinux.c | 1 + 1 files changed, 1 insertions(+), 0 deletions(-) diff --git a/com32/elflink/ldlinux/ldlinux.c b/com32/elflink/ldlinux/ldlinux.c index 84cb41f..5360417 100644 --- a/com32/elflink/ldlinux/ldlinux.c +++ b/com32/elflink/ldlinux/ldlinux.c @@ -42,6 +42,7 @@ static void load_kernel(const char *kernel) if (!allowimplicit) goto bad_implicit; + p = kernel; /* Find the end of the command */ while (*p && !my_isspace(*p)) p++; -- 1.7.4.4
Matt Fleming
2012-Mar-23 18:02 UTC
[syslinux] [PATCH 02/19] ldlinux: Parse kernel type for labels
From: Matt Fleming <matt.fleming at intel.com> We need to parse the kernel type for labels aswell as things entered on the cmdline, instead of always passing KT_KERNEL or KT_NONE to execute(). Move the logic into a new helper function. This fixes a bug where an incorrect kernel type would be passed to execute() if anything other than a linux kernel (such as a .bin) was specified in a LABEL's KERNEL argument, which resulted in the file not being executed. Signed-off-by: Matt Fleming <matt.fleming at intel.com> --- com32/elflink/ldlinux/ldlinux.c | 66 ++++++++++++++++++++++---------------- 1 files changed, 38 insertions(+), 28 deletions(-) diff --git a/com32/elflink/ldlinux/ldlinux.c b/com32/elflink/ldlinux/ldlinux.c index 5360417..dcde542 100644 --- a/com32/elflink/ldlinux/ldlinux.c +++ b/com32/elflink/ldlinux/ldlinux.c @@ -11,43 +11,19 @@ #include <sys/module.h> -/* - * Attempt to load a kernel after deciding what type of image it is. - * - * We only return from this function if something went wrong loading - * the the kernel. If we return the caller should call enter_cmdline() - * so that the user can help us out. - */ -static void load_kernel(const char *kernel) +static enum kernel_type parse_kernel_type(char *kernel) { - struct menu_entry *me; enum kernel_type type; - const char *cmdline, *p; + const char *p; int len; - /* Virtual kernel? */ - me = find_label(kernel); - if (me) { - enum kernel_type type = KT_KERNEL; - - /* cmdline contains type specifier */ - if (me->cmdline[0] == '.') - type = KT_NONE; - - execute(me->cmdline, type); - /* We shouldn't return */ - goto bad_kernel; - } - - if (!allowimplicit) - goto bad_implicit; - - p = kernel; /* Find the end of the command */ + p = kernel; while (*p && !my_isspace(*p)) p++; len = p - kernel; + if (!strncmp(kernel + len - 4, ".c32", 4)) { type = KT_COM32; } else if (!strncmp(kernel + len - 2, ".0", 2)) { @@ -68,6 +44,40 @@ static void load_kernel(const char *kernel) else type = KT_KERNEL; + return type; +} + +/* + * Attempt to load a kernel after deciding what type of image it is. + * + * We only return from this function if something went wrong loading + * the the kernel. If we return the caller should call enter_cmdline() + * so that the user can help us out. + */ +static void load_kernel(const char *kernel) +{ + struct menu_entry *me; + enum kernel_type type; + const char *cmdline; + + /* Virtual kernel? */ + me = find_label(kernel); + if (me) { + type = parse_kernel_type(me->cmdline); + + /* cmdline contains type specifier */ + if (me->cmdline[0] == '.') + type = KT_NONE; + + execute(me->cmdline, type); + /* We shouldn't return */ + goto bad_kernel; + } + + if (!allowimplicit) + goto bad_implicit; + + type = parse_kernel_type(kernel); execute(kernel, type); bad_implicit: -- 1.7.4.4
Matt Fleming
2012-Mar-23 18:02 UTC
[syslinux] [PATCH 03/19] com32/menu: vesamenu.c32 and menu.c32 require multiple obj files
From: Matt Fleming <matt.fleming at intel.com> The standard %.c32 rule in mk/elf.mk doesn't work for vesamenu.c32 and menu.c32 because they need multiple object files to be linked. Replace the *.elf targets with *.c32 because .c32 *IS* an ELF file now. Signed-off-by: Matt Fleming <matt.fleming at intel.com> --- com32/menu/Makefile | 4 ++-- 1 files changed, 2 insertions(+), 2 deletions(-) diff --git a/com32/menu/Makefile b/com32/menu/Makefile index 5a9b3c6..e1c700b 100644 --- a/com32/menu/Makefile +++ b/com32/menu/Makefile @@ -28,10 +28,10 @@ COMMONOBJS = menumain.o readconfig.o passwd.o drain.o printmsg.o colors.o \ all: $(MODULES) $(TESTFILES) -menu.elf : menu.o $(COMMONOBJS) $(C_LIBS) +menu.c32 : menu.o $(COMMONOBJS) $(C_LIBS) $(LD) $(LDFLAGS) -o $@ $^ -vesamenu.elf : vesamenu.o $(COMMONOBJS) $(C_LIBS) +vesamenu.c32 : vesamenu.o $(COMMONOBJS) $(C_LIBS) $(LD) $(LDFLAGS) -o $@ $^ tidy dist: -- 1.7.4.4
Matt Fleming
2012-Mar-23 18:02 UTC
[syslinux] [PATCH 04/19] core: Only adjust screen if we're in text mode
From: Matt Fleming <matt.fleming at intel.com> A bug was introduced in commit 9f51b69d ("core: Reimplement lots asm code in C") when converting the old asm comapi_usingvga function into C. We only want to adjust the screen if we're not using VGA. Signed-off-by: Matt Fleming <matt.fleming at intel.com> --- core/graphics.c | 6 +----- 1 files changed, 1 insertions(+), 5 deletions(-) diff --git a/core/graphics.c b/core/graphics.c index 864550b..4a4af55 100644 --- a/core/graphics.c +++ b/core/graphics.c @@ -367,10 +367,6 @@ void pm_usingvga(com32sys_t *regs) GXPixCols = regs->ecx.w[0]; GXPixRows = regs->edx.w[0]; - if (UsingVGA & 0x08) - regs->eflags.l &= ~EFLAGS_CF; - else { + if (!(UsingVGA & 0x08)) adjust_screen(); - set_flags(regs, EFLAGS_CF); - } } -- 1.7.4.4
From: Matt Fleming <matt.fleming at intel.com> We don't need to use a special aux segment because we can represent 'fontbuf' with OFFS() and SEG(). We're guaranteed to be able to break the 32-bit pointer up with these macros because we control where in the address space the core is loaded. (Not all 32-bit pointers can be represented with OFFS() and SEG(), only addresses in the range 0..0xFFFFF.) This fixes the breakage that was introduced in commit 14531c47bc95 ("core: Delete code that is duplicated in ldlinux"). This allows the default font to be displayed. Previously junk was being returned in the COMBOOT API call to query the userfont, leading the caller to believe that a user font was installed even when it wasn't. Signed-off-by: Matt Fleming <matt.fleming at intel.com> --- core/comboot.inc | 6 ++++-- core/font.c | 20 +++++++++++--------- core/include/core.h | 1 - core/init.inc | 2 +- core/layout.inc | 15 --------------- core/syslinux.ld | 15 --------------- 6 files changed, 16 insertions(+), 43 deletions(-) diff --git a/core/comboot.inc b/core/comboot.inc index e0ad068..38d65dd 100644 --- a/core/comboot.inc +++ b/core/comboot.inc @@ -669,10 +669,12 @@ comapi_userfont: and al,al jz .done mov al,[VGAFontSize] - mov P_ES,aux_seg - mov P_BX,aux.fontbuf + pm_call pm_userfont + mov P_ES,es + mov P_BX,bx .done: ; CF=0 here + mov P_AL,al ret ; diff --git a/core/font.c b/core/font.c index b14d3d2..0eeb90f 100644 --- a/core/font.c +++ b/core/font.c @@ -24,12 +24,8 @@ #include "bios.h" #include "core.h" -struct aux { - char fontbuf[8192]; - char serial[serial_buf_size]; -}; - -#define fontbuf offsetof(struct aux, fontbuf) +char fontbuf[8192]; +char serial[serial_buf_size]; extern uint16_t VGAFontSize; extern uint8_t UserFont; @@ -91,7 +87,7 @@ void loadfont(char *filename) /* Copy to font buffer */ VGAFontSize = height; - di = (uint32_t *)MK_PTR(aux_seg, fontbuf); + di = (uint32_t *)fontbuf; si = (uint32_t *)trackbuf; for (i = 0; i < (height << 6); i++) *di++ = *si++; @@ -118,8 +114,8 @@ void use_font(void) memset(&ireg, 0, sizeof(ireg)); - ireg.es = aux_seg; - ireg.ebp.w[0] = fontbuf; /* ES:BP -> font */ + ireg.es = SEG(fontbuf); + ireg.ebp.w[0] = OFFS(fontbuf); /* ES:BP -> font */ /* Are we using a user-specified font? */ if (UserFont & 0x1) { @@ -193,3 +189,9 @@ void pm_adjust_screen(com32sys_t *regs) { adjust_screen(); } + +void pm_userfont(com32sys_t *regs) +{ + regs->es = SEG(fontbuf); + regs->ebx.w[0] = OFFS(fontbuf); +} diff --git a/core/include/core.h b/core/include/core.h index 69c16d6..a247d49 100644 --- a/core/include/core.h +++ b/core/include/core.h @@ -24,7 +24,6 @@ extern char ConfigFile[]; extern char syslinux_banner[]; extern char copyright_str[]; -extern char aux_seg[]; extern uint8_t KbdMap[256]; /* diskstart.inc isolinux.asm*/ diff --git a/core/init.inc b/core/init.inc index 286b380..e0ffd23 100644 --- a/core/init.inc +++ b/core/init.inc @@ -63,7 +63,7 @@ pm_decompress: mov edi,__bss16_start mov ecx,__bss16_dwords rep stosd - mov edi,__high_clear_start ; .uibss, .auxseg, .lowmem + mov edi,__high_clear_start ; .uibss, .lowmem mov ecx,__high_clear_dwords rep stosd diff --git a/core/layout.inc b/core/layout.inc index dab27dd..c58c0fd 100644 --- a/core/layout.inc +++ b/core/layout.inc @@ -128,21 +128,6 @@ RBFG_brainfuck: resb 2048 ; Bigger than an Ethernet packet... serial_buf_size equ 4096 ; Should be a power of 2 ; -; Contents of aux_seg -; - extern aux_seg ; Actual segment assigned by linker - - struc aux -.fontbuf resb 8192 -.serial resb serial_buf_size - - alignb 4096 ; Align the next segment to 4K - endstruc - - section .auxseg write nobits align=16 -auxseg resb aux_size - -; ; Transfer buffer segment: guaranteed to be aligned 64K, used for disk I/O ; One symbol for the segment number, one for the absolute address ; diff --git a/core/syslinux.ld b/core/syslinux.ld index 43fc153..81d6b11 100644 --- a/core/syslinux.ld +++ b/core/syslinux.ld @@ -212,21 +212,6 @@ SECTIONS xfer_buf_seg = core_xfer_buf >> 4; /* - * The auxilliary data segment is used by the 16-bit code - * for items that don't need to live in the bottom 64K. - */ - - . = ALIGN(16); - .auxseg (NOLOAD) : { - __auxseg_start = .; - *(.auxseg) - __auxseg_end = .; - } - __auxseg_len = ABSOLUTE(__auxseg_end) - ABSOLUTE(__auxseg_start); - __auxseg_dwords = (__auxseg_len + 3) >> 2; - aux_seg = __auxseg_start >> 4; - - /* * Used to allocate lowmem buffers from 32-bit code */ .lowmem (NOLOAD) : { -- 1.7.4.4
Matt Fleming
2012-Mar-23 18:02 UTC
[syslinux] [PATCH 06/19] core: Check for func key in getchar()
From: Matt Fleming <matt.fleming at intel.com> We need to return the value stored in ah after reading from the keyboard with __intcall(0x16, ...) otherwise we won't properly detect function keys such as F1, F2, etc. Signed-off-by: Matt Fleming <matt.fleming at intel.com> --- core/conio.c | 6 ++++-- 1 files changed, 4 insertions(+), 2 deletions(-) diff --git a/core/conio.c b/core/conio.c index 5ed0b4b..70dd3b1 100644 --- a/core/conio.c +++ b/core/conio.c @@ -265,7 +265,7 @@ extern void do_idle(void); /* * getchar: Read a character from keyboard or serial port */ -char getchar(void) +char getchar(char *hi) { com32sys_t ireg, oreg; unsigned char data; @@ -313,6 +313,8 @@ char getchar(void) __intcall(0x16, &ireg, &oreg); data = oreg.eax.b[0]; + *hi = oreg.eax.b[1]; + if (data == 0xE0) data = 0; @@ -331,7 +333,7 @@ char getchar(void) void pm_getchar(com32sys_t *regs) { - regs->eax.b[0] = getchar(); + regs->eax.b[0] = getchar(®s->eax.b[1]); } static void msg_setbg(char data) -- 1.7.4.4
Matt Fleming
2012-Mar-23 18:02 UTC
[syslinux] [PATCH 07/19] ldlinux: Fix detection of function keys
From: Matt Fleming <matt.fleming at intel.com> __get_key() directly calls getchar() but doesn't properly detect when a function key such as F1, F2, etc has been entered. Despite the previous commit to cli.c which read, ldlinux: Accept commands from the serial console To mimic the old (pre-elflink) command-line interface behaviour let's use getchar() instead of reading from stdin. This way, if the user types a command on the serial console it will actually be executed. I can't see how get_key() fails to detect input on the serial console. So let's revert to calling get_key() because it actually handles the detection of function keys. Signed-off-by: Matt Fleming <matt.fleming at intel.com> --- com32/elflink/ldlinux/cli.c | 29 ++--------------------------- 1 files changed, 2 insertions(+), 27 deletions(-) diff --git a/com32/elflink/ldlinux/cli.c b/com32/elflink/ldlinux/cli.c index 7b2da88..8be8c17 100644 --- a/com32/elflink/ldlinux/cli.c +++ b/com32/elflink/ldlinux/cli.c @@ -29,31 +29,6 @@ void clear_screen(void) fputs("\033e\033%@\033)0\033(B\1#0\033[?25l\033[2J", stdout); } -static int __get_key(void) -{ - unsigned char buffer[KEY_MAXLEN]; - int another; - int nc, rv; - int code; - - nc = 0; - do { - buffer[nc++] = getchar(); - - another = 0; - rv = get_key_decode(buffer, nc, &code); - if (!rv) - return code; - else if (rv == 1) - another = 1; - - } while (another); - - /* We got an unrecognized sequence; return the first character */ - /* We really should remember this and return subsequent characters later */ - return buffer[0]; -} - int mygetkey(clock_t timeout) { clock_t t0, t; @@ -62,14 +37,14 @@ int mygetkey(clock_t timeout) //dprintf("enter"); if (!totaltimeout) - return __get_key(); + return get_key(stdin, 0); for (;;) { tto = min(totaltimeout, INT_MAX); to = timeout ? min(tto, timeout) : tto; t0 = 0; - key = __get_key(); + key = get_key(stdin, 0); t = 0 - t0; if (totaltimeout <= t) -- 1.7.4.4
Matt Fleming
2012-Mar-23 18:02 UTC
[syslinux] [PATCH 08/19] core: Shrink core/ldlinux.sys to be under 64K bytes
From: Matt Fleming <matt.fleming at intel.com> It would seem that running from a btrfs file system has been broken for some time. The reason is that core/ldlinux.sys has grown substantially, resulting in it weighing in at a whopping 88K bytes and no longer fitting within the first 64K segment of a btrfs file system. This huge size stems from the fact that the core links with libcom32min.a because it requires various symbols contained within that archive but it includes and exports *all* the symbols from libcom32min.a. The reasoning behind this design decision is that when a module is loaded any undefined symbols that are defined in libcom32min.a can be resolved at runtime by the core, without the module also needing to statically link against libcom32min.a. Unfortunately doing this has increased the size of the core beyond acceptable limits, such that booting from a btrfs file system no longer works. This commit links ldlinux.c32 against libcom32min.a so that now ldlinux.c32 exports all the symbols contained within the archive. Since we will always load ldlinux.c32 before any other modules, any undefined symbols will now be resolved by ldlinux.c32 instead of the core. ldlinux.c32 isn't subject to same size constraints as the core, e.g. fitting within 64K. Here are the sizes in bytes before and after this commit, Before: 33806 com32/elflink/ldlinux/ldlinux.c32 87749 core/ldlinux.sys After: 393871 com32/elflink/ldlinux/ldlinux.c32 45516 core/ldlinux.sys Signed-off-by: Matt Fleming <matt.fleming at intel.com> --- com32/Makefile | 4 +- com32/elflink/ldlinux/Makefile | 3 +- com32/lib/Makefile | 68 +++++++++++++++++++++++----------------- core/Makefile | 2 +- 4 files changed, 44 insertions(+), 33 deletions(-) diff --git a/com32/Makefile b/com32/Makefile index debfe47..6ed2632 100644 --- a/com32/Makefile +++ b/com32/Makefile @@ -1,4 +1,4 @@ -SUBDIRS = elflink/ldlinux libupload tools lib gpllib libutil modules mboot menu samples \ - elflink rosh cmenu hdt gfxboot sysdump lua/src +SUBDIRS = libupload tools lib elflink/ldlinux gpllib libutil modules mboot \ + menu samples elflink rosh cmenu hdt gfxboot sysdump lua/src all tidy dist clean spotless install: set -e; for d in $(SUBDIRS); do $(MAKE) -C $$d $@; done diff --git a/com32/elflink/ldlinux/Makefile b/com32/elflink/ldlinux/Makefile index 5927e50..9960277 100644 --- a/com32/elflink/ldlinux/Makefile +++ b/com32/elflink/ldlinux/Makefile @@ -15,13 +15,14 @@ MAKEDIR = $(topdir)/mk include $(MAKEDIR)/elf.mk CFLAGS += -I$(topdir)/core/elflink -I$(topdir)/core/include +LIBS = --whole-archive $(com32)/lib/libcom32min.a all: ldlinux.c32 ldlinux_lnx.a ldlinux.c32 : ldlinux.o cli.o readconfig.o refstr.o colors.o getadv.o \ adv.o ipappend.o execute.o kernel.o get_key.o \ advwrite.o setadv.o eprintf.o - $(LD) $(LDFLAGS) -o $@ $^ + $(LD) $(LDFLAGS) -o $@ $^ $(LIBS) LNXLIBOBJS = get_key.lo ldlinux_lnx.a: $(LNXLIBOBJS) diff --git a/com32/lib/Makefile b/com32/lib/Makefile index 10fb4de..66cfcbf 100644 --- a/com32/lib/Makefile +++ b/com32/lib/Makefile @@ -100,9 +100,9 @@ LIBCONSOLE_OBJS = \ sys/openconsole.o sys/line_input.o \ sys/colortable.o sys/screensize.o \ \ - sys/stdcon_read.o sys/stdcon_write.o sys/rawcon_read.o \ - sys/rawcon_write.o sys/err_read.o sys/err_write.o \ - sys/null_read.o sys/null_write.o sys/serial_write.o \ + sys/stdcon_read.o sys/rawcon_read.o \ + sys/rawcon_write.o \ + sys/null_write.o sys/serial_write.o \ \ sys/xserial_write.o \ \ @@ -114,30 +114,28 @@ LIBCONSOLE_OBJS = \ LIBOTHER_OBJS = \ atoi.o atol.o atoll.o calloc.o creat.o \ - ctypes.o errno.o fgetc.o fgets.o fopen.o fprintf.o fputc.o \ - fclose.o putchar.o setjmp.o \ - fputs.o fread2.o fread.o fwrite2.o fwrite.o \ + fgets.o fprintf.o fputc.o \ + putchar.o \ getopt.o getopt_long.o \ - lrand48.o stack.o memccpy.o memchr.o memcmp.o \ - memcpy.o mempcpy.o memmem.o memmove.o memset.o memswap.o \ - perror.o printf.o puts.o qsort.o seed48.o snprintf.o \ - sprintf.o srand48.o sscanf.o strcasecmp.o strcat.o \ - strchr.o strcmp.o strcpy.o strdup.o strerror.o strlen.o \ + lrand48.o stack.o memccpy.o memchr.o \ + mempcpy.o memmem.o memmove.o memswap.o \ + perror.o qsort.o seed48.o \ + srand48.o sscanf.o strcasecmp.o strcat.o \ + strerror.o \ strnlen.o \ - strncat.o strncmp.o strncpy.o strndup.o \ - strncasecmp.o \ - stpcpy.o stpncpy.o \ + strncat.o strndup.o \ + stpncpy.o \ strntoimax.o strntoumax.o strrchr.o strsep.o strspn.o strstr.o \ strtoimax.o strtok.o strtol.o strtoll.o strtoul.o strtoull.o \ - strtoumax.o vfprintf.o vprintf.o vsnprintf.o vsprintf.o \ - asprintf.o vasprintf.o strlcpy.o strlcat.o \ + strtoumax.o vprintf.o vsprintf.o \ + asprintf.o vasprintf.o \ vsscanf.o \ skipspace.o \ chrreplace.o \ bufprintf.o \ inet.o \ \ - lmalloc.o lstrdup.o \ + lstrdup.o \ \ dprintf.o vdprintf.o \ \ @@ -145,16 +143,11 @@ LIBOTHER_OBJS = \ \ getcwd.o fdopendir.o \ \ - libgcc/__ashldi3.o libgcc/__udivdi3.o \ - libgcc/__negdi2.o libgcc/__ashrdi3.o libgcc/__lshrdi3.o \ - libgcc/__muldi3.o libgcc/__udivmoddi4.o libgcc/__umoddi3.o \ - libgcc/__divdi3.o libgcc/__moddi3.o \ - \ - sys/openconsole.o sys/line_input.o \ + sys/line_input.o \ sys/colortable.o sys/screensize.o \ \ sys/stdcon_read.o sys/stdcon_write.o sys/rawcon_read.o \ - sys/rawcon_write.o sys/err_read.o sys/err_write.o \ + sys/rawcon_write.o \ sys/null_read.o sys/null_write.o sys/serial_write.o \ \ sys/xserial_write.o \ @@ -168,16 +161,28 @@ LIBOTHER_OBJS = \ pci/writeb.o pci/writew.o pci/writel.o \ \ sys/x86_init_fpu.o math/pow.o math/strtod.o \ - \ - syslinux/memscan.o + +CORELIBOBJS = \ + memcpy.o memset.o memcmp.o printf.o strncmp.o vfprintf.o \ + strlen.o vsnprintf.o snprintf.o stpcpy.o strcmp.o strdup.o \ + strcpy.o strncpy.o setjmp.o fopen.o fread.o fread2.o puts.o \ + sprintf.o strlcat.o strchr.o strlcpy.o strncasecmp.o ctypes.o \ + fputs.o fwrite2.o fwrite.o fgetc.o fclose.o errno.o lmalloc.o \ + sys/err_read.o sys/err_write.o sys/null_read.o \ + sys/stdcon_write.o sys/openconsole.o \ + syslinux/memscan.o \ + libgcc/__ashldi3.o libgcc/__udivdi3.o \ + libgcc/__negdi2.o libgcc/__ashrdi3.o libgcc/__lshrdi3.o \ + libgcc/__muldi3.o libgcc/__udivmoddi4.o libgcc/__umoddi3.o \ + libgcc/__divdi3.o libgcc/__moddi3.o \ + $(LIBENTRY_OBJS) \ + $(LIBMODULE_OBJS) MINLIBOBJS = \ $(LIBOTHER_OBJS) \ - $(LIBENTRY_OBJS) \ $(LIBGCC_OBJS) \ $(LIBCONSOLE_OBJS) \ $(LIBLOAD_OBJS) \ - $(LIBMODULE_OBJS) \ $(LIBZLIB_OBJS) # $(LIBVESA_OBJS) @@ -204,7 +209,7 @@ AUXDIR = $(DATADIR)/syslinux INCDIR = /usr/include COM32DIR = $(AUXDIR)/com32 -all: libcom32.c32 libcom32min.a +all: libcom32.c32 libcom32min.a libcom32core.a libcom32.c32 : $(LIBOBJS) rm -f $@ @@ -215,6 +220,11 @@ libcom32min.a : $(MINLIBOBJS) $(AR) cq $@ $^ $(RANLIB) $@ +libcom32core.a : $(CORELIBOBJS) + rm -f $@ + $(AR) cq $@ $^ + $(RANLIB) $@ + tidy dist clean: rm -f sys/vesa/alphatbl.c find . \( -name \*.o -o -name \*.a -o -name .\*.d -o -name \*.tmp \) -print0 | \ diff --git a/core/Makefile b/core/Makefile index 5288da6..3898b4d 100644 --- a/core/Makefile +++ b/core/Makefile @@ -53,7 +53,7 @@ SOBJ := $(patsubst %.S,%.o,$(SSRC)) COBJS = $(filter-out rawcon.o plaincon.o,$(COBJ)) LIB = libcom32.a -LIBS = $(LIB) --whole-archive $(com32)/lib/libcom32min.a +LIBS = $(LIB) --whole-archive $(com32)/lib/libcom32core.a LIBDEP = $(filter-out -% %start%,$(LIBS)) LIBOBJS = $(COBJS) $(SOBJ) -- 1.7.4.4
Matt Fleming
2012-Mar-23 18:02 UTC
[syslinux] [PATCH 09/19] elf: Support __constructor and __destructor
From: Matt Fleming <matt.fleming at intel.com> The old way of specifying functions that need to be run before/after a main function has never worked for ELF modules. Instead, the only way to get similiar behaviour was by using the MODULE_INIT() and MODULE_EXIT() macros, but no one seems to have bothered converting the old __constructor users over. Anyway, the old way is superior because it allows multiple functions be specified. Delete the MODULE_* macros as there's only one user of them in the entire tree. We can also get rid of the UNKNOWN_MODULE constant because now a module doesn't need a __module_init_ptr symbol to be classed as a library - if a module isn't an executable, it's a library, there's no such thing as an unknown type. It's no longer necessary to explicitly call __syslinux_get_ipappend_strings() from ldlinux.c because the __constructor tag on the version in com32/lib/syslinux will take care of invoking it before ldlinux.c32's main() is executed. Also, since we've refactored unload_module() to now run a module's destructors let's minimise the number of callers by deleting load_library() and unload_library(), which were only called by the test module in com32/elflink. Signed-off-by: Matt Fleming <matt.fleming at intel.com> --- com32/elflink/ldlinux/Makefile | 2 +- com32/elflink/ldlinux/cli.c | 7 +-- com32/elflink/ldlinux/ipappend.c | 58 ----------------------- com32/elflink/ldlinux/ldlinux.c | 1 - com32/include/sys/exec.h | 23 --------- com32/include/sys/module.h | 32 ++++--------- com32/lib/Makefile | 3 +- com32/lib/elf32.ld | 10 +--- com32/lib/sys/module/common.c | 10 ++++- com32/lib/sys/module/elf_module.c | 93 ++++++++++++++++++++++++++++--------- com32/lib/sys/module/exec.c | 87 ++-------------------------------- mk/lib.mk | 2 +- 12 files changed, 103 insertions(+), 225 deletions(-) delete mode 100644 com32/elflink/ldlinux/ipappend.c diff --git a/com32/elflink/ldlinux/Makefile b/com32/elflink/ldlinux/Makefile index 9960277..ca4c7e2 100644 --- a/com32/elflink/ldlinux/Makefile +++ b/com32/elflink/ldlinux/Makefile @@ -20,7 +20,7 @@ LIBS = --whole-archive $(com32)/lib/libcom32min.a all: ldlinux.c32 ldlinux_lnx.a ldlinux.c32 : ldlinux.o cli.o readconfig.o refstr.o colors.o getadv.o \ - adv.o ipappend.o execute.o kernel.o get_key.o \ + adv.o execute.o kernel.o get_key.o \ advwrite.o setadv.o eprintf.o $(LD) $(LDFLAGS) -o $@ $^ $(LIBS) diff --git a/com32/elflink/ldlinux/cli.c b/com32/elflink/ldlinux/cli.c index 8be8c17..fb041ae 100644 --- a/com32/elflink/ldlinux/cli.c +++ b/com32/elflink/ldlinux/cli.c @@ -454,17 +454,14 @@ const char *edit_cmdline(const char *input, int top /*, int width */ , return len ? ret : NULL; } -static int cli_init(void) +static int __constructor cli_init(void) { INIT_LIST_HEAD(&cli_history_head); return 0; } -static void cli_exit(void) +static void __destructor cli_exit(void) { /* Nothing to do */ } - -MODULE_INIT(cli_init); -MODULE_EXIT(cli_exit); diff --git a/com32/elflink/ldlinux/ipappend.c b/com32/elflink/ldlinux/ipappend.c deleted file mode 100644 index cbd02b1..0000000 --- a/com32/elflink/ldlinux/ipappend.c +++ /dev/null @@ -1,58 +0,0 @@ -/* ----------------------------------------------------------------------- * - * - * Copyright 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. - * - * ----------------------------------------------------------------------- */ - -/* - * syslinux/ipappend.c - * - * Get ipappend strings - */ - -#include <syslinux/config.h> -#include <klibc/compiler.h> -#include <com32.h> - -struct syslinux_ipappend_strings __syslinux_ipappend_strings; -static const char *syslinux_ipappend_string_list[32]; - -void __syslinux_get_ipappend_strings(void) -{ - static com32sys_t reg; - int i; - - reg.eax.w[0] = 0x000f; - __intcall(0x22, ®, ®); - - if (!(reg.eflags.l & EFLAGS_CF)) { - __syslinux_ipappend_strings.count = reg.ecx.w[0]; - __syslinux_ipappend_strings.ptr = syslinux_ipappend_string_list; - for (i = 0; i < reg.ecx.w[0]; i++) { - syslinux_ipappend_string_list[i] - MK_PTR(reg.es, - *(uint16_t *) MK_PTR(reg.es, reg.ebx.w[0] + i * 2)); - } - } -} diff --git a/com32/elflink/ldlinux/ldlinux.c b/com32/elflink/ldlinux/ldlinux.c index dcde542..03e2f60 100644 --- a/com32/elflink/ldlinux/ldlinux.c +++ b/com32/elflink/ldlinux/ldlinux.c @@ -121,7 +121,6 @@ int main(int argc, char **argv) openconsole(&dev_rawcon_r, &dev_ansiserial_w); - __syslinux_get_ipappend_strings(); parse_configs(NULL); __syslinux_init(); diff --git a/com32/include/sys/exec.h b/com32/include/sys/exec.h index 9c00e4a..ac05c27 100644 --- a/com32/include/sys/exec.h +++ b/com32/include/sys/exec.h @@ -55,29 +55,6 @@ extern int exec_init(void); /** - * load_library - Loads a dynamic library into the environment. - * @name: the name of the library to load, including the extension - * (e.g. 'sort.c32') - * - * A dynamic library is an ELF module that may contain initialization and - * termination routines, but not a main routine. At the same time, any memory - * allocations using malloc() and its derivatives are made on behalf of the - * currently executing program or the COM32 root module. If the library - * is unloaded, no memory cleanup is performed. - */ -extern int load_library(const char *name); - -/** - * unload_library - unloads a library from the environment. - * @name: the name of the library to unload, including the extension - * (e.g. 'sort.c32') - * - * Note that no memory allocated by the library code is cleaned up, as the - * allocations belong to the innermost calling program in the call stack. - */ -extern int unload_library(const char *name); - -/** * spawnv - Executes a program in the current environment. * @name: the name of the program to spawn, including the extension * (e.g. 'hello.c32') diff --git a/com32/include/sys/module.h b/com32/include/sys/module.h index fb72c4b..d10eae9 100644 --- a/com32/include/sys/module.h +++ b/com32/include/sys/module.h @@ -24,7 +24,6 @@ /* * Some common information about what kind of modules we're dealing with */ -#define UNKNOWN_MODULE -1 #define EXEC_MODULE 0 #define LIB_MODULE 1 @@ -32,24 +31,6 @@ * Initialization and finalization function signatures */ - -/** - * module_init_t - pointer to a initialization routine - * - * The initialization routine is called after all module constructors were invoked. - * It takes no parameters and returns 0 if the module was initialized successfully, - * or a non-zero value if errors have occurred. - */ -typedef int (*module_init_t)(void); - -/** - * module_exit_t - pointer to a finalization routine - * - * The finalization routine is called before the module destructors are to be invoked. - * It simply executes some cleanup code, without error reporting. - */ -typedef void (*module_exit_t)(void); - /** * module_main_t - pointer to an entry routine * @@ -58,6 +39,14 @@ typedef void (*module_exit_t)(void); */ typedef int (*module_main_t)(int, char**); +/** + * module_ctor_t - pointer to a constructor or destructor routine + * + * A module may have multiple routines that need to be executed before + * or after the main routine. These are the constructors and + * destructors, respectively. + */ +typedef void (*module_ctor_t) (void); /** * struct elf_module - structure encapsulating a module loaded in memory. @@ -95,11 +84,10 @@ struct elf_module { struct list_head dependants; // Head of module dependants list struct list_head list; // The list entry in the module list - module_init_t *init_func; // The initialization entry point - module_exit_t *exit_func; // The module finalization code + module_ctor_t *ctors; // module constructors + module_ctor_t *dtors; // module destructors module_main_t main_func; // The main function (for executable modules) - void *module_addr; // The module location in the memory Elf32_Addr base_addr; // The base address of the module Elf32_Word module_size; // The module size in memory diff --git a/com32/lib/Makefile b/com32/lib/Makefile index 66cfcbf..bee1a02 100644 --- a/com32/lib/Makefile +++ b/com32/lib/Makefile @@ -47,7 +47,7 @@ LIBPCI_OBJS = \ LIBSYSLINUX_OBJS = \ syslinux/reboot.o syslinux/keyboard.o \ syslinux/features.o syslinux/config.o \ - syslinux/ipappend.o syslinux/dsinfo.o syslinux/version.o \ + syslinux/dsinfo.o syslinux/version.o \ syslinux/pxe_get_cached.o syslinux/pxe_get_nic.o \ syslinux/pxe_dns.o \ syslinux/video/fontquery.o syslinux/video/forcetext.o \ @@ -179,6 +179,7 @@ CORELIBOBJS = \ $(LIBMODULE_OBJS) MINLIBOBJS = \ + syslinux/ipappend.o \ $(LIBOTHER_OBJS) \ $(LIBGCC_OBJS) \ $(LIBCONSOLE_OBJS) \ diff --git a/com32/lib/elf32.ld b/com32/lib/elf32.ld index 158badb..ddf6e04 100644 --- a/com32/lib/elf32.ld +++ b/com32/lib/elf32.ld @@ -91,13 +91,9 @@ SECTIONS __ctors_start = .; KEEP (*(SORT(.ctors.*))) KEEP (*(.ctors)) - LONG(0x00000000) - __module_init_ptr = .; KEEP (*(.ctors_modinit)) - LONG(0x00000000) - __module_main_ptr = .; KEEP (*(.ctors_modmain)) - LONG(0x00000000) + __ctors_end = .; } .dtors : @@ -105,10 +101,8 @@ SECTIONS __dtors_start = .; KEEP (*(SORT(.dtors.*))) KEEP (*(.dtors)) - LONG(0x00000000) - __module_exit_ptr = .; KEEP (*(.dtors_modexit)) - LONG(0x00000000) + __dtors_end = .; } .jcr : { KEEP (*(.jcr)) } diff --git a/com32/lib/sys/module/common.c b/com32/lib/sys/module/common.c index 71ee0f0..b22e9c8 100644 --- a/com32/lib/sys/module/common.c +++ b/com32/lib/sys/module/common.c @@ -381,7 +381,7 @@ int module_unloadable(struct elf_module *module) { // Unloads the module from the system and releases all the associated memory -int module_unload(struct elf_module *module) { +int _module_unload(struct elf_module *module) { struct module_dep *crt_dep, *tmp; // Make sure nobody needs us if (!module_unloadable(module)) { @@ -410,6 +410,14 @@ int module_unload(struct elf_module *module) { return 0; } +int module_unload(struct elf_module *module) { + module_ctor_t *dtor; + + for (dtor = module->dtors; *dtor; dtor++) + (*dtor) (); + + return _module_unload(module); +} static Elf32_Sym *module_find_symbol_sysv(const char *name, struct elf_module *module) { unsigned long h = elf_hash((const unsigned char*)name); diff --git a/com32/lib/sys/module/elf_module.c b/com32/lib/sys/module/elf_module.c index 7d8dad4..ffdcd52 100644 --- a/com32/lib/sys/module/elf_module.c +++ b/com32/lib/sys/module/elf_module.c @@ -398,40 +398,79 @@ static int resolve_symbols(struct elf_module *module) { return 0; } +static int extract_operations(struct elf_module *module) { + Elf32_Sym *ctors_start, *ctors_end; + Elf32_Sym *dtors_start, *dtors_end; + module_ctor_t *ctors, *dtors; + ctors_start = module_find_symbol("__ctors_start", module); + ctors_end = module_find_symbol("__ctors_end", module); -static int extract_operations(struct elf_module *module) { - Elf32_Sym *init_sym = module_find_symbol(MODULE_ELF_INIT_PTR, module); - Elf32_Sym *exit_sym = module_find_symbol(MODULE_ELF_EXIT_PTR, module); - Elf32_Sym *main_sym = module_find_symbol("main", module); - - if (init_sym) { - module->init_func = (module_init_t*)module_get_absolute( - init_sym->st_value, module); - if (*(module->init_func) == NULL) { - module->init_func = NULL; + if (ctors_start && ctors_end) { + module_ctor_t *start, *end; + int nr_ctors = 0; + int i, size; + + start = module_get_absolute(ctors_start->st_value, module); + end = module_get_absolute(ctors_end->st_value, module); + + nr_ctors = end - start; + + size = nr_ctors * sizeof(module_ctor_t); + size += sizeof(module_ctor_t); /* NULL entry */ + + ctors = malloc(size); + if (!ctors) { + printf("Unable to alloc memory for ctors\n"); + return -1; } + + memset(ctors, 0, size); + for (i = 0; i < nr_ctors; i++) + ctors[i] = start[i]; + + module->ctors = ctors; } - if (exit_sym) { - module->exit_func = (module_exit_t*)module_get_absolute( - exit_sym->st_value, module); - if (*(module->exit_func) == NULL) { - module->exit_func = NULL; + dtors_start = module_find_symbol("__dtors_start", module); + dtors_end = module_find_symbol("__dtors_end", module); + + if (dtors_start && dtors_end) { + module_ctor_t *start, *end; + int nr_dtors = 0; + int i, size; + + start = module_get_absolute(dtors_start->st_value, module); + end = module_get_absolute(dtors_end->st_value, module); + + nr_dtors = end - start; + + size = nr_dtors * sizeof(module_ctor_t); + size += sizeof(module_ctor_t); /* NULL entry */ + + dtors = malloc(size); + if (!dtors) { + printf("Unable to alloc memory for dtors\n"); + free(ctors); + return -1; } - } - if (main_sym) - module->main_func - module_get_absolute(main_sym->st_value, module); + memset(dtors, 0, size); + for (i = 0; i < nr_dtors; i++) + dtors[i] = start[i]; + + module->dtors = dtors; + } return 0; } // Loads the module into the system int module_load(struct elf_module *module) { - int res; + int res, i; + Elf32_Sym *main_sym; Elf32_Ehdr elf_hdr; + module_ctor_t *ctor; // Do not allow duplicate modules if (module_find(module->name) != NULL) { @@ -505,8 +544,11 @@ int module_load(struct elf_module *module) { CHECKED(res, check_symbols(module), error); //printf("check... 5\n"); - // Obtain constructors and destructors - CHECKED(res, extract_operations(module), error); + main_sym = module_find_symbol("main", module); + if (main_sym) + module->main_func + module_get_absolute(main_sym->st_value, module); + //printf("check... 6\n"); // Add the module at the beginning of the module list @@ -515,6 +557,9 @@ int module_load(struct elf_module *module) { // Perform the relocations resolve_symbols(module); + // Obtain constructors and destructors + CHECKED(res, extract_operations(module), error); + //dprintf("module->symtable_size = %d\n", module->symtable_size); //print_elf_symbols(module); @@ -529,6 +574,10 @@ int module_load(struct elf_module *module) { (module->init_func == NULL) ? NULL : *(module->init_func), (module->exit_func == NULL) ? NULL : *(module->exit_func)); */ + + for (ctor = module->ctors; *ctor; ctor++) + (*ctor) (); + return 0; error: diff --git a/com32/lib/sys/module/exec.c b/com32/lib/sys/module/exec.c index 71d3192..29d0a2f 100644 --- a/com32/lib/sys/module/exec.c +++ b/com32/lib/sys/module/exec.c @@ -47,64 +47,7 @@ int exec_init(void) int get_module_type(struct elf_module *module) { if(module->main_func) return EXEC_MODULE; - else if(module->init_func) return LIB_MODULE; - return UNKNOWN_MODULE; -} - -int load_library(const char *name) -{ - int res; - struct elf_module *module = module_alloc(name); - - if (module == NULL) - return -1; - - res = module_load(module); - if (res != 0) { - module_unload(module); - return res; - } - - if (module->main_func != NULL) { - DBG_PRINT("Cannot load executable module as library.\n"); - module_unload(module); - return -1; - } - - if (module->init_func != NULL) { - res = (*(module->init_func))(); - if (res) - DBG_PRINT("Initialization error! function returned: %d\n", res); - } else { - DBG_PRINT("No initialization function present.\n"); - } - - if (res != 0) { - module_unload(module); - return res; - } - - return 0; -} - -int unload_library(const char *name) -{ - int res; - struct elf_module *module = module_find(name); - - if (module == NULL) - return -1; - - if (!module_unloadable(module)) { - return -1; - } - - if (module->exit_func != NULL) { - (*(module->exit_func))(); - } - - res = module_unload(module); - return res; + return LIB_MODULE; } jmp_buf __process_exit_jmp; @@ -243,7 +186,6 @@ int spawn_load(const char *name, int argc, char **argv) //malloc_tag_t prev_mem_tag; struct elf_module *module = module_alloc(name); struct elf_module *prev_module; - int type; dprintf("enter: name = %s", name); @@ -277,7 +219,7 @@ int spawn_load(const char *name, int argc, char **argv) res = module_load(module); if (res != 0) { - module_unload(module); + _module_unload(module); return res; } @@ -288,23 +230,7 @@ int spawn_load(const char *name, int argc, char **argv) dprintf("type = %d, prev = %s, cur = %s", type, prev_module->name, cur_module->name); - if(type==LIB_MODULE) - { - if (module->init_func != NULL) { - res = (*(module->init_func))(); - DBG_PRINT("Initialization function returned: %d\n", res); - } else { - DBG_PRINT("No initialization function present.\n"); - } - - if (res != 0) { - cur_module = prev_module; - module_unload(module); - return res; - } - return 0; - } - else if(type==EXEC_MODULE) + if(type==EXEC_MODULE) { previous = __syslinux_current; //prev_mem_tag = __mem_get_tag_global(); @@ -323,7 +249,6 @@ int spawn_load(const char *name, int argc, char **argv) else exit((module->main_func)(argc, argv)); /* Actually run! */ - // Clean up the allocation context //__free_tagged(module); // Restore the allocation context @@ -340,10 +265,8 @@ int spawn_load(const char *name, int argc, char **argv) return ((unsigned int)ret_val & 0xFF); } - /* - module_unload(module); - return -1; - */ + + return 0; } void exec_term(void) diff --git a/mk/lib.mk b/mk/lib.mk index 604b91a..ea817e6 100644 --- a/mk/lib.mk +++ b/mk/lib.mk @@ -39,7 +39,7 @@ OPTFLAGS = -Os -march=i386 -falign-functions=0 -falign-jumps=0 \ WARNFLAGS = $(GCCWARN) -Wpointer-arith -Wwrite-strings -Wstrict-prototypes -Winline CFLAGS = $(OPTFLAGS) $(REQFLAGS) $(WARNFLAGS) $(LIBFLAGS) -LDFLAGS = -m elf_i386 --hash-style=gnu +LDFLAGS = -m elf_i386 --hash-style=gnu -T $(com32)/lib/elf32.ld .SUFFIXES: .c .o .a .so .lo .i .S .s .ls .ss .lss -- 1.7.4.4
Matt Fleming
2012-Mar-23 18:02 UTC
[syslinux] [PATCH 10/19] ldlinux: Loading a config file should cause re-initialisation
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, ®, ®); - __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 + * 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
Matt Fleming
2012-Mar-23 18:02 UTC
[syslinux] [PATCH 11/19] elflink: Don't use strcmp on a non-NUL terminated string
From: Matt Fleming <matt.fleming at intel.com> The syslinux implementation of strcmp() only checks for NUL in the first argument and will use any NULs in the second argument for comparison with the corresponding character in the first string. This caused problems because at the time strcmp() is called 'path' isn't NUL-terminated. Since we're only checking the first character of 'path' just code it explicitly. This bug caused some modules not to load when resolving module dependencies via the ELF DT_NEEDED field because the "." in the PATH lookup code wouldn't be expanded to the current working directory. For example, instead of expanding to "/foo/bar" if /foo was the cwd, the path would be ".bar". Signed-off-by: Matt Fleming <matt.fleming at intel.com> --- com32/lib/sys/module/common.c | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/com32/lib/sys/module/common.c b/com32/lib/sys/module/common.c index b22e9c8..e26163f 100644 --- a/com32/lib/sys/module/common.c +++ b/com32/lib/sys/module/common.c @@ -74,7 +74,7 @@ again: if (*p == ':') p++; - if (!strcmp(path, ".")) { + if (path[0] == '.' && i == 1) { if (!core_getcwd(path, sizeof(path))) { DBG_PRINT("Could not get cwd\n"); return NULL; -- 1.7.4.4
Matt Fleming
2012-Mar-23 18:02 UTC
[syslinux] [PATCH 12/19] com32: Delete execute.c and use the one from ldlinux
From: Matt Fleming <matt.fleming at intel.com> ldlinux provides us with an execute.c and all the functions that we need, there's no point in duplicating the code in com32/menu. Also, the copy in ldlinux doesn't use __com32.cs_bounce. Using cs_bounce no longer works with dynamic ELF modules because we don't have such tight control over the address space. Instead, memory must be allocated dynamically or reserved as part of the object file. Signed-off-by: Matt Fleming <matt.fleming at intel.com> --- com32/menu/Makefile | 2 +- com32/menu/execute.c | 69 -------------------------------------------------- 2 files changed, 1 insertions(+), 70 deletions(-) delete mode 100644 com32/menu/execute.c diff --git a/com32/menu/Makefile b/com32/menu/Makefile index e1c700b..b771945 100644 --- a/com32/menu/Makefile +++ b/com32/menu/Makefile @@ -24,7 +24,7 @@ MODULES = menu.c32 vesamenu.c32 TESTFILES COMMONOBJS = menumain.o readconfig.o passwd.o drain.o printmsg.o colors.o \ - background.o refstr.o execute.o + background.o refstr.o all: $(MODULES) $(TESTFILES) diff --git a/com32/menu/execute.c b/com32/menu/execute.c deleted file mode 100644 index c2de735..0000000 --- a/com32/menu/execute.c +++ /dev/null @@ -1,69 +0,0 @@ -/* ----------------------------------------------------------------------- * - * - * Copyright 2004-2008 H. Peter Anvin - All Rights Reserved - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, - * Boston MA 02110-1301, USA; either version 2 of the License, or - * (at your option) any later version; incorporated herein by reference. - * - * ----------------------------------------------------------------------- */ - -#include <stdlib.h> -#include <string.h> -#include <com32.h> -#include "menu.h" - -void execute(const char *cmdline, enum kernel_type type) -{ - com32sys_t ireg; - const char *p, *const *pp; - char *q = __com32.cs_bounce; - const char *kernel, *args; - - memset(&ireg, 0, sizeof ireg); - - kernel = q; - p = cmdline; - while (*p && !my_isspace(*p)) { - *q++ = *p++; - } - *q++ = '\0'; - - args = q; - while (*p && my_isspace(*p)) - p++; - - strcpy(q, p); - - if (kernel[0] == '.' && type == KT_NONE) { - /* 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 (type == KT_LOCALBOOT) { - ireg.eax.w[0] = 0x0014; /* Local boot */ - ireg.edx.w[0] = strtoul(kernel, NULL, 0); - } else { - if (type < KT_KERNEL) - type = KT_KERNEL; - - ireg.eax.w[0] = 0x0016; /* Run kernel image */ - ireg.esi.w[0] = OFFS(kernel); - ireg.ds = SEG(kernel); - ireg.ebx.w[0] = OFFS(args); - ireg.es = SEG(args); - ireg.edx.l = type - KT_KERNEL; - /* ireg.ecx.l = 0; *//* We do ipappend "manually" */ - } - - __intcall(0x22, &ireg, NULL); - - /* If this returns, something went bad; return to menu */ -} -- 1.7.4.4
Matt Fleming
2012-Mar-23 18:02 UTC
[syslinux] [PATCH 13/19] ldlinux: chdir to the APPEND str when parsing a CONFIG directive
From: Matt Fleming <matt.fleming at intel.com> If an APPEND directive was specified for a CONFIG label then we need to chdir to that directory after parsing the new config file. Signed-off-by: Matt Fleming <matt.fleming at intel.com> --- com32/elflink/ldlinux/execute.c | 4 ++++ com32/elflink/ldlinux/readconfig.c | 5 +++++ core/fs/lib/searchconfig.c | 1 + core/include/core.h | 1 + 4 files changed, 11 insertions(+), 0 deletions(-) diff --git a/com32/elflink/ldlinux/execute.c b/com32/elflink/ldlinux/execute.c index c01d63f..b3ed958 100644 --- a/com32/elflink/ldlinux/execute.c +++ b/com32/elflink/ldlinux/execute.c @@ -96,6 +96,10 @@ void execute(const char *cmdline, enum kernel_type type) /* kernel contains the config file name */ realpath(ConfigName, kernel, FILENAME_MAX); + /* If we got anything on the command line, do a chdir */ + if (*args) + mangle_name(config_cwd, args); + start_ldlinux("ldlinux.c32", 1, argv); } else { /* process the image need int 22 support */ diff --git a/com32/elflink/ldlinux/readconfig.c b/com32/elflink/ldlinux/readconfig.c index 564cbef..573d724 100644 --- a/com32/elflink/ldlinux/readconfig.c +++ b/com32/elflink/ldlinux/readconfig.c @@ -1345,6 +1345,11 @@ static int parse_one_config(const char *filename) f = fdopen(fd, mode); parse_config_file(f); + if (config_cwd[0]) { + chdir(config_cwd); + config_cwd[0] = NULL; + } + return 0; } diff --git a/core/fs/lib/searchconfig.c b/core/fs/lib/searchconfig.c index 7fdad18..f688e7f 100644 --- a/core/fs/lib/searchconfig.c +++ b/core/fs/lib/searchconfig.c @@ -5,6 +5,7 @@ #include <fs.h> char ConfigName[FILENAME_MAX]; +char config_cwd[FILENAME_MAX]; /* * Common implementation of load_config diff --git a/core/include/core.h b/core/include/core.h index a247d49..d2aaf72 100644 --- a/core/include/core.h +++ b/core/include/core.h @@ -18,6 +18,7 @@ extern char trackbuf[]; extern char CurrentDirName[]; extern char SubvolName[]; extern char ConfigName[]; +extern char config_cwd[]; extern char KernelName[]; extern char cmd_line[]; extern char ConfigFile[]; -- 1.7.4.4
Matt Fleming
2012-Mar-23 18:02 UTC
[syslinux] [PATCH 14/19] ldlinux: Avoid initialised data memory corruption
From: Matt Fleming <matt.fleming at intel.com> We can't realloc() 'PATH' because realloc() may just extend the malloc'd region if the adjacent region is free, as opposed to allocating a new region and then copying the data. This behaviour is fine in most circumstances but not with initialised string data, such as 'PATH'. The reason is that other string data pointers may point to characters in 'PATH' and if we modify it after realloc()'ing, we'll appear to corrupt unrelated string data. For example, the string "/" is used in chdir() and the address of that string is the last "/" in 'PATH'. If we realloc() and then append "foo" to 'PATH' the string pointer in chdir() will now point to "/foo". Initialise 'PATH' at runtime using malloc() and free() to avoid corrupting string data. Signed-off-by: Matt Fleming <matt.fleming at intel.com> --- com32/elflink/ldlinux/readconfig.c | 3 ++- core/elflink/load_env32.c | 9 +++++++++ core/fs/fs.c | 2 +- core/include/fs.h | 1 + 4 files changed, 13 insertions(+), 2 deletions(-) diff --git a/com32/elflink/ldlinux/readconfig.c b/com32/elflink/ldlinux/readconfig.c index 573d724..4f7a4d2 100644 --- a/com32/elflink/ldlinux/readconfig.c +++ b/com32/elflink/ldlinux/readconfig.c @@ -1315,12 +1315,13 @@ do_include: new_path = refstrdup(skipspace(p + 4)); len = strlen(PATH); new_len = strlen(new_path); - _p = realloc(PATH, len + new_len + 2); + _p = malloc(len + new_len + 2); if (_p) { strncpy(_p, PATH, len); _p[len++] = ':'; strncpy(_p + len, new_path, new_len); _p[len + new_len] = '\0'; + free(PATH); PATH = _p; } else eprintf("Failed to realloc PATH\n"); diff --git a/core/elflink/load_env32.c b/core/elflink/load_env32.c index 75f5629..2dd4a7b 100644 --- a/core/elflink/load_env32.c +++ b/core/elflink/load_env32.c @@ -139,6 +139,15 @@ void load_env32(com32sys_t * regs) dprintf("Starting 32 bit elf module subsystem...\n"); call_constr(); + PATH = malloc(strlen(PATH_DEFAULT) + 1); + if (!PATH) { + printf("Couldn't allocate memory for PATH\n"); + return; + } + + strcpy(PATH, PATH_DEFAULT); + PATH[strlen(PATH_DEFAULT)] = '\0'; + init_module_subsystem(&core_module); start_ldlinux(argv); diff --git a/core/fs/fs.c b/core/fs/fs.c index a4fb4f7..d8f8660 100644 --- a/core/fs/fs.c +++ b/core/fs/fs.c @@ -8,7 +8,7 @@ #include "fs.h" #include "cache.h" -char *PATH = ".:/bin/"; +char *PATH; /* The currently mounted filesystem */ struct fs_info *this_fs = NULL; /* Root filesystem */ diff --git a/core/include/fs.h b/core/include/fs.h index a554a46..fd8e483 100644 --- a/core/include/fs.h +++ b/core/include/fs.h @@ -179,6 +179,7 @@ static inline struct file *handle_to_file(uint16_t handle) return handle ? &files[handle-1] : NULL; } +#define PATH_DEFAULT ".:/bin/" extern char *PATH; /* fs.c */ -- 1.7.4.4
Matt Fleming
2012-Mar-23 18:02 UTC
[syslinux] [PATCH 15/19] ldlinux: Make the default execute type KT_KERNEL
From: Matt Fleming <matt.fleming at intel.com> Default to trying to boot a linux kernel image, which was the behaviour of the old asm image file loader. Note that we don't need to go through __intcall() to load a kernel as the dynamic linker will fixup any references to the kernel load functions for us at runtime. Furthermore, modules invoking execute() could be located anywhere in the 32-bit address space and may not be able to represent their pointer arguments with SEG() and OFFS(), so using the comboot API may not even work. Signed-off-by: Matt Fleming <matt.fleming at intel.com> --- com32/elflink/ldlinux/execute.c | 25 +++++++------------------ 1 files changed, 7 insertions(+), 18 deletions(-) diff --git a/com32/elflink/ldlinux/execute.c b/com32/elflink/ldlinux/execute.c index b3ed958..269b74d 100644 --- a/com32/elflink/ldlinux/execute.c +++ b/com32/elflink/ldlinux/execute.c @@ -86,10 +86,6 @@ void execute(const char *cmdline, enum kernel_type type) /* new entry for elf format c32 */ lfree(kernel); create_args_and_load(cmdline); - } else if (type == KT_KERNEL) { - /* Need add one item for kernel load, as we don't use - * the assembly runkernel.inc any more */ - new_linux_kernel(kernel, cmdline); } else if (type == KT_CONFIG) { char *argv[] = { "ldlinux.c32", NULL }; @@ -101,22 +97,15 @@ void execute(const char *cmdline, enum kernel_type type) mangle_name(config_cwd, args); start_ldlinux("ldlinux.c32", 1, argv); - } else { + } else if (type == KT_LOCALBOOT) { /* process the image need int 22 support */ - if (type == KT_LOCALBOOT) { - ireg.eax.w[0] = 0x0014; /* Local boot */ - ireg.edx.w[0] = strtoul(kernel, NULL, 0); - } else { - ireg.eax.w[0] = 0x0016; /* Run kernel image */ - ireg.esi.w[0] = OFFS(kernel); - ireg.ds = SEG(kernel); - ireg.ebx.w[0] = OFFS(args); - ireg.es = SEG(args); - ireg.edx.l = type - KT_KERNEL; - /* ireg.ecx.l = 0; *//* We do ipappend "manually" */ - } - + ireg.eax.w[0] = 0x0014; /* Local boot */ + ireg.edx.w[0] = strtoul(kernel, NULL, 0); __intcall(0x22, &ireg, NULL); + } else { + /* Need add one item for kernel load, as we don't use + * the assembly runkernel.inc any more */ + new_linux_kernel(kernel, cmdline); } lfree(kernel); -- 1.7.4.4
Matt Fleming
2012-Mar-23 18:02 UTC
[syslinux] [PATCH 16/19] ldlinux: Disable VGA graphics when loading a kernel
From: Matt Fleming <matt.fleming at intel.com> The state of the graphics hardware is unknown when we're about to load a new kernel. It could be running in VGA mode, so let's disable VGA graphics before passing control to the kernel. The old assembly version of this code made extensive used of writestr(), which always calls vgaclearmode(). In the C version we're using printf() and so need to call vgaclearmode() directly. Doing it directly has the added advantage of documenting exactly where we need to reset the graphics hardware. Signed-off-by: Matt Fleming <matt.fleming at intel.com> --- com32/elflink/ldlinux/kernel.c | 1 + 1 files changed, 1 insertions(+), 0 deletions(-) diff --git a/com32/elflink/ldlinux/kernel.c b/com32/elflink/ldlinux/kernel.c index 2438d11..ed91b76 100644 --- a/com32/elflink/ldlinux/kernel.c +++ b/com32/elflink/ldlinux/kernel.c @@ -68,6 +68,7 @@ int new_linux_kernel(char *okernel, char *ocmdline) } */ + vgaclearmode(); printf("cmdline = %s\n", cmdline); /* printf("VkernelEnd = %x\n", VKernelEnd); -- 1.7.4.4
Matt Fleming
2012-Mar-23 18:02 UTC
[syslinux] [PATCH 17/19] ldlinux: Don't alloc initramfs unless initrd= is specified
From: Matt Fleming <matt.fleming at intel.com> It only makes sense to allocate memory for 'initramfs' if an initrdargument was on the command line, otherwise we're wasting memory. Furthermore needlessly allocating 'initramfs' actually caused old kernels, such as memtest86, to fail to run because of the following check in syslinux_boot_kernel(), if (initramfs && hdr.version < 0x0200) goto bail; /* initrd/initramfs not supported */ Move the allocation after we've checked for and found an initrdargument. Signed-off-by: Matt Fleming <matt.fleming at intel.com> --- com32/elflink/ldlinux/kernel.c | 12 ++++++------ 1 files changed, 6 insertions(+), 6 deletions(-) diff --git a/com32/elflink/ldlinux/kernel.c b/com32/elflink/ldlinux/kernel.c index ed91b76..6cda659 100644 --- a/com32/elflink/ldlinux/kernel.c +++ b/com32/elflink/ldlinux/kernel.c @@ -16,7 +16,7 @@ const char *append = NULL; int new_linux_kernel(char *okernel, char *ocmdline) { const char *kernel_name; - struct initramfs *initramfs; + struct initramfs *initramfs = NULL; char *temp; void *kernel_data; size_t kernel_len; @@ -99,16 +99,16 @@ int new_linux_kernel(char *okernel, char *ocmdline) if (!opt_quiet) printf("ok\n"); - /* Initialize the initramfs chain */ - initramfs = initramfs_init(); - if (!initramfs) - goto bail; - /* Find and load initramfs */ temp = strstr(cmdline, "initrd="); if (temp) { i = 0; + /* Initialize the initramfs chain */ + initramfs = initramfs_init(); + if (!initramfs) + goto bail; + temp += strlen("initrd="); while (*temp != ' ' && *temp) initrd_name[i++] = *temp++; -- 1.7.4.4
Matt Fleming
2012-Mar-23 18:02 UTC
[syslinux] [PATCH 18/19] mk: Don't link against compiler's version of libgcc
From: Matt Fleming <matt.fleming at intel.com> Syslinux provides its own copy of libgcc functions in com32/lib/libgcc, so we don't need to link against the version provided by the compiler. What's worse, the behaviour is different between the two versions. This caused problems, for example, when parsing the TOTALTIMEOUT config directive in com32/menu because of the following calculation, totaltimeout = (atoll(skipspace(p + 13)) * CLK_TCK + 9) / 10; which invokes __divdi3() as provided by libgcc. The results returned by the Syslinux and compiler's copy of libgcc differ, leading to differences in behaviour. Signed-off-by: Matt Fleming <matt.fleming at intel.com> --- mk/elf.mk | 3 +-- 1 files changed, 1 insertions(+), 2 deletions(-) diff --git a/mk/elf.mk b/mk/elf.mk index 5a2ce2d..ca06115 100644 --- a/mk/elf.mk +++ b/mk/elf.mk @@ -47,14 +47,13 @@ CFLAGS = $(GCCOPT) -W -Wall -march=i386 \ -I$(com32)/libutil/include -I$(com32)/include $(GPLINCLUDE) SFLAGS = $(GCCOPT) -D__COM32__ -march=i386 LDFLAGS = -m elf_i386 -shared --hash-style=gnu -T $(com32)/lib/elf32.ld -LIBGCC := $(shell $(CC) $(GCCOPT) --print-libgcc) LNXCFLAGS = -I$(com32)/libutil/include -W -Wall -O -g -D_GNU_SOURCE LNXSFLAGS = -g LNXLDFLAGS = -g C_LIBS = $(com32)/libutil/libutil_com.c32 $(GPLLIB) \ - $(com32)/lib/libcom32.c32 $(LIBGCC) + $(com32)/lib/libcom32.c32 C_LNXLIBS = $(com32)/libutil/libutil_lnx.a \ $(com32)/elflink/ldlinux/ldlinux_lnx.a -- 1.7.4.4
Matt Fleming
2012-Mar-23 18:02 UTC
[syslinux] [PATCH 19/19] core: Abstract search_config() into search_dirs()
From: Matt Fleming <matt.fleming at intel.com> The core currently abuses search_config() in order to locate ldlinux.c32. The problem with this is that search_config() updates ConfigName with the realpath of the file on every invocation. If we've previously set ConfigName search_config() will overwrite this value. Signed-off-by: Matt Fleming <matt.fleming at intel.com> --- core/elflink/load_env32.c | 5 +++-- core/fs/iso9660/iso9660.c | 2 +- core/fs/lib/loadconfig.c | 2 +- core/fs/lib/searchconfig.c | 18 +++++++++--------- core/include/fs.h | 5 +++-- 5 files changed, 17 insertions(+), 15 deletions(-) diff --git a/core/elflink/load_env32.c b/core/elflink/load_env32.c index 2dd4a7b..28bc70c 100644 --- a/core/elflink/load_env32.c +++ b/core/elflink/load_env32.c @@ -121,6 +121,7 @@ void load_env32(com32sys_t * regs) struct file_info *fp; int fd; char *argv[] = { LDLINUX, NULL }; + char *realname; static const char *search_directories[] = { "/boot/isolinux", @@ -155,7 +156,7 @@ void load_env32(com32sys_t * regs) /* * If we failed to load LDLINUX it could be because our * current working directory isn't the install directory. Try - * a bit harder to find LDLINUX. If search_config() succeeds + * a bit harder to find LDLINUX. If search_dirs() succeeds * in finding LDLINUX it will set the cwd. */ fd = opendev(&__file_dev, NULL, O_RDONLY); @@ -164,7 +165,7 @@ void load_env32(com32sys_t * regs) fp = &__file_info[fd]; - if (!search_config(&fp->i.fd, search_directories, filenames)) + if (!search_dirs(&fp->i.fd, search_directories, filenames, realname)) start_ldlinux(argv); } diff --git a/core/fs/iso9660/iso9660.c b/core/fs/iso9660/iso9660.c index 792cd99..fe58a5b 100644 --- a/core/fs/iso9660/iso9660.c +++ b/core/fs/iso9660/iso9660.c @@ -243,7 +243,7 @@ static int iso_open_config(struct com32_filedata *filedata) NULL }; - return search_config(filedata, search_directories, filenames); + return search_dirs(filedata, search_directories, filenames, ConfigName); } static int iso_fs_init(struct fs_info *fs) diff --git a/core/fs/lib/loadconfig.c b/core/fs/lib/loadconfig.c index 100500c..95e6f3f 100644 --- a/core/fs/lib/loadconfig.c +++ b/core/fs/lib/loadconfig.c @@ -30,5 +30,5 @@ int generic_open_config(struct com32_filedata *filedata) dprintf("CurrentDirName: \"%s\"\n", CurrentDirName); - return search_config(filedata, search_directories, filenames); + return search_dirs(filedata, search_directories, filenames, ConfigName); } diff --git a/core/fs/lib/searchconfig.c b/core/fs/lib/searchconfig.c index f688e7f..f7cfeac 100644 --- a/core/fs/lib/searchconfig.c +++ b/core/fs/lib/searchconfig.c @@ -8,28 +8,28 @@ char ConfigName[FILENAME_MAX]; char config_cwd[FILENAME_MAX]; /* - * Common implementation of load_config - * * This searches for a specified set of filenames in a specified set * of directories. If found, set the current working directory to * match. */ -int search_config(struct com32_filedata *filedata, - const char *search_directories[], const char *filenames[]) +int search_dirs(struct com32_filedata *filedata, + const char *search_directories[], + const char *filenames[], + char *realname) { - char confignamebuf[FILENAME_MAX]; + char namebuf[FILENAME_MAX]; const char *sd, **sdp; const char *sf, **sfp; for (sdp = search_directories; (sd = *sdp); sdp++) { for (sfp = filenames; (sf = *sfp); sfp++) { - snprintf(confignamebuf, sizeof confignamebuf, + snprintf(namebuf, sizeof namebuf, "%s%s%s", sd, (*sd && sd[strlen(sd)-1] == '/') ? "" : "/", sf); - realpath(ConfigName, confignamebuf, FILENAME_MAX); - dprintf("Config search: %s\n", ConfigName); - if (open_file(ConfigName, filedata) >= 0) { + realpath(realname, namebuf, FILENAME_MAX); + dprintf("Directory search: %s\n", realname); + if (open_file(realname, filedata) >= 0) { chdir(sd); return 0; /* Got it */ } diff --git a/core/include/fs.h b/core/include/fs.h index fd8e483..93eb818 100644 --- a/core/include/fs.h +++ b/core/include/fs.h @@ -218,8 +218,9 @@ int generic_chdir_start(void); void generic_mangle_name(char *, const char *); /* loadconfig.c */ -int search_config(struct com32_filedata *filedata, - const char *search_directores[], const char *filenames[]); +int search_dirs(struct com32_filedata *filedata, + const char *search_directores[], const char *filenames[], + char *realname); int generic_open_config(struct com32_filedata *filedata); /* close.c */ -- 1.7.4.4