| From 71270226b14733a4b1f2cde58ea9265caa50b38d Mon Sep 17 00:00:00 2001 |
| From: Adrian Panella <ianchi74@outlook.com> |
| Date: Thu, 9 Mar 2017 09:37:17 +0100 |
| Subject: [PATCH 67/69] generic: Mangle bootloader's kernel arguments |
| |
| The command-line arguments provided by the boot loader will be |
| appended to a new device tree property: bootloader-args. |
| If there is a property "append-rootblock" in DT under /chosen |
| and a root= option in bootloaders command line it will be parsed |
| and added to DT bootargs with the form: <append-rootblock>XX. |
| Only command line ATAG will be processed, the rest of the ATAGs |
| sent by bootloader will be ignored. |
| This is usefull in dual boot systems, to get the current root partition |
| without afecting the rest of the system. |
| |
| Signed-off-by: Adrian Panella <ianchi74@outlook.com> |
| --- |
| arch/arm/Kconfig | 11 +++++ |
| arch/arm/boot/compressed/atags_to_fdt.c | 72 ++++++++++++++++++++++++++++++++- |
| init/main.c | 16 ++++++++ |
| 3 files changed, 98 insertions(+), 1 deletion(-) |
| |
| --- a/arch/arm/Kconfig |
| +++ b/arch/arm/Kconfig |
| @@ -1823,6 +1823,17 @@ config ARM_ATAG_DTB_COMPAT_CMDLINE_EXTEN |
| The command-line arguments provided by the boot loader will be |
| appended to the the device tree bootargs property. |
| |
| +config ARM_ATAG_DTB_COMPAT_CMDLINE_MANGLE |
| + bool "Append rootblock parsing bootloader's kernel arguments" |
| + help |
| + The command-line arguments provided by the boot loader will be |
| + appended to a new device tree property: bootloader-args. |
| + If there is a property "append-rootblock" in DT under /chosen |
| + and a root= option in bootloaders command line it will be parsed |
| + and added to DT bootargs with the form: <append-rootblock>XX. |
| + Only command line ATAG will be processed, the rest of the ATAGs |
| + sent by bootloader will be ignored. |
| + |
| endchoice |
| |
| config CMDLINE |
| --- a/arch/arm/boot/compressed/atags_to_fdt.c |
| +++ b/arch/arm/boot/compressed/atags_to_fdt.c |
| @@ -4,6 +4,8 @@ |
| |
| #if defined(CONFIG_ARM_ATAG_DTB_COMPAT_CMDLINE_EXTEND) |
| #define do_extend_cmdline 1 |
| +#elif defined(CONFIG_ARM_ATAG_DTB_COMPAT_CMDLINE_MANGLE) |
| +#define do_extend_cmdline 1 |
| #else |
| #define do_extend_cmdline 0 |
| #endif |
| @@ -67,6 +69,80 @@ static uint32_t get_cell_size(const void |
| return cell_size; |
| } |
| |
| +#if defined(CONFIG_ARM_ATAG_DTB_COMPAT_CMDLINE_MANGLE) |
| +/** |
| + * taken from arch/x86/boot/string.c |
| + * local_strstr - Find the first substring in a %NUL terminated string |
| + * @s1: The string to be searched |
| + * @s2: The string to search for |
| + */ |
| +static char *local_strstr(const char *s1, const char *s2) |
| +{ |
| + size_t l1, l2; |
| + |
| + l2 = strlen(s2); |
| + if (!l2) |
| + return (char *)s1; |
| + l1 = strlen(s1); |
| + while (l1 >= l2) { |
| + l1--; |
| + if (!memcmp(s1, s2, l2)) |
| + return (char *)s1; |
| + s1++; |
| + } |
| + return NULL; |
| +} |
| + |
| +static char *append_rootblock(char *dest, const char *str, int len, void *fdt) |
| +{ |
| + char *ptr, *end, *tmp; |
| + char *root="root="; |
| + char *find_rootblock; |
| + int i, l; |
| + const char *rootblock; |
| + |
| + find_rootblock = getprop(fdt, "/chosen", "find-rootblock", &l); |
| + if(!find_rootblock) |
| + find_rootblock = root; |
| + |
| + //ARM doesn't have __HAVE_ARCH_STRSTR, so it was copied from x86 |
| + ptr = local_strstr(str, find_rootblock); |
| + |
| + if(!ptr) |
| + return dest; |
| + |
| + end = strchr(ptr, ' '); |
| + end = end ? (end - 1) : (strchr(ptr, 0) - 1); |
| + |
| + // Some boards ubi.mtd=XX,ZZZZ, so let's check for '," too. |
| + tmp = strchr(ptr, ','); |
| + |
| + if(tmp) |
| + end = end < tmp ? end : tmp - 1; |
| + |
| + //find partition number (assumes format root=/dev/mtdXX | /dev/mtdblockXX | yy:XX | ubi.mtd=XX,ZZZZ ) |
| + for( i = 0; end >= ptr && *end >= '0' && *end <= '9'; end--, i++); |
| + ptr = end + 1; |
| + |
| + /* if append-rootblock property is set use it to append to command line */ |
| + rootblock = getprop(fdt, "/chosen", "append-rootblock", &l); |
| + if(rootblock != NULL) { |
| + if(*dest != ' ') { |
| + *dest = ' '; |
| + dest++; |
| + len++; |
| + } |
| + if (len + l + i <= COMMAND_LINE_SIZE) { |
| + memcpy(dest, rootblock, l); |
| + dest += l - 1; |
| + memcpy(dest, ptr, i); |
| + dest += i; |
| + } |
| + } |
| + return dest; |
| +} |
| +#endif |
| + |
| static void merge_fdt_bootargs(void *fdt, const char *fdt_cmdline) |
| { |
| char cmdline[COMMAND_LINE_SIZE]; |
| @@ -86,12 +162,21 @@ static void merge_fdt_bootargs(void *fdt |
| |
| /* and append the ATAG_CMDLINE */ |
| if (fdt_cmdline) { |
| + |
| +#if defined(CONFIG_ARM_ATAG_DTB_COMPAT_CMDLINE_MANGLE) |
| + //save original bootloader args |
| + //and append ubi.mtd with root partition number to current cmdline |
| + setprop_string(fdt, "/chosen", "bootloader-args", fdt_cmdline); |
| + ptr = append_rootblock(ptr, fdt_cmdline, len, fdt); |
| + |
| +#else |
| len = strlen(fdt_cmdline); |
| if (ptr - cmdline + len + 2 < COMMAND_LINE_SIZE) { |
| *ptr++ = ' '; |
| memcpy(ptr, fdt_cmdline, len); |
| ptr += len; |
| } |
| +#endif |
| } |
| *ptr = '\0'; |
| |
| @@ -166,7 +251,9 @@ int atags_to_fdt(void *atag_list, void * |
| else |
| setprop_string(fdt, "/chosen", "bootargs", |
| atag->u.cmdline.cmdline); |
| - } else if (atag->hdr.tag == ATAG_MEM) { |
| + } |
| +#ifndef CONFIG_ARM_ATAG_DTB_COMPAT_CMDLINE_MANGLE |
| + else if (atag->hdr.tag == ATAG_MEM) { |
| if (memcount >= sizeof(mem_reg_property)/4) |
| continue; |
| if (!atag->u.mem.size) |
| @@ -210,6 +297,10 @@ int atags_to_fdt(void *atag_list, void * |
| setprop(fdt, "/memory", "reg", mem_reg_property, |
| 4 * memcount * memsize); |
| } |
| +#else |
| + |
| + } |
| +#endif |
| |
| return fdt_pack(fdt); |
| } |
| --- a/init/main.c |
| +++ b/init/main.c |
| @@ -104,6 +104,10 @@ |
| #define CREATE_TRACE_POINTS |
| #include <trace/events/initcall.h> |
| |
| +#if defined(CONFIG_ARM_ATAG_DTB_COMPAT_CMDLINE_MANGLE) |
| +#include <linux/of.h> |
| +#endif |
| + |
| static int kernel_init(void *); |
| |
| extern void init_IRQ(void); |
| @@ -633,6 +637,18 @@ asmlinkage __visible void __init start_k |
| pr_notice("Kernel command line: %s\n", boot_command_line); |
| /* parameters may set static keys */ |
| jump_label_init(); |
| + |
| +#if defined(CONFIG_ARM_ATAG_DTB_COMPAT_CMDLINE_MANGLE) |
| + //Show bootloader's original command line for reference |
| + if(of_chosen) { |
| + const char *prop = of_get_property(of_chosen, "bootloader-args", NULL); |
| + if(prop) |
| + pr_notice("Bootloader command line (ignored): %s\n", prop); |
| + else |
| + pr_notice("Bootloader command line not present\n"); |
| + } |
| +#endif |
| + |
| parse_early_param(); |
| after_dashes = parse_args("Booting kernel", |
| static_command_line, __start___param, |