| /* SPDX-License-Identifier: Apache-2.0 |
| * Copyright The Zephyr Project contributors |
| */ |
| |
| #include <zephyr/sys/util.h> |
| #include <ctype.h> |
| #include <zephyr/logging/log.h> |
| LOG_MODULE_DECLARE(os, CONFIG_KERNEL_LOG_LEVEL); |
| |
| extern const char *get_bootargs(void); |
| 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)++; |
| } |
| } |