From: Sean Anderson Date: Thu, 19 May 2022 22:26:05 +0000 (-0400) Subject: bootm: Fix Linux silent console on newer kernels X-Git-Url: http://git.dujemihanovic.xyz/login.html?a=commitdiff_plain;h=ba9aa40bb387385b8ef8b6594661a97ddcb8d04c;p=u-boot.git bootm: Fix Linux silent console on newer kernels Linux determines its console based on several sources: 1. the console command line parameter 2. device tree (e.g. /chosen/stdout-path) 3. various other board- and arch-specific sources If the console parameter specifies a real console (e.g. ttyS0) then that is used as /dev/console. However, if it does not specify a real console (e.g. ttyDoesntExist) then *nothing* will be used as /dev/console. Reading/writing it will return ENODEV. Additionally, no other source will be used as a console source. Linux commit ab4af56ae250 ("printk/console: Allow to disable console output by using console="" or console=null") recently changed the semantics of the parameter. Previously, specifying console="" would be treated like specifying some other bad console. This commit changed things so that it added /dev/ttynull as a console (if available). However, it also allows for other console sources. If the device tree specifies a console (such as if U-Boot and Linux share a device tree), then it will be used in addition to /dev/ttynull. This can result in a non-silent console. To avoid this, explicitly set ttynull as the console. This will disable other console sources. If CONFIG_NULL_TTY is disabled, then this will have the same behavior as in the past (no output, and writing /dev/console returns ENODEV). [1] and [2] have additional background on this kernel change. [1] https://lore.kernel.org/all/20201006025935.GA597@jagdpanzerIV.localdomain/ [2] https://lore.kernel.org/all/20201111135450.11214-1-pmladek@suse.com/ Signed-off-by: Sean Anderson --- diff --git a/boot/bootm.c b/boot/bootm.c index 714406ab66..dfa65f125e 100644 --- a/boot/bootm.c +++ b/boot/bootm.c @@ -498,7 +498,8 @@ ulong bootm_disable_interrupts(void) } #define CONSOLE_ARG "console=" -#define CONSOLE_ARG_SIZE sizeof(CONSOLE_ARG) +#define NULL_CONSOLE (CONSOLE_ARG "ttynull") +#define CONSOLE_ARG_SIZE sizeof(NULL_CONSOLE) /** * fixup_silent_linux() - Handle silencing the linux boot if required @@ -550,21 +551,22 @@ static int fixup_silent_linux(char *buf, int maxlen) char *end = strchr(start, ' '); int start_bytes; - start_bytes = start - cmdline + CONSOLE_ARG_SIZE - 1; + start_bytes = start - cmdline; strncpy(buf, cmdline, start_bytes); + strncpy(buf + start_bytes, NULL_CONSOLE, CONSOLE_ARG_SIZE); if (end) - strcpy(buf + start_bytes, end); + strcpy(buf + start_bytes + CONSOLE_ARG_SIZE - 1, end); else - buf[start_bytes] = '\0'; + buf[start_bytes + CONSOLE_ARG_SIZE] = '\0'; } else { - sprintf(buf, "%s %s", cmdline, CONSOLE_ARG); + sprintf(buf, "%s %s", cmdline, NULL_CONSOLE); } if (buf + strlen(buf) >= cmdline) return -ENOSPC; } else { - if (maxlen < sizeof(CONSOLE_ARG)) + if (maxlen < CONSOLE_ARG_SIZE) return -ENOSPC; - strcpy(buf, CONSOLE_ARG); + strcpy(buf, NULL_CONSOLE); } debug("after silent fix-up: %s\n", buf); diff --git a/test/bootm.c b/test/bootm.c index 8528982ae1..7d03e1e0c6 100644 --- a/test/bootm.c +++ b/test/bootm.c @@ -83,12 +83,12 @@ static int bootm_test_silent(struct unit_test_state *uts) ut_assertok(env_set("silent_linux", "yes")); ut_assertok(bootm_process_cmdline(buf, BUF_SIZE, BOOTM_CL_SILENT)); - ut_asserteq_str("console=", buf); + ut_asserteq_str("console=ttynull", buf); /* Empty buffer should still add the string */ *buf = '\0'; ut_assertok(bootm_process_cmdline(buf, BUF_SIZE, BOOTM_CL_SILENT)); - ut_asserteq_str("console=", buf); + ut_asserteq_str("console=ttynull", buf); /* Check nothing happens when do_silent is false */ *buf = '\0'; @@ -97,21 +97,21 @@ static int bootm_test_silent(struct unit_test_state *uts) /* Not enough space */ *buf = '\0'; - ut_asserteq(-ENOSPC, bootm_process_cmdline(buf, 8, BOOTM_CL_SILENT)); + ut_asserteq(-ENOSPC, bootm_process_cmdline(buf, 15, BOOTM_CL_SILENT)); /* Just enough space */ *buf = '\0'; - ut_assertok(bootm_process_cmdline(buf, 9, BOOTM_CL_SILENT)); + ut_assertok(bootm_process_cmdline(buf, 16, BOOTM_CL_SILENT)); /* add at end */ strcpy(buf, "something"); ut_assertok(bootm_process_cmdline(buf, BUF_SIZE, BOOTM_CL_SILENT)); - ut_asserteq_str("something console=", buf); + ut_asserteq_str("something console=ttynull", buf); /* change at start */ strcpy(buf, CONSOLE_STR " something"); ut_assertok(bootm_process_cmdline(buf, BUF_SIZE, BOOTM_CL_SILENT)); - ut_asserteq_str("console= something", buf); + ut_asserteq_str("console=ttynull something", buf); return 0; } @@ -210,12 +210,12 @@ static int bootm_test_subst_var(struct unit_test_state *uts) { env_set("bootargs", NULL); ut_assertok(bootm_process_cmdline_env(BOOTM_CL_SILENT)); - ut_asserteq_str("console=", env_get("bootargs")); + ut_asserteq_str("console=ttynull", env_get("bootargs")); ut_assertok(env_set("var", "abc")); ut_assertok(env_set("bootargs", "some${var}thing")); ut_assertok(bootm_process_cmdline_env(BOOTM_CL_SILENT)); - ut_asserteq_str("some${var}thing console=", env_get("bootargs")); + ut_asserteq_str("some${var}thing console=ttynull", env_get("bootargs")); return 0; } @@ -227,12 +227,12 @@ static int bootm_test_subst_both(struct unit_test_state *uts) ut_assertok(env_set("silent_linux", "yes")); env_set("bootargs", NULL); ut_assertok(bootm_process_cmdline_env(BOOTM_CL_ALL)); - ut_asserteq_str("console=", env_get("bootargs")); + ut_asserteq_str("console=ttynull", env_get("bootargs")); ut_assertok(env_set("bootargs", "some${var}thing " CONSOLE_STR)); ut_assertok(env_set("var", "1234567890")); ut_assertok(bootm_process_cmdline_env(BOOTM_CL_ALL)); - ut_asserteq_str("some1234567890thing console=", env_get("bootargs")); + ut_asserteq_str("some1234567890thing console=ttynull", env_get("bootargs")); return 0; }