From: Christian Marangi Date: Fri, 23 Feb 2024 16:54:52 +0000 (+0100) Subject: ipq806x: replace ARM bootloader patch with pending upstream version X-Git-Url: http://git.openwrt.org/?a=commitdiff_plain;h=b2bb4b0f0a4ecd4c3ad58ea42dde14dce87788fc;p=openwrt%2Fopenwrt.git ipq806x: replace ARM bootloader patch with pending upstream version Replace ARM bootloader patch with pending upstream version. The patch got reviewed upstream and tested on a Netgear R7800. This fix a problem with the ARM decompressor and permits to use AUTO_ZRELADDR without having to hardcode PHYS_OFFSET as the bootloader now correctly parse the memory modes in the appended DTB. Signed-off-by: Christian Marangi --- diff --git a/target/linux/ipq806x/config-6.1 b/target/linux/ipq806x/config-6.1 index e6c9b930a2..598ab305db 100644 --- a/target/linux/ipq806x/config-6.1 +++ b/target/linux/ipq806x/config-6.1 @@ -4,7 +4,6 @@ CONFIG_ALIGNMENT_TRAP=y CONFIG_ARCH_32BIT_OFF_T=y CONFIG_ARCH_HIBERNATION_POSSIBLE=y # CONFIG_ARCH_IPQ40XX is not set -CONFIG_ARCH_IPQ806X=y CONFIG_ARCH_KEEP_MEMBLOCK=y # CONFIG_ARCH_MDM9615 is not set CONFIG_ARCH_MIGHT_HAVE_PC_PARPORT=y @@ -31,6 +30,7 @@ CONFIG_ARM_ARCH_TIMER_EVTSTREAM=y CONFIG_ARM_ATAG_DTB_COMPAT=y # CONFIG_ARM_ATAG_DTB_COMPAT_CMDLINE_FROM_BOOTLOADER is not set CONFIG_ARM_ATAG_DTB_COMPAT_CMDLINE_MANGLE=y +CONFIG_ARM_ATAG_DTB_COMPAT_IGNORE_MEM=y CONFIG_ARM_CPUIDLE=y CONFIG_ARM_CPU_SUSPEND=y # CONFIG_ARM_CPU_TOPOLOGY is not set diff --git a/target/linux/ipq806x/patches-6.1/0060-ARM-mach-qcom-fix-support-for-ipq806x.patch b/target/linux/ipq806x/patches-6.1/0060-ARM-mach-qcom-fix-support-for-ipq806x.patch deleted file mode 100644 index 47053260bb..0000000000 --- a/target/linux/ipq806x/patches-6.1/0060-ARM-mach-qcom-fix-support-for-ipq806x.patch +++ /dev/null @@ -1,60 +0,0 @@ -From 9c896e9fc2ef1209e4a56d8c9fdd183847c2c814 Mon Sep 17 00:00:00 2001 -From: Christian Marangi -Date: Tue, 18 Oct 2022 22:02:46 +0200 -Subject: [PATCH] ARM: mach-qcom: fix support for ipq806x - -Add a specific config flag for Qcom IPQ806x as this SoC can't use -AUTO_ZRELADDR and require the PHYS_OFFSET set to 0x42000000. - -This is needed as some legacy board (or some wrongly configured -bootloader) pass the wrong memory map and doesn't exclude the first -~20MB of RAM reserved for the hardware network accellerators. - -With this change we can correctly support each board and prevent any -kind of misconfiguration done by the OEM. - -Signed-off-by: Christian Marangi ---- - arch/arm/Kconfig | 3 ++- - arch/arm/mach-qcom/Kconfig | 13 +++++++++++++ - 2 files changed, 15 insertions(+), 1 deletion(-) - ---- a/arch/arm/Kconfig -+++ b/arch/arm/Kconfig -@@ -285,6 +285,7 @@ config PHYS_OFFSET - default 0x30000000 if ARCH_S3C24XX - default 0xa0000000 if ARCH_IOP32X || ARCH_PXA - default 0xc0000000 if ARCH_EP93XX || ARCH_SA1100 -+ default 0x42000000 if ARCH_IPQ806X - default 0 - help - Please provide the physical address corresponding to the -@@ -1704,7 +1705,7 @@ config CRASH_DUMP - - config AUTO_ZRELADDR - bool "Auto calculation of the decompressed kernel image address" if !ARCH_MULTIPLATFORM -- default !(ARCH_FOOTBRIDGE || ARCH_RPC || ARCH_SA1100) -+ default !(ARCH_FOOTBRIDGE || ARCH_RPC || ARCH_SA1100 || ARCH_IPQ806X) - help - ZRELADDR is the physical address where the decompressed kernel - image will be placed. If AUTO_ZRELADDR is selected, the address ---- a/arch/arm/mach-qcom/Kconfig -+++ b/arch/arm/mach-qcom/Kconfig -@@ -46,4 +46,17 @@ config ARCH_MDM9615 - bool "Enable support for MDM9615" - select CLKSRC_QCOM - -+config ARCH_IPQ806X -+ bool "Enable support for IPQ806x" -+ help -+ Enable support for the Qualcomm IPQ806x. -+ -+ IPQ806x require special PHYS_OFFSET and can't use AUTO_ZRELADDR. -+ The first ~20MB of RAM is reserved for the hardware network accelerators, -+ and the bootloader removes this section from the layout passed from the -+ ATAGS (when used by some bootloader doesn't even do that). -+ -+ To support every system and handle legacy systems, hardcode PHYS_OFFSET and -+ disable AUTO_ZRELADDR. -+ - endif diff --git a/target/linux/ipq806x/patches-6.1/0067-generic-Mangle-bootloader-s-kernel-arguments.patch b/target/linux/ipq806x/patches-6.1/0067-generic-Mangle-bootloader-s-kernel-arguments.patch deleted file mode 100644 index 4e47c390a2..0000000000 --- a/target/linux/ipq806x/patches-6.1/0067-generic-Mangle-bootloader-s-kernel-arguments.patch +++ /dev/null @@ -1,280 +0,0 @@ -From 71270226b14733a4b1f2cde58ea9265caa50b38d Mon Sep 17 00:00:00 2001 -From: Adrian Panella -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: 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 ---- - 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 -@@ -1588,6 +1588,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: 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 -@@ -5,6 +5,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 -@@ -20,6 +22,7 @@ static int node_offset(void *fdt, const - return offset; - } - -+#ifndef CONFIG_ARM_ATAG_DTB_COMPAT_CMDLINE_MANGLE - static int setprop(void *fdt, const char *node_path, const char *property, - void *val_array, int size) - { -@@ -28,6 +31,7 @@ static int setprop(void *fdt, const char - return offset; - return fdt_setprop(fdt, offset, property, val_array, size); - } -+#endif - - static int setprop_string(void *fdt, const char *node_path, - const char *property, const char *string) -@@ -38,6 +42,7 @@ static int setprop_string(void *fdt, con - return fdt_setprop_string(fdt, offset, property, string); - } - -+#ifndef CONFIG_ARM_ATAG_DTB_COMPAT_CMDLINE_MANGLE - static int setprop_cell(void *fdt, const char *node_path, - const char *property, uint32_t val) - { -@@ -46,6 +51,7 @@ static int setprop_cell(void *fdt, const - return offset; - return fdt_setprop_cell(fdt, offset, property, val); - } -+#endif - - static const void *getprop(const void *fdt, const char *node_path, - const char *property, int *len) -@@ -58,6 +64,7 @@ static const void *getprop(const void *f - return fdt_getprop(fdt, offset, property, len); - } - -+#ifndef CONFIG_ARM_ATAG_DTB_COMPAT_CMDLINE_MANGLE - static uint32_t get_cell_size(const void *fdt) - { - int len; -@@ -68,6 +75,81 @@ static uint32_t get_cell_size(const void - cell_size = fdt32_to_cpu(*size_len); - return cell_size; - } -+#endif -+ -+#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; -+ const char *root="root="; -+ const 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) - { -@@ -88,18 +170,28 @@ 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'; - - setprop_string(fdt, "/chosen", "bootargs", cmdline); - } - -+#ifndef CONFIG_ARM_ATAG_DTB_COMPAT_CMDLINE_MANGLE - static void hex_str(char *out, uint32_t value) - { - uint32_t digit; -@@ -117,6 +209,7 @@ static void hex_str(char *out, uint32_t - } - *out = '\0'; - } -+#endif - - /* - * Convert and fold provided ATAGs into the provided FDT. -@@ -131,9 +224,11 @@ int atags_to_fdt(void *atag_list, void * - struct tag *atag = atag_list; - /* In the case of 64 bits memory size, need to reserve 2 cells for - * address and size for each bank */ -+#ifndef CONFIG_ARM_ATAG_DTB_COMPAT_CMDLINE_MANGLE - __be32 mem_reg_property[2 * 2 * NR_BANKS]; -- int memcount = 0; -- int ret, memsize; -+ int memsize, memcount = 0; -+#endif -+ int ret; - - /* make sure we've got an aligned pointer */ - if ((u32)atag_list & 0x3) -@@ -168,7 +263,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) -@@ -212,6 +309,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 -@@ -112,6 +112,10 @@ - - #include - -+#if defined(CONFIG_ARM_ATAG_DTB_COMPAT_CMDLINE_MANGLE) -+#include -+#endif -+ - static int kernel_init(void *); - - extern void init_IRQ(void); -@@ -995,6 +999,18 @@ asmlinkage __visible void __init __no_sa - pr_notice("Kernel command line: %s\n", saved_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, diff --git a/target/linux/ipq806x/patches-6.1/900-arm-add-cmdline-override.patch b/target/linux/ipq806x/patches-6.1/900-arm-add-cmdline-override.patch index 2004632513..c9583549d0 100644 --- a/target/linux/ipq806x/patches-6.1/900-arm-add-cmdline-override.patch +++ b/target/linux/ipq806x/patches-6.1/900-arm-add-cmdline-override.patch @@ -1,6 +1,6 @@ --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig -@@ -1601,6 +1601,14 @@ config ARM_ATAG_DTB_COMPAT_CMDLINE_MANGL +@@ -1589,6 +1589,14 @@ config ARM_ATAG_DTB_COMPAT_CMDLINE_EXTEN endchoice diff --git a/target/linux/ipq806x/patches-6.1/901-01-ARM-decompressor-support-memory-start-validation-.patch b/target/linux/ipq806x/patches-6.1/901-01-ARM-decompressor-support-memory-start-validation-.patch new file mode 100644 index 0000000000..04e2a0c57e --- /dev/null +++ b/target/linux/ipq806x/patches-6.1/901-01-ARM-decompressor-support-memory-start-validation-.patch @@ -0,0 +1,75 @@ +From 2f86b9b71a11f86e3d850214ab781ebb17d7260e Mon Sep 17 00:00:00 2001 +From: Christian Marangi +Date: Fri, 19 Jan 2024 19:48:30 +0100 +Subject: [PATCH v2 1/2] ARM: decompressor: support memory start validation for + appended DTB + +There is currently a problem with a very specific sets of kernel config +and AUTO_ZRELADDR. + +For the most common case AUTO_ZRELADDR check the PC register and +calculate the start of the physical memory. Then fdt_check_mem_start is +called to make sure the detected value makes sense by comparing it with +what is present in DTB in the memory nodes and if additional fixup are +required with the use of linux,usable-memory-range in the chosen node to +hardcode usable memory range in case some reserved space needs to be +addressed. With the help of this function the right address is +calculated and the kernel correctly decompress and loads. + +Things starts to become problematic when in the mix, +CONFIG_ARM_APPENDED_DTB is used. This is a particular kernel config is +used when legacy systems doesn't support passing a DTB directly and a +DTB is appended at the end of the image. + +In such case, fdt_check_mem_start is skipped in AUTO_ZRELADDR iteration +as the appended DTB can be augumented later with ATAGS passed from the +bootloader (if CONFIG_ARM_ATAG_DTB_COMPAT is enabled). + +The main problem and what this patch address is the fact that +fdt_check_mem_start is never called later when the appended DTB is +augumented, hence any fixup and validation is not done making AUTO_ZRELADDR +detection inconsistent and most of the time wrong. + +Add support in head.S for this by checking if AUTO_ZRELADDR is enabled +and calling fdt_check_mem_start with the appended DTB and the augumented +values permitting legacy device to provide info in DTB instead of +disabling AUTO_ZRELADDR and hardcoding the physical address offsets. + +Signed-off-by: Christian Marangi +Reviewed-by: Geert Uytterhoeven +Reviewed-by: Linus Walleij +--- + arch/arm/boot/compressed/head.S | 22 ++++++++++++++++++++++ + 1 file changed, 22 insertions(+) + +--- a/arch/arm/boot/compressed/head.S ++++ b/arch/arm/boot/compressed/head.S +@@ -443,6 +443,28 @@ restart: adr r0, LC1 + add r6, r6, r5 + add r10, r10, r5 + add sp, sp, r5 ++ ++#ifdef CONFIG_AUTO_ZRELADDR ++ /* ++ * Validate calculated start of physical memory with appended DTB. ++ * In the first iteration for physical memory start calculation, ++ * we skipped validating it as it could have been augumented by ++ * ATAGS stored at an offset from the same start of physical memory. ++ * ++ * We now have parsed them and augumented the appended DTB if asked ++ * so we can finally validate the start of physical memory. ++ * ++ * This is needed to apply additional fixup with ++ * linux,usable-memory-range or to make sure AUTO_ZRELADDR detected ++ * the correct value. ++ */ ++ sub r0, r4, #TEXT_OFFSET @ revert to base address ++ mov r1, r8 @ use appended DTB ++ bl fdt_check_mem_start ++ ++ /* Determine final kernel image address. */ ++ add r4, r0, #TEXT_OFFSET ++#endif + dtb_check_done: + #endif + diff --git a/target/linux/ipq806x/patches-6.1/901-02-ARM-decompressor-add-option-to-ignore-MEM-ATAGs.patch b/target/linux/ipq806x/patches-6.1/901-02-ARM-decompressor-add-option-to-ignore-MEM-ATAGs.patch new file mode 100644 index 0000000000..2e4c4de545 --- /dev/null +++ b/target/linux/ipq806x/patches-6.1/901-02-ARM-decompressor-add-option-to-ignore-MEM-ATAGs.patch @@ -0,0 +1,54 @@ +From 781d7cd4c3364e9d38fa12a342c5ad4c7e33a5ba Mon Sep 17 00:00:00 2001 +From: Christian Marangi +Date: Fri, 19 Jan 2024 20:33:10 +0100 +Subject: [PATCH v2 2/2] ARM: decompressor: add option to ignore MEM ATAGs + +Some bootloaders can pass broken MEM ATAGs that provide hardcoded +information about mounted RAM size and physical location. +Example booloader provide RAM of size 1.7Gb but actual mounted RAM +size is 512Mb causing kernel panic. + +Add option CONFIG_ARM_ATAG_DTB_COMPAT_IGNORE_MEM to ignore these ATAG +and not augument appended DTB memory node. + +Signed-off-by: Christian Marangi +Acked-by: Linus Walleij +--- + arch/arm/Kconfig | 12 ++++++++++++ + arch/arm/boot/compressed/atags_to_fdt.c | 4 ++++ + 2 files changed, 16 insertions(+) + +--- a/arch/arm/Kconfig ++++ b/arch/arm/Kconfig +@@ -1570,6 +1570,18 @@ config ARM_ATAG_DTB_COMPAT + bootloaders, this option allows zImage to extract the information + from the ATAG list and store it at run time into the appended DTB. + ++config ARM_ATAG_DTB_COMPAT_IGNORE_MEM ++ bool "Ignore MEM ATAG information from bootloader" ++ depends on ARM_ATAG_DTB_COMPAT ++ help ++ Some bootloaders can pass broken MEM ATAGs that provide hardcoded ++ information about mounted RAM size and physical location. ++ Example booloader provide RAM of size 1.7Gb but actual mounted RAM ++ size is 512Mb causing kernel panic. ++ ++ Enable this option if MEM ATAGs should be ignored and the memory ++ node in the appended DTB should NOT be augumented. ++ + choice + prompt "Kernel command line type" if ARM_ATAG_DTB_COMPAT + default ARM_ATAG_DTB_COMPAT_CMDLINE_FROM_BOOTLOADER +--- a/arch/arm/boot/compressed/atags_to_fdt.c ++++ b/arch/arm/boot/compressed/atags_to_fdt.c +@@ -169,6 +169,10 @@ int atags_to_fdt(void *atag_list, void * + setprop_string(fdt, "/chosen", "bootargs", + atag->u.cmdline.cmdline); + } else if (atag->hdr.tag == ATAG_MEM) { ++ /* Bootloader MEM ATAG are broken and should be ignored */ ++ if (IS_ENABLED(CONFIG_ARM_ATAG_DTB_COMPAT_IGNORE_MEM)) ++ continue; ++ + if (memcount >= sizeof(mem_reg_property)/4) + continue; + if (!atag->u.mem.size) diff --git a/target/linux/ipq806x/patches-6.1/902-ARM-decompressor-support-for-ATAGs-rootblock-parsing.patch b/target/linux/ipq806x/patches-6.1/902-ARM-decompressor-support-for-ATAGs-rootblock-parsing.patch new file mode 100644 index 0000000000..60b80fefe1 --- /dev/null +++ b/target/linux/ipq806x/patches-6.1/902-ARM-decompressor-support-for-ATAGs-rootblock-parsing.patch @@ -0,0 +1,197 @@ +From 13bb6d8dd9138927950a520a288401db82871dc9 Mon Sep 17 00:00:00 2001 +From: Christian Marangi +Date: Sun, 21 Jan 2024 23:36:57 +0100 +Subject: [PATCH] ARM: decompressor: support for ATAGs rootblock parsing + +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: XX. + +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 +[ reworked to a cleaner patch ] +Signed-off-by: Christian Marangi +--- + arch/arm/Kconfig | 10 +++ + arch/arm/boot/compressed/atags_to_fdt.c | 102 ++++++++++++++++++++++-- + init/main.c | 12 +++ + 3 files changed, 117 insertions(+), 7 deletions(-) + +--- a/arch/arm/Kconfig ++++ b/arch/arm/Kconfig +@@ -1599,6 +1599,16 @@ 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: XX. ++ + endchoice + + config CMDLINE_OVERRIDE +--- a/arch/arm/boot/compressed/atags_to_fdt.c ++++ b/arch/arm/boot/compressed/atags_to_fdt.c +@@ -3,7 +3,8 @@ + #include + #include + +-#if defined(CONFIG_ARM_ATAG_DTB_COMPAT_CMDLINE_EXTEND) ++#if defined(CONFIG_ARM_ATAG_DTB_COMPAT_CMDLINE_EXTEND) || \ ++ defined(CONFIG_ARM_ATAG_DTB_COMPAT_CMDLINE_MANGLE) + #define do_extend_cmdline 1 + #else + #define do_extend_cmdline 0 +@@ -69,6 +70,83 @@ static uint32_t get_cell_size(const void + return cell_size; + } + ++/** ++ * 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; ++ const char *root="root="; ++ const 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; ++} ++ + static void merge_fdt_bootargs(void *fdt, const char *fdt_cmdline) + { + char cmdline[COMMAND_LINE_SIZE]; +@@ -86,13 +164,23 @@ static void merge_fdt_bootargs(void *fdt + ptr += len - 1; + } + +- /* and append the ATAG_CMDLINE */ + if (fdt_cmdline) { +- len = strlen(fdt_cmdline); +- if (ptr - cmdline + len + 2 < COMMAND_LINE_SIZE) { +- *ptr++ = ' '; +- memcpy(ptr, fdt_cmdline, len); +- ptr += len; ++ if (IS_ENABLED(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 { ++ /* and append the ATAG_CMDLINE */ ++ len = strlen(fdt_cmdline); ++ if (ptr - cmdline + len + 2 < COMMAND_LINE_SIZE) { ++ *ptr++ = ' '; ++ memcpy(ptr, fdt_cmdline, len); ++ ptr += len; ++ } + } + } + *ptr = '\0'; +--- a/init/main.c ++++ b/init/main.c +@@ -28,6 +28,7 @@ + #include + #include + #include ++#include + #include + #include + #include +@@ -995,6 +996,17 @@ asmlinkage __visible void __init __no_sa + pr_notice("Kernel command line: %s\n", saved_command_line); + /* parameters may set static keys */ + jump_label_init(); ++ ++ /* Show bootloader's original command line for reference */ ++ if (IS_ENABLED(CONFIG_ARM_ATAG_DTB_COMPAT_CMDLINE_MANGLE) && 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"); ++ } ++ + parse_early_param(); + after_dashes = parse_args("Booting kernel", + static_command_line, __start___param,