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
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
+++ /dev/null
-From 9c896e9fc2ef1209e4a56d8c9fdd183847c2c814 Mon Sep 17 00:00:00 2001
-From: Christian Marangi <ansuelsmth@gmail.com>
-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 <ansuelsmth@gmail.com>
----
- 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
+++ /dev/null
-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
-@@ -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: <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
-@@ -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 <kunit/test.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);
-@@ -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,
--- 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
--- /dev/null
+From 2f86b9b71a11f86e3d850214ab781ebb17d7260e Mon Sep 17 00:00:00 2001
+From: Christian Marangi <ansuelsmth@gmail.com>
+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 <ansuelsmth@gmail.com>
+Reviewed-by: Geert Uytterhoeven <geert+renesas@glider.be>
+Reviewed-by: Linus Walleij <linus.walleij@linaro.org>
+---
+ 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
+
--- /dev/null
+From 781d7cd4c3364e9d38fa12a342c5ad4c7e33a5ba Mon Sep 17 00:00:00 2001
+From: Christian Marangi <ansuelsmth@gmail.com>
+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 <ansuelsmth@gmail.com>
+Acked-by: Linus Walleij <linus.walleij@linaro.org>
+---
+ 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)
--- /dev/null
+From 13bb6d8dd9138927950a520a288401db82871dc9 Mon Sep 17 00:00:00 2001
+From: Christian Marangi <ansuelsmth@gmail.com>
+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: <append-rootblock>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 <ianchi74@outlook.com>
+[ reworked to a cleaner patch ]
+Signed-off-by: Christian Marangi <ansuelsmth@gmail.com>
+---
+ 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: <append-rootblock>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 <asm/setup.h>
+ #include <libfdt.h>
+
+-#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 <linux/initrd.h>
+ #include <linux/memblock.h>
+ #include <linux/acpi.h>
++#include <linux/of.h>
+ #include <linux/bootconfig.h>
+ #include <linux/console.h>
+ #include <linux/nmi.h>
+@@ -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,