| From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 |
| From: Carlos Llamas <cmllamas@google.com> |
| Date: Sun, 19 Sep 2021 01:30:28 +0000 |
| Subject: ANDROID: Support CONFIG_CMDLINE_EXTEND |
| |
| The old logic assumes CMDLINE_FROM_BOOTLOADER vs. CMDLINE_FORCE and |
| ignores CMDLINE_EXTEND. Here's the old logic: |
| |
| - CONFIG_CMDLINE_FORCE=true |
| CONFIG_CMDLINE |
| - dt bootargs=non-empty: |
| dt bootargs |
| - dt bootargs=empty, @data is non-empty string |
| @data is left unchanged |
| - dt bootargs=empty, @data is empty string |
| CONFIG_CMDLINE (or "" if that's not defined) |
| |
| The new logic is now documented in of_fdt.h and is copied here for |
| reference: |
| |
| - CONFIG_CMDLINE_FORCE=true |
| CONFIG_CMDLINE |
| - CONFIG_CMDLINE_EXTEND=true, @data is non-empty string |
| @data + dt bootargs (even if dt bootargs are empty) |
| - CONFIG_CMDLINE_EXTEND=true, @data is empty string |
| CONFIG_CMDLINE + dt bootargs (even if dt bootargs are empty) |
| - CMDLINE_FROM_BOOTLOADER=true, dt bootargs=non-empty: |
| dt bootargs |
| - CMDLINE_FROM_BOOTLOADER=true, dt bootargs=empty, @data is non-empty string |
| @data is left unchanged |
| - CMDLINE_FROM_BOOTLOADER=true, dt bootargs=empty, @data is empty string |
| CONFIG_CMDLINE (or "" if that's not defined) |
| |
| [CPNOTE: 03/06/21] Lee: Pinged the bug and re-assigned Doug |
| [CPNOTE: 21/06/21] Lee: Will Deacon is continuing with this - bug now assigned to him |
| [CPNOTE: 05/08/21] Lee: There are competing replacements on the MLs - pinged Rob Herring for updates |
| |
| Signed-off-by: Doug Anderson <dianders@chromium.org> |
| CC: devicetree-discuss@lists.ozlabs.org |
| CC: Grant Likely <grant.likely@secretlab.ca> |
| CC: Benjamin Herrenschmidt <benh@kernel.crashing.org> |
| CC: Rob Herring <rob.herring@calxeda.com> |
| Bug: 120440972 |
| Change-Id: I40ace250847f813358125dfcaa8998fd32cf7ea3 |
| Signed-off-by: Colin Cross <ccross@android.com> |
| [AmitP: Folded following android-4.9 commit changes into this patch |
| e820270abb5d ("ANDROID: of: fix CONFIG_CMDLINE_EXTEND") |
| 9a4a74055444 ("ANDROID: of: Fix build warnings")] |
| Signed-off-by: Amit Pundir <amit.pundir@linaro.org> |
| --- |
| arch/arm64/Kconfig | 6 +++ |
| arch/arm64/kernel/idreg-override.c | 5 +- |
| drivers/of/fdt.c | 74 ++++++++++++++++++++---------- |
| include/linux/of_fdt.h | 21 +++++++++ |
| 4 files changed, 80 insertions(+), 26 deletions(-) |
| |
| diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig |
| --- a/arch/arm64/Kconfig |
| +++ b/arch/arm64/Kconfig |
| @@ -1982,6 +1982,12 @@ config CMDLINE_FROM_BOOTLOADER |
| the boot loader doesn't provide any, the default kernel command |
| string provided in CMDLINE will be used. |
| |
| +config CMDLINE_EXTEND |
| + bool "Extend bootloader kernel arguments" |
| + help |
| + The command-line arguments provided by the boot loader will be |
| + appended to the default kernel command string. |
| + |
| config CMDLINE_FORCE |
| bool "Always use the default kernel command string" |
| help |
| diff --git a/arch/arm64/kernel/idreg-override.c b/arch/arm64/kernel/idreg-override.c |
| --- a/arch/arm64/kernel/idreg-override.c |
| +++ b/arch/arm64/kernel/idreg-override.c |
| @@ -214,8 +214,11 @@ static __init void parse_cmdline(void) |
| { |
| const u8 *prop = get_bootargs_cmdline(); |
| |
| - if (IS_ENABLED(CONFIG_CMDLINE_FORCE) || !prop) |
| + if (IS_ENABLED(CONFIG_CMDLINE_EXTEND) || |
| + IS_ENABLED(CONFIG_CMDLINE_FORCE) || |
| + !prop) { |
| __parse_cmdline(CONFIG_CMDLINE, true); |
| + } |
| |
| if (!IS_ENABLED(CONFIG_CMDLINE_FORCE) && prop) |
| __parse_cmdline(prop, true); |
| diff --git a/drivers/of/fdt.c b/drivers/of/fdt.c |
| --- a/drivers/of/fdt.c |
| +++ b/drivers/of/fdt.c |
| @@ -1124,16 +1124,40 @@ int __init early_init_dt_scan_memory(unsigned long node, const char *uname, |
| return 0; |
| } |
| |
| +/* |
| + * Convert configs to something easy to use in C code |
| + */ |
| +#if defined(CONFIG_CMDLINE_FORCE) |
| +static const int overwrite_incoming_cmdline = 1; |
| +static const int read_dt_cmdline; |
| +static const int concat_cmdline; |
| +#elif defined(CONFIG_CMDLINE_EXTEND) |
| +static const int overwrite_incoming_cmdline; |
| +static const int read_dt_cmdline = 1; |
| +static const int concat_cmdline = 1; |
| +#else /* CMDLINE_FROM_BOOTLOADER */ |
| +static const int overwrite_incoming_cmdline; |
| +static const int read_dt_cmdline = 1; |
| +static const int concat_cmdline; |
| +#endif |
| + |
| +#ifdef CONFIG_CMDLINE |
| +static const char *config_cmdline = CONFIG_CMDLINE; |
| +#else |
| +static const char *config_cmdline = ""; |
| +#endif |
| + |
| int __init early_init_dt_scan_chosen(unsigned long node, const char *uname, |
| int depth, void *data) |
| { |
| - int l; |
| - const char *p; |
| + int l = 0; |
| + const char *p = NULL; |
| const void *rng_seed; |
| + char *cmdline = data; |
| |
| pr_debug("search \"chosen\", depth: %d, uname: %s\n", depth, uname); |
| |
| - if (depth != 1 || !data || |
| + if (depth != 1 || !cmdline || |
| (strcmp(uname, "chosen") != 0 && strcmp(uname, "chosen@0") != 0)) |
| return 0; |
| |
| @@ -1141,28 +1165,28 @@ int __init early_init_dt_scan_chosen(unsigned long node, const char *uname, |
| early_init_dt_check_for_elfcorehdr(node); |
| early_init_dt_check_for_usable_mem_range(node); |
| |
| - /* Retrieve command line */ |
| - p = of_get_flat_dt_prop(node, "bootargs", &l); |
| - if (p != NULL && l > 0) |
| - strlcpy(data, p, min(l, COMMAND_LINE_SIZE)); |
| - |
| - /* |
| - * CONFIG_CMDLINE is meant to be a default in case nothing else |
| - * managed to set the command line, unless CONFIG_CMDLINE_FORCE |
| - * is set in which case we override whatever was found earlier. |
| - */ |
| -#ifdef CONFIG_CMDLINE |
| -#if defined(CONFIG_CMDLINE_EXTEND) |
| - strlcat(data, " ", COMMAND_LINE_SIZE); |
| - strlcat(data, CONFIG_CMDLINE, COMMAND_LINE_SIZE); |
| -#elif defined(CONFIG_CMDLINE_FORCE) |
| - strlcpy(data, CONFIG_CMDLINE, COMMAND_LINE_SIZE); |
| -#else |
| - /* No arguments from boot loader, use kernel's cmdl*/ |
| - if (!((char *)data)[0]) |
| - strlcpy(data, CONFIG_CMDLINE, COMMAND_LINE_SIZE); |
| -#endif |
| -#endif /* CONFIG_CMDLINE */ |
| + /* Put CONFIG_CMDLINE in if forced or if data had nothing in it to start */ |
| + if (overwrite_incoming_cmdline || !cmdline[0]) |
| + strlcpy(cmdline, config_cmdline, COMMAND_LINE_SIZE); |
| + |
| + /* Retrieve command line unless forcing */ |
| + if (read_dt_cmdline) |
| + p = of_get_flat_dt_prop(node, "bootargs", &l); |
| + |
| + if (p != NULL && l > 0) { |
| + if (concat_cmdline) { |
| + int cmdline_len; |
| + int copy_len; |
| + strlcat(cmdline, " ", COMMAND_LINE_SIZE); |
| + cmdline_len = strlen(cmdline); |
| + copy_len = COMMAND_LINE_SIZE - cmdline_len - 1; |
| + copy_len = min((int)l, copy_len); |
| + strncpy(cmdline + cmdline_len, p, copy_len); |
| + cmdline[cmdline_len + copy_len] = '\0'; |
| + } else { |
| + strlcpy(cmdline, p, min(l, COMMAND_LINE_SIZE)); |
| + } |
| + } |
| |
| pr_debug("Command line is: %s\n", (char *)data); |
| |
| diff --git a/include/linux/of_fdt.h b/include/linux/of_fdt.h |
| --- a/include/linux/of_fdt.h |
| +++ b/include/linux/of_fdt.h |
| @@ -58,6 +58,27 @@ extern int of_flat_dt_is_compatible(unsigned long node, const char *name); |
| extern unsigned long of_get_flat_dt_root(void); |
| extern uint32_t of_get_flat_dt_phandle(unsigned long node); |
| |
| +/* |
| + * early_init_dt_scan_chosen - scan the device tree for ramdisk and bootargs |
| + * |
| + * The boot arguments will be placed into the memory pointed to by @data. |
| + * That memory should be COMMAND_LINE_SIZE big and initialized to be a valid |
| + * (possibly empty) string. Logic for what will be in @data after this |
| + * function finishes: |
| + * |
| + * - CONFIG_CMDLINE_FORCE=true |
| + * CONFIG_CMDLINE |
| + * - CONFIG_CMDLINE_EXTEND=true, @data is non-empty string |
| + * @data + dt bootargs (even if dt bootargs are empty) |
| + * - CONFIG_CMDLINE_EXTEND=true, @data is empty string |
| + * CONFIG_CMDLINE + dt bootargs (even if dt bootargs are empty) |
| + * - CMDLINE_FROM_BOOTLOADER=true, dt bootargs=non-empty: |
| + * dt bootargs |
| + * - CMDLINE_FROM_BOOTLOADER=true, dt bootargs=empty, @data is non-empty string |
| + * @data is left unchanged |
| + * - CMDLINE_FROM_BOOTLOADER=true, dt bootargs=empty, @data is empty string |
| + * CONFIG_CMDLINE (or "" if that's not defined) |
| + */ |
| extern int early_init_dt_scan_chosen(unsigned long node, const char *uname, |
| int depth, void *data); |
| extern int early_init_dt_scan_memory(unsigned long node, const char *uname, |