diff options
| author | Akira Takeuchi <takeuchi.akr@jp.panasonic.com> | 2013-06-28 11:53:03 -0400 |
|---|---|---|
| committer | David Howells <dhowells@redhat.com> | 2013-06-28 11:53:03 -0400 |
| commit | e3f12a53042e26202993baa3ad4ff8768173653d (patch) | |
| tree | 94586c5b1a5926f8560aee111a053e8ea06c226a | |
| parent | c6dc9f0a4eeb7c014904475372c66e6d0ac5a572 (diff) | |
mn10300: Use early_param() to parse "mem=" parameter
This fixes the problem that "init=" options may not be passed to kernel
correctly.
parse_mem_cmdline() of mn10300 arch gets rid of "mem=" string from
redboot_command_line. Then init_setup() parses the "init=" options from
static_command_line, which is a copy of redboot_command_line, and keeps
the pointer to the init options in execute_command variable.
Since the commit 026cee0 upstream (params: <level>_initcall-like kernel
parameters), static_command_line becomes overwritten by saved_command_line at
do_initcall_level(). Notice that saved_command_line is a command line
which includes "mem=" string.
As a result, execute_command may point to weird string by the length of
"mem=" parameter.
I noticed this problem when using the command line like this:
mem=128M console=ttyS0,115200 init=/bin/sh
Here is the processing flow of command line parameters.
start_kernel()
setup_arch(&command_line)
parse_mem_cmdline(cmdline_p)
* strcpy(boot_command_line, redboot_command_line);
* Remove "mem=xxx" from redboot_command_line.
* *cmdline_p = redboot_command_line;
setup_command_line(command_line) <-- command_line is redboot_command_line
* strcpy(saved_command_line, boot_command_line)
* strcpy(static_command_line, command_line)
parse_early_param()
strlcpy(tmp_cmdline, boot_command_line, COMMAND_LINE_SIZE);
parse_early_options(tmp_cmdline);
parse_args("early options", cmdline, NULL, 0, 0, 0, do_early_param);
parse_args("Booting ..", static_command_line, ...);
init_setup() <-- save the pointer in execute_command
rest_init()
kernel_thread(kernel_init, NULL, CLONE_FS | CLONE_SIGHAND);
At this point, execute_command points to "/bin/sh" string.
kernel_init()
kernel_init_freeable()
do_basic_setup()
do_initcalls()
do_initcall_level()
(*) strcpy(static_command_line, saved_command_line);
Here, execute_command gets to point to "200" string !!
Signed-off-by: David Howells <dhowells@redhat.com>
| -rw-r--r-- | arch/mn10300/kernel/setup.c | 54 |
1 files changed, 21 insertions, 33 deletions
diff --git a/arch/mn10300/kernel/setup.c b/arch/mn10300/kernel/setup.c index 33c3bd1e5c6d..ebac9c11f796 100644 --- a/arch/mn10300/kernel/setup.c +++ b/arch/mn10300/kernel/setup.c | |||
| @@ -38,6 +38,7 @@ struct mn10300_cpuinfo boot_cpu_data; | |||
| 38 | /* For PCI or other memory-mapped resources */ | 38 | /* For PCI or other memory-mapped resources */ |
| 39 | unsigned long pci_mem_start = 0x18000000; | 39 | unsigned long pci_mem_start = 0x18000000; |
| 40 | 40 | ||
| 41 | static char __initdata cmd_line[COMMAND_LINE_SIZE]; | ||
| 41 | char redboot_command_line[COMMAND_LINE_SIZE] = | 42 | char redboot_command_line[COMMAND_LINE_SIZE] = |
| 42 | "console=ttyS0,115200 root=/dev/mtdblock3 rw"; | 43 | "console=ttyS0,115200 root=/dev/mtdblock3 rw"; |
| 43 | 44 | ||
| @@ -74,45 +75,19 @@ static const char *const mn10300_cputypes[] = { | |||
| 74 | }; | 75 | }; |
| 75 | 76 | ||
| 76 | /* | 77 | /* |
| 77 | * | 78 | * Pick out the memory size. We look for mem=size, |
| 79 | * where size is "size[KkMm]" | ||
| 78 | */ | 80 | */ |
| 79 | static void __init parse_mem_cmdline(char **cmdline_p) | 81 | static int __init early_mem(char *p) |
| 80 | { | 82 | { |
| 81 | char *from, *to, c; | 83 | memory_size = memparse(p, &p); |
| 82 | |||
| 83 | /* save unparsed command line copy for /proc/cmdline */ | ||
| 84 | strcpy(boot_command_line, redboot_command_line); | ||
| 85 | |||
| 86 | /* see if there's an explicit memory size option */ | ||
| 87 | from = redboot_command_line; | ||
| 88 | to = redboot_command_line; | ||
| 89 | c = ' '; | ||
| 90 | |||
| 91 | for (;;) { | ||
| 92 | if (c == ' ' && !memcmp(from, "mem=", 4)) { | ||
| 93 | if (to != redboot_command_line) | ||
| 94 | to--; | ||
| 95 | memory_size = memparse(from + 4, &from); | ||
| 96 | } | ||
| 97 | |||
| 98 | c = *(from++); | ||
| 99 | if (!c) | ||
| 100 | break; | ||
| 101 | |||
| 102 | *(to++) = c; | ||
| 103 | } | ||
| 104 | |||
| 105 | *to = '\0'; | ||
| 106 | *cmdline_p = redboot_command_line; | ||
| 107 | 84 | ||
| 108 | if (memory_size == 0) | 85 | if (memory_size == 0) |
| 109 | panic("Memory size not known\n"); | 86 | panic("Memory size not known\n"); |
| 110 | 87 | ||
| 111 | memory_end = (unsigned long) CONFIG_KERNEL_RAM_BASE_ADDRESS + | 88 | return 0; |
| 112 | memory_size; | ||
| 113 | if (memory_end > phys_memory_end) | ||
| 114 | memory_end = phys_memory_end; | ||
| 115 | } | 89 | } |
| 90 | early_param("mem", early_mem); | ||
| 116 | 91 | ||
| 117 | /* | 92 | /* |
| 118 | * architecture specific setup | 93 | * architecture specific setup |
| @@ -125,7 +100,20 @@ void __init setup_arch(char **cmdline_p) | |||
| 125 | cpu_init(); | 100 | cpu_init(); |
| 126 | unit_setup(); | 101 | unit_setup(); |
| 127 | smp_init_cpus(); | 102 | smp_init_cpus(); |
| 128 | parse_mem_cmdline(cmdline_p); | 103 | |
| 104 | /* save unparsed command line copy for /proc/cmdline */ | ||
| 105 | strlcpy(boot_command_line, redboot_command_line, COMMAND_LINE_SIZE); | ||
| 106 | |||
| 107 | /* populate cmd_line too for later use, preserving boot_command_line */ | ||
| 108 | strlcpy(cmd_line, boot_command_line, COMMAND_LINE_SIZE); | ||
| 109 | *cmdline_p = cmd_line; | ||
| 110 | |||
| 111 | parse_early_param(); | ||
| 112 | |||
| 113 | memory_end = (unsigned long) CONFIG_KERNEL_RAM_BASE_ADDRESS + | ||
| 114 | memory_size; | ||
| 115 | if (memory_end > phys_memory_end) | ||
| 116 | memory_end = phys_memory_end; | ||
| 129 | 117 | ||
| 130 | init_mm.start_code = (unsigned long)&_text; | 118 | init_mm.start_code = (unsigned long)&_text; |
| 131 | init_mm.end_code = (unsigned long) &_etext; | 119 | init_mm.end_code = (unsigned long) &_etext; |
