From: Sven Eckelmann Date: Mon, 23 Nov 2020 16:57:31 +0100 Subject: ath79: Fix fallback to bootloader cmdline on empty DT bootargs The MIPS code is supposed to fall back to u-boots bootargs whenever the /chosen/bootargs property is missing. But this feature was accidentally disabled when the boot_command_line was initialized with an empty space just to work around problems with early_init_dt_scan_chosen. But this feature is necessary for some boards which have a dualboot mechanism and whose u-boot is calculating the correct partition at runtime without writing this information back to the u-boot-env. Signed-off-by: Sven Eckelmann Origin: backport, https://github.com/openwrt/openwrt/commit/727eebbad1b9dea91174ea675cb64ea13484f790 diff --git a/target/linux/ath79/patches-4.14/0038-MIPS-Setup-boot_command_line-before-plat_mem_setup.patch b/target/linux/ath79/patches-4.14/0038-MIPS-Setup-boot_command_line-before-plat_mem_setup.patch new file mode 100644 index 0000000000000000000000000000000000000000..90d2ca7a0cb16d3f1e71779bfa551f498fd59755 --- /dev/null +++ b/target/linux/ath79/patches-4.14/0038-MIPS-Setup-boot_command_line-before-plat_mem_setup.patch @@ -0,0 +1,82 @@ +From: Paul Burton +Date: Tue, 16 Jan 2018 16:47:57 +0100 +Subject: MIPS: Setup boot_command_line before plat_mem_setup + +Platforms using DT will typically call __dt_setup_arch from +plat_mem_setup. This in turn calls early_init_dt_scan. When +CONFIG_CMDLINE is set, this leads to its value being copied into +boot_command_line by early_init_dt_scan_chosen. If this happens before +the code setting up boot_command_line in arch_mem_init runs, that code +will go on to append CONFIG_CMDLINE (via builtin_cmdline) to +boot_command_line again, duplicating it. For some command line +parameters (eg. earlycon) this can be a problem. Set up +boot_command_line before early_init_dt_scan_chosen gets called such that +it will not write CONFIG_CMDLINE in this scenario & the arguments aren't +duplicated. + +Origin: upstream, https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=8ce355cf2e38afdb364d03d12b23d9cf44c3b7f1 +Signed-off-by: Paul Burton +Acked-by: Mathieu Malaterre +Cc: Ralf Baechle +Cc: Maarten ter Huurne +Cc: linux-mips@linux-mips.org +Patchwork: https://patchwork.linux-mips.org/patch/18483/ +Signed-off-by: James Hogan + +diff --git a/arch/mips/kernel/setup.c b/arch/mips/kernel/setup.c +index abd7ee9e90ab0dd0d01d970c84d90a2c4edf609b..c0f51fd4e0b3970e4f019094091578504e2f56eb 100644 +--- a/arch/mips/kernel/setup.c ++++ b/arch/mips/kernel/setup.c +@@ -833,25 +833,6 @@ static void __init arch_mem_init(char **cmdline_p) + struct memblock_region *reg; + extern void plat_mem_setup(void); + +- /* call board setup routine */ +- plat_mem_setup(); +- +- /* +- * Make sure all kernel memory is in the maps. The "UP" and +- * "DOWN" are opposite for initdata since if it crosses over +- * into another memory section you don't want that to be +- * freed when the initdata is freed. +- */ +- arch_mem_addpart(PFN_DOWN(__pa_symbol(&_text)) << PAGE_SHIFT, +- PFN_UP(__pa_symbol(&_edata)) << PAGE_SHIFT, +- BOOT_MEM_RAM); +- arch_mem_addpart(PFN_UP(__pa_symbol(&__init_begin)) << PAGE_SHIFT, +- PFN_DOWN(__pa_symbol(&__init_end)) << PAGE_SHIFT, +- BOOT_MEM_INIT_RAM); +- +- pr_info("Determined physical RAM map:\n"); +- print_memory_map(); +- + #if defined(CONFIG_CMDLINE_BOOL) && defined(CONFIG_CMDLINE_OVERRIDE) + strlcpy(boot_command_line, builtin_cmdline, COMMAND_LINE_SIZE); + #else +@@ -879,6 +860,26 @@ static void __init arch_mem_init(char **cmdline_p) + } + #endif + #endif ++ ++ /* call board setup routine */ ++ plat_mem_setup(); ++ ++ /* ++ * Make sure all kernel memory is in the maps. The "UP" and ++ * "DOWN" are opposite for initdata since if it crosses over ++ * into another memory section you don't want that to be ++ * freed when the initdata is freed. ++ */ ++ arch_mem_addpart(PFN_DOWN(__pa_symbol(&_text)) << PAGE_SHIFT, ++ PFN_UP(__pa_symbol(&_edata)) << PAGE_SHIFT, ++ BOOT_MEM_RAM); ++ arch_mem_addpart(PFN_UP(__pa_symbol(&__init_begin)) << PAGE_SHIFT, ++ PFN_DOWN(__pa_symbol(&__init_end)) << PAGE_SHIFT, ++ BOOT_MEM_INIT_RAM); ++ ++ pr_info("Determined physical RAM map:\n"); ++ print_memory_map(); ++ + strlcpy(command_line, boot_command_line, COMMAND_LINE_SIZE); + + *cmdline_p = command_line; diff --git a/target/linux/ath79/patches-4.14/0039-MIPS-Fix-CONFIG_CMDLINE-handling.patch b/target/linux/ath79/patches-4.14/0039-MIPS-Fix-CONFIG_CMDLINE-handling.patch new file mode 100644 index 0000000000000000000000000000000000000000..ab040c459454b1670b08afa2082e06637280da52 --- /dev/null +++ b/target/linux/ath79/patches-4.14/0039-MIPS-Fix-CONFIG_CMDLINE-handling.patch @@ -0,0 +1,119 @@ +From: Paul Burton +Date: Thu, 27 Sep 2018 22:59:18 +0000 +Subject: MIPS: Fix CONFIG_CMDLINE handling + +Commit 8ce355cf2e38 ("MIPS: Setup boot_command_line before +plat_mem_setup") fixed a problem for systems which have +CONFIG_CMDLINE_BOOL=y & use a DT with a chosen node that has either no +bootargs property or an empty one. In this configuration +early_init_dt_scan_chosen() copies CONFIG_CMDLINE into +boot_command_line, but the MIPS code doesn't know this so it appends +CONFIG_CMDLINE (via builtin_cmdline) to boot_command_line again. The +result is that boot_command_line contains the arguments from +CONFIG_CMDLINE twice. + +That commit took the approach of simply setting up boot_command_line +from the MIPS code before early_init_dt_scan_chosen() runs, causing it +not to copy CONFIG_CMDLINE to boot_command_line if a chosen node with no +bootargs property is found. + +Unfortunately this is problematic for systems which do have a non-empty +bootargs property & CONFIG_CMDLINE_BOOL=y. There +early_init_dt_scan_chosen() will overwrite boot_command_line with the +arguments from DT, which means we lose those from CONFIG_CMDLINE +entirely. This breaks CONFIG_MIPS_CMDLINE_DTB_EXTEND. If we have +CONFIG_MIPS_CMDLINE_FROM_BOOTLOADER or +CONFIG_MIPS_CMDLINE_BUILTIN_EXTEND selected and the DT has a bootargs +property which we should ignore, it will instead be honoured breaking +those configurations too. + +Fix this by reverting commit 8ce355cf2e38 ("MIPS: Setup +boot_command_line before plat_mem_setup") to restore the former +behaviour, and fixing the CONFIG_CMDLINE duplication issue by +initializing boot_command_line to a non-empty string that +early_init_dt_scan_chosen() will not overwrite with CONFIG_CMDLINE. + +This is a little ugly, but cleanup in this area is on its way. In the +meantime this is at least easy to backport & contains the ugliness +within arch/mips/. + +Origin: upstream, https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=951d223c6c16ed5d2a71a4d1f13c1e65d6882156 +Signed-off-by: Paul Burton +Fixes: 8ce355cf2e38 ("MIPS: Setup boot_command_line before plat_mem_setup") +References: https://patchwork.linux-mips.org/patch/18804/ +Patchwork: https://patchwork.linux-mips.org/patch/20813/ +Cc: Frank Rowand +Cc: Jaedon Shin +Cc: Mathieu Malaterre +Cc: Rob Herring +Cc: devicetree@vger.kernel.org +Cc: linux-kernel@vger.kernel.org +Cc: linux-mips@linux-mips.org +Cc: stable@vger.kernel.org # v4.16+ + +diff --git a/arch/mips/kernel/setup.c b/arch/mips/kernel/setup.c +index c0f51fd4e0b3970e4f019094091578504e2f56eb..71070ec8da136495d2efed0aa79dff44149d565f 100644 +--- a/arch/mips/kernel/setup.c ++++ b/arch/mips/kernel/setup.c +@@ -833,6 +833,34 @@ static void __init arch_mem_init(char **cmdline_p) + struct memblock_region *reg; + extern void plat_mem_setup(void); + ++ /* ++ * Initialize boot_command_line to an innocuous but non-empty string in ++ * order to prevent early_init_dt_scan_chosen() from copying ++ * CONFIG_CMDLINE into it without our knowledge. We handle ++ * CONFIG_CMDLINE ourselves below & don't want to duplicate its ++ * content because repeating arguments can be problematic. ++ */ ++ strlcpy(boot_command_line, " ", COMMAND_LINE_SIZE); ++ ++ /* call board setup routine */ ++ plat_mem_setup(); ++ ++ /* ++ * Make sure all kernel memory is in the maps. The "UP" and ++ * "DOWN" are opposite for initdata since if it crosses over ++ * into another memory section you don't want that to be ++ * freed when the initdata is freed. ++ */ ++ arch_mem_addpart(PFN_DOWN(__pa_symbol(&_text)) << PAGE_SHIFT, ++ PFN_UP(__pa_symbol(&_edata)) << PAGE_SHIFT, ++ BOOT_MEM_RAM); ++ arch_mem_addpart(PFN_UP(__pa_symbol(&__init_begin)) << PAGE_SHIFT, ++ PFN_DOWN(__pa_symbol(&__init_end)) << PAGE_SHIFT, ++ BOOT_MEM_INIT_RAM); ++ ++ pr_info("Determined physical RAM map:\n"); ++ print_memory_map(); ++ + #if defined(CONFIG_CMDLINE_BOOL) && defined(CONFIG_CMDLINE_OVERRIDE) + strlcpy(boot_command_line, builtin_cmdline, COMMAND_LINE_SIZE); + #else +@@ -860,26 +888,6 @@ static void __init arch_mem_init(char **cmdline_p) + } + #endif + #endif +- +- /* call board setup routine */ +- plat_mem_setup(); +- +- /* +- * Make sure all kernel memory is in the maps. The "UP" and +- * "DOWN" are opposite for initdata since if it crosses over +- * into another memory section you don't want that to be +- * freed when the initdata is freed. +- */ +- arch_mem_addpart(PFN_DOWN(__pa_symbol(&_text)) << PAGE_SHIFT, +- PFN_UP(__pa_symbol(&_edata)) << PAGE_SHIFT, +- BOOT_MEM_RAM); +- arch_mem_addpart(PFN_UP(__pa_symbol(&__init_begin)) << PAGE_SHIFT, +- PFN_DOWN(__pa_symbol(&__init_end)) << PAGE_SHIFT, +- BOOT_MEM_INIT_RAM); +- +- pr_info("Determined physical RAM map:\n"); +- print_memory_map(); +- + strlcpy(command_line, boot_command_line, COMMAND_LINE_SIZE); + + *cmdline_p = command_line; diff --git a/target/linux/ath79/patches-4.14/0040-MIPS-cmdline-Clean-up-boot_command_line-initializati.patch b/target/linux/ath79/patches-4.14/0040-MIPS-cmdline-Clean-up-boot_command_line-initializati.patch new file mode 100644 index 0000000000000000000000000000000000000000..2cba97d5e85bb863ca95c0715110b69e4964ea51 --- /dev/null +++ b/target/linux/ath79/patches-4.14/0040-MIPS-cmdline-Clean-up-boot_command_line-initializati.patch @@ -0,0 +1,196 @@ +From: Paul Burton +Date: Wed, 9 Oct 2019 23:09:45 +0000 +Subject: MIPS: cmdline: Clean up boot_command_line initialization + +Our current code to initialize boot_command_line is a mess. Some of this +is due to the addition of too many options over the years, and some of +this is due to workarounds for early_init_dt_scan_chosen() performing +actions specific to options from other architectures that probably +shouldn't be in generic code. + +Clean this up by introducing a new bootcmdline_init() function that +simplifies the initialization somewhat. The major changes are: + +- Because bootcmdline_init() is a function it can return early in the + CONFIG_CMDLINE_OVERRIDE case. + +- We clear boot_command_line rather than inheriting whatever + early_init_dt_scan_chosen() may have left us. This means we no longer + need to set boot_command_line to a space character in an attempt to + prevent early_init_dt_scan_chosen() from copying CONFIG_CMDLINE into + boot_command_line without us knowing about it. + +- Indirection via USE_PROM_CMDLINE, USE_DTB_CMDLINE, EXTEND_WITH_PROM & + BUILTIN_EXTEND_WITH_PROM macros is removed; they seemingly served only + to obfuscate the code. + +- The logic is cleaner, clearer & commented. + +Two minor drawbacks of this approach are: + +1) We call of_scan_flat_dt(), which means we scan through the DT again. + The overhead is fairly minimal & shouldn't be noticeable. + +2) cmdline_scan_chosen() duplicates a small amount of the logic from + early_init_dt_scan_chosen(). Alternatives might be to allow the + generic FDT code to keep & expose a copy of the arguments taken from + the /chosen node's bootargs property, or to introduce a function like + early_init_dt_scan_chosen() that retrieves them without modification + to handle CONFIG_CMDLINE. Neither of these sounds particularly + cleaner though, and this way we at least keep the extra work in + arch/mips. + +Origin: backport, https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=7784cac697351f0cc0a4bb619594c0c99348c5aa +Signed-off-by: Paul Burton +Cc: linux-mips@vger.kernel.org + +diff --git a/arch/mips/kernel/setup.c b/arch/mips/kernel/setup.c +index 71070ec8da136495d2efed0aa79dff44149d565f..c2b659a2e2ce0f2074f4fc13cd24283d66ac5594 100644 +--- a/arch/mips/kernel/setup.c ++++ b/arch/mips/kernel/setup.c +@@ -822,26 +822,94 @@ static void __init request_crashkernel(struct resource *res) + } + #endif /* !defined(CONFIG_KEXEC) */ + +-#define USE_PROM_CMDLINE IS_ENABLED(CONFIG_MIPS_CMDLINE_FROM_BOOTLOADER) +-#define USE_DTB_CMDLINE IS_ENABLED(CONFIG_MIPS_CMDLINE_FROM_DTB) +-#define EXTEND_WITH_PROM IS_ENABLED(CONFIG_MIPS_CMDLINE_DTB_EXTEND) +-#define BUILTIN_EXTEND_WITH_PROM \ +- IS_ENABLED(CONFIG_MIPS_CMDLINE_BUILTIN_EXTEND) ++static void __init bootcmdline_append(const char *s, size_t max) ++{ ++ if (!s[0] || !max) ++ return; ++ ++ if (boot_command_line[0]) ++ strlcat(boot_command_line, " ", COMMAND_LINE_SIZE); ++ ++ strlcat(boot_command_line, s, max); ++} ++ ++static int __init bootcmdline_scan_chosen(unsigned long node, const char *uname, ++ int depth, void *data) ++{ ++ bool *dt_bootargs = data; ++ const char *p; ++ int l; ++ ++ if (depth != 1 || !data || ++ (strcmp(uname, "chosen") != 0 && strcmp(uname, "chosen@0") != 0)) ++ return 0; ++ ++ p = of_get_flat_dt_prop(node, "bootargs", &l); ++ if (p != NULL && l > 0) { ++ bootcmdline_append(p, min(l, COMMAND_LINE_SIZE)); ++ *dt_bootargs = true; ++ } ++ ++ return 1; ++} ++ ++static void __init bootcmdline_init(char **cmdline_p) ++{ ++ bool dt_bootargs = false; ++ ++ /* ++ * If CMDLINE_OVERRIDE is enabled then initializing the command line is ++ * trivial - we simply use the built-in command line unconditionally & ++ * unmodified. ++ */ ++ if (IS_ENABLED(CONFIG_CMDLINE_OVERRIDE)) { ++ strlcpy(boot_command_line, builtin_cmdline, COMMAND_LINE_SIZE); ++ return; ++ } ++ ++ /* ++ * If the user specified a built-in command line & ++ * MIPS_CMDLINE_BUILTIN_EXTEND, then the built-in command line is ++ * prepended to arguments from the bootloader or DT so we'll copy them ++ * to the start of boot_command_line here. Otherwise, empty ++ * boot_command_line to undo anything early_init_dt_scan_chosen() did. ++ */ ++ if (IS_ENABLED(CONFIG_MIPS_CMDLINE_BUILTIN_EXTEND)) ++ strlcpy(boot_command_line, builtin_cmdline, COMMAND_LINE_SIZE); ++ else ++ boot_command_line[0] = 0; ++ ++ /* ++ * If we're configured to take boot arguments from DT, look for those ++ * now. ++ */ ++ if (IS_ENABLED(CONFIG_MIPS_CMDLINE_FROM_DTB)) ++ of_scan_flat_dt(bootcmdline_scan_chosen, &dt_bootargs); ++ ++ /* ++ * If we didn't get any arguments from DT (regardless of whether that's ++ * because we weren't configured to look for them, or because we looked ++ * & found none) then we'll take arguments from the bootloader. ++ * plat_mem_setup() should have filled arcs_cmdline with arguments from ++ * the bootloader. ++ */ ++ if (IS_ENABLED(CONFIG_MIPS_CMDLINE_DTB_EXTEND) || !dt_bootargs) ++ bootcmdline_append(arcs_cmdline, COMMAND_LINE_SIZE); ++ ++ /* ++ * If the user specified a built-in command line & we didn't already ++ * prepend it, we append it to boot_command_line here. ++ */ ++ if (IS_ENABLED(CONFIG_CMDLINE_BOOL) && ++ !IS_ENABLED(CONFIG_MIPS_CMDLINE_BUILTIN_EXTEND)) ++ bootcmdline_append(builtin_cmdline, COMMAND_LINE_SIZE); ++} + + static void __init arch_mem_init(char **cmdline_p) + { + struct memblock_region *reg; + extern void plat_mem_setup(void); + +- /* +- * Initialize boot_command_line to an innocuous but non-empty string in +- * order to prevent early_init_dt_scan_chosen() from copying +- * CONFIG_CMDLINE into it without our knowledge. We handle +- * CONFIG_CMDLINE ourselves below & don't want to duplicate its +- * content because repeating arguments can be problematic. +- */ +- strlcpy(boot_command_line, " ", COMMAND_LINE_SIZE); +- + /* call board setup routine */ + plat_mem_setup(); + +@@ -861,35 +929,8 @@ static void __init arch_mem_init(char **cmdline_p) + pr_info("Determined physical RAM map:\n"); + print_memory_map(); + +-#if defined(CONFIG_CMDLINE_BOOL) && defined(CONFIG_CMDLINE_OVERRIDE) +- strlcpy(boot_command_line, builtin_cmdline, COMMAND_LINE_SIZE); +-#else +- if ((USE_PROM_CMDLINE && arcs_cmdline[0]) || +- (USE_DTB_CMDLINE && !boot_command_line[0])) +- strlcpy(boot_command_line, arcs_cmdline, COMMAND_LINE_SIZE); +- +- if (EXTEND_WITH_PROM && arcs_cmdline[0]) { +- if (boot_command_line[0]) +- strlcat(boot_command_line, " ", COMMAND_LINE_SIZE); +- strlcat(boot_command_line, arcs_cmdline, COMMAND_LINE_SIZE); +- } +- +-#if defined(CONFIG_CMDLINE_BOOL) +- if (builtin_cmdline[0]) { +- if (boot_command_line[0]) +- strlcat(boot_command_line, " ", COMMAND_LINE_SIZE); +- strlcat(boot_command_line, builtin_cmdline, COMMAND_LINE_SIZE); +- } +- +- if (BUILTIN_EXTEND_WITH_PROM && arcs_cmdline[0]) { +- if (boot_command_line[0]) +- strlcat(boot_command_line, " ", COMMAND_LINE_SIZE); +- strlcat(boot_command_line, arcs_cmdline, COMMAND_LINE_SIZE); +- } +-#endif +-#endif ++ bootcmdline_init(cmdline_p); + strlcpy(command_line, boot_command_line, COMMAND_LINE_SIZE); +- + *cmdline_p = command_line; + + parse_early_param();