From 240c76841b26f1b09aaced33414ee1d08b6454cf Mon Sep 17 00:00:00 2001 From: Wu Zhangjin Date: Sat, 15 Jan 2011 12:46:03 +0000 Subject: MIPS: Get kernel parameters from kexec-tools Before, we simply use the command lines from the original bootloader, but it is not convenient. Now, we accept the kernel parameters from the --command-line or --append option of the kexec-tools. But If not --command-line or --apend option indicated, will fall back to use the ones from the original bootloader. Signed-off-by: Wu Zhangjin --- --- a/arch/mips/kernel/machine_kexec.c +++ b/arch/mips/kernel/machine_kexec.c @@ -13,6 +13,7 @@ #include #include #include +#include int (*_machine_kexec_prepare)(struct kimage *) = NULL; void (*_machine_kexec_shutdown)(void) = NULL; @@ -35,6 +36,56 @@ static void machine_kexec_init_args(void pr_info("kexec_args[3] (desc): %p\n", (void *)kexec_args[3]); } +#define ARGV_MAX_ARGS (COMMAND_LINE_SIZE / 15) + +int machine_kexec_pass_args(struct kimage *image) +{ + int i, argc = 0; + char *bootloader = "kexec"; + int *kexec_argv = (int *)kexec_args[1]; + + for (i = 0; i < image->nr_segments; i++) { + if (!strncmp(bootloader, (char *)image->segment[i].buf, + strlen(bootloader))) { + /* + * convert command line string to array + * of parameters (as bootloader does). + */ + /* + * Note: we do treat the 1st string "kexec" as an + * argument ;-) so, argc here is 1. + */ + char *str = (char *)image->segment[i].buf; + char *ptr = strchr(str, ' '); + char *kbuf = (char *)kexec_argv[0]; + /* Whenever --command-line or --append used, "kexec" is copied */ + argc = 1; + /* Parse the offset */ + while (ptr && (ARGV_MAX_ARGS > argc)) { + *ptr = '\0'; + if (ptr[1] != ' ' && ptr[1] != '\0') { + int offt = (int)(ptr - str + 1); + kexec_argv[argc] = (int)kbuf + offt; + argc++; + } + ptr = strchr(ptr + 1, ' '); + } + if (argc > 1) { + /* Copy to kernel space */ + copy_from_user(kbuf, (char *)image->segment[i].buf, image->segment[i].bufsz); + fw_arg0 = kexec_args[0] = argc; + } + break; + } + } + + pr_info("argc = %lu\n", kexec_args[0]); + for (i = 0; i < kexec_args[0]; i++) + pr_info("argv[%d] = %p, %s\n", i, (char *)kexec_argv[i], (char *)kexec_argv[i]); + + return 0; +} + int machine_kexec_prepare(struct kimage *kimage) { @@ -45,6 +96,7 @@ machine_kexec_prepare(struct kimage *kim * This can be overrided by _machine_kexec_prepare(). */ machine_kexec_init_args(); + machine_kexec_pass_args(kimage); if (_machine_kexec_prepare) return _machine_kexec_prepare(kimage);