1 /* SPDX-License-Identifier: Apache-2.0
2  * Copyright The Zephyr Project contributors
3  */
4 
5 #include <zephyr/sys/util.h>
6 #include <ctype.h>
7 #include <zephyr/logging/log.h>
8 LOG_MODULE_DECLARE(os, CONFIG_KERNEL_LOG_LEVEL);
9 
10 extern const char *get_bootargs(void);
prepare_main_args(int * argc)11 char **prepare_main_args(int *argc)
12 {
13 #ifdef CONFIG_DYNAMIC_BOOTARGS
14 	const char *bootargs = get_bootargs();
15 #else
16 	const char bootargs[] = CONFIG_BOOTARGS_STRING;
17 #endif
18 
19 	/* beginning of the buffer contains argument's strings, end of it contains argvs */
20 	static char args_buf[CONFIG_BOOTARGS_ARGS_BUFFER_SIZE];
21 	char *strings_end = (char *)args_buf;
22 	char **argv_begin = (char **)WB_DN(
23 		args_buf + CONFIG_BOOTARGS_ARGS_BUFFER_SIZE - sizeof(char *));
24 	int i = 0;
25 
26 	*argc = 0;
27 	*argv_begin = NULL;
28 
29 #ifdef CONFIG_DYNAMIC_BOOTARGS
30 	if (!bootargs) {
31 		return argv_begin;
32 	}
33 #endif
34 
35 	while (1) {
36 		while (isspace(bootargs[i])) {
37 			i++;
38 		}
39 
40 		if (bootargs[i] == '\0') {
41 			return argv_begin;
42 		}
43 
44 		if (strings_end + sizeof(char *) >= (char *)argv_begin) {
45 			LOG_WRN("not enough space in args buffer to accommodate all bootargs"
46 				" - bootargs truncated");
47 			return argv_begin;
48 		}
49 
50 		argv_begin--;
51 		memmove(argv_begin, argv_begin + 1, *argc * sizeof(char *));
52 		argv_begin[*argc] = strings_end;
53 
54 		bool quoted = false;
55 
56 		if (bootargs[i] == '\"' || bootargs[i] == '\'') {
57 			char delimiter = bootargs[i];
58 
59 			for (int j = i + 1; bootargs[j] != '\0'; j++) {
60 				if (bootargs[j] == delimiter) {
61 					quoted = true;
62 					break;
63 				}
64 			}
65 		}
66 
67 		if (quoted) {
68 			char delimiter  = bootargs[i];
69 
70 			i++; /* strip quotes */
71 			while (bootargs[i] != delimiter
72 				&& strings_end < (char *)argv_begin) {
73 				*strings_end++ = bootargs[i++];
74 			}
75 			i++; /* strip quotes */
76 		} else {
77 			while (!isspace(bootargs[i])
78 				&& bootargs[i] != '\0'
79 				&& strings_end < (char *)argv_begin) {
80 				*strings_end++ = bootargs[i++];
81 			}
82 		}
83 
84 		if (strings_end < (char *)argv_begin) {
85 			*strings_end++ = '\0';
86 		} else {
87 			LOG_WRN("not enough space in args buffer to accommodate all bootargs"
88 				" - bootargs truncated");
89 			argv_begin[*argc] = NULL;
90 			return argv_begin;
91 		}
92 		(*argc)++;
93 	}
94 }
95