From 77c1b364a530e51287f274a90b0744436c3312e8 Mon Sep 17 00:00:00 2001 From: Matt Fleming Date: Wed, 31 Oct 2012 14:17:49 +0000 Subject: pxe: Don't call open_config() from the pxe core Delete some stale comments about ldlinux.c32 requiring ConfigName to be initialised before it's launched - this is no longer true. ldlinux.c32 takes care of opening the config files. Signed-off-by: Matt Fleming --- core/pxelinux.asm | 13 +------------ 1 file changed, 1 insertion(+), 12 deletions(-) diff --git a/core/pxelinux.asm b/core/pxelinux.asm index ef9c7238..35c74088 100644 --- a/core/pxelinux.asm +++ b/core/pxelinux.asm @@ -192,8 +192,7 @@ ROOT_FS_OPS: call reset_idle ; -; Now we're all set to start with our *real* business. First load the -; configuration file (if any) and parse it. +; Now we're all set to start with our *real* business. ; ; In previous versions I avoided using 32-bit registers because of a ; rumour some BIOSes clobbered the upper half of 32-bit registers at @@ -216,16 +215,6 @@ ROOT_FS_OPS: pm_call unload_pxe %endmacro -; -; Open configuration file. ldlinux.c32 needs ConfigName to be set - so we need -; to call open_config() before loading it. -; -; Note: We don't need to check return value of open_config() function. It will -; call kaboom() on failure. -; - extern open_config - pm_call open_config - ; ; Jump to 32-bit ELF space ; -- cgit v1.2.1 From a06aa6db6177f412718d1d121b5cf83616c281e9 Mon Sep 17 00:00:00 2001 From: Matt Fleming Date: Wed, 31 Oct 2012 12:49:43 +0000 Subject: ldlinux: Print a warning if no config file is found This behaviour is taken from 4.06, where an error message is printed if no config file is found. A warning is a more user-friendly choice since Syslinux will still function without a config file. Signed-off-by: Matt Fleming --- com32/elflink/ldlinux/readconfig.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/com32/elflink/ldlinux/readconfig.c b/com32/elflink/ldlinux/readconfig.c index 1db397a1..2fa0641e 100644 --- a/com32/elflink/ldlinux/readconfig.c +++ b/com32/elflink/ldlinux/readconfig.c @@ -1420,7 +1420,10 @@ void parse_configs(char **argv) current_menu = root_menu; if (!argv || !*argv) { - parse_one_config(NULL); + if (parse_one_config(NULL) < 0) { + printf("WARNING: No configuration file found\n"); + return; + } } else { while ((filename = *argv++)) { dprintf("Parsing config: %s", filename); -- cgit v1.2.1 From 06f042df3c483c442f1150b862ef043711288f5e Mon Sep 17 00:00:00 2001 From: Matt Fleming Date: Wed, 31 Oct 2012 12:42:25 +0000 Subject: ldlinux: Fix logic if no DEFAULT or UI directive is found Somewhere along the way the code that prints, No DEFAULT or UI configuration directive found! was broken, and now no longer prints at all. While we're fixing this it's a good opportunity to rework the logic to be clearer. Now we only print the message if a config file was found, since these directives are obviously missing if there is no config file (a warning will be printed about the lack of config file anyway). Signed-off-by: Matt Fleming --- com32/elflink/ldlinux/config.h | 2 +- com32/elflink/ldlinux/execute.c | 2 +- com32/elflink/ldlinux/ldlinux.c | 56 ++++++++++++++++++++--------------------- 3 files changed, 30 insertions(+), 30 deletions(-) diff --git a/com32/elflink/ldlinux/config.h b/com32/elflink/ldlinux/config.h index ea4736e6..63e33b69 100644 --- a/com32/elflink/ldlinux/config.h +++ b/com32/elflink/ldlinux/config.h @@ -47,6 +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); +extern void ldlinux_enter_command(void); #endif /* __CONFIG_H__ */ diff --git a/com32/elflink/ldlinux/execute.c b/com32/elflink/ldlinux/execute.c index e7969c2e..6ccde49d 100644 --- a/com32/elflink/ldlinux/execute.c +++ b/com32/elflink/ldlinux/execute.c @@ -102,7 +102,7 @@ void execute(const char *cmdline, uint32_t type) * e.g. from vesamenu.c32. */ unload_modules_since("ldlinux.c32"); - ldlinux_enter_command(!noescape); + ldlinux_enter_command(); } 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 d9635956..59c55980 100644 --- a/com32/elflink/ldlinux/ldlinux.c +++ b/com32/elflink/ldlinux/ldlinux.c @@ -216,41 +216,36 @@ static void enter_cmdline(void) printf("\n"); /* return if user only press enter or we timed out */ - if (!cmdline || cmdline[0] == '\0') + if (!cmdline || cmdline[0] == '\0') { + if (ontimeoutlen) + load_kernel(ontimeout); return; + } load_kernel(cmdline); } } -void ldlinux_enter_command(bool prompt) +/* + * If this function returns you must call ldinux_enter_command() to + * preserve the 4.0x behaviour. + */ +void ldlinux_auto_boot(void) { - 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 { + if (!defaultlevel) { + if (strlen(ConfigName)) printf("No DEFAULT or UI configuration directive found!\n"); + if (noescape) + kaboom(); + } else + load_kernel(default_cmd); +} - if (noescape) - kaboom(); - } - } - -cmdline: - /* Only returns if the user pressed enter or input timed out */ +void ldlinux_enter_command(void) +{ + if (noescape) + ldlinux_auto_boot(); enter_cmdline(); - - cmdline = ontimeoutlen ? ontimeout : default_cmd; - - goto auto_boot; } /* @@ -291,7 +286,7 @@ int main(int argc __unused, char **argv __unused) cmdline = dst = malloc(count + 1); if (!dst) { printf("Failed to allocate memory for ADV\n"); - ldlinux_enter_command(true); + ldlinux_enter_command(); } for (i = 0; i < count; i++) @@ -303,11 +298,16 @@ int main(int argc __unused, char **argv __unused) syslinux_adv_write(); load_kernel(cmdline); /* Shouldn't return */ - ldlinux_enter_command(true); + ldlinux_enter_command(); } /* TODO: Check KbdFlags? */ + if (!forceprompt) + ldlinux_auto_boot(); + + if (defaultlevel > 1) + ldlinux_auto_boot(); - ldlinux_enter_command(forceprompt); + ldlinux_enter_command(); return 0; } -- cgit v1.2.1 From 7cb503fd746b80c8613a3e76dde93aedb6e75830 Mon Sep 17 00:00:00 2001 From: Matt Fleming Date: Wed, 31 Oct 2012 15:55:02 +0000 Subject: ldlinux: get_key() requires raw access to user input commit 4503e6260c0 ("ldlinux: Use stdcon instead of rawcon for the console") broke get_key() because it was no longer possible to read raw data from stdin. Provide a new function raw_read() that will return user input a character at a time. Signed-off-by: Matt Fleming --- com32/elflink/ldlinux/Makefile | 2 +- com32/elflink/ldlinux/get_key.c | 22 +++++++++++++++++++++- com32/libutil/ansiraw.c | 19 +++++++++++++++++++ 3 files changed, 41 insertions(+), 2 deletions(-) diff --git a/com32/elflink/ldlinux/Makefile b/com32/elflink/ldlinux/Makefile index dc48ca97..0666d9f6 100644 --- a/com32/elflink/ldlinux/Makefile +++ b/com32/elflink/ldlinux/Makefile @@ -14,7 +14,7 @@ topdir = ../../.. MAKEDIR = $(topdir)/mk include $(MAKEDIR)/elf.mk -CFLAGS += -I$(topdir)/core/elflink -I$(topdir)/core/include +CFLAGS += -I$(topdir)/core/elflink -I$(topdir)/core/include -I$(topdir)/com32/lib LIBS = --whole-archive $(com32)/lib/libcom32min.a all: ldlinux.c32 ldlinux_lnx.a diff --git a/com32/elflink/ldlinux/get_key.c b/com32/elflink/ldlinux/get_key.c index 0be06b98..123171ae 100644 --- a/com32/elflink/ldlinux/get_key.c +++ b/com32/elflink/ldlinux/get_key.c @@ -41,6 +41,7 @@ #include #include #include +#include struct keycode { int code; @@ -146,6 +147,25 @@ int get_key_decode(char *buffer, int nc, int *code) return rv; } +#ifdef __COM32__ +extern ssize_t __rawcon_read(struct file_info *fp, void *buf, size_t count); + +int raw_read(int fd, void *buf, size_t count) +{ + (void)fd; + + /* + * Instead of using the read(2) stdlib function use + * __rawcon_read() directly since we want a single key and + * don't want any processing/batching of the user input to + * occur - we want the raw data. + */ + return __rawcon_read(NULL, buf, count); +} +#else +extern int raw_read(int fd, void *buf, size_t count); +#endif + int get_key(FILE * f, clock_t timeout) { char buffer[KEY_MAXLEN]; @@ -162,7 +182,7 @@ int get_key(FILE * f, clock_t timeout) nc = 0; start = times(NULL); do { - rv = read(fileno(f), &ch, 1); + rv = raw_read(fileno(f), &ch, 1); if (rv == 0 || (rv == -1 && errno == EAGAIN)) { clock_t lateness = times(NULL) - start; if (nc && lateness > 1 + KEY_TIMEOUT) { diff --git a/com32/libutil/ansiraw.c b/com32/libutil/ansiraw.c index 2afd48a7..b67768c5 100644 --- a/com32/libutil/ansiraw.c +++ b/com32/libutil/ansiraw.c @@ -47,6 +47,7 @@ void console_ansi_raw(void) #include #include +#include static struct termios original_termios_settings; @@ -82,4 +83,22 @@ void console_ansi_raw(void) tcsetattr(0, TCSAFLUSH, &tio); } +int raw_read(int fd, void *buf, size_t count) +{ + struct termios tio, rtio; + int rv; + + tcgetattr(fd, &tio); + + cfmakeraw(&rtio); + tcsetattr(fd, 0, &rtio); + + rv = read(fd, buf, count); + + /* Restore settings */ + tcsetattr(fd, 0, &tio); + + return rv; +} + #endif -- cgit v1.2.1 From e55d4988880a538fa81fe6bb2bf4fd5604174f06 Mon Sep 17 00:00:00 2001 From: Matt Fleming Date: Thu, 1 Nov 2012 09:50:46 +0000 Subject: com32: Include .init_array section in .ctors in linker script GCC 4.7 now places pointers to functions with the 'constructor' and 'destructor' function attributes in .init_array and .fini_array sections, respectively, whereas previously they were in the .ctors and .dtors sections. This change breaks the ctors/dtors code as it only expects function to be in the .ctors and .dtors sections, meaning the ctors and dtors functions are never executed. While a COM32_INIT() macro exists that places functions in the .init_array section, no function makes use of it, so there should be no fallout from this change. Signed-off-by: Matt Fleming --- com32/lib/elf32.ld | 15 ++++----------- com32/lib/init.h | 15 --------------- com32/lib/malloc.c | 1 - 3 files changed, 4 insertions(+), 27 deletions(-) delete mode 100644 com32/lib/init.h diff --git a/com32/lib/elf32.ld b/com32/lib/elf32.ld index ddf6e048..16d10a38 100644 --- a/com32/lib/elf32.ld +++ b/com32/lib/elf32.ld @@ -75,17 +75,6 @@ SECTIONS { KEEP (*(.preinit_array)) } - .init_array : - { - KEEP (*(SORT(.init_array.*))) - KEEP (*(.init_array)) - } - .fini_array : - { - KEEP (*(.fini_array)) - KEEP (*(SORT(.fini_array.*))) - } - .ctors : { __ctors_start = .; @@ -93,6 +82,8 @@ SECTIONS KEEP (*(.ctors)) KEEP (*(.ctors_modinit)) KEEP (*(.ctors_modmain)) + KEEP (*(SORT(.init_array.*))) + KEEP (*(.init_array)) __ctors_end = .; } @@ -102,6 +93,8 @@ SECTIONS KEEP (*(SORT(.dtors.*))) KEEP (*(.dtors)) KEEP (*(.dtors_modexit)) + KEEP (*(.fini_array)) + KEEP (*(SORT(.fini_array.*))) __dtors_end = .; } diff --git a/com32/lib/init.h b/com32/lib/init.h deleted file mode 100644 index 2d983427..00000000 --- a/com32/lib/init.h +++ /dev/null @@ -1,15 +0,0 @@ -/* - * init.h - * - * Magic to set up initializers - */ - -#ifndef _INIT_H -#define _INIT_H 1 - -#include - -#define COM32_INIT(x) static const void * const __COM32_INIT \ - __attribute__((section(".init_array"),unused)) = (const void * const)&x - -#endif /* _INIT_H */ diff --git a/com32/lib/malloc.c b/com32/lib/malloc.c index ec103ab3..ce35f3d1 100644 --- a/com32/lib/malloc.c +++ b/com32/lib/malloc.c @@ -8,7 +8,6 @@ #include #include #include -#include "init.h" #include "malloc.h" struct free_arena_header __malloc_head = { -- cgit v1.2.1 From c7381a5cef7f38e0176b8bc90e7ca54c4d0711d2 Mon Sep 17 00:00:00 2001 From: Matt Fleming Date: Thu, 1 Nov 2012 10:56:06 +0000 Subject: CLI: Fix command history traversal The up/down keys were broken with respect to traversing through the command history because it was dereferencing a NULL pointer on the first iteration. Signed-off-by: Matt Fleming --- com32/elflink/ldlinux/cli.c | 22 ++++++++++++++++++---- 1 file changed, 18 insertions(+), 4 deletions(-) diff --git a/com32/elflink/ldlinux/cli.c b/com32/elflink/ldlinux/cli.c index a1cf50cc..65a50577 100644 --- a/com32/elflink/ldlinux/cli.c +++ b/com32/elflink/ldlinux/cli.c @@ -340,9 +340,16 @@ const char *edit_cmdline(const char *input, int top /*, int width */ , case KEY_UP: { if (!list_empty(&cli_history_head)) { + struct list_head *next; + + if (!comm_counter) + next = cli_history_head.next; + else + next = comm_counter->list.next; + comm_counter = - list_entry(comm_counter->list.next, - typeof(*comm_counter), list); + list_entry(next, typeof(*comm_counter), list); + if (&comm_counter->list == &cli_history_head) { strcpy(cmdline, temp_cmdline); } else { @@ -357,9 +364,16 @@ const char *edit_cmdline(const char *input, int top /*, int width */ , case KEY_DOWN: { if (!list_empty(&cli_history_head)) { + struct list_head *prev; + + if (!comm_counter) + prev = cli_history_head.prev; + else + prev = comm_counter->list.prev; + comm_counter = - list_entry(comm_counter->list.prev, - typeof(*comm_counter), list); + list_entry(prev, typeof(*comm_counter), list); + if (&comm_counter->list == &cli_history_head) { strcpy(cmdline, temp_cmdline); } else { -- cgit v1.2.1 From b5d5717baa264897425a4bdd8f64ac393756f64a Mon Sep 17 00:00:00 2001 From: Matt Fleming Date: Thu, 1 Nov 2012 11:12:03 +0000 Subject: win: Fix installing to a directory commit bda54cb68067 ("installers: Install ldlinux.c32 automatically)" introduced a bug in the move_file() function. move_file() isn't deleting the destination path, including the --directory argument, that ldlinux.sys should be installed to ('new_name'), which means that the MoveFile() calls fails. What it's actually doing is deleting ldlinux.sys from the file destination system. Signed-off-by: Matt Fleming --- win/syslinux.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/win/syslinux.c b/win/syslinux.c index f8e27801..64369d5c 100644 --- a/win/syslinux.c +++ b/win/syslinux.c @@ -270,8 +270,8 @@ static void move_file(char *pathname, char *filename) memcpy(cp, filename, 12); /* Delete any previous file */ - SetFileAttributes(pathname, FILE_ATTRIBUTE_NORMAL); - DeleteFile(pathname); + SetFileAttributes(new_name, FILE_ATTRIBUTE_NORMAL); + DeleteFile(new_name); if (!MoveFile(pathname, new_name)) SetFileAttributes(pathname, FILE_ATTRIBUTE_READONLY | FILE_ATTRIBUTE_SYSTEM | -- cgit v1.2.1 From 8eb17b56985cd5aea70ab5947585615b08da6151 Mon Sep 17 00:00:00 2001 From: Matt Fleming Date: Thu, 1 Nov 2012 11:30:42 +0000 Subject: win: Print error message if we fail to install to --directory Instead of silently returning with no indication of error if we couldn't install to the --directory argument, print an error message that tells the user the files are not where they wanted. Signed-off-by: Matt Fleming --- win/syslinux.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/win/syslinux.c b/win/syslinux.c index 64369d5c..c291f005 100644 --- a/win/syslinux.c +++ b/win/syslinux.c @@ -272,11 +272,15 @@ static void move_file(char *pathname, char *filename) /* Delete any previous file */ SetFileAttributes(new_name, FILE_ATTRIBUTE_NORMAL); DeleteFile(new_name); - if (!MoveFile(pathname, new_name)) + if (!MoveFile(pathname, new_name)) { + fprintf(stderr, + "Failed to move %s to destination directory: %s\n", + filename, opt.directory); + SetFileAttributes(pathname, FILE_ATTRIBUTE_READONLY | FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN); - else + } else SetFileAttributes(new_name, FILE_ATTRIBUTE_READONLY | FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN); -- cgit v1.2.1 From 967ee8a1ed49092ed2a6296936698a40b115a013 Mon Sep 17 00:00:00 2001 From: Matt Fleming Date: Thu, 1 Nov 2012 12:26:22 +0000 Subject: CLI: Add Ctrl + V support for printing the Syslinux version The cli code is missing support for printing the version string that is available in Syslinux 4.06 and earlier. Signed-off-by: Matt Fleming --- com32/elflink/ldlinux/cli.c | 10 ++++++++++ core/diskstart.inc | 1 + core/include/core.h | 1 + core/pxelinux.asm | 3 ++- 4 files changed, 14 insertions(+), 1 deletion(-) diff --git a/com32/elflink/ldlinux/cli.c b/com32/elflink/ldlinux/cli.c index 65a50577..ebeaeece 100644 --- a/com32/elflink/ldlinux/cli.c +++ b/com32/elflink/ldlinux/cli.c @@ -13,6 +13,7 @@ #include #include #include +#include #include "getkey.h" #include "menu.h" @@ -421,6 +422,15 @@ const char *edit_cmdline(const char *input, int top /*, int width */ , redraw = 1; break; } + case KEY_CTRL('V'): + if (BIOSName) + eprintf("%s%s%s", syslinux_banner, + MK_PTR(0, BIOSName), copyright_str); + else + eprintf("%s%s", syslinux_banner, copyright_str); + + redraw = 1; + break; default: if (key >= ' ' && key <= 0xFF && len < MAX_CMDLINE_LEN - 1) { diff --git a/core/diskstart.inc b/core/diskstart.inc index c8f79366..8806593d 100644 --- a/core/diskstart.inc +++ b/core/diskstart.inc @@ -142,6 +142,7 @@ print_bios: call writestr_early section .earlybss + global BIOSName alignb 2 %define HAVE_BIOSNAME 1 BIOSName resw 1 diff --git a/core/include/core.h b/core/include/core.h index da94dbf4..a6ecbc4a 100644 --- a/core/include/core.h +++ b/core/include/core.h @@ -24,6 +24,7 @@ extern char cmd_line[]; extern char ConfigFile[]; extern char syslinux_banner[]; extern char copyright_str[]; +extern uint16_t BIOSName; extern char StackBuf[]; extern unsigned int __bcopyxx_len; diff --git a/core/pxelinux.asm b/core/pxelinux.asm index 35c74088..63334ffa 100644 --- a/core/pxelinux.asm +++ b/core/pxelinux.asm @@ -81,12 +81,13 @@ InitStack resd 1 PXEStack resd 1 ; Saved stack during PXE call alignb 4 - global DHCPMagic, RebootTime, APIVer + global DHCPMagic, RebootTime, APIVer, BIOSName RebootTime resd 1 ; Reboot timeout, if set by option StrucPtr resw 2 ; Pointer to PXENV+ or !PXE structure APIVer resw 1 ; PXE API version found LocalBootType resw 1 ; Local boot return code DHCPMagic resb 1 ; PXELINUX magic flags +BIOSName resw 1 ; Dummy variable - always 0 section .text16 global StackBuf -- cgit v1.2.1 From 8eaa4ebbe2a6999bd58aa68054dd48ec26cabd28 Mon Sep 17 00:00:00 2001 From: Matt Fleming Date: Fri, 2 Nov 2012 21:52:52 -0400 Subject: linux.c32: Add find_arguments function The 'find_argument' function already finds the last instance of a command-line option. For symmetry, we introduce a 'find_arguments' function which will help to iterate each instance of a command-line option. Also, this commit uses 'strncmp' in both, instead of 'memcmp'. Modified-by: Shao Miller Signed-off-by: Shao Miller --- com32/modules/linux.c | 57 ++++++++++++++++++++++++++++++++++++--------------- 1 file changed, 41 insertions(+), 16 deletions(-) diff --git a/com32/modules/linux.c b/com32/modules/linux.c index e4c067ff..0d9e962e 100644 --- a/com32/modules/linux.c +++ b/com32/modules/linux.c @@ -59,13 +59,34 @@ static char *find_argument(char **argv, const char *argument) char *ptr = NULL; for (arg = argv; *arg; arg++) { - if (!memcmp(*arg, argument, la)) + if (!strncmp(*arg, argument, la)) ptr = *arg + la; } return ptr; } +/* Find the next instance of a particular command line argument */ +static char **find_arguments(char **argv, char **ptr, + const char *argument) +{ + int la = strlen(argument); + char **arg; + + for (arg = argv; *arg; arg++) { + if (!strncmp(*arg, argument, la)) { + *ptr = *arg + la; + break; + } + } + + /* Exhausted all arguments */ + if (!*arg) + return NULL; + + return arg; +} + /* Search for a boolean argument; return its position, or 0 if not present */ static int find_boolean(char **argv, const char *argument) { @@ -246,24 +267,28 @@ int main(int argc, char *argv[]) if (!setup_data) goto bail; - for (argl = argv; (arg = *argl); argl++) { - if (!memcmp(arg, "dtb=", 4)) { - if (setup_data_file(setup_data, SETUP_DTB, arg+4, opt_quiet)) - goto bail; - } else if (!memcmp(arg, "blob.", 5)) { - uint32_t type; - char *ep; + argl = argv; + while ((argl = find_arguments(argl, &arg, "dtb="))) { + argl++; + if (setup_data_file(setup_data, SETUP_DTB, arg, opt_quiet)) + goto bail; + } - type = strtoul(arg + 5, &ep, 10); - if (ep[0] != '=' || !ep[1]) - continue; + argl = argv; + while ((argl = find_arguments(argl, &arg, "blob."))) { + uint32_t type; + char *ep; - if (!type) - continue; + argl++; + type = strtoul(arg, &ep, 10); + if (ep[0] != '=' || !ep[1]) + continue; - if (setup_data_file(setup_data, type, ep+1, opt_quiet)) - goto bail; - } + if (!type) + continue; + + if (setup_data_file(setup_data, type, ep+1, opt_quiet)) + goto bail; } /* This should not return... */ -- cgit v1.2.1 From 5d7c2cdf73c3d901637d8e9f0a612f2cd8624cd0 Mon Sep 17 00:00:00 2001 From: Shao Miller Date: Thu, 25 Oct 2012 02:17:36 -0400 Subject: linux.c32: Move some initrd=x,y,z code out of main In handling an "initrd=x,y,z" option, it seems reasonable to be able to handle similar options in a similar fashion, so some of the code has been moved out of 'main' and into a new 'process_initramfs_args' function. Signed-off-by: Shao Miller --- com32/modules/linux.c | 82 ++++++++++++++++++++++++++++++++++++++------------- 1 file changed, 61 insertions(+), 21 deletions(-) diff --git a/com32/modules/linux.c b/com32/modules/linux.c index 0d9e962e..3ff50076 100644 --- a/com32/modules/linux.c +++ b/com32/modules/linux.c @@ -48,6 +48,13 @@ #include #include +enum ldmode { + ldmode_raw, + ldmodes +}; + +typedef int f_ldinitramfs(struct initramfs *, char *); + const char *progname = "linux.c32"; /* Find the last instance of a particular command line argument @@ -130,6 +137,55 @@ static char *make_cmdline(char **argv) return cmdline; } +static f_ldinitramfs ldinitramfs_raw; +static int ldinitramfs_raw(struct initramfs *initramfs, char *fname) +{ + return initramfs_load_archive(initramfs, fname); +} + +/* It only makes sense to call this function from main */ +static int process_initramfs_args(char *arg, struct initramfs *initramfs, + const char *kernel_name, enum ldmode mode, + bool opt_quiet) +{ + const char *mode_msg; + f_ldinitramfs *ldinitramfs; + char *p; + + switch (mode) { + case ldmode_raw: + mode_msg = "Loading"; + ldinitramfs = ldinitramfs_raw; + break; + case ldmodes: + default: + return 1; + } + + do { + p = strchr(arg, ','); + if (p) + *p = '\0'; + + if (!opt_quiet) + printf("%s %s... ", mode_msg, arg); + errno = 0; + if (ldinitramfs(initramfs, arg)) { + if (opt_quiet) + printf("Loading %s ", kernel_name); + printf("failed: "); + return 1; + } + if (!opt_quiet) + printf("ok\n"); + + if (p) + *p++ = ','; + } while ((arg = p)); + + return 0; +} + static int setup_data_file(struct setup_data *setup_data, uint32_t type, const char *filename, bool opt_quiet) @@ -163,7 +219,7 @@ int main(int argc, char *argv[]) bool opt_quiet = false; void *dhcpdata; size_t dhcplen; - char **argp, **argl, *arg, *p; + char **argp, **argl, *arg; (void)argc; argp = argv + 1; @@ -228,27 +284,11 @@ int main(int argc, char *argv[]) goto bail; } + /* Process initramfs arguments */ if ((arg = find_argument(argp, "initrd="))) { - do { - p = strchr(arg, ','); - if (p) - *p = '\0'; - - if (!opt_quiet) - printf("Loading %s... ", arg); - errno = 0; - if (initramfs_load_archive(initramfs, arg)) { - if (opt_quiet) - printf("Loading %s ", kernel_name); - printf("failed: "); - goto bail; - } - if (!opt_quiet) - printf("ok\n"); - - if (p) - *p++ = ','; - } while ((arg = p)); + if (process_initramfs_args(arg, initramfs, kernel_name, ldmode_raw, + opt_quiet)) + goto bail; } /* Append the DHCP info */ -- cgit v1.2.1 From 66484b55fe52e1393b8c6b522ca8d18b898e18f3 Mon Sep 17 00:00:00 2001 From: Shao Miller Date: Thu, 25 Oct 2012 03:58:07 -0400 Subject: linux.c32: Add new initrd+= option for multiple initrds linux.c32 now processes the kernel's command-line for "initrd+=" options. Given "initrd+=foo", linux.c32 will concatenate the file "foo" to the initrds that it has already loaded due to the "initrd=" option. Given "initrd+=foo,bar", linux.c32 will concatenate both files "foo" and "bar" to the initrds that it has already loaded due to the "initrd=" option. That is, multiple filenames can be specified with comma separators. Given "initrd+=foo initrd+=bar", linux.c32 will concatenate both files "foo" and "bar" to the initrds that it has already loaded due to the "initrd=" option. That is, the "initrd+=" option can be specified multiple times. The position of any "initrd=" option relative to any "initrd+=" option is irrelevant. The "initrd=" option is always processed before all "initrd+=" options. PLEASE NOTE: It is important to note that there are NO SPACES involved in using the "initrd+=" option. "initrd += foo" will not work. Signed-off-by: Shao Miller --- com32/modules/linux.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/com32/modules/linux.c b/com32/modules/linux.c index 3ff50076..11cdc18f 100644 --- a/com32/modules/linux.c +++ b/com32/modules/linux.c @@ -291,6 +291,14 @@ int main(int argc, char *argv[]) goto bail; } + argl = argv; + while ((argl = find_arguments(argl, &arg, "initrd+="))) { + argl++; + if (process_initramfs_args(arg, initramfs, kernel_name, ldmode_raw, + opt_quiet)) + goto bail; + } + /* Append the DHCP info */ if (opt_dhcpinfo && !pxe_get_cached_info(PXENV_PACKET_TYPE_DHCP_ACK, &dhcpdata, &dhcplen)) { -- cgit v1.2.1 From fb3e1a576ca0243c37786bfd81cc9600d589db45 Mon Sep 17 00:00:00 2001 From: Shao Miller Date: Thu, 25 Oct 2012 21:25:38 -0400 Subject: linux.c32: Introduce initrdfile= option It is useful to be able to load a file and pass it into a kernel's rootfs via the initramfs scheme. Given "initrdfile=foo", we will load the file foo, encapsulate it with the initramfs cpio format, then pass it alongside any initramfs files that were specified by "initrd=" and "initrd+=" options. One can specify the desired path/filename for the file to have within the rootfs by using the at (@) sign, as in: initrdfile=foo@/goes/to/foo One can also specify multiple files, separated by commas, such as: initrdfile=foo,bar@/somewhere/bar,baz One can also use this option multiple times, as in: initrdfile=foo,bar initrdfile=baz@/somewhere/baz Signed-off-by: Shao Miller --- com32/modules/linux.c | 53 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 53 insertions(+) diff --git a/com32/modules/linux.c b/com32/modules/linux.c index 11cdc18f..f657eab4 100644 --- a/com32/modules/linux.c +++ b/com32/modules/linux.c @@ -50,6 +50,7 @@ enum ldmode { ldmode_raw, + ldmode_cpio, ldmodes }; @@ -143,6 +144,46 @@ static int ldinitramfs_raw(struct initramfs *initramfs, char *fname) return initramfs_load_archive(initramfs, fname); } +static f_ldinitramfs ldinitramfs_cpio; +static int ldinitramfs_cpio(struct initramfs *initramfs, char *fname) +{ + char *target_fname, *p; + int do_mkdir, unmangle, rc; + + /* Choose target_fname based on presence of "@" syntax */ + target_fname = strchr(fname, '@'); + if (target_fname) { + /* Temporarily mangle */ + unmangle = 1; + *target_fname++ = '\0'; + + /* Make parent directories? */ + do_mkdir = !!strchr(target_fname, '/'); + } else { + unmangle = 0; + + /* Forget the source path */ + target_fname = fname; + while ((p = strchr(target_fname, '/'))) + target_fname = p + 1; + + /* The user didn't specify a desired path */ + do_mkdir = 0; + } + + /* + * Load the file, encapsulate it with the desired path, make the + * parent directories if the desired path contains them, add to initramfs + */ + rc = initramfs_load_file(initramfs, fname, target_fname, do_mkdir, 0755); + + /* Unmangle, if needed*/ + if (unmangle) + *--target_fname = '@'; + + return rc; +} + /* It only makes sense to call this function from main */ static int process_initramfs_args(char *arg, struct initramfs *initramfs, const char *kernel_name, enum ldmode mode, @@ -157,6 +198,10 @@ static int process_initramfs_args(char *arg, struct initramfs *initramfs, mode_msg = "Loading"; ldinitramfs = ldinitramfs_raw; break; + case ldmode_cpio: + mode_msg = "Encapsulating"; + ldinitramfs = ldinitramfs_cpio; + break; case ldmodes: default: return 1; @@ -299,6 +344,14 @@ int main(int argc, char *argv[]) goto bail; } + argl = argv; + while ((argl = find_arguments(argl, &arg, "initrdfile="))) { + argl++; + if (process_initramfs_args(arg, initramfs, kernel_name, ldmode_cpio, + opt_quiet)) + goto bail; + } + /* Append the DHCP info */ if (opt_dhcpinfo && !pxe_get_cached_info(PXENV_PACKET_TYPE_DHCP_ACK, &dhcpdata, &dhcplen)) { -- cgit v1.2.1 From 28b3a9d4d7eb932b827122f3e641ce14fb2cbd03 Mon Sep 17 00:00:00 2001 From: Shao Miller Date: Fri, 26 Oct 2012 02:14:28 -0400 Subject: initramfs chain handling: Accounting fixes for padding, etc. Signed-off-by: Shao Miller --- com32/lib/syslinux/initramfs_file.c | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/com32/lib/syslinux/initramfs_file.c b/com32/lib/syslinux/initramfs_file.c index 763eff28..7eb55b5e 100644 --- a/com32/lib/syslinux/initramfs_file.c +++ b/com32/lib/syslinux/initramfs_file.c @@ -65,7 +65,7 @@ static size_t initramfs_mkdirs(const char *filename, void *buffer, const char *p = filename; char *bp = buffer; int len; - size_t bytes = 0; + size_t bytes = 0, hdr_sz; int pad; while ((p = strchr(p, '/'))) { @@ -81,15 +81,17 @@ static size_t initramfs_mkdirs(const char *filename, void *buffer, while ((p = strchr(p, '/'))) { if (p != filename && p[-1] != '/') { len = p - filename; + hdr_sz = ((sizeof(struct cpio_header) + len + 1) + 3) & ~3; bp += sprintf(bp, "070701%08x%08x%08x%08x%08x%08x%08x%08x%08x" "%08x%08x%08x%08x", next_ino++, S_IFDIR | 0755, 0, 0, 1, 0, 0, 0, 1, 0, 1, len + 1, 0); memcpy(bp, filename, len); bp += len; - pad = (-(sizeof(struct cpio_header) + len) & 3) + 1; + pad = hdr_sz - (sizeof(struct cpio_header) + len); memset(bp, 0, pad); bp += pad; } + p++; } } @@ -104,7 +106,7 @@ int initramfs_mknod(struct initramfs *ihead, const char *filename, int do_mkdir, uint16_t mode, size_t len, uint32_t major, uint32_t minor) { - size_t bytes; + size_t bytes, hdr_sz; int namelen = strlen(filename); int pad; char *buffer, *bp; @@ -114,7 +116,8 @@ int initramfs_mknod(struct initramfs *ihead, const char *filename, else bytes = 0; - bytes += ((sizeof(struct cpio_header) + namelen + 1) + 3) & ~3; + hdr_sz = ((sizeof(struct cpio_header) + namelen + 1) + 3) & ~3; + bytes += hdr_sz; bp = buffer = malloc(bytes); if (!buffer) @@ -127,8 +130,8 @@ int initramfs_mknod(struct initramfs *ihead, const char *filename, "%08x%08x%08x%08x", next_ino++, mode, 0, 0, 1, 0, len, 0, 1, major, minor, namelen + 1, 0); memcpy(bp, filename, namelen); - bp += len; - pad = (-(sizeof(struct cpio_header) + namelen) & 3) + 1; + bp += namelen; + pad = hdr_sz - (sizeof(struct cpio_header) + namelen); memset(bp, 0, pad); if (initramfs_add_data(ihead, buffer, bytes, bytes, 4)) { -- cgit v1.2.1 From c9c67dd61ba0b11e46d514601cf0722e1b43017c Mon Sep 17 00:00:00 2001 From: Shao Miller Date: Sun, 4 Nov 2012 00:26:32 -0400 Subject: hexdump.c32: Simple file hex-dumper Usage: %s [