blob: 4511cfa7f9bf77eddcf53a5a65a0180a3722dc83 [file] [log] [blame]
Simon Glassfb1451b2022-04-24 23:31:24 -06001// SPDX-License-Identifier: GPL-2.0+
2/*
3 * Test for bootdev functions. All start with 'bootdev'
4 *
5 * Copyright 2021 Google LLC
6 * Written by Simon Glass <sjg@chromium.org>
7 */
8
Simon Glassfb1451b2022-04-24 23:31:24 -06009#include <bootdev.h>
10#include <bootflow.h>
Simon Glass0917f772022-07-30 15:52:34 -060011#include <bootmeth.h>
Simon Glassfb1451b2022-04-24 23:31:24 -060012#include <bootstd.h>
Simon Glassd985f1d2023-01-06 08:52:41 -060013#include <cli.h>
Simon Glassfb1451b2022-04-24 23:31:24 -060014#include <dm.h>
Heinrich Schuchardt92f4cb62024-04-03 23:39:48 +020015#include <efi_default_filename.h>
Simon Glasse64c2952023-01-06 08:52:42 -060016#include <expo.h>
Simon Glass11361c52022-07-30 15:52:36 -060017#ifdef CONFIG_SANDBOX
Simon Glass2662b542022-07-30 15:52:22 -060018#include <asm/test.h>
Simon Glass11361c52022-07-30 15:52:36 -060019#endif
Simon Glassd985f1d2023-01-06 08:52:41 -060020#include <dm/device-internal.h>
Simon Glassfb1451b2022-04-24 23:31:24 -060021#include <dm/lists.h>
22#include <test/suites.h>
23#include <test/ut.h>
24#include "bootstd_common.h"
Simon Glasse64c2952023-01-06 08:52:42 -060025#include "../../boot/bootflow_internal.h"
26#include "../../boot/scene_internal.h"
Simon Glassfb1451b2022-04-24 23:31:24 -060027
Simon Glassd985f1d2023-01-06 08:52:41 -060028DECLARE_GLOBAL_DATA_PTR;
29
Simon Glassd08db022023-08-24 13:55:41 -060030extern U_BOOT_DRIVER(bootmeth_cros);
Simon Glass5986d462023-08-19 16:49:35 -060031extern U_BOOT_DRIVER(bootmeth_2script);
Simon Glassd985f1d2023-01-06 08:52:41 -060032
Simon Glassf25f5752022-07-30 15:52:16 -060033static int inject_response(struct unit_test_state *uts)
34{
35 /*
36 * The image being booted presents a menu of options:
37 *
38 * Fedora-Workstation-armhfp-31-1.9 Boot Options.
39 * 1: Fedora-Workstation-armhfp-31-1.9 (5.3.7-301.fc31.armv7hl)
40 * Enter choice:
41 *
42 * Provide input for this, to avoid waiting two seconds for a timeout.
43 */
44 ut_asserteq(2, console_in_puts("1\n"));
45
46 return 0;
47}
48
Simon Glassfb1451b2022-04-24 23:31:24 -060049/* Check 'bootflow scan/list' commands */
50static int bootflow_cmd(struct unit_test_state *uts)
51{
52 console_record_reset_enable();
53 ut_assertok(run_command("bootdev select 1", 0));
54 ut_assert_console_end();
Simon Glass18552d22023-01-17 10:48:13 -070055 ut_assertok(run_command("bootflow scan -lH", 0));
Simon Glassfb1451b2022-04-24 23:31:24 -060056 ut_assert_nextline("Scanning for bootflows in bootdev 'mmc1.bootdev'");
57 ut_assert_nextline("Seq Method State Uclass Part Name Filename");
58 ut_assert_nextlinen("---");
Simon Glass47aedc22023-01-17 10:48:14 -070059 ut_assert_nextline("Scanning bootdev 'mmc2.bootdev':");
60 ut_assert_nextline("Scanning bootdev 'mmc1.bootdev':");
Simon Glass79f66352023-05-10 16:34:46 -060061 ut_assert_nextline(" 0 extlinux ready mmc 1 mmc1.bootdev.part_1 /extlinux/extlinux.conf");
Simon Glass47aedc22023-01-17 10:48:14 -070062 ut_assert_nextline("No more bootdevs");
Simon Glassfb1451b2022-04-24 23:31:24 -060063 ut_assert_nextlinen("---");
64 ut_assert_nextline("(1 bootflow, 1 valid)");
65 ut_assert_console_end();
66
67 ut_assertok(run_command("bootflow list", 0));
68 ut_assert_nextline("Showing bootflows for bootdev 'mmc1.bootdev'");
69 ut_assert_nextline("Seq Method State Uclass Part Name Filename");
70 ut_assert_nextlinen("---");
Simon Glass79f66352023-05-10 16:34:46 -060071 ut_assert_nextline(" 0 extlinux ready mmc 1 mmc1.bootdev.part_1 /extlinux/extlinux.conf");
Simon Glassfb1451b2022-04-24 23:31:24 -060072 ut_assert_nextlinen("---");
73 ut_assert_nextline("(1 bootflow, 1 valid)");
74 ut_assert_console_end();
75
76 return 0;
77}
78BOOTSTD_TEST(bootflow_cmd, UT_TESTF_DM | UT_TESTF_SCAN_FDT);
79
Simon Glass47aedc22023-01-17 10:48:14 -070080/* Check 'bootflow scan' with a label / seq */
Simon Glassfb1451b2022-04-24 23:31:24 -060081static int bootflow_cmd_label(struct unit_test_state *uts)
82{
Simon Glass47aedc22023-01-17 10:48:14 -070083 test_set_eth_enable(false);
84
Simon Glassfb1451b2022-04-24 23:31:24 -060085 console_record_reset_enable();
Simon Glass18552d22023-01-17 10:48:13 -070086 ut_assertok(run_command("bootflow scan -lH mmc1", 0));
Simon Glass47aedc22023-01-17 10:48:14 -070087 ut_assert_nextline("Scanning for bootflows with label 'mmc1'");
Simon Glassfb1451b2022-04-24 23:31:24 -060088 ut_assert_skip_to_line("(1 bootflow, 1 valid)");
89 ut_assert_console_end();
90
Simon Glass47aedc22023-01-17 10:48:14 -070091 ut_assertok(run_command("bootflow scan -lH 0", 0));
92 ut_assert_nextline("Scanning for bootflows with label '0'");
Simon Glassfb1451b2022-04-24 23:31:24 -060093 ut_assert_skip_to_line("(0 bootflows, 0 valid)");
94 ut_assert_console_end();
95
Simon Glass47aedc22023-01-17 10:48:14 -070096 /*
97 * with ethernet enabled we have 8 devices ahead of the mmc ones:
98 *
99 * ut_assertok(run_command("bootdev list", 0));
100 * Seq Probed Status Uclass Name
101 * --- ------ ------ -------- ------------------
102 * 0 [ + ] OK ethernet eth@10002000.bootdev
103 * 1 [ ] OK ethernet eth@10003000.bootdev
104 * 2 [ ] OK ethernet sbe5.bootdev
105 * 3 [ ] OK ethernet eth@10004000.bootdev
106 * 4 [ ] OK ethernet phy-test-eth.bootdev
107 * 5 [ ] OK ethernet dsa-test-eth.bootdev
108 * 6 [ ] OK ethernet dsa-test@0.bootdev
109 * 7 [ ] OK ethernet dsa-test@1.bootdev
110 * 8 [ ] OK mmc mmc2.bootdev
111 * 9 [ + ] OK mmc mmc1.bootdev
112 * a [ ] OK mmc mmc0.bootdev
113 */
114 ut_assertok(run_command("bootflow scan -lH 9", 0));
115 ut_assert_nextline("Scanning for bootflows with label '9'");
116 ut_assert_skip_to_line("(1 bootflow, 1 valid)");
117
Simon Glass18552d22023-01-17 10:48:13 -0700118 ut_assertok(run_command("bootflow scan -lH 0", 0));
Simon Glass47aedc22023-01-17 10:48:14 -0700119 ut_assert_nextline("Scanning for bootflows with label '0'");
Simon Glassfb1451b2022-04-24 23:31:24 -0600120 ut_assert_skip_to_line("(0 bootflows, 0 valid)");
121 ut_assert_console_end();
122
123 return 0;
124}
Simon Glass47aedc22023-01-17 10:48:14 -0700125BOOTSTD_TEST(bootflow_cmd_label, UT_TESTF_DM | UT_TESTF_SCAN_FDT |
126 UT_TESTF_ETH_BOOTDEV);
Simon Glassfb1451b2022-04-24 23:31:24 -0600127
128/* Check 'bootflow scan/list' commands using all bootdevs */
129static int bootflow_cmd_glob(struct unit_test_state *uts)
130{
131 ut_assertok(bootstd_test_drop_bootdev_order(uts));
132
133 console_record_reset_enable();
Simon Glass18552d22023-01-17 10:48:13 -0700134 ut_assertok(run_command("bootflow scan -lGH", 0));
Simon Glassfb1451b2022-04-24 23:31:24 -0600135 ut_assert_nextline("Scanning for bootflows in all bootdevs");
136 ut_assert_nextline("Seq Method State Uclass Part Name Filename");
137 ut_assert_nextlinen("---");
138 ut_assert_nextline("Scanning bootdev 'mmc2.bootdev':");
139 ut_assert_nextline("Scanning bootdev 'mmc1.bootdev':");
Simon Glass79f66352023-05-10 16:34:46 -0600140 ut_assert_nextline(" 0 extlinux ready mmc 1 mmc1.bootdev.part_1 /extlinux/extlinux.conf");
Simon Glassfb1451b2022-04-24 23:31:24 -0600141 ut_assert_nextline("Scanning bootdev 'mmc0.bootdev':");
142 ut_assert_nextline("No more bootdevs");
143 ut_assert_nextlinen("---");
144 ut_assert_nextline("(1 bootflow, 1 valid)");
145 ut_assert_console_end();
146
147 ut_assertok(run_command("bootflow list", 0));
148 ut_assert_nextline("Showing all bootflows");
149 ut_assert_nextline("Seq Method State Uclass Part Name Filename");
150 ut_assert_nextlinen("---");
Simon Glass79f66352023-05-10 16:34:46 -0600151 ut_assert_nextline(" 0 extlinux ready mmc 1 mmc1.bootdev.part_1 /extlinux/extlinux.conf");
Simon Glassfb1451b2022-04-24 23:31:24 -0600152 ut_assert_nextlinen("---");
153 ut_assert_nextline("(1 bootflow, 1 valid)");
154 ut_assert_console_end();
155
156 return 0;
157}
158BOOTSTD_TEST(bootflow_cmd_glob, UT_TESTF_DM | UT_TESTF_SCAN_FDT);
159
160/* Check 'bootflow scan -e' */
161static int bootflow_cmd_scan_e(struct unit_test_state *uts)
162{
163 ut_assertok(bootstd_test_drop_bootdev_order(uts));
164
165 console_record_reset_enable();
Simon Glass18552d22023-01-17 10:48:13 -0700166 ut_assertok(run_command("bootflow scan -aleGH", 0));
Simon Glassfb1451b2022-04-24 23:31:24 -0600167 ut_assert_nextline("Scanning for bootflows in all bootdevs");
168 ut_assert_nextline("Seq Method State Uclass Part Name Filename");
169 ut_assert_nextlinen("---");
170 ut_assert_nextline("Scanning bootdev 'mmc2.bootdev':");
Simon Glassc3867e22023-08-24 13:55:39 -0600171 ut_assert_nextline(" 0 extlinux media mmc 0 mmc2.bootdev.whole ");
Simon Glassc8894342023-05-10 16:34:26 -0600172 ut_assert_nextline(" ** No partition found, err=-93: Protocol not supported");
Simon Glassc3867e22023-08-24 13:55:39 -0600173 ut_assert_nextline(" 1 efi media mmc 0 mmc2.bootdev.whole ");
Simon Glassc8894342023-05-10 16:34:26 -0600174 ut_assert_nextline(" ** No partition found, err=-93: Protocol not supported");
Simon Glassfb1451b2022-04-24 23:31:24 -0600175
176 ut_assert_nextline("Scanning bootdev 'mmc1.bootdev':");
Simon Glassc3867e22023-08-24 13:55:39 -0600177 ut_assert_nextline(" 2 extlinux media mmc 0 mmc1.bootdev.whole ");
Simon Glassc8894342023-05-10 16:34:26 -0600178 ut_assert_nextline(" ** No partition found, err=-2: No such file or directory");
Simon Glassc3867e22023-08-24 13:55:39 -0600179 ut_assert_nextline(" 3 efi media mmc 0 mmc1.bootdev.whole ");
Simon Glassc8894342023-05-10 16:34:26 -0600180 ut_assert_nextline(" ** No partition found, err=-2: No such file or directory");
Simon Glass79f66352023-05-10 16:34:46 -0600181 ut_assert_nextline(" 4 extlinux ready mmc 1 mmc1.bootdev.part_1 /extlinux/extlinux.conf");
Heinrich Schuchardt92f4cb62024-04-03 23:39:48 +0200182 ut_assert_nextline(" 5 efi fs mmc 1 mmc1.bootdev.part_1 /EFI/BOOT/"
183 BOOTEFI_NAME);
Simon Glassfb1451b2022-04-24 23:31:24 -0600184
185 ut_assert_skip_to_line("Scanning bootdev 'mmc0.bootdev':");
Simon Glassc3867e22023-08-24 13:55:39 -0600186 ut_assert_skip_to_line(
187 " 3f efi media mmc 0 mmc0.bootdev.whole ");
Simon Glassc8894342023-05-10 16:34:26 -0600188 ut_assert_nextline(" ** No partition found, err=-93: Protocol not supported");
Simon Glassfb1451b2022-04-24 23:31:24 -0600189 ut_assert_nextline("No more bootdevs");
190 ut_assert_nextlinen("---");
191 ut_assert_nextline("(64 bootflows, 1 valid)");
192 ut_assert_console_end();
193
194 ut_assertok(run_command("bootflow list", 0));
195 ut_assert_nextline("Showing all bootflows");
196 ut_assert_nextline("Seq Method State Uclass Part Name Filename");
197 ut_assert_nextlinen("---");
Simon Glassc3867e22023-08-24 13:55:39 -0600198 ut_assert_nextline(" 0 extlinux media mmc 0 mmc2.bootdev.whole ");
199 ut_assert_nextline(" 1 efi media mmc 0 mmc2.bootdev.whole ");
200 ut_assert_skip_to_line(
201 " 4 extlinux ready mmc 1 mmc1.bootdev.part_1 /extlinux/extlinux.conf");
202 ut_assert_skip_to_line(" 3f efi media mmc 0 mmc0.bootdev.whole ");
Simon Glassfb1451b2022-04-24 23:31:24 -0600203 ut_assert_nextlinen("---");
204 ut_assert_nextline("(64 bootflows, 1 valid)");
205 ut_assert_console_end();
206
207 return 0;
208}
209BOOTSTD_TEST(bootflow_cmd_scan_e, UT_TESTF_DM | UT_TESTF_SCAN_FDT);
210
211/* Check 'bootflow info' */
212static int bootflow_cmd_info(struct unit_test_state *uts)
213{
214 console_record_reset_enable();
215 ut_assertok(run_command("bootdev select 1", 0));
216 ut_assert_console_end();
217 ut_assertok(run_command("bootflow scan", 0));
218 ut_assert_console_end();
219 ut_assertok(run_command("bootflow select 0", 0));
220 ut_assert_console_end();
221 ut_assertok(run_command("bootflow info", 0));
222 ut_assert_nextline("Name: mmc1.bootdev.part_1");
223 ut_assert_nextline("Device: mmc1.bootdev");
224 ut_assert_nextline("Block dev: mmc1.blk");
Simon Glass79f66352023-05-10 16:34:46 -0600225 ut_assert_nextline("Method: extlinux");
Simon Glassfb1451b2022-04-24 23:31:24 -0600226 ut_assert_nextline("State: ready");
227 ut_assert_nextline("Partition: 1");
228 ut_assert_nextline("Subdir: (none)");
229 ut_assert_nextline("Filename: /extlinux/extlinux.conf");
230 ut_assert_nextlinen("Buffer: ");
231 ut_assert_nextline("Size: 253 (595 bytes)");
Simon Glass2175e762023-01-06 08:52:33 -0600232 ut_assert_nextline("OS: Fedora-Workstation-armhfp-31-1.9 (5.3.7-301.fc31.armv7hl)");
Simon Glassf4a91652023-07-12 09:04:34 -0600233 ut_assert_nextline("Cmdline: (none)");
Simon Glass24d8e1b2023-01-06 08:52:34 -0600234 ut_assert_nextline("Logo: (none)");
Simon Glass7638c852023-01-17 10:47:56 -0700235 ut_assert_nextline("FDT: <NULL>");
Simon Glassfb1451b2022-04-24 23:31:24 -0600236 ut_assert_nextline("Error: 0");
237 ut_assert_console_end();
238
239 ut_assertok(run_command("bootflow info -d", 0));
240 ut_assert_nextline("Name: mmc1.bootdev.part_1");
241 ut_assert_skip_to_line("Error: 0");
242 ut_assert_nextline("Contents:");
243 ut_assert_nextline("%s", "");
244 ut_assert_nextline("# extlinux.conf generated by appliance-creator");
245 ut_assert_skip_to_line(" initrd /initramfs-5.3.7-301.fc31.armv7hl.img");
246 ut_assert_console_end();
247
248 return 0;
249}
250BOOTSTD_TEST(bootflow_cmd_info, UT_TESTF_DM | UT_TESTF_SCAN_FDT);
251
252/* Check 'bootflow scan -b' to boot the first available bootdev */
253static int bootflow_scan_boot(struct unit_test_state *uts)
254{
255 console_record_reset_enable();
Simon Glassf25f5752022-07-30 15:52:16 -0600256 ut_assertok(inject_response(uts));
Simon Glassfb1451b2022-04-24 23:31:24 -0600257 ut_assertok(run_command("bootflow scan -b", 0));
258 ut_assert_nextline(
Simon Glass79f66352023-05-10 16:34:46 -0600259 "** Booting bootflow 'mmc1.bootdev.part_1' with extlinux");
Simon Glassfb1451b2022-04-24 23:31:24 -0600260 ut_assert_nextline("Ignoring unknown command: ui");
261
262 /*
263 * We expect it to get through to boot although sandbox always returns
264 * -EFAULT as it cannot actually boot the kernel
265 */
266 ut_assert_skip_to_line("sandbox: continuing, as we cannot run Linux");
267 ut_assert_nextline("Boot failed (err=-14)");
268 ut_assert_console_end();
269
270 return 0;
271}
272BOOTSTD_TEST(bootflow_scan_boot, UT_TESTF_DM | UT_TESTF_SCAN_FDT);
273
274/* Check iterating through available bootflows */
275static int bootflow_iter(struct unit_test_state *uts)
276{
277 struct bootflow_iter iter;
278 struct bootflow bflow;
279
280 bootstd_clear_glob();
281
282 /* The first device is mmc2.bootdev which has no media */
283 ut_asserteq(-EPROTONOSUPPORT,
Simon Glass4b7cb052023-01-17 10:48:16 -0700284 bootflow_scan_first(NULL, NULL, &iter,
Simon Glass4f806f32023-02-22 12:17:03 -0700285 BOOTFLOWIF_ALL | BOOTFLOWIF_SKIP_GLOBAL, &bflow));
Simon Glassfb1451b2022-04-24 23:31:24 -0600286 ut_asserteq(2, iter.num_methods);
287 ut_asserteq(0, iter.cur_method);
288 ut_asserteq(0, iter.part);
289 ut_asserteq(0, iter.max_part);
Simon Glass79f66352023-05-10 16:34:46 -0600290 ut_asserteq_str("extlinux", iter.method->name);
Simon Glassfb1451b2022-04-24 23:31:24 -0600291 ut_asserteq(0, bflow.err);
292
293 /*
Simon Glass0917f772022-07-30 15:52:34 -0600294 * This shows MEDIA even though there is none, since in
Simon Glassfb1451b2022-04-24 23:31:24 -0600295 * bootdev_find_in_blk() we call part_get_info() which returns
296 * -EPROTONOSUPPORT. Ideally it would return -EEOPNOTSUPP and we would
297 * know.
298 */
299 ut_asserteq(BOOTFLOWST_MEDIA, bflow.state);
300
301 ut_asserteq(-EPROTONOSUPPORT, bootflow_scan_next(&iter, &bflow));
302 ut_asserteq(2, iter.num_methods);
303 ut_asserteq(1, iter.cur_method);
304 ut_asserteq(0, iter.part);
305 ut_asserteq(0, iter.max_part);
306 ut_asserteq_str("efi", iter.method->name);
307 ut_asserteq(0, bflow.err);
308 ut_asserteq(BOOTFLOWST_MEDIA, bflow.state);
309 bootflow_free(&bflow);
310
311 /* The next device is mmc1.bootdev - at first we use the whole device */
312 ut_asserteq(-ENOENT, bootflow_scan_next(&iter, &bflow));
313 ut_asserteq(2, iter.num_methods);
314 ut_asserteq(0, iter.cur_method);
315 ut_asserteq(0, iter.part);
316 ut_asserteq(0x1e, iter.max_part);
Simon Glass79f66352023-05-10 16:34:46 -0600317 ut_asserteq_str("extlinux", iter.method->name);
Simon Glassfb1451b2022-04-24 23:31:24 -0600318 ut_asserteq(0, bflow.err);
319 ut_asserteq(BOOTFLOWST_MEDIA, bflow.state);
320 bootflow_free(&bflow);
321
322 ut_asserteq(-ENOENT, bootflow_scan_next(&iter, &bflow));
323 ut_asserteq(2, iter.num_methods);
324 ut_asserteq(1, iter.cur_method);
325 ut_asserteq(0, iter.part);
326 ut_asserteq(0x1e, iter.max_part);
327 ut_asserteq_str("efi", iter.method->name);
328 ut_asserteq(0, bflow.err);
329 ut_asserteq(BOOTFLOWST_MEDIA, bflow.state);
330 bootflow_free(&bflow);
331
332 /* Then more to partition 1 where we find something */
333 ut_assertok(bootflow_scan_next(&iter, &bflow));
334 ut_asserteq(2, iter.num_methods);
335 ut_asserteq(0, iter.cur_method);
336 ut_asserteq(1, iter.part);
337 ut_asserteq(0x1e, iter.max_part);
Simon Glass79f66352023-05-10 16:34:46 -0600338 ut_asserteq_str("extlinux", iter.method->name);
Simon Glassfb1451b2022-04-24 23:31:24 -0600339 ut_asserteq(0, bflow.err);
340 ut_asserteq(BOOTFLOWST_READY, bflow.state);
341 bootflow_free(&bflow);
342
343 ut_asserteq(-ENOENT, bootflow_scan_next(&iter, &bflow));
344 ut_asserteq(2, iter.num_methods);
345 ut_asserteq(1, iter.cur_method);
346 ut_asserteq(1, iter.part);
347 ut_asserteq(0x1e, iter.max_part);
348 ut_asserteq_str("efi", iter.method->name);
349 ut_asserteq(0, bflow.err);
350 ut_asserteq(BOOTFLOWST_FS, bflow.state);
351 bootflow_free(&bflow);
352
Simon Glassdcffa442023-01-17 10:47:41 -0700353 /* Then more to partition 2 which exists but is not bootable */
Simon Glassf0e358f2023-01-17 10:47:42 -0700354 ut_asserteq(-EINVAL, bootflow_scan_next(&iter, &bflow));
Simon Glassfb1451b2022-04-24 23:31:24 -0600355 ut_asserteq(2, iter.num_methods);
356 ut_asserteq(0, iter.cur_method);
357 ut_asserteq(2, iter.part);
358 ut_asserteq(0x1e, iter.max_part);
Simon Glass79f66352023-05-10 16:34:46 -0600359 ut_asserteq_str("extlinux", iter.method->name);
Simon Glassfb1451b2022-04-24 23:31:24 -0600360 ut_asserteq(0, bflow.err);
Simon Glassf0e358f2023-01-17 10:47:42 -0700361 ut_asserteq(BOOTFLOWST_MEDIA, bflow.state);
Simon Glassfb1451b2022-04-24 23:31:24 -0600362 bootflow_free(&bflow);
363
364 bootflow_iter_uninit(&iter);
365
366 ut_assert_console_end();
367
368 return 0;
369}
370BOOTSTD_TEST(bootflow_iter, UT_TESTF_DM | UT_TESTF_SCAN_FDT);
371
Simon Glass11361c52022-07-30 15:52:36 -0600372#if defined(CONFIG_SANDBOX) && defined(CONFIG_BOOTMETH_GLOBAL)
Simon Glassfb1451b2022-04-24 23:31:24 -0600373/* Check using the system bootdev */
374static int bootflow_system(struct unit_test_state *uts)
375{
Simon Glassecb274c2023-01-17 10:47:23 -0700376 struct udevice *bootstd, *dev;
Simon Glassfb1451b2022-04-24 23:31:24 -0600377
AKASHI Takahiro279b03d2024-01-17 13:39:42 +0900378 if (!IS_ENABLED(CONFIG_EFI_BOOTMGR))
Simon Glassc43635b2022-10-20 18:22:49 -0600379 return -EAGAIN;
Simon Glassecb274c2023-01-17 10:47:23 -0700380 ut_assertok(uclass_first_device_err(UCLASS_BOOTSTD, &bootstd));
Heinrich Schuchardt08c51a72024-04-03 20:34:15 +0200381 ut_assertok(device_bind(bootstd, DM_DRIVER_GET(bootmeth_3efi_mgr),
Simon Glassecb274c2023-01-17 10:47:23 -0700382 "efi_mgr", 0, ofnode_null(), &dev));
383 ut_assertok(device_probe(dev));
Simon Glass2662b542022-07-30 15:52:22 -0600384 sandbox_set_fake_efi_mgr_dev(dev, true);
Simon Glassfb1451b2022-04-24 23:31:24 -0600385
Simon Glassfb1451b2022-04-24 23:31:24 -0600386 /* We should get a single 'bootmgr' method right at the end */
387 bootstd_clear_glob();
388 console_record_reset_enable();
Simon Glass18552d22023-01-17 10:48:13 -0700389 ut_assertok(run_command("bootflow scan -lH", 0));
Simon Glassc627cfc2022-07-30 15:52:27 -0600390 ut_assert_skip_to_line(
Simon Glassc3867e22023-08-24 13:55:39 -0600391 " 0 efi_mgr ready (none) 0 <NULL> ");
Simon Glassc627cfc2022-07-30 15:52:27 -0600392 ut_assert_skip_to_line("No more bootdevs");
Simon Glassecb274c2023-01-17 10:47:23 -0700393 ut_assert_skip_to_line("(2 bootflows, 2 valid)");
Simon Glassfb1451b2022-04-24 23:31:24 -0600394 ut_assert_console_end();
395
396 return 0;
397}
Simon Glassbd18b692022-07-30 15:52:28 -0600398BOOTSTD_TEST(bootflow_system, UT_TESTF_DM | UT_TESTF_SCAN_PDATA |
399 UT_TESTF_SCAN_FDT);
Simon Glass11361c52022-07-30 15:52:36 -0600400#endif
Simon Glassfb1451b2022-04-24 23:31:24 -0600401
402/* Check disabling a bootmethod if it requests it */
403static int bootflow_iter_disable(struct unit_test_state *uts)
404{
405 struct udevice *bootstd, *dev;
406 struct bootflow_iter iter;
407 struct bootflow bflow;
408 int i;
409
410 /* Add the EFI bootmgr driver */
411 ut_assertok(uclass_first_device_err(UCLASS_BOOTSTD, &bootstd));
412 ut_assertok(device_bind_driver(bootstd, "bootmeth_sandbox", "sandbox",
413 &dev));
414
Simon Glassfb1451b2022-04-24 23:31:24 -0600415 ut_assertok(bootstd_test_drop_bootdev_order(uts));
416
417 bootstd_clear_glob();
Simon Glassf25f5752022-07-30 15:52:16 -0600418 console_record_reset_enable();
419 ut_assertok(inject_response(uts));
Simon Glass18552d22023-01-17 10:48:13 -0700420 ut_assertok(run_command("bootflow scan -lbH", 0));
Simon Glassfb1451b2022-04-24 23:31:24 -0600421
422 /* Try to boot the bootmgr flow, which will fail */
423 console_record_reset_enable();
Simon Glass4b7cb052023-01-17 10:48:16 -0700424 ut_assertok(bootflow_scan_first(NULL, NULL, &iter, 0, &bflow));
Simon Glassfb1451b2022-04-24 23:31:24 -0600425 ut_asserteq(3, iter.num_methods);
426 ut_asserteq_str("sandbox", iter.method->name);
Simon Glassf25f5752022-07-30 15:52:16 -0600427 ut_assertok(inject_response(uts));
Simon Glassfb1451b2022-04-24 23:31:24 -0600428 ut_asserteq(-ENOTSUPP, bootflow_run_boot(&iter, &bflow));
429
430 ut_assert_skip_to_line("Boot method 'sandbox' failed and will not be retried");
431 ut_assert_console_end();
432
433 /* Check that the sandbox bootmeth has been removed */
434 ut_asserteq(2, iter.num_methods);
435 for (i = 0; i < iter.num_methods; i++)
436 ut_assert(strcmp("sandbox", iter.method_order[i]->name));
437
438 return 0;
439}
440BOOTSTD_TEST(bootflow_iter_disable, UT_TESTF_DM | UT_TESTF_SCAN_FDT);
441
Simon Glass0917f772022-07-30 15:52:34 -0600442/* Check 'bootflow scan' with a bootmeth ordering including a global bootmeth */
443static int bootflow_scan_glob_bootmeth(struct unit_test_state *uts)
444{
Simon Glass11361c52022-07-30 15:52:36 -0600445 if (!IS_ENABLED(CONFIG_BOOTMETH_GLOBAL))
Simon Glassc43635b2022-10-20 18:22:49 -0600446 return -EAGAIN;
Simon Glass11361c52022-07-30 15:52:36 -0600447
Simon Glass0917f772022-07-30 15:52:34 -0600448 ut_assertok(bootstd_test_drop_bootdev_order(uts));
449
450 /*
451 * Make sure that the -G flag makes the scan fail, since this is not
452 * supported when an ordering is provided
453 */
454 console_record_reset_enable();
455 ut_assertok(bootmeth_set_order("efi firmware0"));
Simon Glass18552d22023-01-17 10:48:13 -0700456 ut_assertok(run_command("bootflow scan -lGH", 0));
Simon Glass0917f772022-07-30 15:52:34 -0600457 ut_assert_nextline("Scanning for bootflows in all bootdevs");
458 ut_assert_nextline(
459 "Seq Method State Uclass Part Name Filename");
460 ut_assert_nextlinen("---");
461 ut_assert_nextlinen("---");
462 ut_assert_nextline("(0 bootflows, 0 valid)");
463 ut_assert_console_end();
464
Simon Glass18552d22023-01-17 10:48:13 -0700465 ut_assertok(run_command("bootflow scan -lH", 0));
Simon Glass0917f772022-07-30 15:52:34 -0600466 ut_assert_nextline("Scanning for bootflows in all bootdevs");
467 ut_assert_nextline(
468 "Seq Method State Uclass Part Name Filename");
469 ut_assert_nextlinen("---");
470 ut_assert_nextline("Scanning global bootmeth 'firmware0':");
471 ut_assert_nextline("Scanning bootdev 'mmc2.bootdev':");
472 ut_assert_nextline("Scanning bootdev 'mmc1.bootdev':");
473 ut_assert_nextline("Scanning bootdev 'mmc0.bootdev':");
474 ut_assert_nextline("No more bootdevs");
475 ut_assert_nextlinen("---");
476 ut_assert_nextline("(0 bootflows, 0 valid)");
477 ut_assert_console_end();
478
479 return 0;
480}
481BOOTSTD_TEST(bootflow_scan_glob_bootmeth, UT_TESTF_DM | UT_TESTF_SCAN_FDT);
482
Simon Glassfb1451b2022-04-24 23:31:24 -0600483/* Check 'bootflow boot' to boot a selected bootflow */
484static int bootflow_cmd_boot(struct unit_test_state *uts)
485{
486 console_record_reset_enable();
487 ut_assertok(run_command("bootdev select 1", 0));
488 ut_assert_console_end();
489 ut_assertok(run_command("bootflow scan", 0));
490 ut_assert_console_end();
491 ut_assertok(run_command("bootflow select 0", 0));
492 ut_assert_console_end();
Simon Glassf25f5752022-07-30 15:52:16 -0600493
494 ut_assertok(inject_response(uts));
Simon Glassfb1451b2022-04-24 23:31:24 -0600495 ut_asserteq(1, run_command("bootflow boot", 0));
496 ut_assert_nextline(
Simon Glass79f66352023-05-10 16:34:46 -0600497 "** Booting bootflow 'mmc1.bootdev.part_1' with extlinux");
Simon Glassfb1451b2022-04-24 23:31:24 -0600498 ut_assert_nextline("Ignoring unknown command: ui");
499
500 /*
501 * We expect it to get through to boot although sandbox always returns
502 * -EFAULT as it cannot actually boot the kernel
503 */
504 ut_assert_skip_to_line("sandbox: continuing, as we cannot run Linux");
505 ut_assert_nextline("Boot failed (err=-14)");
506 ut_assert_console_end();
507
508 return 0;
509}
510BOOTSTD_TEST(bootflow_cmd_boot, UT_TESTF_DM | UT_TESTF_SCAN_FDT);
Simon Glassd985f1d2023-01-06 08:52:41 -0600511
Simon Glasse64c2952023-01-06 08:52:42 -0600512/**
Simon Glass2b9adca2023-08-24 13:55:40 -0600513 * prep_mmc_bootdev() - Set up an mmc bootdev so we can access other distros
Simon Glasse64c2952023-01-06 08:52:42 -0600514 *
Simon Glassbaea7ec2023-10-01 19:14:37 -0600515 * After calling this function, set std->bootdev_order to *@old_orderp to
516 * restore normal operation of bootstd (i.e. with the original bootdev order)
517 *
Simon Glasse64c2952023-01-06 08:52:42 -0600518 * @uts: Unit test state
Simon Glassbaea7ec2023-10-01 19:14:37 -0600519 * @mmc_dev: MMC device to use, e.g. "mmc4". Note that this must remain valid
520 * in the caller until
521 * @bind_cros: true to bind the ChromiumOS bootmeth
522 * @old_orderp: Returns the original bootdev order, which must be restored
Simon Glasse64c2952023-01-06 08:52:42 -0600523 * Returns 0 on success, -ve on failure
524 */
Simon Glassd08db022023-08-24 13:55:41 -0600525static int prep_mmc_bootdev(struct unit_test_state *uts, const char *mmc_dev,
Simon Glassbaea7ec2023-10-01 19:14:37 -0600526 bool bind_cros, const char ***old_orderp)
Simon Glassd985f1d2023-01-06 08:52:41 -0600527{
Simon Glassbaea7ec2023-10-01 19:14:37 -0600528 static const char *order[] = {"mmc2", "mmc1", NULL, NULL};
Simon Glassd985f1d2023-01-06 08:52:41 -0600529 struct udevice *dev, *bootstd;
530 struct bootstd_priv *std;
531 const char **old_order;
Simon Glass2b9adca2023-08-24 13:55:40 -0600532 ofnode root, node;
Simon Glassd985f1d2023-01-06 08:52:41 -0600533
Simon Glassbaea7ec2023-10-01 19:14:37 -0600534 order[2] = mmc_dev;
535
Simon Glassd985f1d2023-01-06 08:52:41 -0600536 /* Enable the mmc4 node since we need a second bootflow */
Simon Glass2b9adca2023-08-24 13:55:40 -0600537 root = oftree_root(oftree_default());
538 node = ofnode_find_subnode(root, mmc_dev);
539 ut_assert(ofnode_valid(node));
Simon Glassd985f1d2023-01-06 08:52:41 -0600540 ut_assertok(lists_bind_fdt(gd->dm_root, node, &dev, NULL, false));
541
542 /* Enable the script bootmeth too */
543 ut_assertok(uclass_first_device_err(UCLASS_BOOTSTD, &bootstd));
Simon Glass5986d462023-08-19 16:49:35 -0600544 ut_assertok(device_bind(bootstd, DM_DRIVER_REF(bootmeth_2script),
Simon Glassd985f1d2023-01-06 08:52:41 -0600545 "bootmeth_script", 0, ofnode_null(), &dev));
546
Simon Glassd08db022023-08-24 13:55:41 -0600547 /* Enable the cros bootmeth if needed */
Dan Carpenter2160cb12024-02-21 09:26:09 +0300548 if (IS_ENABLED(CONFIG_BOOTMETH_CROS) && bind_cros) {
Simon Glassd08db022023-08-24 13:55:41 -0600549 ut_assertok(uclass_first_device_err(UCLASS_BOOTSTD, &bootstd));
550 ut_assertok(device_bind(bootstd, DM_DRIVER_REF(bootmeth_cros),
551 "cros", 0, ofnode_null(), &dev));
552 }
553
Simon Glass2b9adca2023-08-24 13:55:40 -0600554 /* Change the order to include the device */
Simon Glassd985f1d2023-01-06 08:52:41 -0600555 std = dev_get_priv(bootstd);
556 old_order = std->bootdev_order;
557 std->bootdev_order = order;
Simon Glassbaea7ec2023-10-01 19:14:37 -0600558 *old_orderp = old_order;
559
560 return 0;
561}
562
563/**
564 * scan_mmc_bootdev() - Set up an mmc bootdev so we can access other distros
565 *
566 * @uts: Unit test state
567 * @mmc_dev: MMC device to use, e.g. "mmc4"
568 * @bind_cros: true to bind the ChromiumOS bootmeth
569 * Returns 0 on success, -ve on failure
570 */
571static int scan_mmc_bootdev(struct unit_test_state *uts, const char *mmc_dev,
572 bool bind_cros)
573{
574 struct bootstd_priv *std;
575 struct udevice *bootstd;
576 const char **old_order;
577
578 ut_assertok(prep_mmc_bootdev(uts, mmc_dev, bind_cros, &old_order));
Simon Glassd985f1d2023-01-06 08:52:41 -0600579
580 console_record_reset_enable();
581 ut_assertok(run_command("bootflow scan", 0));
582 ut_assert_console_end();
583
584 /* Restore the order used by the device tree */
Simon Glassbaea7ec2023-10-01 19:14:37 -0600585 ut_assertok(uclass_first_device_err(UCLASS_BOOTSTD, &bootstd));
586 std = dev_get_priv(bootstd);
Simon Glassd985f1d2023-01-06 08:52:41 -0600587 std->bootdev_order = old_order;
588
Simon Glasse64c2952023-01-06 08:52:42 -0600589 return 0;
590}
591
Simon Glass2b9adca2023-08-24 13:55:40 -0600592/**
Simon Glassbaea7ec2023-10-01 19:14:37 -0600593 * scan_mmc4_bootdev() - Set up the mmc4 bootdev so we can access a fake Armbian
Simon Glass2b9adca2023-08-24 13:55:40 -0600594 *
595 * @uts: Unit test state
596 * Returns 0 on success, -ve on failure
597 */
Simon Glassbaea7ec2023-10-01 19:14:37 -0600598static int scan_mmc4_bootdev(struct unit_test_state *uts)
Simon Glass2b9adca2023-08-24 13:55:40 -0600599{
Simon Glassbaea7ec2023-10-01 19:14:37 -0600600 ut_assertok(scan_mmc_bootdev(uts, "mmc4", false));
Simon Glass2b9adca2023-08-24 13:55:40 -0600601
602 return 0;
603}
604
Simon Glasse64c2952023-01-06 08:52:42 -0600605/* Check 'bootflow menu' to select a bootflow */
606static int bootflow_cmd_menu(struct unit_test_state *uts)
607{
Simon Glass3fa53b92023-10-01 19:14:38 -0600608 struct bootstd_priv *std;
Simon Glasse64c2952023-01-06 08:52:42 -0600609 char prev[3];
610
Simon Glass3fa53b92023-10-01 19:14:38 -0600611 /* get access to the current bootflow */
612 ut_assertok(bootstd_get_priv(&std));
613
Simon Glassbaea7ec2023-10-01 19:14:37 -0600614 ut_assertok(scan_mmc4_bootdev(uts));
Simon Glasse64c2952023-01-06 08:52:42 -0600615
Simon Glassd985f1d2023-01-06 08:52:41 -0600616 /* Add keypresses to move to and select the second one in the list */
617 prev[0] = CTL_CH('n');
618 prev[1] = '\r';
619 prev[2] = '\0';
620 ut_asserteq(2, console_in_puts(prev));
621
622 ut_assertok(run_command("bootflow menu", 0));
623 ut_assert_nextline("Selected: Armbian");
Simon Glass3fa53b92023-10-01 19:14:38 -0600624 ut_assertnonnull(std->cur_bootflow);
625 ut_assert_console_end();
626
627 /* Check not selecting anything */
628 prev[0] = '\e';
629 prev[1] = '\0';
630 ut_asserteq(1, console_in_puts(prev));
631
632 ut_asserteq(1, run_command("bootflow menu", 0));
633 ut_assertnull(std->cur_bootflow);
634 ut_assert_nextline("Nothing chosen");
Simon Glassd985f1d2023-01-06 08:52:41 -0600635 ut_assert_console_end();
636
637 return 0;
638}
639BOOTSTD_TEST(bootflow_cmd_menu, UT_TESTF_DM | UT_TESTF_SCAN_FDT);
Simon Glasse64c2952023-01-06 08:52:42 -0600640
Simon Glassa4bee0b2023-10-01 19:15:25 -0600641/* Check 'bootflow scan -m' to select a bootflow using a menu */
642static int bootflow_scan_menu(struct unit_test_state *uts)
643{
644 struct bootstd_priv *std;
645 const char **old_order, **new_order;
646 char prev[3];
647
648 /* get access to the current bootflow */
649 ut_assertok(bootstd_get_priv(&std));
650
651 ut_assertok(prep_mmc_bootdev(uts, "mmc4", false, &old_order));
652
653 /* Add keypresses to move to and select the second one in the list */
654 prev[0] = CTL_CH('n');
655 prev[1] = '\r';
656 prev[2] = '\0';
657 ut_asserteq(2, console_in_puts(prev));
658
659 ut_assertok(run_command("bootflow scan -lm", 0));
660 new_order = std->bootdev_order;
661 std->bootdev_order = old_order;
662
663 ut_assert_skip_to_line("No more bootdevs");
664 ut_assert_nextlinen("--");
665 ut_assert_nextline("(2 bootflows, 2 valid)");
666
667 ut_assert_nextline("Selected: Armbian");
668 ut_assertnonnull(std->cur_bootflow);
669 ut_assert_console_end();
670
671 /* Check not selecting anything */
672 prev[0] = '\e';
673 prev[1] = '\0';
674 ut_asserteq(1, console_in_puts(prev));
675
676 std->bootdev_order = new_order; /* Blue Monday */
677 ut_assertok(run_command("bootflow scan -lm", 0));
678 std->bootdev_order = old_order;
679
680 ut_assertnull(std->cur_bootflow);
681 ut_assert_skip_to_line("(2 bootflows, 2 valid)");
682 ut_assert_nextline("Nothing chosen");
683 ut_assert_console_end();
684
685 return 0;
686}
687BOOTSTD_TEST(bootflow_scan_menu,
688 UT_TESTF_DM | UT_TESTF_SCAN_FDT | UT_TESTF_CONSOLE_REC);
689
690/* Check 'bootflow scan -mb' to select and boot a bootflow using a menu */
691static int bootflow_scan_menu_boot(struct unit_test_state *uts)
692{
693 struct bootstd_priv *std;
694 const char **old_order;
695 char prev[3];
696
697 /* get access to the current bootflow */
698 ut_assertok(bootstd_get_priv(&std));
699
700 ut_assertok(prep_mmc_bootdev(uts, "mmc4", false, &old_order));
701
702 /* Add keypresses to move to and select the second one in the list */
703 prev[0] = CTL_CH('n');
704 prev[1] = '\r';
705 prev[2] = '\0';
706 ut_asserteq(2, console_in_puts(prev));
707
708 ut_assertok(run_command("bootflow scan -lmb", 0));
709 std->bootdev_order = old_order;
710
711 ut_assert_skip_to_line("(2 bootflows, 2 valid)");
712
713 ut_assert_nextline("Selected: Armbian");
Francis Laniel3ea3c572023-12-22 22:02:35 +0100714
715 if (gd->flags & GD_FLG_HUSH_OLD_PARSER) {
716 /*
717 * With old hush, despite booti failing to boot, i.e. returning
718 * CMD_RET_FAILURE, run_command() returns 0 which leads bootflow_boot(), as
719 * we are using bootmeth_script here, to return -EFAULT.
720 */
721 ut_assert_skip_to_line("Boot failed (err=-14)");
722 } else if (gd->flags & GD_FLG_HUSH_MODERN_PARSER) {
723 /*
724 * While with modern one, run_command() propagates CMD_RET_FAILURE returned
725 * by booti, so we get 1 here.
726 */
727 ut_assert_skip_to_line("Boot failed (err=1)");
728 }
Simon Glassa4bee0b2023-10-01 19:15:25 -0600729 ut_assertnonnull(std->cur_bootflow);
730 ut_assert_console_end();
731
732 return 0;
733}
734BOOTSTD_TEST(bootflow_scan_menu_boot,
735 UT_TESTF_DM | UT_TESTF_SCAN_FDT | UT_TESTF_CONSOLE_REC);
736
Simon Glass91943ff2023-01-17 10:48:15 -0700737/* Check searching for a single bootdev using the hunters */
738static int bootflow_cmd_hunt_single(struct unit_test_state *uts)
739{
740 struct bootstd_priv *std;
741
742 /* get access to the used hunters */
743 ut_assertok(bootstd_get_priv(&std));
744
745 ut_assertok(bootstd_test_drop_bootdev_order(uts));
746
747 console_record_reset_enable();
748 ut_assertok(run_command("bootflow scan -l mmc1", 0));
749 ut_assert_nextline("Scanning for bootflows with label 'mmc1'");
750 ut_assert_skip_to_line("(1 bootflow, 1 valid)");
751 ut_assert_console_end();
752
753 /* check that the hunter was used */
754 ut_asserteq(BIT(MMC_HUNTER) | BIT(1), std->hunters_used);
755
756 return 0;
757}
758BOOTSTD_TEST(bootflow_cmd_hunt_single, UT_TESTF_DM | UT_TESTF_SCAN_FDT);
759
760/* Check searching for a uclass label using the hunters */
761static int bootflow_cmd_hunt_label(struct unit_test_state *uts)
762{
763 struct bootstd_priv *std;
764
765 /* get access to the used hunters */
766 ut_assertok(bootstd_get_priv(&std));
767
768 test_set_skip_delays(true);
769 test_set_eth_enable(false);
770 ut_assertok(bootstd_test_drop_bootdev_order(uts));
771
772 console_record_reset_enable();
773 ut_assertok(run_command("bootflow scan -l mmc", 0));
774
775 /* check that the hunter was used */
776 ut_asserteq(BIT(MMC_HUNTER) | BIT(1), std->hunters_used);
777
778 /* check that we got the mmc1 bootflow */
779 ut_assert_nextline("Scanning for bootflows with label 'mmc'");
780 ut_assert_nextlinen("Seq");
781 ut_assert_nextlinen("---");
782 ut_assert_nextline("Hunting with: simple_bus");
783 ut_assert_nextline("Found 2 extension board(s).");
784 ut_assert_nextline("Hunting with: mmc");
785 ut_assert_nextline("Scanning bootdev 'mmc2.bootdev':");
786 ut_assert_nextline("Scanning bootdev 'mmc1.bootdev':");
787 ut_assert_nextline(
Simon Glass79f66352023-05-10 16:34:46 -0600788 " 0 extlinux ready mmc 1 mmc1.bootdev.part_1 /extlinux/extlinux.conf");
Simon Glass91943ff2023-01-17 10:48:15 -0700789 ut_assert_nextline("Scanning bootdev 'mmc0.bootdev':");
790 ut_assert_skip_to_line("(1 bootflow, 1 valid)");
791 ut_assert_console_end();
792
793 return 0;
794}
795BOOTSTD_TEST(bootflow_cmd_hunt_label, UT_TESTF_DM | UT_TESTF_SCAN_FDT);
796
Simon Glasse64c2952023-01-06 08:52:42 -0600797/**
798 * check_font() - Check that the font size for an item matches expectations
799 *
800 * @uts: Unit test state
801 * @scn: Scene containing the text object
802 * @id: ID of the text object
803 * Returns 0 on success, -ve on failure
804 */
805static int check_font(struct unit_test_state *uts, struct scene *scn, uint id,
806 int font_size)
807{
808 struct scene_obj_txt *txt;
809
810 txt = scene_obj_find(scn, id, SCENEOBJT_TEXT);
811 ut_assertnonnull(txt);
812
813 ut_asserteq(font_size, txt->font_size);
814
815 return 0;
816}
817
818/* Check themes work with a bootflow menu */
819static int bootflow_menu_theme(struct unit_test_state *uts)
820{
821 const int font_size = 30;
822 struct scene *scn;
823 struct expo *exp;
824 ofnode node;
825 int i;
826
Simon Glassbaea7ec2023-10-01 19:14:37 -0600827 ut_assertok(scan_mmc4_bootdev(uts));
Simon Glasse64c2952023-01-06 08:52:42 -0600828
829 ut_assertok(bootflow_menu_new(&exp));
830 node = ofnode_path("/bootstd/theme");
831 ut_assert(ofnode_valid(node));
832 ut_assertok(bootflow_menu_apply_theme(exp, node));
833
834 scn = expo_lookup_scene_id(exp, MAIN);
835 ut_assertnonnull(scn);
836
837 /*
838 * Check that the txt objects have the correct font size from the
839 * device tree node: bootstd/theme
840 *
841 * Check both menu items, since there are two bootflows
842 */
843 ut_assertok(check_font(uts, scn, OBJ_PROMPT, font_size));
844 ut_assertok(check_font(uts, scn, OBJ_POINTER, font_size));
845 for (i = 0; i < 2; i++) {
846 ut_assertok(check_font(uts, scn, ITEM_DESC + i, font_size));
847 ut_assertok(check_font(uts, scn, ITEM_KEY + i, font_size));
848 ut_assertok(check_font(uts, scn, ITEM_LABEL + i, font_size));
849 }
850
851 expo_destroy(exp);
852
853 return 0;
854}
855BOOTSTD_TEST(bootflow_menu_theme, UT_TESTF_DM | UT_TESTF_SCAN_FDT);
Simon Glassd07861c2023-07-12 09:04:38 -0600856
857/**
858 * check_arg() - Check both the normal case and the buffer-overflow case
859 *
860 * @uts: Unit-test state
861 * @expect_ret: Expected return value (i.e. buffer length)
862 * @expect_str: String expected to be returned
863 * @buf: Buffer to use
864 * @from: Original cmdline to update
865 * @arg: Argument to update (e.g. "console")
866 * @val: Value to set (e.g. "ttyS2") or NULL to delete the argument if present,
867 * "" to set it to an empty value (e.g. "console=") and BOOTFLOWCL_EMPTY to add
868 * it without any value ("initrd")
869 */
870static int check_arg(struct unit_test_state *uts, int expect_ret,
871 const char *expect_str, char *buf, const char *from,
872 const char *arg, const char *val)
873{
874 /* check for writing outside the reported bounds */
875 buf[expect_ret] = '[';
876 ut_asserteq(expect_ret,
877 cmdline_set_arg(buf, expect_ret, from, arg, val, NULL));
878 ut_asserteq_str(expect_str, buf);
879 ut_asserteq('[', buf[expect_ret]);
880
881 /* do the test again but with one less byte in the buffer */
882 ut_asserteq(-E2BIG, cmdline_set_arg(buf, expect_ret - 1, from, arg,
883 val, NULL));
884
885 return 0;
886}
887
888/* Test of bootflow_cmdline_set_arg() */
889static int test_bootflow_cmdline_set(struct unit_test_state *uts)
890{
891 char buf[50];
892 const int size = sizeof(buf);
893
894 /*
895 * note that buffer-overflow tests are immediately each test case, just
896 * top keep the code together
897 */
898
899 /* add an arg that doesn't already exist, starting from empty */
900 ut_asserteq(-ENOENT, cmdline_set_arg(buf, size, NULL, "me", NULL,
901 NULL));
902
903 ut_assertok(check_arg(uts, 3, "me", buf, NULL, "me", BOOTFLOWCL_EMPTY));
904 ut_assertok(check_arg(uts, 4, "me=", buf, NULL, "me", ""));
905 ut_assertok(check_arg(uts, 8, "me=fred", buf, NULL, "me", "fred"));
906
907 /* add an arg that doesn't already exist, starting from non-empty */
908 ut_assertok(check_arg(uts, 11, "arg=123 me", buf, "arg=123", "me",
909 BOOTFLOWCL_EMPTY));
910 ut_assertok(check_arg(uts, 12, "arg=123 me=", buf, "arg=123", "me",
911 ""));
912 ut_assertok(check_arg(uts, 16, "arg=123 me=fred", buf, "arg=123", "me",
913 "fred"));
914
915 /* update an arg at the start */
916 ut_assertok(check_arg(uts, 1, "", buf, "arg=123", "arg", NULL));
917 ut_assertok(check_arg(uts, 4, "arg", buf, "arg=123", "arg",
918 BOOTFLOWCL_EMPTY));
919 ut_assertok(check_arg(uts, 5, "arg=", buf, "arg=123", "arg", ""));
920 ut_assertok(check_arg(uts, 6, "arg=1", buf, "arg=123", "arg", "1"));
921 ut_assertok(check_arg(uts, 9, "arg=1234", buf, "arg=123", "arg",
922 "1234"));
923
924 /* update an arg at the end */
925 ut_assertok(check_arg(uts, 5, "mary", buf, "mary arg=123", "arg",
926 NULL));
927 ut_assertok(check_arg(uts, 9, "mary arg", buf, "mary arg=123", "arg",
928 BOOTFLOWCL_EMPTY));
929 ut_assertok(check_arg(uts, 10, "mary arg=", buf, "mary arg=123", "arg",
930 ""));
931 ut_assertok(check_arg(uts, 11, "mary arg=1", buf, "mary arg=123", "arg",
932 "1"));
933 ut_assertok(check_arg(uts, 14, "mary arg=1234", buf, "mary arg=123",
934 "arg", "1234"));
935
936 /* update an arg in the middle */
937 ut_assertok(check_arg(uts, 16, "mary=abc john=2", buf,
938 "mary=abc arg=123 john=2", "arg", NULL));
939 ut_assertok(check_arg(uts, 20, "mary=abc arg john=2", buf,
940 "mary=abc arg=123 john=2", "arg",
941 BOOTFLOWCL_EMPTY));
942 ut_assertok(check_arg(uts, 21, "mary=abc arg= john=2", buf,
943 "mary=abc arg=123 john=2", "arg", ""));
944 ut_assertok(check_arg(uts, 22, "mary=abc arg=1 john=2", buf,
945 "mary=abc arg=123 john=2", "arg", "1"));
946 ut_assertok(check_arg(uts, 25, "mary=abc arg=1234 john=2", buf,
947 "mary=abc arg=123 john=2", "arg", "1234"));
948
949 /* handle existing args with quotes */
950 ut_assertok(check_arg(uts, 16, "mary=\"abc\" john", buf,
951 "mary=\"abc\" arg=123 john", "arg", NULL));
952
953 /* handle existing args with quoted spaces */
954 ut_assertok(check_arg(uts, 20, "mary=\"abc def\" john", buf,
955 "mary=\"abc def\" arg=123 john", "arg", NULL));
956
957 ut_assertok(check_arg(uts, 34, "mary=\"abc def\" arg=123 john def=4",
958 buf, "mary=\"abc def\" arg=123 john", "def",
959 "4"));
960
961 /* quote at the start */
962 ut_asserteq(-EBADF, cmdline_set_arg(buf, size,
963 "mary=\"abc def\" arg=\"123 456\"",
964 "arg", "\"4 5 6", NULL));
965
966 /* quote at the end */
967 ut_asserteq(-EBADF, cmdline_set_arg(buf, size,
968 "mary=\"abc def\" arg=\"123 456\"",
969 "arg", "4 5 6\"", NULL));
970
971 /* quote in the middle */
972 ut_asserteq(-EBADF, cmdline_set_arg(buf, size,
973 "mary=\"abc def\" arg=\"123 456\"",
974 "arg", "\"4 \"5 6\"", NULL));
975
976 /* handle updating a quoted arg */
977 ut_assertok(check_arg(uts, 27, "mary=\"abc def\" arg=\"4 5 6\"", buf,
978 "mary=\"abc def\" arg=\"123 456\"", "arg",
979 "4 5 6"));
980
981 /* changing a quoted arg to a non-quoted arg */
982 ut_assertok(check_arg(uts, 23, "mary=\"abc def\" arg=789", buf,
983 "mary=\"abc def\" arg=\"123 456\"", "arg",
984 "789"));
985
986 /* changing a non-quoted arg to a quoted arg */
987 ut_assertok(check_arg(uts, 29, "mary=\"abc def\" arg=\"456 789\"", buf,
988 "mary=\"abc def\" arg=123", "arg", "456 789"));
989
990 /* handling of spaces */
991 ut_assertok(check_arg(uts, 8, "arg=123", buf, " ", "arg", "123"));
992 ut_assertok(check_arg(uts, 8, "arg=123", buf, " ", "arg", "123"));
993 ut_assertok(check_arg(uts, 13, "john arg=123", buf, " john ", "arg",
994 "123"));
995 ut_assertok(check_arg(uts, 13, "john arg=123", buf, " john arg=123 ",
996 "arg", "123"));
997 ut_assertok(check_arg(uts, 18, "john arg=123 mary", buf,
998 " john arg=123 mary ", "arg", "123"));
999
1000 /* unchanged arg */
1001 ut_assertok(check_arg(uts, 3, "me", buf, "me", "me", BOOTFLOWCL_EMPTY));
1002
1003 /* arg which starts with the same name */
1004 ut_assertok(check_arg(uts, 28, "mary=abc johnathon=2 john=3", buf,
1005 "mary=abc johnathon=2 john=1", "john", "3"));
1006
1007 return 0;
1008}
1009BOOTSTD_TEST(test_bootflow_cmdline_set, 0);
Simon Glass82c09382023-07-12 09:04:39 -06001010
1011/* Test of bootflow_cmdline_set_arg() */
1012static int bootflow_set_arg(struct unit_test_state *uts)
1013{
1014 struct bootflow s_bflow, *bflow = &s_bflow;
1015 ulong mem_start;
1016
1017 ut_assertok(env_set("bootargs", NULL));
1018
1019 mem_start = ut_check_delta(0);
1020
1021 /* Do a simple sanity check. Rely on bootflow_cmdline() for the rest */
1022 bflow->cmdline = NULL;
1023 ut_assertok(bootflow_cmdline_set_arg(bflow, "fred", "123", false));
1024 ut_asserteq_str(bflow->cmdline, "fred=123");
1025
1026 ut_assertok(bootflow_cmdline_set_arg(bflow, "mary", "and here", false));
1027 ut_asserteq_str(bflow->cmdline, "fred=123 mary=\"and here\"");
1028
1029 ut_assertok(bootflow_cmdline_set_arg(bflow, "mary", NULL, false));
1030 ut_asserteq_str(bflow->cmdline, "fred=123");
1031 ut_assertok(bootflow_cmdline_set_arg(bflow, "fred", NULL, false));
1032 ut_asserteq_ptr(bflow->cmdline, NULL);
1033
1034 ut_asserteq(0, ut_check_delta(mem_start));
1035
1036 ut_assertok(bootflow_cmdline_set_arg(bflow, "mary", "here", true));
1037 ut_asserteq_str("mary=here", env_get("bootargs"));
1038 ut_assertok(env_set("bootargs", NULL));
1039
1040 return 0;
1041}
1042BOOTSTD_TEST(bootflow_set_arg, 0);
1043
1044/* Test of bootflow_cmdline_get_arg() */
1045static int bootflow_cmdline_get(struct unit_test_state *uts)
1046{
1047 int pos;
1048
1049 /* empty string */
1050 ut_asserteq(-ENOENT, cmdline_get_arg("", "fred", &pos));
1051
1052 /* arg with empty value */
1053 ut_asserteq(0, cmdline_get_arg("fred= mary", "fred", &pos));
1054 ut_asserteq(5, pos);
1055
1056 /* arg with a value */
1057 ut_asserteq(2, cmdline_get_arg("fred=23", "fred", &pos));
1058 ut_asserteq(5, pos);
1059
1060 /* arg with a value */
1061 ut_asserteq(3, cmdline_get_arg("mary=1 fred=234", "fred", &pos));
1062 ut_asserteq(12, pos);
1063
1064 /* arg with a value, after quoted arg */
1065 ut_asserteq(3, cmdline_get_arg("mary=\"1 2\" fred=234", "fred", &pos));
1066 ut_asserteq(16, pos);
1067
1068 /* arg in the middle */
1069 ut_asserteq(0, cmdline_get_arg("mary=\"1 2\" fred john=23", "fred",
1070 &pos));
1071 ut_asserteq(15, pos);
1072
1073 /* quoted arg */
1074 ut_asserteq(3, cmdline_get_arg("mary=\"1 2\" fred=\"3 4\" john=23",
1075 "fred", &pos));
1076 ut_asserteq(17, pos);
1077
1078 /* args starting with the same prefix */
1079 ut_asserteq(1, cmdline_get_arg("mary=abc johnathon=3 john=1", "john",
1080 &pos));
1081 ut_asserteq(26, pos);
1082
1083 return 0;
1084}
1085BOOTSTD_TEST(bootflow_cmdline_get, 0);
1086
1087static int bootflow_cmdline(struct unit_test_state *uts)
1088{
1089 ut_assertok(run_command("bootflow scan mmc", 0));
1090 ut_assertok(run_command("bootflow sel 0", 0));
1091 console_record_reset_enable();
1092
1093 ut_asserteq(1, run_command("bootflow cmdline get fred", 0));
1094 ut_assert_nextline("Argument not found");
1095 ut_assert_console_end();
1096
1097 ut_asserteq(0, run_command("bootflow cmdline set fred 123", 0));
1098 ut_asserteq(0, run_command("bootflow cmdline get fred", 0));
1099 ut_assert_nextline("123");
1100
1101 ut_asserteq(0, run_command("bootflow cmdline set mary abc", 0));
1102 ut_asserteq(0, run_command("bootflow cmdline get mary", 0));
1103 ut_assert_nextline("abc");
1104
1105 ut_asserteq(0, run_command("bootflow cmdline delete fred", 0));
1106 ut_asserteq(1, run_command("bootflow cmdline get fred", 0));
1107 ut_assert_nextline("Argument not found");
1108
1109 ut_asserteq(0, run_command("bootflow cmdline clear mary", 0));
1110 ut_asserteq(0, run_command("bootflow cmdline get mary", 0));
1111 ut_assert_nextline_empty();
1112
Simon Glass921f63e2023-11-29 10:31:19 -07001113 ut_asserteq(0, run_command("bootflow cmdline set mary abc", 0));
1114 ut_asserteq(0, run_command("bootflow cmdline set mary", 0));
1115 ut_assert_nextline_empty();
1116
Simon Glass82c09382023-07-12 09:04:39 -06001117 ut_assert_console_end();
1118
1119 return 0;
1120}
1121BOOTSTD_TEST(bootflow_cmdline, 0);
Simon Glassd08db022023-08-24 13:55:41 -06001122
Simon Glass19248dc2023-10-25 07:17:36 +13001123/* test a few special changes to a long command line */
1124static int bootflow_cmdline_special(struct unit_test_state *uts)
1125{
1126 char buf[500];
1127 int pos;
1128
1129 /*
1130 * check handling of an argument which has an embedded '=', as well as
1131 * handling of a argument which partially matches ("ro" and "root")
1132 */
1133 ut_asserteq(32, cmdline_set_arg(
1134 buf, sizeof(buf),
1135 "loglevel=7 root=PARTUUID=d68352e3 rootwait ro noinitrd",
1136 "root", NULL, &pos));
1137 ut_asserteq_str("loglevel=7 rootwait ro noinitrd", buf);
1138
1139 return 0;
1140}
1141BOOTSTD_TEST(bootflow_cmdline_special, 0);
1142
Simon Glassd08db022023-08-24 13:55:41 -06001143/* Test ChromiumOS bootmeth */
1144static int bootflow_cros(struct unit_test_state *uts)
1145{
Simon Glassbaea7ec2023-10-01 19:14:37 -06001146 ut_assertok(scan_mmc_bootdev(uts, "mmc5", true));
Simon Glassd08db022023-08-24 13:55:41 -06001147 ut_assertok(run_command("bootflow list", 0));
1148
1149 ut_assert_nextlinen("Showing all");
1150 ut_assert_nextlinen("Seq");
1151 ut_assert_nextlinen("---");
1152 ut_assert_nextlinen(" 0 extlinux");
Simon Glass71f634b2023-08-24 13:55:45 -06001153 ut_assert_nextlinen(" 1 cros ready mmc 2 mmc5.bootdev.part_2 ");
1154 ut_assert_nextlinen(" 2 cros ready mmc 4 mmc5.bootdev.part_4 ");
Simon Glassd08db022023-08-24 13:55:41 -06001155 ut_assert_nextlinen("---");
Simon Glass71f634b2023-08-24 13:55:45 -06001156 ut_assert_skip_to_line("(3 bootflows, 3 valid)");
Simon Glassd08db022023-08-24 13:55:41 -06001157
1158 ut_assert_console_end();
1159
1160 return 0;
1161}
1162BOOTSTD_TEST(bootflow_cros, 0);