Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit e3f12a53 authored by Akira Takeuchi's avatar Akira Takeuchi Committed by David Howells
Browse files

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 026cee00 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: default avatarDavid Howells <dhowells@redhat.com>
parent c6dc9f0a
Loading
Loading
Loading
Loading
+21 −33
Original line number Diff line number Diff line
@@ -38,6 +38,7 @@ struct mn10300_cpuinfo boot_cpu_data;
/* For PCI or other memory-mapped resources */
unsigned long pci_mem_start = 0x18000000;

static char __initdata cmd_line[COMMAND_LINE_SIZE];
char redboot_command_line[COMMAND_LINE_SIZE] =
	"console=ttyS0,115200 root=/dev/mtdblock3 rw";

@@ -74,45 +75,19 @@ static const char *const mn10300_cputypes[] = {
};

/*
 *
 * Pick out the memory size.  We look for mem=size,
 * where size is "size[KkMm]"
 */
static void __init parse_mem_cmdline(char **cmdline_p)
static int __init early_mem(char *p)
{
	char *from, *to, c;

	/* save unparsed command line copy for /proc/cmdline */
	strcpy(boot_command_line, redboot_command_line);

	/* see if there's an explicit memory size option */
	from = redboot_command_line;
	to = redboot_command_line;
	c = ' ';

	for (;;) {
		if (c == ' ' && !memcmp(from, "mem=", 4)) {
			if (to != redboot_command_line)
				to--;
			memory_size = memparse(from + 4, &from);
		}

		c = *(from++);
		if (!c)
			break;

		*(to++) = c;
	}

	*to = '\0';
	*cmdline_p = redboot_command_line;
	memory_size = memparse(p, &p);

	if (memory_size == 0)
		panic("Memory size not known\n");

	memory_end = (unsigned long) CONFIG_KERNEL_RAM_BASE_ADDRESS +
		memory_size;
	if (memory_end > phys_memory_end)
		memory_end = phys_memory_end;
	return 0;
}
early_param("mem", early_mem);

/*
 * architecture specific setup
@@ -125,7 +100,20 @@ void __init setup_arch(char **cmdline_p)
	cpu_init();
	unit_setup();
	smp_init_cpus();
	parse_mem_cmdline(cmdline_p);

	/* save unparsed command line copy for /proc/cmdline */
	strlcpy(boot_command_line, redboot_command_line, COMMAND_LINE_SIZE);

	/* populate cmd_line too for later use, preserving boot_command_line */
	strlcpy(cmd_line, boot_command_line, COMMAND_LINE_SIZE);
	*cmdline_p = cmd_line;

	parse_early_param();

	memory_end = (unsigned long) CONFIG_KERNEL_RAM_BASE_ADDRESS +
		memory_size;
	if (memory_end > phys_memory_end)
		memory_end = phys_memory_end;

	init_mm.start_code = (unsigned long)&_text;
	init_mm.end_code = (unsigned long) &_etext;