ath79: Fix fallback to bootloader cmdline on empty DT bootargs
authorSven Eckelmann <sven@narfation.org>
Mon, 23 Nov 2020 15:57:31 +0000 (16:57 +0100)
committerPetr Štetiar <ynezz@true.cz>
Tue, 22 Dec 2020 18:11:50 +0000 (19:11 +0100)
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 <sven@narfation.org>
target/linux/ath79/patches-5.4/0001-MIPS-cmdline-Clean-up-boot_command_line-initializati.patch [new file with mode: 0644]

diff --git a/target/linux/ath79/patches-5.4/0001-MIPS-cmdline-Clean-up-boot_command_line-initializati.patch b/target/linux/ath79/patches-5.4/0001-MIPS-cmdline-Clean-up-boot_command_line-initializati.patch
new file mode 100644 (file)
index 0000000..4cadd5a
--- /dev/null
@@ -0,0 +1,194 @@
+From: Paul Burton <paul.burton@mips.com>
+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: upstream, https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=7784cac697351f0cc0a4bb619594c0c99348c5aa
+Signed-off-by: Paul Burton <paul.burton@mips.com>
+Cc: linux-mips@vger.kernel.org
+
+diff --git a/arch/mips/kernel/setup.c b/arch/mips/kernel/setup.c
+index b8884de89c81e1b444b218a15519556b4a374089..e56dd6c25d46336fcb9af21326f697d0c37aac1c 100644
+--- a/arch/mips/kernel/setup.c
++++ b/arch/mips/kernel/setup.c
+@@ -538,11 +538,88 @@ static void __init check_kernel_sections_mem(void)
+       }
+ }
+-#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);
++}
+ /*
+  * arch_mem_init - initialize memory management subsystem
+@@ -570,48 +647,12 @@ static void __init arch_mem_init(char **cmdline_p)
+ {
+       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();
+       memblock_set_bottom_up(true);
+-#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();