This makes fixup_silent_linux() use malloc() to allocate its working space, meaning that our maximum kernel command line should only be limited by malloc(). Previously it was silently overflowing the stack.
Signed-off-by: Doug Anderson <diand...@chromium.org> --- common/cmd_bootm.c | 125 ++++++++++++++++++++++++++++++++++++++++++++-------- 1 files changed, 106 insertions(+), 19 deletions(-) diff --git a/common/cmd_bootm.c b/common/cmd_bootm.c index ece1b9a..f426e2f 100644 --- a/common/cmd_bootm.c +++ b/common/cmd_bootm.c @@ -26,6 +26,7 @@ * Boot support */ #include <common.h> +#include <cmdline.h> #include <watchdog.h> #include <command.h> #include <image.h> @@ -1200,36 +1201,122 @@ U_BOOT_CMD( /* helper routines */ /*******************************************************************/ #ifdef CONFIG_SILENT_CONSOLE + +/** + * Remove "console=blah" and from cmdline, replace w/ "console=". + * + * This has the effect of telling Linux that we'd like it to have a silent + * console. + * + * @param cmdline The original commanjd line. + * @return The new command line, which has been allocated with malloc(). + * Might be NULL if we ran out of memory. + */ +static char *do_fixup_silent_linux(const char *cmdline) +{ + char *buf; + int bufsize; + int did_remove; + + if (!cmdline) + cmdline = ""; + + /* + * Allocate enough space for: + * - a copy of the command line + * - a space + * - a blank "console=" argument + * - the '\0' + * + * ...we might not need all this space, but it's OK to overallocate a + * little. + */ + bufsize = strlen(cmdline) + 1 + sizeof("console="); + buf = malloc(bufsize); + if (!buf) { + debug("WARNING: malloc failed in fixup_silent_linux\n"); + return NULL; + } + + strcpy(buf, cmdline); + do { + did_remove = remove_cmdline_param(buf, "console"); + } while (did_remove); + add_cmdline_param(buf, "console=", bufsize); + + return buf; +} + static void fixup_silent_linux(void) { - char buf[256], *start, *end; - char *cmdline = getenv("bootargs"); + char *buf; + const char *cmdline = getenv("bootargs"); /* Only fix cmdline when requested */ if (!(gd->flags & GD_FLG_SILENT)) return; debug("before silent fix-up: %s\n", cmdline); - if (cmdline) { - start = strstr(cmdline, "console="); - if (start) { - end = strchr(start, ' '); - strncpy(buf, cmdline, (start - cmdline + 8)); - if (end) - strcpy(buf + (start - cmdline + 8), end); - else - buf[start - cmdline + 8] = '\0'; - } else { - strcpy(buf, cmdline); - strcat(buf, " console="); - } - } else { - strcpy(buf, "console="); + + buf = do_fixup_silent_linux(cmdline); + if (buf) { + setenv("bootargs", buf); + debug("after silent fix-up: %s\n", buf); + free(buf); } +} - setenv("bootargs", buf); - debug("after silent fix-up: %s\n", buf); +/** + * Unit tests for do_fixup_silent_linux(). + * + * At the moment, there's no easy way to run this other than to copy it (and + * do_fixup_silent_linux) to another file. + */ +#ifdef RUN_UNITTESTS +void do_fixup_silent_linux_unittest(void) +{ + char *original_str; + char *expected_str; + char *result; + + /* Simple case first, as an example */ + original_str = "console=ttyS0,115200n8 root=/dev/mmcblk0p3 rootwait ro"; + expected_str = "root=/dev/mmcblk0p3 rootwait ro console="; + result = do_fixup_silent_linux(original_str); + assert(strcmp(result, expected_str) == 0); + free(result); + + /* Null cases next */ + original_str = NULL; + expected_str = "console="; + result = do_fixup_silent_linux(original_str); + assert(strcmp(result, expected_str) == 0); + free(result); + + original_str = ""; + expected_str = "console="; + result = do_fixup_silent_linux(original_str); + assert(strcmp(result, expected_str) == 0); + free(result); + + /* Throw console= at the end */ + original_str = "root=/dev/mmcblk0p3 rootwait ro console=ttyS0,115200n8"; + expected_str = "root=/dev/mmcblk0p3 rootwait ro console="; + result = do_fixup_silent_linux(original_str); + assert(strcmp(result, expected_str) == 0); + free(result); + + /* Something non-NULL with no "console=" */ + original_str = "root=/dev/mmcblk0p3 rootwait ro"; + expected_str = "root=/dev/mmcblk0p3 rootwait ro console="; + result = do_fixup_silent_linux(original_str); + assert(strcmp(result, expected_str) == 0); + free(result); + + debug("do_fixup_silent_linux_unittest: pass\n"); } +#endif /* RUN_UNITTESTS */ + #endif /* CONFIG_SILENT_CONSOLE */ -- 1.7.3.1 _______________________________________________ U-Boot mailing list U-Boot@lists.denx.de http://lists.denx.de/mailman/listinfo/u-boot