From 174d3c4fe3f3cdf35e0587623897957def73f7b5 Mon Sep 17 00:00:00 2001 From: Keir Fraser Date: Mon, 29 Jan 2024 16:17:04 +0000 Subject: [PATCH] Revert "Revert "ANDROID: Support CONFIG_CMDLINE_EXTEND"" This reverts commit 68cf9989a1fff78fe0700c051a202b6e2a7c9fe4 and reinstates long-standing Android command-line parsing behaviour with CONFIG_CMDLINE_EXTEND. Bug: 357781595 Bug: 120440972 Bug: 278749606 Signed-off-by: Keir Fraser Change-Id: Iac374066a980d38a1dadf1fa13fff16f48bd44c5 --- arch/arm64/Kconfig | 6 +++ arch/arm64/configs/gki_defconfig | 1 + arch/arm64/kernel/pi/idreg-override.c | 5 +- drivers/of/fdt.c | 70 ++++++++++++++++++--------- include/linux/of_fdt.h | 21 ++++++++ 5 files changed, 78 insertions(+), 25 deletions(-) diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig index 8015f95cbc24..c800879ee950 100644 --- a/arch/arm64/Kconfig +++ b/arch/arm64/Kconfig @@ -2355,6 +2355,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/configs/gki_defconfig b/arch/arm64/configs/gki_defconfig index a83fcdd4b90b..4b9a1ed56536 100644 --- a/arch/arm64/configs/gki_defconfig +++ b/arch/arm64/configs/gki_defconfig @@ -68,6 +68,7 @@ CONFIG_RANDOMIZE_BASE=y # CONFIG_RANDOMIZE_MODULE_REGION_FULL is not set CONFIG_UNWIND_PATCH_PAC_INTO_SCS=y CONFIG_CMDLINE="console=ttynull stack_depot_disable=on cgroup_disable=pressure kasan.stacktrace=off kvm-arm.mode=protected bootconfig ioremap_guard" +CONFIG_CMDLINE_EXTEND=y # CONFIG_DMI is not set CONFIG_HIBERNATION=y CONFIG_PM_WAKELOCKS=y diff --git a/arch/arm64/kernel/pi/idreg-override.c b/arch/arm64/kernel/pi/idreg-override.c index 29d4b6244a6f..19d1211d365c 100644 --- a/arch/arm64/kernel/pi/idreg-override.c +++ b/arch/arm64/kernel/pi/idreg-override.c @@ -361,8 +361,11 @@ static __init void parse_cmdline(const void *fdt, int chosen) static char const cmdline[] __initconst = CONFIG_CMDLINE; const u8 *prop = get_bootargs_cmdline(fdt, chosen); - if (IS_ENABLED(CONFIG_CMDLINE_FORCE) || !prop) + if (IS_ENABLED(CONFIG_CMDLINE_EXTEND) || + IS_ENABLED(CONFIG_CMDLINE_FORCE) || + !prop) { __parse_cmdline(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 index 4d528c10df3a..9a8d821a7c3a 100644 --- a/drivers/of/fdt.c +++ b/drivers/of/fdt.c @@ -1016,10 +1016,33 @@ int __init early_init_dt_scan_memory(void) return found_memory; } +/* + * 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(char *cmdline) { - int l, node; - const char *p; + int l = 0, node; + const char *p = NULL; const void *rng_seed; const void *fdt = initial_boot_params; @@ -1047,30 +1070,29 @@ int __init early_init_dt_scan_chosen(char *cmdline) fdt_totalsize(initial_boot_params)); } - /* Retrieve command line */ - p = of_get_flat_dt_prop(node, "bootargs", &l); - if (p != NULL && l > 0) - strscpy(cmdline, p, min(l, COMMAND_LINE_SIZE)); + /* Put CONFIG_CMDLINE in if forced or if data had nothing in it to start */ + if (overwrite_incoming_cmdline || !cmdline[0]) + strscpy(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 { + strscpy(cmdline, p, min(l, COMMAND_LINE_SIZE)); + } + } handle_cmdline: - /* - * 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(cmdline, " ", COMMAND_LINE_SIZE); - strlcat(cmdline, CONFIG_CMDLINE, COMMAND_LINE_SIZE); -#elif defined(CONFIG_CMDLINE_FORCE) - strscpy(cmdline, CONFIG_CMDLINE, COMMAND_LINE_SIZE); -#else - /* No arguments from boot loader, use kernel's cmdl*/ - if (!((char *)cmdline)[0]) - strscpy(cmdline, CONFIG_CMDLINE, COMMAND_LINE_SIZE); -#endif -#endif /* CONFIG_CMDLINE */ - pr_debug("Command line is: %s\n", (char *)cmdline); return 0; diff --git a/include/linux/of_fdt.h b/include/linux/of_fdt.h index d69ad5bb1eb1..991e4c1c87ba 100644 --- 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(char *cmdline); extern int early_init_dt_scan_memory(void); extern void early_init_dt_check_for_usable_mem_range(void);