[openwrt/openwrt] ipq806x: replace ARM bootloader patch with pending upstream version

LEDE Commits lede-commits at lists.infradead.org
Fri Feb 23 09:07:03 PST 2024


ansuel pushed a commit to openwrt/openwrt.git, branch main:
https://git.openwrt.org/b2bb4b0f0a4ecd4c3ad58ea42dde14dce87788fc

commit b2bb4b0f0a4ecd4c3ad58ea42dde14dce87788fc
Author: Christian Marangi <ansuelsmth at gmail.com>
AuthorDate: Fri Feb 23 17:54:52 2024 +0100

    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 <ansuelsmth at gmail.com>
---
 target/linux/ipq806x/config-6.1                    |   2 +-
 ...060-ARM-mach-qcom-fix-support-for-ipq806x.patch |  60 -----
 ...eric-Mangle-bootloader-s-kernel-arguments.patch | 280 ---------------------
 .../patches-6.1/900-arm-add-cmdline-override.patch |   2 +-
 ...mpressor-support-memory-start-validation-.patch |  75 ++++++
 ...compressor-add-option-to-ignore-MEM-ATAGs.patch |  54 ++++
 ...essor-support-for-ATAGs-rootblock-parsing.patch | 197 +++++++++++++++
 7 files changed, 328 insertions(+), 342 deletions(-)

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 <ansuelsmth at 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 at 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
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 <ianchi74 at 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 at 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,
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 <ansuelsmth at 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 at gmail.com>
+Reviewed-by: Geert Uytterhoeven <geert+renesas at glider.be>
+Reviewed-by: Linus Walleij <linus.walleij at 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
+ 
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 <ansuelsmth at 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 at gmail.com>
+Acked-by: Linus Walleij <linus.walleij at 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)
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 <ansuelsmth at 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 at outlook.com>
+[ reworked to a cleaner patch ]
+Signed-off-by: Christian Marangi <ansuelsmth at 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,




More information about the lede-commits mailing list