blob: a930d2cc309a21b9fb3855b30b22e3b68098b4f0 [file] [log] [blame]
Simon Glassb255efc2022-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 Glassb255efc2022-04-24 23:31:24 -06009#include <bootdev.h>
10#include <bootflow.h>
Simon Glassc8d37212022-07-30 15:52:34 -060011#include <bootmeth.h>
Simon Glassb255efc2022-04-24 23:31:24 -060012#include <bootstd.h>
Simon Glassd2bc33ed2023-01-06 08:52:41 -060013#include <cli.h>
Simon Glassb255efc2022-04-24 23:31:24 -060014#include <dm.h>
Simon Glass3b1e60b2024-11-07 14:31:43 -070015#include <efi.h>
Simon Glass4f378de2024-11-07 14:31:50 -070016#include <efi_loader.h>
Tom Rini22856382025-05-14 16:46:03 -060017#include <env.h>
Simon Glassd92bcc42023-01-06 08:52:42 -060018#include <expo.h>
Simon Glassc6a52e72024-11-15 16:19:23 -070019#include <mapmem.h>
Simon Glass90b643d2022-07-30 15:52:36 -060020#ifdef CONFIG_SANDBOX
Simon Glass161e1e32022-07-30 15:52:22 -060021#include <asm/test.h>
Simon Glass90b643d2022-07-30 15:52:36 -060022#endif
Simon Glassd2bc33ed2023-01-06 08:52:41 -060023#include <dm/device-internal.h>
Simon Glassb255efc2022-04-24 23:31:24 -060024#include <dm/lists.h>
Simon Glassb255efc2022-04-24 23:31:24 -060025#include <test/ut.h>
26#include "bootstd_common.h"
Simon Glassd92bcc42023-01-06 08:52:42 -060027#include "../../boot/bootflow_internal.h"
28#include "../../boot/scene_internal.h"
Simon Glassb255efc2022-04-24 23:31:24 -060029
Simon Glassd2bc33ed2023-01-06 08:52:41 -060030DECLARE_GLOBAL_DATA_PTR;
31
Mattijs Korpershoekd77f8152024-07-10 10:40:06 +020032extern U_BOOT_DRIVER(bootmeth_android);
Simon Glassfff928c2023-08-24 13:55:41 -060033extern U_BOOT_DRIVER(bootmeth_cros);
Simon Glass2f27e472023-08-19 16:49:35 -060034extern U_BOOT_DRIVER(bootmeth_2script);
Simon Glassd2bc33ed2023-01-06 08:52:41 -060035
Simon Glass4f378de2024-11-07 14:31:50 -070036/* Use this as the vendor for EFI to tell the app to exit boot services */
37static u16 __efi_runtime_data test_vendor[] = u"U-Boot testing";
38
Simon Glass49ad1d82022-07-30 15:52:16 -060039static int inject_response(struct unit_test_state *uts)
40{
41 /*
42 * The image being booted presents a menu of options:
43 *
44 * Fedora-Workstation-armhfp-31-1.9 Boot Options.
45 * 1: Fedora-Workstation-armhfp-31-1.9 (5.3.7-301.fc31.armv7hl)
46 * Enter choice:
47 *
48 * Provide input for this, to avoid waiting two seconds for a timeout.
49 */
50 ut_asserteq(2, console_in_puts("1\n"));
51
52 return 0;
53}
54
Simon Glassb255efc2022-04-24 23:31:24 -060055/* Check 'bootflow scan/list' commands */
56static int bootflow_cmd(struct unit_test_state *uts)
57{
Simon Glassb255efc2022-04-24 23:31:24 -060058 ut_assertok(run_command("bootdev select 1", 0));
59 ut_assert_console_end();
Simon Glasse4cf1062023-01-17 10:48:13 -070060 ut_assertok(run_command("bootflow scan -lH", 0));
Simon Glassb255efc2022-04-24 23:31:24 -060061 ut_assert_nextline("Scanning for bootflows in bootdev 'mmc1.bootdev'");
62 ut_assert_nextline("Seq Method State Uclass Part Name Filename");
63 ut_assert_nextlinen("---");
Simon Glass484e4072023-01-17 10:48:14 -070064 ut_assert_nextline("Scanning bootdev 'mmc2.bootdev':");
65 ut_assert_nextline("Scanning bootdev 'mmc1.bootdev':");
Simon Glassb71d7f72023-05-10 16:34:46 -060066 ut_assert_nextline(" 0 extlinux ready mmc 1 mmc1.bootdev.part_1 /extlinux/extlinux.conf");
Simon Glass484e4072023-01-17 10:48:14 -070067 ut_assert_nextline("No more bootdevs");
Simon Glassb255efc2022-04-24 23:31:24 -060068 ut_assert_nextlinen("---");
69 ut_assert_nextline("(1 bootflow, 1 valid)");
70 ut_assert_console_end();
71
72 ut_assertok(run_command("bootflow list", 0));
73 ut_assert_nextline("Showing bootflows for bootdev 'mmc1.bootdev'");
74 ut_assert_nextline("Seq Method State Uclass Part Name Filename");
75 ut_assert_nextlinen("---");
Simon Glassb71d7f72023-05-10 16:34:46 -060076 ut_assert_nextline(" 0 extlinux ready mmc 1 mmc1.bootdev.part_1 /extlinux/extlinux.conf");
Simon Glassb255efc2022-04-24 23:31:24 -060077 ut_assert_nextlinen("---");
78 ut_assert_nextline("(1 bootflow, 1 valid)");
79 ut_assert_console_end();
80
Simon Glassc6a52e72024-11-15 16:19:23 -070081 ut_assertok(run_command("bootstd images", 0));
82 ut_assert_nextlinen("Seq");
83 ut_assert_nextlinen("---");
84 ut_assert_nextlinen(" 0 mmc1.bootdev.part_1 extlinux_cfg");
85 ut_assert_nextlinen("---");
86 ut_assert_nextline("(1 image)");
87 ut_assert_console_end();
88
Simon Glassb255efc2022-04-24 23:31:24 -060089 return 0;
90}
Simon Glassf0425022024-08-22 07:57:54 -060091BOOTSTD_TEST(bootflow_cmd, UTF_DM | UTF_SCAN_FDT | UTF_CONSOLE);
Simon Glassb255efc2022-04-24 23:31:24 -060092
Simon Glass484e4072023-01-17 10:48:14 -070093/* Check 'bootflow scan' with a label / seq */
Simon Glassb255efc2022-04-24 23:31:24 -060094static int bootflow_cmd_label(struct unit_test_state *uts)
95{
Simon Glass484e4072023-01-17 10:48:14 -070096 test_set_eth_enable(false);
97
Simon Glasse4cf1062023-01-17 10:48:13 -070098 ut_assertok(run_command("bootflow scan -lH mmc1", 0));
Simon Glass484e4072023-01-17 10:48:14 -070099 ut_assert_nextline("Scanning for bootflows with label 'mmc1'");
Simon Glassb255efc2022-04-24 23:31:24 -0600100 ut_assert_skip_to_line("(1 bootflow, 1 valid)");
101 ut_assert_console_end();
102
Simon Glass484e4072023-01-17 10:48:14 -0700103 ut_assertok(run_command("bootflow scan -lH 0", 0));
104 ut_assert_nextline("Scanning for bootflows with label '0'");
Simon Glassb255efc2022-04-24 23:31:24 -0600105 ut_assert_skip_to_line("(0 bootflows, 0 valid)");
106 ut_assert_console_end();
107
Simon Glass484e4072023-01-17 10:48:14 -0700108 /*
109 * with ethernet enabled we have 8 devices ahead of the mmc ones:
110 *
111 * ut_assertok(run_command("bootdev list", 0));
112 * Seq Probed Status Uclass Name
113 * --- ------ ------ -------- ------------------
114 * 0 [ + ] OK ethernet eth@10002000.bootdev
115 * 1 [ ] OK ethernet eth@10003000.bootdev
116 * 2 [ ] OK ethernet sbe5.bootdev
117 * 3 [ ] OK ethernet eth@10004000.bootdev
118 * 4 [ ] OK ethernet phy-test-eth.bootdev
119 * 5 [ ] OK ethernet dsa-test-eth.bootdev
120 * 6 [ ] OK ethernet dsa-test@0.bootdev
121 * 7 [ ] OK ethernet dsa-test@1.bootdev
122 * 8 [ ] OK mmc mmc2.bootdev
123 * 9 [ + ] OK mmc mmc1.bootdev
124 * a [ ] OK mmc mmc0.bootdev
Jerome Forissier253d5982024-10-16 11:56:26 +0200125 *
126 * However with CONFIG_DSA_SANDBOX=n we have two fewer (dsa-test@0 and
127 * dsa-test@1).
Simon Glass484e4072023-01-17 10:48:14 -0700128 */
Jerome Forissier253d5982024-10-16 11:56:26 +0200129 if (CONFIG_IS_ENABLED(DSA_SANDBOX)) {
130 ut_assertok(run_command("bootflow scan -lH 9", 0));
131 ut_assert_nextline("Scanning for bootflows with label '9'");
132 } else {
133 ut_assertok(run_command("bootflow scan -lH 7", 0));
134 ut_assert_nextline("Scanning for bootflows with label '7'");
135 }
Simon Glass484e4072023-01-17 10:48:14 -0700136 ut_assert_skip_to_line("(1 bootflow, 1 valid)");
137
Simon Glasse4cf1062023-01-17 10:48:13 -0700138 ut_assertok(run_command("bootflow scan -lH 0", 0));
Simon Glass484e4072023-01-17 10:48:14 -0700139 ut_assert_nextline("Scanning for bootflows with label '0'");
Simon Glassb255efc2022-04-24 23:31:24 -0600140 ut_assert_skip_to_line("(0 bootflows, 0 valid)");
141 ut_assert_console_end();
142
143 return 0;
144}
Simon Glassf0425022024-08-22 07:57:54 -0600145BOOTSTD_TEST(bootflow_cmd_label, UTF_DM | UTF_SCAN_FDT | UTF_ETH_BOOTDEV |
146 UTF_CONSOLE);
Simon Glassb255efc2022-04-24 23:31:24 -0600147
148/* Check 'bootflow scan/list' commands using all bootdevs */
149static int bootflow_cmd_glob(struct unit_test_state *uts)
150{
151 ut_assertok(bootstd_test_drop_bootdev_order(uts));
152
Simon Glasse4cf1062023-01-17 10:48:13 -0700153 ut_assertok(run_command("bootflow scan -lGH", 0));
Simon Glassb255efc2022-04-24 23:31:24 -0600154 ut_assert_nextline("Scanning for bootflows in all bootdevs");
155 ut_assert_nextline("Seq Method State Uclass Part Name Filename");
156 ut_assert_nextlinen("---");
157 ut_assert_nextline("Scanning bootdev 'mmc2.bootdev':");
158 ut_assert_nextline("Scanning bootdev 'mmc1.bootdev':");
Simon Glassb71d7f72023-05-10 16:34:46 -0600159 ut_assert_nextline(" 0 extlinux ready mmc 1 mmc1.bootdev.part_1 /extlinux/extlinux.conf");
Simon Glassb255efc2022-04-24 23:31:24 -0600160 ut_assert_nextline("Scanning bootdev 'mmc0.bootdev':");
161 ut_assert_nextline("No more bootdevs");
162 ut_assert_nextlinen("---");
163 ut_assert_nextline("(1 bootflow, 1 valid)");
164 ut_assert_console_end();
165
166 ut_assertok(run_command("bootflow list", 0));
167 ut_assert_nextline("Showing all bootflows");
168 ut_assert_nextline("Seq Method State Uclass Part Name Filename");
169 ut_assert_nextlinen("---");
Simon Glassb71d7f72023-05-10 16:34:46 -0600170 ut_assert_nextline(" 0 extlinux ready mmc 1 mmc1.bootdev.part_1 /extlinux/extlinux.conf");
Simon Glassb255efc2022-04-24 23:31:24 -0600171 ut_assert_nextlinen("---");
172 ut_assert_nextline("(1 bootflow, 1 valid)");
173 ut_assert_console_end();
174
175 return 0;
176}
Simon Glassf0425022024-08-22 07:57:54 -0600177BOOTSTD_TEST(bootflow_cmd_glob, UTF_DM | UTF_SCAN_FDT | UTF_CONSOLE);
Simon Glassb255efc2022-04-24 23:31:24 -0600178
179/* Check 'bootflow scan -e' */
180static int bootflow_cmd_scan_e(struct unit_test_state *uts)
181{
182 ut_assertok(bootstd_test_drop_bootdev_order(uts));
183
Simon Glasse4cf1062023-01-17 10:48:13 -0700184 ut_assertok(run_command("bootflow scan -aleGH", 0));
Simon Glassb255efc2022-04-24 23:31:24 -0600185 ut_assert_nextline("Scanning for bootflows in all bootdevs");
186 ut_assert_nextline("Seq Method State Uclass Part Name Filename");
187 ut_assert_nextlinen("---");
188 ut_assert_nextline("Scanning bootdev 'mmc2.bootdev':");
Simon Glassd465ad52023-08-24 13:55:39 -0600189 ut_assert_nextline(" 0 extlinux media mmc 0 mmc2.bootdev.whole ");
Simon Glass9482fdf2023-05-10 16:34:26 -0600190 ut_assert_nextline(" ** No partition found, err=-93: Protocol not supported");
Simon Glassd465ad52023-08-24 13:55:39 -0600191 ut_assert_nextline(" 1 efi media mmc 0 mmc2.bootdev.whole ");
Simon Glass9482fdf2023-05-10 16:34:26 -0600192 ut_assert_nextline(" ** No partition found, err=-93: Protocol not supported");
Simon Glassb255efc2022-04-24 23:31:24 -0600193
194 ut_assert_nextline("Scanning bootdev 'mmc1.bootdev':");
Simon Glassd465ad52023-08-24 13:55:39 -0600195 ut_assert_nextline(" 2 extlinux media mmc 0 mmc1.bootdev.whole ");
Simon Glass9482fdf2023-05-10 16:34:26 -0600196 ut_assert_nextline(" ** No partition found, err=-2: No such file or directory");
Simon Glassd465ad52023-08-24 13:55:39 -0600197 ut_assert_nextline(" 3 efi media mmc 0 mmc1.bootdev.whole ");
Simon Glass9482fdf2023-05-10 16:34:26 -0600198 ut_assert_nextline(" ** No partition found, err=-2: No such file or directory");
Simon Glassb71d7f72023-05-10 16:34:46 -0600199 ut_assert_nextline(" 4 extlinux ready mmc 1 mmc1.bootdev.part_1 /extlinux/extlinux.conf");
Simon Glass3b1e60b2024-11-07 14:31:43 -0700200 ut_assert_nextline(
201 " 5 efi fs mmc 1 mmc1.bootdev.part_1 /EFI/BOOT/%s",
202 efi_get_basename());
Simon Glassb255efc2022-04-24 23:31:24 -0600203
204 ut_assert_skip_to_line("Scanning bootdev 'mmc0.bootdev':");
Simon Glassd465ad52023-08-24 13:55:39 -0600205 ut_assert_skip_to_line(
206 " 3f efi media mmc 0 mmc0.bootdev.whole ");
Simon Glass9482fdf2023-05-10 16:34:26 -0600207 ut_assert_nextline(" ** No partition found, err=-93: Protocol not supported");
Simon Glassb255efc2022-04-24 23:31:24 -0600208 ut_assert_nextline("No more bootdevs");
209 ut_assert_nextlinen("---");
210 ut_assert_nextline("(64 bootflows, 1 valid)");
211 ut_assert_console_end();
212
213 ut_assertok(run_command("bootflow list", 0));
214 ut_assert_nextline("Showing all bootflows");
215 ut_assert_nextline("Seq Method State Uclass Part Name Filename");
216 ut_assert_nextlinen("---");
Simon Glassd465ad52023-08-24 13:55:39 -0600217 ut_assert_nextline(" 0 extlinux media mmc 0 mmc2.bootdev.whole ");
218 ut_assert_nextline(" 1 efi media mmc 0 mmc2.bootdev.whole ");
219 ut_assert_skip_to_line(
220 " 4 extlinux ready mmc 1 mmc1.bootdev.part_1 /extlinux/extlinux.conf");
221 ut_assert_skip_to_line(" 3f efi media mmc 0 mmc0.bootdev.whole ");
Simon Glassb255efc2022-04-24 23:31:24 -0600222 ut_assert_nextlinen("---");
223 ut_assert_nextline("(64 bootflows, 1 valid)");
224 ut_assert_console_end();
225
226 return 0;
227}
Simon Glassf0425022024-08-22 07:57:54 -0600228BOOTSTD_TEST(bootflow_cmd_scan_e, UTF_DM | UTF_SCAN_FDT | UTF_CONSOLE);
Simon Glassb255efc2022-04-24 23:31:24 -0600229
230/* Check 'bootflow info' */
231static int bootflow_cmd_info(struct unit_test_state *uts)
232{
Simon Glassb255efc2022-04-24 23:31:24 -0600233 ut_assertok(run_command("bootdev select 1", 0));
234 ut_assert_console_end();
235 ut_assertok(run_command("bootflow scan", 0));
236 ut_assert_console_end();
237 ut_assertok(run_command("bootflow select 0", 0));
238 ut_assert_console_end();
239 ut_assertok(run_command("bootflow info", 0));
240 ut_assert_nextline("Name: mmc1.bootdev.part_1");
241 ut_assert_nextline("Device: mmc1.bootdev");
242 ut_assert_nextline("Block dev: mmc1.blk");
Simon Glassb71d7f72023-05-10 16:34:46 -0600243 ut_assert_nextline("Method: extlinux");
Simon Glassb255efc2022-04-24 23:31:24 -0600244 ut_assert_nextline("State: ready");
245 ut_assert_nextline("Partition: 1");
246 ut_assert_nextline("Subdir: (none)");
247 ut_assert_nextline("Filename: /extlinux/extlinux.conf");
248 ut_assert_nextlinen("Buffer: ");
249 ut_assert_nextline("Size: 253 (595 bytes)");
Simon Glass72b7b192023-01-06 08:52:33 -0600250 ut_assert_nextline("OS: Fedora-Workstation-armhfp-31-1.9 (5.3.7-301.fc31.armv7hl)");
Simon Glass33927522023-07-12 09:04:34 -0600251 ut_assert_nextline("Cmdline: (none)");
Simon Glass612b9cc2023-01-06 08:52:34 -0600252 ut_assert_nextline("Logo: (none)");
Simon Glass7b8c6342023-01-17 10:47:56 -0700253 ut_assert_nextline("FDT: <NULL>");
Simon Glassb255efc2022-04-24 23:31:24 -0600254 ut_assert_nextline("Error: 0");
255 ut_assert_console_end();
256
257 ut_assertok(run_command("bootflow info -d", 0));
258 ut_assert_nextline("Name: mmc1.bootdev.part_1");
259 ut_assert_skip_to_line("Error: 0");
260 ut_assert_nextline("Contents:");
261 ut_assert_nextline("%s", "");
262 ut_assert_nextline("# extlinux.conf generated by appliance-creator");
263 ut_assert_skip_to_line(" initrd /initramfs-5.3.7-301.fc31.armv7hl.img");
264 ut_assert_console_end();
265
266 return 0;
267}
Simon Glassf0425022024-08-22 07:57:54 -0600268BOOTSTD_TEST(bootflow_cmd_info, UTF_DM | UTF_SCAN_FDT | UTF_CONSOLE);
Simon Glassb255efc2022-04-24 23:31:24 -0600269
270/* Check 'bootflow scan -b' to boot the first available bootdev */
271static int bootflow_scan_boot(struct unit_test_state *uts)
272{
Simon Glass49ad1d82022-07-30 15:52:16 -0600273 ut_assertok(inject_response(uts));
Simon Glassb255efc2022-04-24 23:31:24 -0600274 ut_assertok(run_command("bootflow scan -b", 0));
275 ut_assert_nextline(
Simon Glassb71d7f72023-05-10 16:34:46 -0600276 "** Booting bootflow 'mmc1.bootdev.part_1' with extlinux");
Simon Glassb255efc2022-04-24 23:31:24 -0600277 ut_assert_nextline("Ignoring unknown command: ui");
278
279 /*
280 * We expect it to get through to boot although sandbox always returns
281 * -EFAULT as it cannot actually boot the kernel
282 */
283 ut_assert_skip_to_line("sandbox: continuing, as we cannot run Linux");
284 ut_assert_nextline("Boot failed (err=-14)");
285 ut_assert_console_end();
286
287 return 0;
288}
Simon Glassf0425022024-08-22 07:57:54 -0600289BOOTSTD_TEST(bootflow_scan_boot, UTF_DM | UTF_SCAN_FDT | UTF_CONSOLE);
Simon Glassb255efc2022-04-24 23:31:24 -0600290
291/* Check iterating through available bootflows */
292static int bootflow_iter(struct unit_test_state *uts)
293{
294 struct bootflow_iter iter;
295 struct bootflow bflow;
296
297 bootstd_clear_glob();
298
299 /* The first device is mmc2.bootdev which has no media */
300 ut_asserteq(-EPROTONOSUPPORT,
Simon Glass3c63a872025-03-15 14:25:58 +0000301 bootflow_scan_first(NULL, NULL, &iter, BOOTFLOWIF_ALL |
302 BOOTFLOWIF_SKIP_GLOBAL |
303 BOOTFLOWIF_ONLY_BOOTABLE, &bflow));
Simon Glassb255efc2022-04-24 23:31:24 -0600304 ut_asserteq(2, iter.num_methods);
305 ut_asserteq(0, iter.cur_method);
306 ut_asserteq(0, iter.part);
307 ut_asserteq(0, iter.max_part);
Simon Glassb71d7f72023-05-10 16:34:46 -0600308 ut_asserteq_str("extlinux", iter.method->name);
Simon Glassb255efc2022-04-24 23:31:24 -0600309 ut_asserteq(0, bflow.err);
310
311 /*
Simon Glassc8d37212022-07-30 15:52:34 -0600312 * This shows MEDIA even though there is none, since in
Simon Glassb255efc2022-04-24 23:31:24 -0600313 * bootdev_find_in_blk() we call part_get_info() which returns
314 * -EPROTONOSUPPORT. Ideally it would return -EEOPNOTSUPP and we would
315 * know.
316 */
317 ut_asserteq(BOOTFLOWST_MEDIA, bflow.state);
318
319 ut_asserteq(-EPROTONOSUPPORT, bootflow_scan_next(&iter, &bflow));
320 ut_asserteq(2, iter.num_methods);
321 ut_asserteq(1, iter.cur_method);
322 ut_asserteq(0, iter.part);
323 ut_asserteq(0, iter.max_part);
324 ut_asserteq_str("efi", iter.method->name);
325 ut_asserteq(0, bflow.err);
326 ut_asserteq(BOOTFLOWST_MEDIA, bflow.state);
327 bootflow_free(&bflow);
328
329 /* The next device is mmc1.bootdev - at first we use the whole device */
330 ut_asserteq(-ENOENT, bootflow_scan_next(&iter, &bflow));
331 ut_asserteq(2, iter.num_methods);
332 ut_asserteq(0, iter.cur_method);
333 ut_asserteq(0, iter.part);
334 ut_asserteq(0x1e, iter.max_part);
Simon Glassb71d7f72023-05-10 16:34:46 -0600335 ut_asserteq_str("extlinux", iter.method->name);
Simon Glassb255efc2022-04-24 23:31:24 -0600336 ut_asserteq(0, bflow.err);
337 ut_asserteq(BOOTFLOWST_MEDIA, bflow.state);
338 bootflow_free(&bflow);
339
340 ut_asserteq(-ENOENT, bootflow_scan_next(&iter, &bflow));
341 ut_asserteq(2, iter.num_methods);
342 ut_asserteq(1, iter.cur_method);
343 ut_asserteq(0, iter.part);
344 ut_asserteq(0x1e, iter.max_part);
345 ut_asserteq_str("efi", iter.method->name);
346 ut_asserteq(0, bflow.err);
347 ut_asserteq(BOOTFLOWST_MEDIA, bflow.state);
348 bootflow_free(&bflow);
349
350 /* Then more to partition 1 where we find something */
351 ut_assertok(bootflow_scan_next(&iter, &bflow));
352 ut_asserteq(2, iter.num_methods);
353 ut_asserteq(0, iter.cur_method);
354 ut_asserteq(1, iter.part);
355 ut_asserteq(0x1e, iter.max_part);
Simon Glassb71d7f72023-05-10 16:34:46 -0600356 ut_asserteq_str("extlinux", iter.method->name);
Simon Glassb255efc2022-04-24 23:31:24 -0600357 ut_asserteq(0, bflow.err);
358 ut_asserteq(BOOTFLOWST_READY, bflow.state);
359 bootflow_free(&bflow);
360
361 ut_asserteq(-ENOENT, bootflow_scan_next(&iter, &bflow));
362 ut_asserteq(2, iter.num_methods);
363 ut_asserteq(1, iter.cur_method);
364 ut_asserteq(1, iter.part);
365 ut_asserteq(0x1e, iter.max_part);
366 ut_asserteq_str("efi", iter.method->name);
367 ut_asserteq(0, bflow.err);
368 ut_asserteq(BOOTFLOWST_FS, bflow.state);
369 bootflow_free(&bflow);
370
Simon Glassf5e2df02023-01-17 10:47:41 -0700371 /* Then more to partition 2 which exists but is not bootable */
Simon Glass64cbc5c2023-01-17 10:47:42 -0700372 ut_asserteq(-EINVAL, bootflow_scan_next(&iter, &bflow));
Simon Glassb255efc2022-04-24 23:31:24 -0600373 ut_asserteq(2, iter.num_methods);
374 ut_asserteq(0, iter.cur_method);
375 ut_asserteq(2, iter.part);
376 ut_asserteq(0x1e, iter.max_part);
Simon Glassb71d7f72023-05-10 16:34:46 -0600377 ut_asserteq_str("extlinux", iter.method->name);
Simon Glassb255efc2022-04-24 23:31:24 -0600378 ut_asserteq(0, bflow.err);
Simon Glass64cbc5c2023-01-17 10:47:42 -0700379 ut_asserteq(BOOTFLOWST_MEDIA, bflow.state);
Simon Glassb255efc2022-04-24 23:31:24 -0600380 bootflow_free(&bflow);
381
382 bootflow_iter_uninit(&iter);
383
384 ut_assert_console_end();
385
386 return 0;
387}
Simon Glass129ba732024-10-19 09:21:58 -0600388BOOTSTD_TEST(bootflow_iter, UTF_DM | UTF_SCAN_FDT | UTF_CONSOLE);
Simon Glassb255efc2022-04-24 23:31:24 -0600389
Simon Glass90b643d2022-07-30 15:52:36 -0600390#if defined(CONFIG_SANDBOX) && defined(CONFIG_BOOTMETH_GLOBAL)
Simon Glassb255efc2022-04-24 23:31:24 -0600391/* Check using the system bootdev */
392static int bootflow_system(struct unit_test_state *uts)
393{
Simon Glassb9ff6482023-01-17 10:47:23 -0700394 struct udevice *bootstd, *dev;
Simon Glassb255efc2022-04-24 23:31:24 -0600395
AKASHI Takahiroe3e542d2024-01-17 13:39:42 +0900396 if (!IS_ENABLED(CONFIG_EFI_BOOTMGR))
Simon Glassc7599442022-10-20 18:22:49 -0600397 return -EAGAIN;
Simon Glassb9ff6482023-01-17 10:47:23 -0700398 ut_assertok(uclass_first_device_err(UCLASS_BOOTSTD, &bootstd));
Heinrich Schuchardtdc1f0062024-04-03 20:34:15 +0200399 ut_assertok(device_bind(bootstd, DM_DRIVER_GET(bootmeth_3efi_mgr),
Simon Glassb9ff6482023-01-17 10:47:23 -0700400 "efi_mgr", 0, ofnode_null(), &dev));
401 ut_assertok(device_probe(dev));
Simon Glass161e1e32022-07-30 15:52:22 -0600402 sandbox_set_fake_efi_mgr_dev(dev, true);
Simon Glassb255efc2022-04-24 23:31:24 -0600403
Simon Glassb255efc2022-04-24 23:31:24 -0600404 /* We should get a single 'bootmgr' method right at the end */
405 bootstd_clear_glob();
Simon Glasse4cf1062023-01-17 10:48:13 -0700406 ut_assertok(run_command("bootflow scan -lH", 0));
Simon Glasscc15e142022-07-30 15:52:27 -0600407 ut_assert_skip_to_line(
Simon Glassd465ad52023-08-24 13:55:39 -0600408 " 0 efi_mgr ready (none) 0 <NULL> ");
Simon Glasscc15e142022-07-30 15:52:27 -0600409 ut_assert_skip_to_line("No more bootdevs");
Simon Glassb9ff6482023-01-17 10:47:23 -0700410 ut_assert_skip_to_line("(2 bootflows, 2 valid)");
Simon Glassb255efc2022-04-24 23:31:24 -0600411 ut_assert_console_end();
412
413 return 0;
414}
Simon Glassf0425022024-08-22 07:57:54 -0600415BOOTSTD_TEST(bootflow_system, UTF_DM | UTF_SCAN_PDATA | UTF_SCAN_FDT |
416 UTF_CONSOLE);
Simon Glass90b643d2022-07-30 15:52:36 -0600417#endif
Simon Glassb255efc2022-04-24 23:31:24 -0600418
419/* Check disabling a bootmethod if it requests it */
420static int bootflow_iter_disable(struct unit_test_state *uts)
421{
422 struct udevice *bootstd, *dev;
423 struct bootflow_iter iter;
424 struct bootflow bflow;
425 int i;
426
427 /* Add the EFI bootmgr driver */
428 ut_assertok(uclass_first_device_err(UCLASS_BOOTSTD, &bootstd));
429 ut_assertok(device_bind_driver(bootstd, "bootmeth_sandbox", "sandbox",
430 &dev));
431
Simon Glassb255efc2022-04-24 23:31:24 -0600432 ut_assertok(bootstd_test_drop_bootdev_order(uts));
433
434 bootstd_clear_glob();
Simon Glass49ad1d82022-07-30 15:52:16 -0600435 ut_assertok(inject_response(uts));
Simon Glasse4cf1062023-01-17 10:48:13 -0700436 ut_assertok(run_command("bootflow scan -lbH", 0));
Simon Glassb255efc2022-04-24 23:31:24 -0600437
438 /* Try to boot the bootmgr flow, which will fail */
439 console_record_reset_enable();
Simon Glass5d3d44f2023-01-17 10:48:16 -0700440 ut_assertok(bootflow_scan_first(NULL, NULL, &iter, 0, &bflow));
Simon Glassb255efc2022-04-24 23:31:24 -0600441 ut_asserteq(3, iter.num_methods);
442 ut_asserteq_str("sandbox", iter.method->name);
Simon Glass49ad1d82022-07-30 15:52:16 -0600443 ut_assertok(inject_response(uts));
Simon Glassb255efc2022-04-24 23:31:24 -0600444 ut_asserteq(-ENOTSUPP, bootflow_run_boot(&iter, &bflow));
445
446 ut_assert_skip_to_line("Boot method 'sandbox' failed and will not be retried");
447 ut_assert_console_end();
448
449 /* Check that the sandbox bootmeth has been removed */
450 ut_asserteq(2, iter.num_methods);
451 for (i = 0; i < iter.num_methods; i++)
452 ut_assert(strcmp("sandbox", iter.method_order[i]->name));
453
454 return 0;
455}
Simon Glassf0425022024-08-22 07:57:54 -0600456BOOTSTD_TEST(bootflow_iter_disable, UTF_DM | UTF_SCAN_FDT | UTF_CONSOLE);
Simon Glassb255efc2022-04-24 23:31:24 -0600457
Simon Glassc8d37212022-07-30 15:52:34 -0600458/* Check 'bootflow scan' with a bootmeth ordering including a global bootmeth */
459static int bootflow_scan_glob_bootmeth(struct unit_test_state *uts)
460{
Simon Glass90b643d2022-07-30 15:52:36 -0600461 if (!IS_ENABLED(CONFIG_BOOTMETH_GLOBAL))
Simon Glassc7599442022-10-20 18:22:49 -0600462 return -EAGAIN;
Simon Glass90b643d2022-07-30 15:52:36 -0600463
Simon Glassc8d37212022-07-30 15:52:34 -0600464 ut_assertok(bootstd_test_drop_bootdev_order(uts));
465
466 /*
467 * Make sure that the -G flag makes the scan fail, since this is not
468 * supported when an ordering is provided
469 */
Simon Glassc8d37212022-07-30 15:52:34 -0600470 ut_assertok(bootmeth_set_order("efi firmware0"));
Simon Glasse4cf1062023-01-17 10:48:13 -0700471 ut_assertok(run_command("bootflow scan -lGH", 0));
Simon Glassc8d37212022-07-30 15:52:34 -0600472 ut_assert_nextline("Scanning for bootflows in all bootdevs");
473 ut_assert_nextline(
474 "Seq Method State Uclass Part Name Filename");
475 ut_assert_nextlinen("---");
476 ut_assert_nextlinen("---");
477 ut_assert_nextline("(0 bootflows, 0 valid)");
478 ut_assert_console_end();
479
Simon Glasse4cf1062023-01-17 10:48:13 -0700480 ut_assertok(run_command("bootflow scan -lH", 0));
Simon Glassc8d37212022-07-30 15:52:34 -0600481 ut_assert_nextline("Scanning for bootflows in all bootdevs");
482 ut_assert_nextline(
483 "Seq Method State Uclass Part Name Filename");
484 ut_assert_nextlinen("---");
485 ut_assert_nextline("Scanning global bootmeth 'firmware0':");
486 ut_assert_nextline("Scanning bootdev 'mmc2.bootdev':");
487 ut_assert_nextline("Scanning bootdev 'mmc1.bootdev':");
488 ut_assert_nextline("Scanning bootdev 'mmc0.bootdev':");
489 ut_assert_nextline("No more bootdevs");
490 ut_assert_nextlinen("---");
491 ut_assert_nextline("(0 bootflows, 0 valid)");
492 ut_assert_console_end();
493
494 return 0;
495}
Simon Glassf0425022024-08-22 07:57:54 -0600496BOOTSTD_TEST(bootflow_scan_glob_bootmeth, UTF_DM | UTF_SCAN_FDT |
497 UTF_CONSOLE);
Simon Glassc8d37212022-07-30 15:52:34 -0600498
Simon Glassb255efc2022-04-24 23:31:24 -0600499/* Check 'bootflow boot' to boot a selected bootflow */
500static int bootflow_cmd_boot(struct unit_test_state *uts)
501{
Simon Glassb255efc2022-04-24 23:31:24 -0600502 ut_assertok(run_command("bootdev select 1", 0));
503 ut_assert_console_end();
504 ut_assertok(run_command("bootflow scan", 0));
505 ut_assert_console_end();
506 ut_assertok(run_command("bootflow select 0", 0));
507 ut_assert_console_end();
Simon Glass49ad1d82022-07-30 15:52:16 -0600508
509 ut_assertok(inject_response(uts));
Simon Glassb255efc2022-04-24 23:31:24 -0600510 ut_asserteq(1, run_command("bootflow boot", 0));
511 ut_assert_nextline(
Simon Glassb71d7f72023-05-10 16:34:46 -0600512 "** Booting bootflow 'mmc1.bootdev.part_1' with extlinux");
Simon Glassb255efc2022-04-24 23:31:24 -0600513 ut_assert_nextline("Ignoring unknown command: ui");
514
515 /*
516 * We expect it to get through to boot although sandbox always returns
517 * -EFAULT as it cannot actually boot the kernel
518 */
519 ut_assert_skip_to_line("sandbox: continuing, as we cannot run Linux");
520 ut_assert_nextline("Boot failed (err=-14)");
521 ut_assert_console_end();
522
523 return 0;
524}
Simon Glassf0425022024-08-22 07:57:54 -0600525BOOTSTD_TEST(bootflow_cmd_boot, UTF_DM | UTF_SCAN_FDT | UTF_CONSOLE);
Simon Glassd2bc33ed2023-01-06 08:52:41 -0600526
Simon Glassd92bcc42023-01-06 08:52:42 -0600527/**
Simon Glassbb76a5c2023-08-24 13:55:40 -0600528 * prep_mmc_bootdev() - Set up an mmc bootdev so we can access other distros
Simon Glassd92bcc42023-01-06 08:52:42 -0600529 *
Simon Glass3ff8a9a2023-10-01 19:14:37 -0600530 * After calling this function, set std->bootdev_order to *@old_orderp to
531 * restore normal operation of bootstd (i.e. with the original bootdev order)
532 *
Simon Glassd92bcc42023-01-06 08:52:42 -0600533 * @uts: Unit test state
Simon Glass3ff8a9a2023-10-01 19:14:37 -0600534 * @mmc_dev: MMC device to use, e.g. "mmc4". Note that this must remain valid
535 * in the caller until
Mattijs Korpershoekd77f8152024-07-10 10:40:06 +0200536 * @bind_cros: true to bind the ChromiumOS and Android bootmeths
Simon Glass3ff8a9a2023-10-01 19:14:37 -0600537 * @old_orderp: Returns the original bootdev order, which must be restored
Simon Glassd92bcc42023-01-06 08:52:42 -0600538 * Returns 0 on success, -ve on failure
539 */
Simon Glassfff928c2023-08-24 13:55:41 -0600540static int prep_mmc_bootdev(struct unit_test_state *uts, const char *mmc_dev,
Mattijs Korpershoekd77f8152024-07-10 10:40:06 +0200541 bool bind_cros_android, const char ***old_orderp)
Simon Glassd2bc33ed2023-01-06 08:52:41 -0600542{
Simon Glass3ff8a9a2023-10-01 19:14:37 -0600543 static const char *order[] = {"mmc2", "mmc1", NULL, NULL};
Simon Glassd2bc33ed2023-01-06 08:52:41 -0600544 struct udevice *dev, *bootstd;
545 struct bootstd_priv *std;
546 const char **old_order;
Simon Glassbb76a5c2023-08-24 13:55:40 -0600547 ofnode root, node;
Simon Glassd2bc33ed2023-01-06 08:52:41 -0600548
Simon Glass3ff8a9a2023-10-01 19:14:37 -0600549 order[2] = mmc_dev;
550
Simon Glass64c63252024-11-07 14:31:49 -0700551 /* Enable the requested mmc node since we need a second bootflow */
Simon Glassbb76a5c2023-08-24 13:55:40 -0600552 root = oftree_root(oftree_default());
553 node = ofnode_find_subnode(root, mmc_dev);
554 ut_assert(ofnode_valid(node));
Simon Glassd2bc33ed2023-01-06 08:52:41 -0600555 ut_assertok(lists_bind_fdt(gd->dm_root, node, &dev, NULL, false));
556
557 /* Enable the script bootmeth too */
558 ut_assertok(uclass_first_device_err(UCLASS_BOOTSTD, &bootstd));
Simon Glass2f27e472023-08-19 16:49:35 -0600559 ut_assertok(device_bind(bootstd, DM_DRIVER_REF(bootmeth_2script),
Simon Glassa59d6d32024-10-19 09:21:50 -0600560 "script", 0, ofnode_null(), &dev));
Simon Glassd2bc33ed2023-01-06 08:52:41 -0600561
Simon Glassfff928c2023-08-24 13:55:41 -0600562 /* Enable the cros bootmeth if needed */
Mattijs Korpershoekd77f8152024-07-10 10:40:06 +0200563 if (IS_ENABLED(CONFIG_BOOTMETH_CROS) && bind_cros_android) {
Simon Glassfff928c2023-08-24 13:55:41 -0600564 ut_assertok(uclass_first_device_err(UCLASS_BOOTSTD, &bootstd));
565 ut_assertok(device_bind(bootstd, DM_DRIVER_REF(bootmeth_cros),
566 "cros", 0, ofnode_null(), &dev));
567 }
568
Mattijs Korpershoekd77f8152024-07-10 10:40:06 +0200569 /* Enable the android bootmeths if needed */
570 if (IS_ENABLED(CONFIG_BOOTMETH_ANDROID) && bind_cros_android) {
571 ut_assertok(uclass_first_device_err(UCLASS_BOOTSTD, &bootstd));
572 ut_assertok(device_bind(bootstd, DM_DRIVER_REF(bootmeth_android),
573 "android", 0, ofnode_null(), &dev));
574 }
575
Simon Glassbb76a5c2023-08-24 13:55:40 -0600576 /* Change the order to include the device */
Simon Glassd2bc33ed2023-01-06 08:52:41 -0600577 std = dev_get_priv(bootstd);
578 old_order = std->bootdev_order;
579 std->bootdev_order = order;
Simon Glass3ff8a9a2023-10-01 19:14:37 -0600580 *old_orderp = old_order;
581
582 return 0;
583}
584
585/**
586 * scan_mmc_bootdev() - Set up an mmc bootdev so we can access other distros
587 *
588 * @uts: Unit test state
589 * @mmc_dev: MMC device to use, e.g. "mmc4"
590 * @bind_cros: true to bind the ChromiumOS bootmeth
591 * Returns 0 on success, -ve on failure
592 */
593static int scan_mmc_bootdev(struct unit_test_state *uts, const char *mmc_dev,
594 bool bind_cros)
595{
596 struct bootstd_priv *std;
597 struct udevice *bootstd;
598 const char **old_order;
599
600 ut_assertok(prep_mmc_bootdev(uts, mmc_dev, bind_cros, &old_order));
Simon Glassd2bc33ed2023-01-06 08:52:41 -0600601
Simon Glassd2bc33ed2023-01-06 08:52:41 -0600602 ut_assertok(run_command("bootflow scan", 0));
603 ut_assert_console_end();
604
605 /* Restore the order used by the device tree */
Simon Glass3ff8a9a2023-10-01 19:14:37 -0600606 ut_assertok(uclass_first_device_err(UCLASS_BOOTSTD, &bootstd));
607 std = dev_get_priv(bootstd);
Simon Glassd2bc33ed2023-01-06 08:52:41 -0600608 std->bootdev_order = old_order;
609
Simon Glassd92bcc42023-01-06 08:52:42 -0600610 return 0;
611}
612
Simon Glassbb76a5c2023-08-24 13:55:40 -0600613/**
Mattijs Korpershoekd77f8152024-07-10 10:40:06 +0200614 * scan_mmc_android_bootdev() - Set up an mmc bootdev so we can access other
615 * distros. Android bootflow might print "ANDROID:*" while scanning
616 *
617 * @uts: Unit test state
618 * @mmc_dev: MMC device to use, e.g. "mmc4"
619 * Returns 0 on success, -ve on failure
620 */
621static int scan_mmc_android_bootdev(struct unit_test_state *uts, const char *mmc_dev)
622{
623 struct bootstd_priv *std;
624 struct udevice *bootstd;
625 const char **old_order;
626
627 ut_assertok(prep_mmc_bootdev(uts, mmc_dev, true, &old_order));
628
Mattijs Korpershoekd77f8152024-07-10 10:40:06 +0200629 ut_assertok(run_command("bootflow scan", 0));
630 /* Android bootflow might print one or two 'ANDROID:*' logs */
631 ut_check_skipline(uts);
632 ut_check_skipline(uts);
633 ut_assert_console_end();
634
635 /* Restore the order used by the device tree */
636 ut_assertok(uclass_first_device_err(UCLASS_BOOTSTD, &bootstd));
637 std = dev_get_priv(bootstd);
638 std->bootdev_order = old_order;
639
640 return 0;
641}
642
643/**
Simon Glass3ff8a9a2023-10-01 19:14:37 -0600644 * scan_mmc4_bootdev() - Set up the mmc4 bootdev so we can access a fake Armbian
Simon Glassbb76a5c2023-08-24 13:55:40 -0600645 *
646 * @uts: Unit test state
647 * Returns 0 on success, -ve on failure
648 */
Simon Glass3ff8a9a2023-10-01 19:14:37 -0600649static int scan_mmc4_bootdev(struct unit_test_state *uts)
Simon Glassbb76a5c2023-08-24 13:55:40 -0600650{
Simon Glass3ff8a9a2023-10-01 19:14:37 -0600651 ut_assertok(scan_mmc_bootdev(uts, "mmc4", false));
Simon Glassbb76a5c2023-08-24 13:55:40 -0600652
653 return 0;
654}
655
Simon Glassd92bcc42023-01-06 08:52:42 -0600656/* Check 'bootflow menu' to select a bootflow */
657static int bootflow_cmd_menu(struct unit_test_state *uts)
658{
Simon Glass6d5083b2023-10-01 19:14:38 -0600659 struct bootstd_priv *std;
Simon Glassd92bcc42023-01-06 08:52:42 -0600660 char prev[3];
661
Simon Glass6d5083b2023-10-01 19:14:38 -0600662 /* get access to the current bootflow */
663 ut_assertok(bootstd_get_priv(&std));
664
Simon Glass3ff8a9a2023-10-01 19:14:37 -0600665 ut_assertok(scan_mmc4_bootdev(uts));
Simon Glassd92bcc42023-01-06 08:52:42 -0600666
Simon Glassd2bc33ed2023-01-06 08:52:41 -0600667 /* Add keypresses to move to and select the second one in the list */
668 prev[0] = CTL_CH('n');
669 prev[1] = '\r';
670 prev[2] = '\0';
671 ut_asserteq(2, console_in_puts(prev));
672
673 ut_assertok(run_command("bootflow menu", 0));
674 ut_assert_nextline("Selected: Armbian");
Simon Glass6d5083b2023-10-01 19:14:38 -0600675 ut_assertnonnull(std->cur_bootflow);
676 ut_assert_console_end();
677
678 /* Check not selecting anything */
679 prev[0] = '\e';
680 prev[1] = '\0';
681 ut_asserteq(1, console_in_puts(prev));
682
683 ut_asserteq(1, run_command("bootflow menu", 0));
684 ut_assertnull(std->cur_bootflow);
685 ut_assert_nextline("Nothing chosen");
Simon Glassd2bc33ed2023-01-06 08:52:41 -0600686 ut_assert_console_end();
687
688 return 0;
689}
Simon Glassf0425022024-08-22 07:57:54 -0600690BOOTSTD_TEST(bootflow_cmd_menu, UTF_DM | UTF_SCAN_FDT | UTF_CONSOLE);
Simon Glassd92bcc42023-01-06 08:52:42 -0600691
Simon Glass9bf27862023-10-01 19:15:25 -0600692/* Check 'bootflow scan -m' to select a bootflow using a menu */
693static int bootflow_scan_menu(struct unit_test_state *uts)
694{
695 struct bootstd_priv *std;
696 const char **old_order, **new_order;
697 char prev[3];
698
699 /* get access to the current bootflow */
700 ut_assertok(bootstd_get_priv(&std));
701
702 ut_assertok(prep_mmc_bootdev(uts, "mmc4", false, &old_order));
703
704 /* Add keypresses to move to and select the second one in the list */
705 prev[0] = CTL_CH('n');
706 prev[1] = '\r';
707 prev[2] = '\0';
708 ut_asserteq(2, console_in_puts(prev));
709
710 ut_assertok(run_command("bootflow scan -lm", 0));
711 new_order = std->bootdev_order;
712 std->bootdev_order = old_order;
713
714 ut_assert_skip_to_line("No more bootdevs");
715 ut_assert_nextlinen("--");
716 ut_assert_nextline("(2 bootflows, 2 valid)");
717
718 ut_assert_nextline("Selected: Armbian");
719 ut_assertnonnull(std->cur_bootflow);
720 ut_assert_console_end();
721
722 /* Check not selecting anything */
723 prev[0] = '\e';
724 prev[1] = '\0';
725 ut_asserteq(1, console_in_puts(prev));
726
727 std->bootdev_order = new_order; /* Blue Monday */
728 ut_assertok(run_command("bootflow scan -lm", 0));
729 std->bootdev_order = old_order;
730
731 ut_assertnull(std->cur_bootflow);
732 ut_assert_skip_to_line("(2 bootflows, 2 valid)");
733 ut_assert_nextline("Nothing chosen");
734 ut_assert_console_end();
735
736 return 0;
737}
Simon Glass11fcfa32024-08-22 07:57:50 -0600738BOOTSTD_TEST(bootflow_scan_menu, UTF_DM | UTF_SCAN_FDT | UTF_CONSOLE);
Simon Glass9bf27862023-10-01 19:15:25 -0600739
740/* Check 'bootflow scan -mb' to select and boot a bootflow using a menu */
741static int bootflow_scan_menu_boot(struct unit_test_state *uts)
742{
743 struct bootstd_priv *std;
744 const char **old_order;
745 char prev[3];
746
747 /* get access to the current bootflow */
748 ut_assertok(bootstd_get_priv(&std));
749
750 ut_assertok(prep_mmc_bootdev(uts, "mmc4", false, &old_order));
751
752 /* Add keypresses to move to and select the second one in the list */
753 prev[0] = CTL_CH('n');
754 prev[1] = '\r';
755 prev[2] = '\0';
756 ut_asserteq(2, console_in_puts(prev));
757
758 ut_assertok(run_command("bootflow scan -lmb", 0));
759 std->bootdev_order = old_order;
760
761 ut_assert_skip_to_line("(2 bootflows, 2 valid)");
762
763 ut_assert_nextline("Selected: Armbian");
Francis Laniel5b64c452023-12-22 22:02:35 +0100764
765 if (gd->flags & GD_FLG_HUSH_OLD_PARSER) {
766 /*
767 * With old hush, despite booti failing to boot, i.e. returning
768 * CMD_RET_FAILURE, run_command() returns 0 which leads bootflow_boot(), as
769 * we are using bootmeth_script here, to return -EFAULT.
770 */
771 ut_assert_skip_to_line("Boot failed (err=-14)");
772 } else if (gd->flags & GD_FLG_HUSH_MODERN_PARSER) {
773 /*
774 * While with modern one, run_command() propagates CMD_RET_FAILURE returned
775 * by booti, so we get 1 here.
776 */
777 ut_assert_skip_to_line("Boot failed (err=1)");
778 }
Simon Glass9bf27862023-10-01 19:15:25 -0600779 ut_assertnonnull(std->cur_bootflow);
780 ut_assert_console_end();
781
782 return 0;
783}
Simon Glass11fcfa32024-08-22 07:57:50 -0600784BOOTSTD_TEST(bootflow_scan_menu_boot, UTF_DM | UTF_SCAN_FDT | UTF_CONSOLE);
Simon Glass9bf27862023-10-01 19:15:25 -0600785
Simon Glassba3d5372023-01-17 10:48:15 -0700786/* Check searching for a single bootdev using the hunters */
787static int bootflow_cmd_hunt_single(struct unit_test_state *uts)
788{
789 struct bootstd_priv *std;
790
791 /* get access to the used hunters */
792 ut_assertok(bootstd_get_priv(&std));
793
794 ut_assertok(bootstd_test_drop_bootdev_order(uts));
795
Simon Glassba3d5372023-01-17 10:48:15 -0700796 ut_assertok(run_command("bootflow scan -l mmc1", 0));
797 ut_assert_nextline("Scanning for bootflows with label 'mmc1'");
798 ut_assert_skip_to_line("(1 bootflow, 1 valid)");
799 ut_assert_console_end();
800
801 /* check that the hunter was used */
802 ut_asserteq(BIT(MMC_HUNTER) | BIT(1), std->hunters_used);
803
804 return 0;
805}
Simon Glassf0425022024-08-22 07:57:54 -0600806BOOTSTD_TEST(bootflow_cmd_hunt_single, UTF_DM | UTF_SCAN_FDT |
807 UTF_CONSOLE);
Simon Glassba3d5372023-01-17 10:48:15 -0700808
809/* Check searching for a uclass label using the hunters */
810static int bootflow_cmd_hunt_label(struct unit_test_state *uts)
811{
812 struct bootstd_priv *std;
813
814 /* get access to the used hunters */
815 ut_assertok(bootstd_get_priv(&std));
816
817 test_set_skip_delays(true);
818 test_set_eth_enable(false);
819 ut_assertok(bootstd_test_drop_bootdev_order(uts));
820
Simon Glassba3d5372023-01-17 10:48:15 -0700821 ut_assertok(run_command("bootflow scan -l mmc", 0));
822
823 /* check that the hunter was used */
824 ut_asserteq(BIT(MMC_HUNTER) | BIT(1), std->hunters_used);
825
826 /* check that we got the mmc1 bootflow */
827 ut_assert_nextline("Scanning for bootflows with label 'mmc'");
828 ut_assert_nextlinen("Seq");
829 ut_assert_nextlinen("---");
830 ut_assert_nextline("Hunting with: simple_bus");
831 ut_assert_nextline("Found 2 extension board(s).");
832 ut_assert_nextline("Hunting with: mmc");
833 ut_assert_nextline("Scanning bootdev 'mmc2.bootdev':");
834 ut_assert_nextline("Scanning bootdev 'mmc1.bootdev':");
835 ut_assert_nextline(
Simon Glassb71d7f72023-05-10 16:34:46 -0600836 " 0 extlinux ready mmc 1 mmc1.bootdev.part_1 /extlinux/extlinux.conf");
Simon Glassba3d5372023-01-17 10:48:15 -0700837 ut_assert_nextline("Scanning bootdev 'mmc0.bootdev':");
838 ut_assert_skip_to_line("(1 bootflow, 1 valid)");
839 ut_assert_console_end();
840
841 return 0;
842}
Simon Glassf0425022024-08-22 07:57:54 -0600843BOOTSTD_TEST(bootflow_cmd_hunt_label, UTF_DM | UTF_SCAN_FDT | UTF_CONSOLE);
Simon Glassba3d5372023-01-17 10:48:15 -0700844
Simon Glassd92bcc42023-01-06 08:52:42 -0600845/**
846 * check_font() - Check that the font size for an item matches expectations
847 *
848 * @uts: Unit test state
849 * @scn: Scene containing the text object
850 * @id: ID of the text object
851 * Returns 0 on success, -ve on failure
852 */
853static int check_font(struct unit_test_state *uts, struct scene *scn, uint id,
854 int font_size)
855{
856 struct scene_obj_txt *txt;
857
858 txt = scene_obj_find(scn, id, SCENEOBJT_TEXT);
859 ut_assertnonnull(txt);
860
861 ut_asserteq(font_size, txt->font_size);
862
863 return 0;
864}
865
866/* Check themes work with a bootflow menu */
867static int bootflow_menu_theme(struct unit_test_state *uts)
868{
869 const int font_size = 30;
870 struct scene *scn;
871 struct expo *exp;
872 ofnode node;
873 int i;
874
Marek Vasutabb772a2024-10-20 17:43:12 +0200875 if (!CONFIG_IS_ENABLED(BOOTSTD_MENU))
876 return -EAGAIN;
877
Simon Glass3ff8a9a2023-10-01 19:14:37 -0600878 ut_assertok(scan_mmc4_bootdev(uts));
Simon Glassd92bcc42023-01-06 08:52:42 -0600879
880 ut_assertok(bootflow_menu_new(&exp));
881 node = ofnode_path("/bootstd/theme");
882 ut_assert(ofnode_valid(node));
883 ut_assertok(bootflow_menu_apply_theme(exp, node));
884
885 scn = expo_lookup_scene_id(exp, MAIN);
886 ut_assertnonnull(scn);
887
888 /*
889 * Check that the txt objects have the correct font size from the
890 * device tree node: bootstd/theme
891 *
892 * Check both menu items, since there are two bootflows
893 */
894 ut_assertok(check_font(uts, scn, OBJ_PROMPT, font_size));
895 ut_assertok(check_font(uts, scn, OBJ_POINTER, font_size));
896 for (i = 0; i < 2; i++) {
897 ut_assertok(check_font(uts, scn, ITEM_DESC + i, font_size));
898 ut_assertok(check_font(uts, scn, ITEM_KEY + i, font_size));
899 ut_assertok(check_font(uts, scn, ITEM_LABEL + i, font_size));
900 }
901
902 expo_destroy(exp);
903
904 return 0;
905}
Simon Glassf0425022024-08-22 07:57:54 -0600906BOOTSTD_TEST(bootflow_menu_theme, UTF_DM | UTF_SCAN_FDT | UTF_CONSOLE);
Simon Glassa08adca2023-07-12 09:04:38 -0600907
908/**
909 * check_arg() - Check both the normal case and the buffer-overflow case
910 *
911 * @uts: Unit-test state
912 * @expect_ret: Expected return value (i.e. buffer length)
913 * @expect_str: String expected to be returned
914 * @buf: Buffer to use
915 * @from: Original cmdline to update
916 * @arg: Argument to update (e.g. "console")
917 * @val: Value to set (e.g. "ttyS2") or NULL to delete the argument if present,
918 * "" to set it to an empty value (e.g. "console=") and BOOTFLOWCL_EMPTY to add
919 * it without any value ("initrd")
920 */
921static int check_arg(struct unit_test_state *uts, int expect_ret,
922 const char *expect_str, char *buf, const char *from,
923 const char *arg, const char *val)
924{
925 /* check for writing outside the reported bounds */
926 buf[expect_ret] = '[';
927 ut_asserteq(expect_ret,
928 cmdline_set_arg(buf, expect_ret, from, arg, val, NULL));
929 ut_asserteq_str(expect_str, buf);
930 ut_asserteq('[', buf[expect_ret]);
931
932 /* do the test again but with one less byte in the buffer */
933 ut_asserteq(-E2BIG, cmdline_set_arg(buf, expect_ret - 1, from, arg,
934 val, NULL));
935
936 return 0;
937}
938
939/* Test of bootflow_cmdline_set_arg() */
940static int test_bootflow_cmdline_set(struct unit_test_state *uts)
941{
942 char buf[50];
943 const int size = sizeof(buf);
944
945 /*
946 * note that buffer-overflow tests are immediately each test case, just
947 * top keep the code together
948 */
949
950 /* add an arg that doesn't already exist, starting from empty */
951 ut_asserteq(-ENOENT, cmdline_set_arg(buf, size, NULL, "me", NULL,
952 NULL));
953
954 ut_assertok(check_arg(uts, 3, "me", buf, NULL, "me", BOOTFLOWCL_EMPTY));
955 ut_assertok(check_arg(uts, 4, "me=", buf, NULL, "me", ""));
956 ut_assertok(check_arg(uts, 8, "me=fred", buf, NULL, "me", "fred"));
957
958 /* add an arg that doesn't already exist, starting from non-empty */
959 ut_assertok(check_arg(uts, 11, "arg=123 me", buf, "arg=123", "me",
960 BOOTFLOWCL_EMPTY));
961 ut_assertok(check_arg(uts, 12, "arg=123 me=", buf, "arg=123", "me",
962 ""));
963 ut_assertok(check_arg(uts, 16, "arg=123 me=fred", buf, "arg=123", "me",
964 "fred"));
965
966 /* update an arg at the start */
967 ut_assertok(check_arg(uts, 1, "", buf, "arg=123", "arg", NULL));
968 ut_assertok(check_arg(uts, 4, "arg", buf, "arg=123", "arg",
969 BOOTFLOWCL_EMPTY));
970 ut_assertok(check_arg(uts, 5, "arg=", buf, "arg=123", "arg", ""));
971 ut_assertok(check_arg(uts, 6, "arg=1", buf, "arg=123", "arg", "1"));
972 ut_assertok(check_arg(uts, 9, "arg=1234", buf, "arg=123", "arg",
973 "1234"));
974
975 /* update an arg at the end */
976 ut_assertok(check_arg(uts, 5, "mary", buf, "mary arg=123", "arg",
977 NULL));
978 ut_assertok(check_arg(uts, 9, "mary arg", buf, "mary arg=123", "arg",
979 BOOTFLOWCL_EMPTY));
980 ut_assertok(check_arg(uts, 10, "mary arg=", buf, "mary arg=123", "arg",
981 ""));
982 ut_assertok(check_arg(uts, 11, "mary arg=1", buf, "mary arg=123", "arg",
983 "1"));
984 ut_assertok(check_arg(uts, 14, "mary arg=1234", buf, "mary arg=123",
985 "arg", "1234"));
986
987 /* update an arg in the middle */
988 ut_assertok(check_arg(uts, 16, "mary=abc john=2", buf,
989 "mary=abc arg=123 john=2", "arg", NULL));
990 ut_assertok(check_arg(uts, 20, "mary=abc arg john=2", buf,
991 "mary=abc arg=123 john=2", "arg",
992 BOOTFLOWCL_EMPTY));
993 ut_assertok(check_arg(uts, 21, "mary=abc arg= john=2", buf,
994 "mary=abc arg=123 john=2", "arg", ""));
995 ut_assertok(check_arg(uts, 22, "mary=abc arg=1 john=2", buf,
996 "mary=abc arg=123 john=2", "arg", "1"));
997 ut_assertok(check_arg(uts, 25, "mary=abc arg=1234 john=2", buf,
998 "mary=abc arg=123 john=2", "arg", "1234"));
999
1000 /* handle existing args with quotes */
1001 ut_assertok(check_arg(uts, 16, "mary=\"abc\" john", buf,
1002 "mary=\"abc\" arg=123 john", "arg", NULL));
1003
1004 /* handle existing args with quoted spaces */
1005 ut_assertok(check_arg(uts, 20, "mary=\"abc def\" john", buf,
1006 "mary=\"abc def\" arg=123 john", "arg", NULL));
1007
1008 ut_assertok(check_arg(uts, 34, "mary=\"abc def\" arg=123 john def=4",
1009 buf, "mary=\"abc def\" arg=123 john", "def",
1010 "4"));
1011
1012 /* quote at the start */
1013 ut_asserteq(-EBADF, cmdline_set_arg(buf, size,
1014 "mary=\"abc def\" arg=\"123 456\"",
1015 "arg", "\"4 5 6", NULL));
1016
1017 /* quote at the end */
1018 ut_asserteq(-EBADF, cmdline_set_arg(buf, size,
1019 "mary=\"abc def\" arg=\"123 456\"",
1020 "arg", "4 5 6\"", NULL));
1021
1022 /* quote in the middle */
1023 ut_asserteq(-EBADF, cmdline_set_arg(buf, size,
1024 "mary=\"abc def\" arg=\"123 456\"",
1025 "arg", "\"4 \"5 6\"", NULL));
1026
1027 /* handle updating a quoted arg */
1028 ut_assertok(check_arg(uts, 27, "mary=\"abc def\" arg=\"4 5 6\"", buf,
1029 "mary=\"abc def\" arg=\"123 456\"", "arg",
1030 "4 5 6"));
1031
1032 /* changing a quoted arg to a non-quoted arg */
1033 ut_assertok(check_arg(uts, 23, "mary=\"abc def\" arg=789", buf,
1034 "mary=\"abc def\" arg=\"123 456\"", "arg",
1035 "789"));
1036
1037 /* changing a non-quoted arg to a quoted arg */
1038 ut_assertok(check_arg(uts, 29, "mary=\"abc def\" arg=\"456 789\"", buf,
1039 "mary=\"abc def\" arg=123", "arg", "456 789"));
1040
1041 /* handling of spaces */
1042 ut_assertok(check_arg(uts, 8, "arg=123", buf, " ", "arg", "123"));
1043 ut_assertok(check_arg(uts, 8, "arg=123", buf, " ", "arg", "123"));
1044 ut_assertok(check_arg(uts, 13, "john arg=123", buf, " john ", "arg",
1045 "123"));
1046 ut_assertok(check_arg(uts, 13, "john arg=123", buf, " john arg=123 ",
1047 "arg", "123"));
1048 ut_assertok(check_arg(uts, 18, "john arg=123 mary", buf,
1049 " john arg=123 mary ", "arg", "123"));
1050
1051 /* unchanged arg */
1052 ut_assertok(check_arg(uts, 3, "me", buf, "me", "me", BOOTFLOWCL_EMPTY));
1053
1054 /* arg which starts with the same name */
1055 ut_assertok(check_arg(uts, 28, "mary=abc johnathon=2 john=3", buf,
1056 "mary=abc johnathon=2 john=1", "john", "3"));
1057
1058 return 0;
1059}
1060BOOTSTD_TEST(test_bootflow_cmdline_set, 0);
Simon Glass55a2da32023-07-12 09:04:39 -06001061
1062/* Test of bootflow_cmdline_set_arg() */
1063static int bootflow_set_arg(struct unit_test_state *uts)
1064{
1065 struct bootflow s_bflow, *bflow = &s_bflow;
1066 ulong mem_start;
1067
1068 ut_assertok(env_set("bootargs", NULL));
1069
1070 mem_start = ut_check_delta(0);
1071
1072 /* Do a simple sanity check. Rely on bootflow_cmdline() for the rest */
1073 bflow->cmdline = NULL;
1074 ut_assertok(bootflow_cmdline_set_arg(bflow, "fred", "123", false));
1075 ut_asserteq_str(bflow->cmdline, "fred=123");
1076
1077 ut_assertok(bootflow_cmdline_set_arg(bflow, "mary", "and here", false));
1078 ut_asserteq_str(bflow->cmdline, "fred=123 mary=\"and here\"");
1079
1080 ut_assertok(bootflow_cmdline_set_arg(bflow, "mary", NULL, false));
1081 ut_asserteq_str(bflow->cmdline, "fred=123");
1082 ut_assertok(bootflow_cmdline_set_arg(bflow, "fred", NULL, false));
1083 ut_asserteq_ptr(bflow->cmdline, NULL);
1084
1085 ut_asserteq(0, ut_check_delta(mem_start));
1086
1087 ut_assertok(bootflow_cmdline_set_arg(bflow, "mary", "here", true));
1088 ut_asserteq_str("mary=here", env_get("bootargs"));
1089 ut_assertok(env_set("bootargs", NULL));
1090
1091 return 0;
1092}
1093BOOTSTD_TEST(bootflow_set_arg, 0);
1094
1095/* Test of bootflow_cmdline_get_arg() */
1096static int bootflow_cmdline_get(struct unit_test_state *uts)
1097{
1098 int pos;
1099
1100 /* empty string */
1101 ut_asserteq(-ENOENT, cmdline_get_arg("", "fred", &pos));
1102
1103 /* arg with empty value */
1104 ut_asserteq(0, cmdline_get_arg("fred= mary", "fred", &pos));
1105 ut_asserteq(5, pos);
1106
1107 /* arg with a value */
1108 ut_asserteq(2, cmdline_get_arg("fred=23", "fred", &pos));
1109 ut_asserteq(5, pos);
1110
1111 /* arg with a value */
1112 ut_asserteq(3, cmdline_get_arg("mary=1 fred=234", "fred", &pos));
1113 ut_asserteq(12, pos);
1114
1115 /* arg with a value, after quoted arg */
1116 ut_asserteq(3, cmdline_get_arg("mary=\"1 2\" fred=234", "fred", &pos));
1117 ut_asserteq(16, pos);
1118
1119 /* arg in the middle */
1120 ut_asserteq(0, cmdline_get_arg("mary=\"1 2\" fred john=23", "fred",
1121 &pos));
1122 ut_asserteq(15, pos);
1123
1124 /* quoted arg */
1125 ut_asserteq(3, cmdline_get_arg("mary=\"1 2\" fred=\"3 4\" john=23",
1126 "fred", &pos));
1127 ut_asserteq(17, pos);
1128
1129 /* args starting with the same prefix */
1130 ut_asserteq(1, cmdline_get_arg("mary=abc johnathon=3 john=1", "john",
1131 &pos));
1132 ut_asserteq(26, pos);
1133
1134 return 0;
1135}
1136BOOTSTD_TEST(bootflow_cmdline_get, 0);
1137
1138static int bootflow_cmdline(struct unit_test_state *uts)
1139{
1140 ut_assertok(run_command("bootflow scan mmc", 0));
1141 ut_assertok(run_command("bootflow sel 0", 0));
Simon Glass55a2da32023-07-12 09:04:39 -06001142
1143 ut_asserteq(1, run_command("bootflow cmdline get fred", 0));
1144 ut_assert_nextline("Argument not found");
1145 ut_assert_console_end();
1146
1147 ut_asserteq(0, run_command("bootflow cmdline set fred 123", 0));
1148 ut_asserteq(0, run_command("bootflow cmdline get fred", 0));
1149 ut_assert_nextline("123");
1150
1151 ut_asserteq(0, run_command("bootflow cmdline set mary abc", 0));
1152 ut_asserteq(0, run_command("bootflow cmdline get mary", 0));
1153 ut_assert_nextline("abc");
1154
1155 ut_asserteq(0, run_command("bootflow cmdline delete fred", 0));
1156 ut_asserteq(1, run_command("bootflow cmdline get fred", 0));
1157 ut_assert_nextline("Argument not found");
1158
1159 ut_asserteq(0, run_command("bootflow cmdline clear mary", 0));
1160 ut_asserteq(0, run_command("bootflow cmdline get mary", 0));
1161 ut_assert_nextline_empty();
1162
Simon Glass7a164f82023-11-29 10:31:19 -07001163 ut_asserteq(0, run_command("bootflow cmdline set mary abc", 0));
1164 ut_asserteq(0, run_command("bootflow cmdline set mary", 0));
Simon Glass55a2da32023-07-12 09:04:39 -06001165 ut_assert_console_end();
1166
1167 return 0;
1168}
Simon Glassf0425022024-08-22 07:57:54 -06001169BOOTSTD_TEST(bootflow_cmdline, UTF_CONSOLE);
Simon Glassfff928c2023-08-24 13:55:41 -06001170
Simon Glassa61057f2023-10-25 07:17:36 +13001171/* test a few special changes to a long command line */
1172static int bootflow_cmdline_special(struct unit_test_state *uts)
1173{
1174 char buf[500];
1175 int pos;
1176
1177 /*
1178 * check handling of an argument which has an embedded '=', as well as
1179 * handling of a argument which partially matches ("ro" and "root")
1180 */
1181 ut_asserteq(32, cmdline_set_arg(
1182 buf, sizeof(buf),
1183 "loglevel=7 root=PARTUUID=d68352e3 rootwait ro noinitrd",
1184 "root", NULL, &pos));
1185 ut_asserteq_str("loglevel=7 rootwait ro noinitrd", buf);
1186
1187 return 0;
1188}
1189BOOTSTD_TEST(bootflow_cmdline_special, 0);
1190
Simon Glassfff928c2023-08-24 13:55:41 -06001191/* Test ChromiumOS bootmeth */
1192static int bootflow_cros(struct unit_test_state *uts)
1193{
Simon Glass3ff8a9a2023-10-01 19:14:37 -06001194 ut_assertok(scan_mmc_bootdev(uts, "mmc5", true));
Simon Glassfff928c2023-08-24 13:55:41 -06001195 ut_assertok(run_command("bootflow list", 0));
1196
1197 ut_assert_nextlinen("Showing all");
1198 ut_assert_nextlinen("Seq");
1199 ut_assert_nextlinen("---");
1200 ut_assert_nextlinen(" 0 extlinux");
Simon Glassd7d3a972023-08-24 13:55:45 -06001201 ut_assert_nextlinen(" 1 cros ready mmc 2 mmc5.bootdev.part_2 ");
1202 ut_assert_nextlinen(" 2 cros ready mmc 4 mmc5.bootdev.part_4 ");
Simon Glassfff928c2023-08-24 13:55:41 -06001203 ut_assert_nextlinen("---");
Simon Glassd7d3a972023-08-24 13:55:45 -06001204 ut_assert_skip_to_line("(3 bootflows, 3 valid)");
Simon Glassfff928c2023-08-24 13:55:41 -06001205
Simon Glassc6a52e72024-11-15 16:19:23 -07001206 ut_assertok(run_command("bootstd images", 0));
1207 ut_assert_nextlinen("Seq");
1208 ut_assert_nextlinen("---");
1209 ut_assert_nextlinen(" 0 mmc1.bootdev.part_1 extlinux_cfg");
1210 ut_assert_nextlinen(" 1 mmc5.bootdev.part_2 x86_setup");
1211 ut_assert_nextlinen(" 1 mmc5.bootdev.part_2 cmdline");
1212 ut_assert_nextlinen(" 1 mmc5.bootdev.part_2 kernel - 4000 kernel");
1213 ut_assert_nextlinen(" 2 mmc5.bootdev.part_4 x86_setup");
1214 ut_assert_nextlinen(" 2 mmc5.bootdev.part_4 cmdline");
1215 ut_assert_nextlinen(" 2 mmc5.bootdev.part_4 kernel - 4000 kernel");
1216 ut_assert_nextlinen("---");
1217 ut_assert_nextline("(7 images)");
1218
Simon Glassfff928c2023-08-24 13:55:41 -06001219 ut_assert_console_end();
1220
1221 return 0;
1222}
Mattijs Korpershoek33342f02024-11-22 15:11:34 +01001223BOOTSTD_TEST(bootflow_cros, UTF_CONSOLE | UTF_DM | UTF_SCAN_FDT);
Mattijs Korpershoekd77f8152024-07-10 10:40:06 +02001224
Guillaume La Roque368ad9e2024-11-26 09:06:13 +01001225/* Test Android bootmeth with boot image version 4 */
1226static int bootflow_android_image_v4(struct unit_test_state *uts)
Mattijs Korpershoekd77f8152024-07-10 10:40:06 +02001227{
1228 if (!IS_ENABLED(CONFIG_BOOTMETH_ANDROID))
1229 return -EAGAIN;
1230
1231 ut_assertok(scan_mmc_android_bootdev(uts, "mmc7"));
1232 ut_assertok(run_command("bootflow list", 0));
1233
1234 ut_assert_nextlinen("Showing all");
1235 ut_assert_nextlinen("Seq");
1236 ut_assert_nextlinen("---");
1237 ut_assert_nextlinen(" 0 extlinux");
1238 ut_assert_nextlinen(" 1 android ready mmc 0 mmc7.bootdev.whole ");
1239 ut_assert_nextlinen("---");
1240 ut_assert_skip_to_line("(2 bootflows, 2 valid)");
1241
1242 ut_assert_console_end();
1243
1244 return 0;
1245}
Guillaume La Roque368ad9e2024-11-26 09:06:13 +01001246BOOTSTD_TEST(bootflow_android_image_v4, UTF_CONSOLE | UTF_DM | UTF_SCAN_FDT);
1247
1248/* Test Android bootmeth with boot image version 2 */
1249static int bootflow_android_image_v2(struct unit_test_state *uts)
1250{
1251 if (!IS_ENABLED(CONFIG_BOOTMETH_ANDROID))
1252 return -EAGAIN;
1253
1254 ut_assertok(scan_mmc_android_bootdev(uts, "mmc8"));
1255 ut_assertok(run_command("bootflow list", 0));
1256
1257 ut_assert_nextlinen("Showing all");
1258 ut_assert_nextlinen("Seq");
1259 ut_assert_nextlinen("---");
1260 ut_assert_nextlinen(" 0 extlinux");
1261 ut_assert_nextlinen(" 1 android ready mmc 0 mmc8.bootdev.whole ");
1262 ut_assert_nextlinen("---");
1263 ut_assert_skip_to_line("(2 bootflows, 2 valid)");
1264
1265 ut_assert_console_end();
1266
1267 return 0;
1268}
1269BOOTSTD_TEST(bootflow_android_image_v2, UTF_CONSOLE | UTF_DM | UTF_SCAN_FDT);
Simon Glass4f378de2024-11-07 14:31:50 -07001270
1271/* Test EFI bootmeth */
1272static int bootflow_efi(struct unit_test_state *uts)
1273{
1274 static const char *order[] = {"mmc1", "usb", NULL};
1275 struct bootstd_priv *std;
1276 struct udevice *bootstd;
1277 const char **old_order;
1278
1279 ut_assertok(uclass_first_device_err(UCLASS_BOOTSTD, &bootstd));
1280 std = dev_get_priv(bootstd);
1281 old_order = std->bootdev_order;
1282 std->bootdev_order = order;
1283
1284 /* disable ethernet since the hunter will run dhcp */
1285 test_set_eth_enable(false);
1286
1287 /* make USB scan without delays */
1288 test_set_skip_delays(true);
1289
1290 bootstd_reset_usb();
1291
1292 ut_assertok(run_command("bootflow scan", 0));
1293 ut_assert_skip_to_line(
Jerome Forissier219dade2025-04-18 16:09:41 +02001294 "Bus usb@1: 5 USB Device(s) found");
Simon Glass4f378de2024-11-07 14:31:50 -07001295
1296 ut_assertok(run_command("bootflow list", 0));
1297
1298 ut_assert_nextlinen("Showing all");
1299 ut_assert_nextlinen("Seq");
1300 ut_assert_nextlinen("---");
1301 ut_assert_nextlinen(" 0 extlinux");
1302 ut_assert_nextlinen(
1303 " 1 efi ready usb_mass_ 1 usb_mass_storage.lun0.boo /EFI/BOOT/BOOTSBOX.EFI");
1304 ut_assert_nextlinen("---");
1305 ut_assert_skip_to_line("(2 bootflows, 2 valid)");
1306 ut_assert_console_end();
1307
1308 ut_assertok(run_command("bootflow select 1", 0));
1309 ut_assert_console_end();
1310
1311 systab.fw_vendor = test_vendor;
1312
1313 ut_asserteq(1, run_command("bootflow boot", 0));
1314 ut_assert_nextline(
1315 "** Booting bootflow 'usb_mass_storage.lun0.bootdev.part_1' with efi");
1316 if (IS_ENABLED(CONFIG_LOGF_FUNC))
1317 ut_assert_skip_to_line(" efi_run_image() Booting /\\EFI\\BOOT\\BOOTSBOX.EFI");
1318 else
1319 ut_assert_skip_to_line("Booting /\\EFI\\BOOT\\BOOTSBOX.EFI");
1320
1321 /* TODO: Why the \r ? */
1322 ut_assert_nextline("U-Boot test app for EFI_LOADER\r");
1323 ut_assert_nextline("Exiting test app");
1324 ut_assert_nextline("Boot failed (err=-14)");
1325
1326 ut_assert_console_end();
1327
1328 ut_assertok(bootstd_test_drop_bootdev_order(uts));
1329
1330 return 0;
1331}
1332BOOTSTD_TEST(bootflow_efi, UTF_CONSOLE);
Simon Glassc6a52e72024-11-15 16:19:23 -07001333
1334/* Check 'bootflow scan' provides a list of images */
1335static int bootstd_images(struct unit_test_state *uts)
1336{
1337 static const char *order[] = {"mmc2", "mmc1", "mmc4", "mmc5", NULL};
1338 const struct legacy_img_hdr *hdr;
1339 const struct bootflow_img *img;
1340 const struct bootflow *bflow;
1341 struct bootstd_priv *std;
1342 const char **old_order;
1343 struct udevice *dev;
1344 ofnode root, node;
1345 ulong data, len;
1346 char *ptr;
1347
1348 /* get access to the current bootflow */
1349 ut_assertok(bootstd_get_priv(&std));
1350
1351 ut_assertok(prep_mmc_bootdev(uts, "mmc4", true, &old_order));
1352
1353 /* bind mmc5 too, for cros */
1354 root = oftree_root(oftree_default());
1355 node = ofnode_find_subnode(root, "mmc5");
1356 ut_assert(ofnode_valid(node));
1357 ut_assertok(lists_bind_fdt(gd->dm_root, node, &dev, NULL, false));
1358
1359 std->bootdev_order = order;
1360 ut_assertok(run_command("bootflow scan", 0));
1361 ut_assert_console_end();
1362 std->bootdev_order = old_order;
1363
1364 ut_assertok(run_command("bootflow list", 0));
1365 ut_assert_skip_to_line("(4 bootflows, 4 valid)");
1366
1367 ut_assertok(run_command("bootstd images", 0));
1368 ut_assert_nextlinen("Seq");
1369 ut_assert_nextlinen("---");
1370 ut_assert_nextlinen(" 0 mmc1.bootdev.part_1 extlinux_cfg");
1371 ut_assert_nextlinen(" 1 mmc4.bootdev.part_1 script");
1372 ut_assert_nextlinen(" 1 mmc4.bootdev.part_1 logo");
1373 ut_assert_nextlinen(" 2 mmc5.bootdev.part_2 x86_setup");
1374 ut_assert_nextlinen(" 2 mmc5.bootdev.part_2 cmdline");
1375 ut_assert_nextlinen(" 2 mmc5.bootdev.part_2 kernel -");
1376 ut_assert_nextlinen(" 3 mmc5.bootdev.part_4 x86_setup");
1377 ut_assert_nextlinen(" 3 mmc5.bootdev.part_4 cmdline");
1378 ut_assert_nextlinen(" 3 mmc5.bootdev.part_4 kernel -");
1379 ut_assert_nextlinen("---");
1380 ut_assert_nextline("(9 images)");
1381
1382 /* check the first image */
1383 bflow = alist_get(&std->bootflows, 0, struct bootflow);
1384 img = alist_get(&bflow->images, 0, struct bootflow_img);
1385 ut_asserteq_strn("# extlinux.conf", map_sysmem(img->addr, 0));
1386
1387 /* check the second image */
1388 bflow = alist_get(&std->bootflows, 1, struct bootflow);
1389 img = alist_get(&bflow->images, 0, struct bootflow_img);
1390
1391 /* this is the length of the script in bytes */
1392 hdr = map_sysmem(img->addr, 0);
1393 image_multi_getimg(hdr, 0, &data, &len);
1394 ptr = (void *)data;
1395 ut_asserteq_strn("# DO NOT EDIT THIS FILE", ptr);
1396
1397 /* check the ChromiumOS images */
1398 bflow = alist_get(&std->bootflows, 2, struct bootflow);
1399 img = alist_get(&bflow->images, 1, struct bootflow_img);
1400 ptr = map_sysmem(img->addr, 0);
1401 ut_asserteq_strn("BOOT_IMAGE=/vmlinuz-5.15.0-121-generic root=", ptr);
1402
1403 /*
1404 * the x86 setup is not a real binary, so just check that it is empty,
1405 * so that if this changes in the future someone will notice and update
1406 * this test
1407 */
1408 img = alist_get(&bflow->images, 0, struct bootflow_img);
1409 ptr = map_sysmem(img->addr, 0);
1410 ut_asserteq(0, *(ulong *)ptr);
1411
1412 ut_assert_console_end();
1413
1414 return 0;
1415}
1416BOOTSTD_TEST(bootstd_images, UTF_CONSOLE);