1// SPDX-License-Identifier: GPL-2.0+
2/*
3 * Tests for bootm routines
4 *
5 * Copyright 2020 Google LLC
6 */
7
8#include <common.h>
9#include <bootm.h>
10#include <asm/global_data.h>
11#include <test/suites.h>
12#include <test/test.h>
13#include <test/ut.h>
14
15DECLARE_GLOBAL_DATA_PTR;
16
17#define BOOTM_TEST(_name, _flags)	UNIT_TEST(_name, _flags, bootm_test)
18
19enum {
20	BUF_SIZE	= 1024,
21};
22
23#define CONSOLE_STR	"console=/dev/ttyS0"
24
25/* Test cmdline processing where nothing happens */
26static int bootm_test_nop(struct unit_test_state *uts)
27{
28	char buf[BUF_SIZE];
29
30	*buf = '\0';
31	ut_assertok(bootm_process_cmdline(buf, BUF_SIZE, true));
32	ut_asserteq_str("", buf);
33
34	strcpy(buf, "test");
35	ut_assertok(bootm_process_cmdline(buf, BUF_SIZE, true));
36	ut_asserteq_str("test", buf);
37
38	return 0;
39}
40BOOTM_TEST(bootm_test_nop, 0);
41
42/* Test cmdline processing when out of space */
43static int bootm_test_nospace(struct unit_test_state *uts)
44{
45	char buf[BUF_SIZE];
46
47	/* Zero buffer size */
48	*buf = '\0';
49	ut_asserteq(-ENOSPC, bootm_process_cmdline(buf, 0, true));
50
51	/* Buffer string not terminated */
52	memset(buf, 'a', BUF_SIZE);
53	ut_asserteq(-ENOSPC, bootm_process_cmdline(buf, BUF_SIZE, true));
54
55	/* Not enough space to copy string */
56	memset(buf, '\0', BUF_SIZE);
57	memset(buf, 'a', BUF_SIZE / 2);
58	ut_asserteq(-ENOSPC, bootm_process_cmdline(buf, BUF_SIZE, true));
59
60	/* Just enough space */
61	memset(buf, '\0', BUF_SIZE);
62	memset(buf, 'a', BUF_SIZE / 2 - 1);
63	ut_assertok(bootm_process_cmdline(buf, BUF_SIZE, true));
64
65	return 0;
66}
67BOOTM_TEST(bootm_test_nospace, 0);
68
69/* Test silent processing */
70static int bootm_test_silent(struct unit_test_state *uts)
71{
72	char buf[BUF_SIZE];
73
74	/* 'silent_linux' not set should do nothing */
75	env_set("silent_linux", NULL);
76	strcpy(buf, CONSOLE_STR);
77	ut_assertok(bootm_process_cmdline(buf, BUF_SIZE, BOOTM_CL_SILENT));
78	ut_asserteq_str(CONSOLE_STR, buf);
79
80	ut_assertok(env_set("silent_linux", "no"));
81	ut_assertok(bootm_process_cmdline(buf, BUF_SIZE, BOOTM_CL_SILENT));
82	ut_asserteq_str(CONSOLE_STR, buf);
83
84	ut_assertok(env_set("silent_linux", "yes"));
85	ut_assertok(bootm_process_cmdline(buf, BUF_SIZE, BOOTM_CL_SILENT));
86	ut_asserteq_str("console=ttynull", buf);
87
88	/* Empty buffer should still add the string */
89	*buf = '\0';
90	ut_assertok(bootm_process_cmdline(buf, BUF_SIZE, BOOTM_CL_SILENT));
91	ut_asserteq_str("console=ttynull", buf);
92
93	/* Check nothing happens when do_silent is false */
94	*buf = '\0';
95	ut_assertok(bootm_process_cmdline(buf, BUF_SIZE, 0));
96	ut_asserteq_str("", buf);
97
98	/* Not enough space */
99	*buf = '\0';
100	ut_asserteq(-ENOSPC, bootm_process_cmdline(buf, 15, BOOTM_CL_SILENT));
101
102	/* Just enough space */
103	*buf = '\0';
104	ut_assertok(bootm_process_cmdline(buf, 16, BOOTM_CL_SILENT));
105
106	/* add at end */
107	strcpy(buf, "something");
108	ut_assertok(bootm_process_cmdline(buf, BUF_SIZE, BOOTM_CL_SILENT));
109	ut_asserteq_str("something console=ttynull", buf);
110
111	/* change at start */
112	strcpy(buf, CONSOLE_STR " something");
113	ut_assertok(bootm_process_cmdline(buf, BUF_SIZE, BOOTM_CL_SILENT));
114	ut_asserteq_str("console=ttynull something", buf);
115
116	return 0;
117}
118BOOTM_TEST(bootm_test_silent, 0);
119
120/* Test substitution processing */
121static int bootm_test_subst(struct unit_test_state *uts)
122{
123	char buf[BUF_SIZE];
124
125	/* try with an unset variable */
126	ut_assertok(env_set("var", NULL));
127	strcpy(buf, "some${var}thing");
128	ut_assertok(bootm_process_cmdline(buf, BUF_SIZE, BOOTM_CL_SUBST));
129	ut_asserteq_str("something", buf);
130
131	/* Replace with shorter string */
132	ut_assertok(env_set("var", "bb"));
133	strcpy(buf, "some${var}thing");
134	ut_assertok(bootm_process_cmdline(buf, BUF_SIZE, BOOTM_CL_SUBST));
135	ut_asserteq_str("somebbthing", buf);
136
137	/* Replace with same-length string */
138	ut_assertok(env_set("var", "abc"));
139	strcpy(buf, "some${var}thing");
140	ut_assertok(bootm_process_cmdline(buf, BUF_SIZE, BOOTM_CL_SUBST));
141	ut_asserteq_str("someabcthing", buf);
142
143	/* Replace with longer string */
144	ut_assertok(env_set("var", "abcde"));
145	strcpy(buf, "some${var}thing");
146	ut_assertok(bootm_process_cmdline(buf, BUF_SIZE, BOOTM_CL_SUBST));
147	ut_asserteq_str("someabcdething", buf);
148
149	/* Check it is case sensitive */
150	ut_assertok(env_set("VAR", NULL));
151	strcpy(buf, "some${VAR}thing");
152	ut_assertok(bootm_process_cmdline(buf, BUF_SIZE, BOOTM_CL_SUBST));
153	ut_asserteq_str("something", buf);
154
155	/* Check too long - need 12 bytes for each string */
156	strcpy(buf, "some${var}thing");
157	ut_asserteq(-ENOSPC,
158		    bootm_process_cmdline(buf, 12 * 2 - 1, BOOTM_CL_SUBST));
159
160	/* Check just enough space */
161	strcpy(buf, "some${var}thing");
162	ut_assertok(bootm_process_cmdline(buf, 16 * 2, BOOTM_CL_SUBST));
163	ut_asserteq_str("someabcdething", buf);
164
165	/*
166	 * Check the substition string being too long. This results in a string
167	 * of 12 (13 bytes). We need enough space for that plus the original
168	 * "a${var}c" string of 9 bytes. So 12 + 9 = 21 bytes.
169	 */
170	ut_assertok(env_set("var", "1234567890"));
171	strcpy(buf, "a${var}c");
172	ut_asserteq(-ENOSPC, bootm_process_cmdline(buf, 21, BOOTM_CL_SUBST));
173
174	strcpy(buf, "a${var}c");
175	ut_asserteq(0, bootm_process_cmdline(buf, 22, BOOTM_CL_SUBST));
176
177	/* Check multiple substitutions */
178	ut_assertok(env_set("var", "abc"));
179	strcpy(buf, "some${var}thing${bvar}else");
180	ut_asserteq(0, bootm_process_cmdline(buf, BUF_SIZE, BOOTM_CL_SUBST));
181	ut_asserteq_str("someabcthingelse", buf);
182
183	/* Check multiple substitutions */
184	ut_assertok(env_set("bvar", "123"));
185	strcpy(buf, "some${var}thing${bvar}else");
186	ut_asserteq(0, bootm_process_cmdline(buf, BUF_SIZE, BOOTM_CL_SUBST));
187	ut_asserteq_str("someabcthing123else", buf);
188
189	return 0;
190}
191BOOTM_TEST(bootm_test_subst, 0);
192
193/* Test silent processing in the bootargs variable */
194static int bootm_test_silent_var(struct unit_test_state *uts)
195{
196	env_set("bootargs", NULL);
197	ut_assertok(bootm_process_cmdline_env(BOOTM_CL_SUBST));
198	ut_assertnull(env_get("bootargs"));
199
200	ut_assertok(env_set("bootargs", "some${var}thing"));
201	ut_assertok(bootm_process_cmdline_env(BOOTM_CL_SUBST));
202	ut_asserteq_str("something", env_get("bootargs"));
203
204	return 0;
205}
206BOOTM_TEST(bootm_test_silent_var, 0);
207
208/* Test substitution processing in the bootargs variable */
209static int bootm_test_subst_var(struct unit_test_state *uts)
210{
211	ut_assertok(env_set("silent_linux", "yes"));
212	ut_assertok(env_set("bootargs", NULL));
213	ut_assertok(bootm_process_cmdline_env(BOOTM_CL_SILENT));
214	ut_asserteq_str("console=ttynull", env_get("bootargs"));
215
216	ut_assertok(env_set("var", "abc"));
217	ut_assertok(env_set("bootargs", "some${var}thing"));
218	ut_assertok(bootm_process_cmdline_env(BOOTM_CL_SILENT));
219	ut_asserteq_str("some${var}thing console=ttynull", env_get("bootargs"));
220
221	return 0;
222}
223BOOTM_TEST(bootm_test_subst_var, 0);
224
225/* Test substitution and silent console processing in the bootargs variable */
226static int bootm_test_subst_both(struct unit_test_state *uts)
227{
228	ut_assertok(env_set("silent_linux", "yes"));
229	env_set("bootargs", NULL);
230	ut_assertok(bootm_process_cmdline_env(BOOTM_CL_ALL));
231	ut_asserteq_str("console=ttynull", env_get("bootargs"));
232
233	ut_assertok(env_set("bootargs", "some${var}thing " CONSOLE_STR));
234	ut_assertok(env_set("var", "1234567890"));
235	ut_assertok(bootm_process_cmdline_env(BOOTM_CL_ALL));
236	ut_asserteq_str("some1234567890thing console=ttynull", env_get("bootargs"));
237
238	return 0;
239}
240BOOTM_TEST(bootm_test_subst_both, 0);
241
242int do_ut_bootm(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
243{
244	struct unit_test *tests = UNIT_TEST_SUITE_START(bootm_test);
245	const int n_ents = UNIT_TEST_SUITE_COUNT(bootm_test);
246
247	return cmd_ut_category("bootm", "bootm_test_", tests, n_ents,
248			       argc, argv);
249}
250