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