From 49fc106c606f470c22bc3f1786fa0966899571de Mon Sep 17 00:00:00 2001 From: Jakub Michalski Date: Thu, 11 Jul 2024 15:10:43 +0200 Subject: [PATCH] kernel: add bootargs support Add support for passing args to main(). The content of bootargs is taken from get_bootargs() which should be implemented for each loader and then its split into args and passed to main. Signed-off-by: Jakub Michalski Signed-off-by: Filip Kokosinski --- kernel/Kconfig | 25 +++++++++++++ kernel/init.c | 100 ++++++++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 123 insertions(+), 2 deletions(-) diff --git a/kernel/Kconfig b/kernel/Kconfig index 716294a39da..d0ce98b4e73 100644 --- a/kernel/Kconfig +++ b/kernel/Kconfig @@ -998,6 +998,31 @@ config STATIC_INIT_GNU Note the option CMAKE_LINKER_GENERATOR does not yet support this feature or CPP. +config BOOTARGS + bool "Support bootargs" + help + Enables bootargs support and passing them to main(). + +config DYNAMIC_BOOTARGS + bool "Support dynamic bootargs" + depends on BOOTARGS + help + Enables dynamic bootargs support. + +config BOOTARGS_STRING + string "static bootargs string" + depends on BOOTARGS && !DYNAMIC_BOOTARGS + help + Static bootargs string. It includes argv[0], so if its expected that it + contains executable name it should be put at the beginning of this string. + +config BOOTARGS_ARGS_BUFFER_SIZE + int "Size of buffer containing main arguments in bytes" + default 1024 + depends on BOOTARGS + help + Configures size of buffer containing all arguments passed to main. + endmenu rsource "Kconfig.device" diff --git a/kernel/init.c b/kernel/init.c index 8b7d62b8671..14a48c26e12 100644 --- a/kernel/init.c +++ b/kernel/init.c @@ -11,6 +11,9 @@ * This module contains routines that are used to initialize the kernel. */ +#include +#include +#include #include #include #include @@ -24,13 +27,11 @@ #include #include #include -#include #include #include #include #include #include -#include #include #include #include @@ -403,6 +404,93 @@ static inline int z_vrfy_device_init(const struct device *dev) extern void boot_banner(void); +#ifdef CONFIG_BOOTARGS +extern const char *get_bootargs(void); +static char **prepare_main_args(int *argc) +{ +#ifdef CONFIG_DYNAMIC_BOOTARGS + const char *bootargs = get_bootargs(); +#else + const char bootargs[] = CONFIG_BOOTARGS_STRING; +#endif + + /* beginning of the buffer contains argument's strings, end of it contains argvs */ + static char args_buf[CONFIG_BOOTARGS_ARGS_BUFFER_SIZE]; + char *strings_end = (char *)args_buf; + char **argv_begin = (char **)WB_DN( + args_buf + CONFIG_BOOTARGS_ARGS_BUFFER_SIZE - sizeof(char *)); + int i = 0; + + *argc = 0; + *argv_begin = NULL; + +#ifdef CONFIG_DYNAMIC_BOOTARGS + if (!bootargs) { + return argv_begin; + } +#endif + + while (1) { + while (isspace(bootargs[i])) { + i++; + } + + if (bootargs[i] == '\0') { + return argv_begin; + } + + if (strings_end + sizeof(char *) >= (char *)argv_begin) { + LOG_WRN("not enough space in args buffer to accommodate all bootargs" + " - bootargs truncated"); + return argv_begin; + } + + argv_begin--; + memmove(argv_begin, argv_begin + 1, *argc * sizeof(char *)); + argv_begin[*argc] = strings_end; + + bool quoted = false; + + if (bootargs[i] == '\"' || bootargs[i] == '\'') { + char delimiter = bootargs[i]; + + for (int j = i + 1; bootargs[j] != '\0'; j++) { + if (bootargs[j] == delimiter) { + quoted = true; + break; + } + } + } + + if (quoted) { + char delimiter = bootargs[i]; + + i++; /* strip quotes */ + while (bootargs[i] != delimiter + && strings_end < (char *)argv_begin) { + *strings_end++ = bootargs[i++]; + } + i++; /* strip quotes */ + } else { + while (!isspace(bootargs[i]) + && bootargs[i] != '\0' + && strings_end < (char *)argv_begin) { + *strings_end++ = bootargs[i++]; + } + } + + if (strings_end < (char *)argv_begin) { + *strings_end++ = '\0'; + } else { + LOG_WRN("not enough space in args buffer to accommodate all bootargs" + " - bootargs truncated"); + argv_begin[*argc] = NULL; + return argv_begin; + } + (*argc)++; + } +} +#endif /** * @brief Mainline for kernel's background thread @@ -456,9 +544,17 @@ static void bg_thread_main(void *unused1, void *unused2, void *unused3) z_mem_manage_boot_finish(); #endif /* CONFIG_MMU */ +#ifdef CONFIG_BOOTARGS + extern int main(int, char **); + + int argc = 0; + char **argv = prepare_main_args(&argc); + (void)main(argc, argv); +#else extern int main(void); (void)main(); +#endif /* CONFIG_BOOTARGS */ /* Mark non-essential since main() has no more work to do */ z_thread_essential_clear(&z_main_thread);