blob: ea1a994fd3d21b9ebf73ba2d755a262b8280d070 [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
Simon Glass9ef02aa2025-05-02 08:46:37 -0600861 ut_asserteq(font_size, txt->gen.font_size);
Simon Glassd92bcc42023-01-06 08:52:42 -0600862
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));
Simon Glassd9da19a2025-05-02 08:46:28 -0600881 ut_assertok(bootflow_menu_add_all(exp));
Simon Glassd92bcc42023-01-06 08:52:42 -0600882 node = ofnode_path("/bootstd/theme");
883 ut_assert(ofnode_valid(node));
884 ut_assertok(bootflow_menu_apply_theme(exp, node));
885
886 scn = expo_lookup_scene_id(exp, MAIN);
887 ut_assertnonnull(scn);
888
889 /*
890 * Check that the txt objects have the correct font size from the
891 * device tree node: bootstd/theme
892 *
893 * Check both menu items, since there are two bootflows
894 */
895 ut_assertok(check_font(uts, scn, OBJ_PROMPT, font_size));
896 ut_assertok(check_font(uts, scn, OBJ_POINTER, font_size));
897 for (i = 0; i < 2; i++) {
898 ut_assertok(check_font(uts, scn, ITEM_DESC + i, font_size));
899 ut_assertok(check_font(uts, scn, ITEM_KEY + i, font_size));
900 ut_assertok(check_font(uts, scn, ITEM_LABEL + i, font_size));
901 }
902
903 expo_destroy(exp);
904
905 return 0;
906}
Simon Glassf0425022024-08-22 07:57:54 -0600907BOOTSTD_TEST(bootflow_menu_theme, UTF_DM | UTF_SCAN_FDT | UTF_CONSOLE);
Simon Glassa08adca2023-07-12 09:04:38 -0600908
909/**
910 * check_arg() - Check both the normal case and the buffer-overflow case
911 *
912 * @uts: Unit-test state
913 * @expect_ret: Expected return value (i.e. buffer length)
914 * @expect_str: String expected to be returned
915 * @buf: Buffer to use
916 * @from: Original cmdline to update
917 * @arg: Argument to update (e.g. "console")
918 * @val: Value to set (e.g. "ttyS2") or NULL to delete the argument if present,
919 * "" to set it to an empty value (e.g. "console=") and BOOTFLOWCL_EMPTY to add
920 * it without any value ("initrd")
921 */
922static int check_arg(struct unit_test_state *uts, int expect_ret,
923 const char *expect_str, char *buf, const char *from,
924 const char *arg, const char *val)
925{
926 /* check for writing outside the reported bounds */
927 buf[expect_ret] = '[';
928 ut_asserteq(expect_ret,
929 cmdline_set_arg(buf, expect_ret, from, arg, val, NULL));
930 ut_asserteq_str(expect_str, buf);
931 ut_asserteq('[', buf[expect_ret]);
932
933 /* do the test again but with one less byte in the buffer */
934 ut_asserteq(-E2BIG, cmdline_set_arg(buf, expect_ret - 1, from, arg,
935 val, NULL));
936
937 return 0;
938}
939
940/* Test of bootflow_cmdline_set_arg() */
941static int test_bootflow_cmdline_set(struct unit_test_state *uts)
942{
943 char buf[50];
944 const int size = sizeof(buf);
945
946 /*
947 * note that buffer-overflow tests are immediately each test case, just
948 * top keep the code together
949 */
950
951 /* add an arg that doesn't already exist, starting from empty */
952 ut_asserteq(-ENOENT, cmdline_set_arg(buf, size, NULL, "me", NULL,
953 NULL));
954
955 ut_assertok(check_arg(uts, 3, "me", buf, NULL, "me", BOOTFLOWCL_EMPTY));
956 ut_assertok(check_arg(uts, 4, "me=", buf, NULL, "me", ""));
957 ut_assertok(check_arg(uts, 8, "me=fred", buf, NULL, "me", "fred"));
958
959 /* add an arg that doesn't already exist, starting from non-empty */
960 ut_assertok(check_arg(uts, 11, "arg=123 me", buf, "arg=123", "me",
961 BOOTFLOWCL_EMPTY));
962 ut_assertok(check_arg(uts, 12, "arg=123 me=", buf, "arg=123", "me",
963 ""));
964 ut_assertok(check_arg(uts, 16, "arg=123 me=fred", buf, "arg=123", "me",
965 "fred"));
966
967 /* update an arg at the start */
968 ut_assertok(check_arg(uts, 1, "", buf, "arg=123", "arg", NULL));
969 ut_assertok(check_arg(uts, 4, "arg", buf, "arg=123", "arg",
970 BOOTFLOWCL_EMPTY));
971 ut_assertok(check_arg(uts, 5, "arg=", buf, "arg=123", "arg", ""));
972 ut_assertok(check_arg(uts, 6, "arg=1", buf, "arg=123", "arg", "1"));
973 ut_assertok(check_arg(uts, 9, "arg=1234", buf, "arg=123", "arg",
974 "1234"));
975
976 /* update an arg at the end */
977 ut_assertok(check_arg(uts, 5, "mary", buf, "mary arg=123", "arg",
978 NULL));
979 ut_assertok(check_arg(uts, 9, "mary arg", buf, "mary arg=123", "arg",
980 BOOTFLOWCL_EMPTY));
981 ut_assertok(check_arg(uts, 10, "mary arg=", buf, "mary arg=123", "arg",
982 ""));
983 ut_assertok(check_arg(uts, 11, "mary arg=1", buf, "mary arg=123", "arg",
984 "1"));
985 ut_assertok(check_arg(uts, 14, "mary arg=1234", buf, "mary arg=123",
986 "arg", "1234"));
987
988 /* update an arg in the middle */
989 ut_assertok(check_arg(uts, 16, "mary=abc john=2", buf,
990 "mary=abc arg=123 john=2", "arg", NULL));
991 ut_assertok(check_arg(uts, 20, "mary=abc arg john=2", buf,
992 "mary=abc arg=123 john=2", "arg",
993 BOOTFLOWCL_EMPTY));
994 ut_assertok(check_arg(uts, 21, "mary=abc arg= john=2", buf,
995 "mary=abc arg=123 john=2", "arg", ""));
996 ut_assertok(check_arg(uts, 22, "mary=abc arg=1 john=2", buf,
997 "mary=abc arg=123 john=2", "arg", "1"));
998 ut_assertok(check_arg(uts, 25, "mary=abc arg=1234 john=2", buf,
999 "mary=abc arg=123 john=2", "arg", "1234"));
1000
1001 /* handle existing args with quotes */
1002 ut_assertok(check_arg(uts, 16, "mary=\"abc\" john", buf,
1003 "mary=\"abc\" arg=123 john", "arg", NULL));
1004
1005 /* handle existing args with quoted spaces */
1006 ut_assertok(check_arg(uts, 20, "mary=\"abc def\" john", buf,
1007 "mary=\"abc def\" arg=123 john", "arg", NULL));
1008
1009 ut_assertok(check_arg(uts, 34, "mary=\"abc def\" arg=123 john def=4",
1010 buf, "mary=\"abc def\" arg=123 john", "def",
1011 "4"));
1012
1013 /* quote at the start */
1014 ut_asserteq(-EBADF, cmdline_set_arg(buf, size,
1015 "mary=\"abc def\" arg=\"123 456\"",
1016 "arg", "\"4 5 6", NULL));
1017
1018 /* quote at the end */
1019 ut_asserteq(-EBADF, cmdline_set_arg(buf, size,
1020 "mary=\"abc def\" arg=\"123 456\"",
1021 "arg", "4 5 6\"", NULL));
1022
1023 /* quote in the middle */
1024 ut_asserteq(-EBADF, cmdline_set_arg(buf, size,
1025 "mary=\"abc def\" arg=\"123 456\"",
1026 "arg", "\"4 \"5 6\"", NULL));
1027
1028 /* handle updating a quoted arg */
1029 ut_assertok(check_arg(uts, 27, "mary=\"abc def\" arg=\"4 5 6\"", buf,
1030 "mary=\"abc def\" arg=\"123 456\"", "arg",
1031 "4 5 6"));
1032
1033 /* changing a quoted arg to a non-quoted arg */
1034 ut_assertok(check_arg(uts, 23, "mary=\"abc def\" arg=789", buf,
1035 "mary=\"abc def\" arg=\"123 456\"", "arg",
1036 "789"));
1037
1038 /* changing a non-quoted arg to a quoted arg */
1039 ut_assertok(check_arg(uts, 29, "mary=\"abc def\" arg=\"456 789\"", buf,
1040 "mary=\"abc def\" arg=123", "arg", "456 789"));
1041
1042 /* handling of spaces */
1043 ut_assertok(check_arg(uts, 8, "arg=123", buf, " ", "arg", "123"));
1044 ut_assertok(check_arg(uts, 8, "arg=123", buf, " ", "arg", "123"));
1045 ut_assertok(check_arg(uts, 13, "john arg=123", buf, " john ", "arg",
1046 "123"));
1047 ut_assertok(check_arg(uts, 13, "john arg=123", buf, " john arg=123 ",
1048 "arg", "123"));
1049 ut_assertok(check_arg(uts, 18, "john arg=123 mary", buf,
1050 " john arg=123 mary ", "arg", "123"));
1051
1052 /* unchanged arg */
1053 ut_assertok(check_arg(uts, 3, "me", buf, "me", "me", BOOTFLOWCL_EMPTY));
1054
1055 /* arg which starts with the same name */
1056 ut_assertok(check_arg(uts, 28, "mary=abc johnathon=2 john=3", buf,
1057 "mary=abc johnathon=2 john=1", "john", "3"));
1058
1059 return 0;
1060}
1061BOOTSTD_TEST(test_bootflow_cmdline_set, 0);
Simon Glass55a2da32023-07-12 09:04:39 -06001062
1063/* Test of bootflow_cmdline_set_arg() */
1064static int bootflow_set_arg(struct unit_test_state *uts)
1065{
1066 struct bootflow s_bflow, *bflow = &s_bflow;
1067 ulong mem_start;
1068
1069 ut_assertok(env_set("bootargs", NULL));
1070
1071 mem_start = ut_check_delta(0);
1072
1073 /* Do a simple sanity check. Rely on bootflow_cmdline() for the rest */
1074 bflow->cmdline = NULL;
1075 ut_assertok(bootflow_cmdline_set_arg(bflow, "fred", "123", false));
1076 ut_asserteq_str(bflow->cmdline, "fred=123");
1077
1078 ut_assertok(bootflow_cmdline_set_arg(bflow, "mary", "and here", false));
1079 ut_asserteq_str(bflow->cmdline, "fred=123 mary=\"and here\"");
1080
1081 ut_assertok(bootflow_cmdline_set_arg(bflow, "mary", NULL, false));
1082 ut_asserteq_str(bflow->cmdline, "fred=123");
1083 ut_assertok(bootflow_cmdline_set_arg(bflow, "fred", NULL, false));
1084 ut_asserteq_ptr(bflow->cmdline, NULL);
1085
1086 ut_asserteq(0, ut_check_delta(mem_start));
1087
1088 ut_assertok(bootflow_cmdline_set_arg(bflow, "mary", "here", true));
1089 ut_asserteq_str("mary=here", env_get("bootargs"));
1090 ut_assertok(env_set("bootargs", NULL));
1091
1092 return 0;
1093}
1094BOOTSTD_TEST(bootflow_set_arg, 0);
1095
1096/* Test of bootflow_cmdline_get_arg() */
1097static int bootflow_cmdline_get(struct unit_test_state *uts)
1098{
1099 int pos;
1100
1101 /* empty string */
1102 ut_asserteq(-ENOENT, cmdline_get_arg("", "fred", &pos));
1103
1104 /* arg with empty value */
1105 ut_asserteq(0, cmdline_get_arg("fred= mary", "fred", &pos));
1106 ut_asserteq(5, pos);
1107
1108 /* arg with a value */
1109 ut_asserteq(2, cmdline_get_arg("fred=23", "fred", &pos));
1110 ut_asserteq(5, pos);
1111
1112 /* arg with a value */
1113 ut_asserteq(3, cmdline_get_arg("mary=1 fred=234", "fred", &pos));
1114 ut_asserteq(12, pos);
1115
1116 /* arg with a value, after quoted arg */
1117 ut_asserteq(3, cmdline_get_arg("mary=\"1 2\" fred=234", "fred", &pos));
1118 ut_asserteq(16, pos);
1119
1120 /* arg in the middle */
1121 ut_asserteq(0, cmdline_get_arg("mary=\"1 2\" fred john=23", "fred",
1122 &pos));
1123 ut_asserteq(15, pos);
1124
1125 /* quoted arg */
1126 ut_asserteq(3, cmdline_get_arg("mary=\"1 2\" fred=\"3 4\" john=23",
1127 "fred", &pos));
1128 ut_asserteq(17, pos);
1129
1130 /* args starting with the same prefix */
1131 ut_asserteq(1, cmdline_get_arg("mary=abc johnathon=3 john=1", "john",
1132 &pos));
1133 ut_asserteq(26, pos);
1134
1135 return 0;
1136}
1137BOOTSTD_TEST(bootflow_cmdline_get, 0);
1138
1139static int bootflow_cmdline(struct unit_test_state *uts)
1140{
1141 ut_assertok(run_command("bootflow scan mmc", 0));
1142 ut_assertok(run_command("bootflow sel 0", 0));
Simon Glass55a2da32023-07-12 09:04:39 -06001143
1144 ut_asserteq(1, run_command("bootflow cmdline get fred", 0));
1145 ut_assert_nextline("Argument not found");
1146 ut_assert_console_end();
1147
1148 ut_asserteq(0, run_command("bootflow cmdline set fred 123", 0));
1149 ut_asserteq(0, run_command("bootflow cmdline get fred", 0));
1150 ut_assert_nextline("123");
1151
1152 ut_asserteq(0, run_command("bootflow cmdline set mary abc", 0));
1153 ut_asserteq(0, run_command("bootflow cmdline get mary", 0));
1154 ut_assert_nextline("abc");
1155
1156 ut_asserteq(0, run_command("bootflow cmdline delete fred", 0));
1157 ut_asserteq(1, run_command("bootflow cmdline get fred", 0));
1158 ut_assert_nextline("Argument not found");
1159
1160 ut_asserteq(0, run_command("bootflow cmdline clear mary", 0));
1161 ut_asserteq(0, run_command("bootflow cmdline get mary", 0));
1162 ut_assert_nextline_empty();
1163
Simon Glass7a164f82023-11-29 10:31:19 -07001164 ut_asserteq(0, run_command("bootflow cmdline set mary abc", 0));
1165 ut_asserteq(0, run_command("bootflow cmdline set mary", 0));
Simon Glass55a2da32023-07-12 09:04:39 -06001166 ut_assert_console_end();
1167
1168 return 0;
1169}
Simon Glassf0425022024-08-22 07:57:54 -06001170BOOTSTD_TEST(bootflow_cmdline, UTF_CONSOLE);
Simon Glassfff928c2023-08-24 13:55:41 -06001171
Simon Glassa61057f2023-10-25 07:17:36 +13001172/* test a few special changes to a long command line */
1173static int bootflow_cmdline_special(struct unit_test_state *uts)
1174{
1175 char buf[500];
1176 int pos;
1177
1178 /*
1179 * check handling of an argument which has an embedded '=', as well as
1180 * handling of a argument which partially matches ("ro" and "root")
1181 */
1182 ut_asserteq(32, cmdline_set_arg(
1183 buf, sizeof(buf),
1184 "loglevel=7 root=PARTUUID=d68352e3 rootwait ro noinitrd",
1185 "root", NULL, &pos));
1186 ut_asserteq_str("loglevel=7 rootwait ro noinitrd", buf);
1187
1188 return 0;
1189}
1190BOOTSTD_TEST(bootflow_cmdline_special, 0);
1191
Simon Glassfff928c2023-08-24 13:55:41 -06001192/* Test ChromiumOS bootmeth */
1193static int bootflow_cros(struct unit_test_state *uts)
1194{
Simon Glass3ff8a9a2023-10-01 19:14:37 -06001195 ut_assertok(scan_mmc_bootdev(uts, "mmc5", true));
Simon Glassfff928c2023-08-24 13:55:41 -06001196 ut_assertok(run_command("bootflow list", 0));
1197
1198 ut_assert_nextlinen("Showing all");
1199 ut_assert_nextlinen("Seq");
1200 ut_assert_nextlinen("---");
1201 ut_assert_nextlinen(" 0 extlinux");
Simon Glassd7d3a972023-08-24 13:55:45 -06001202 ut_assert_nextlinen(" 1 cros ready mmc 2 mmc5.bootdev.part_2 ");
1203 ut_assert_nextlinen(" 2 cros ready mmc 4 mmc5.bootdev.part_4 ");
Simon Glassfff928c2023-08-24 13:55:41 -06001204 ut_assert_nextlinen("---");
Simon Glassd7d3a972023-08-24 13:55:45 -06001205 ut_assert_skip_to_line("(3 bootflows, 3 valid)");
Simon Glassfff928c2023-08-24 13:55:41 -06001206
Simon Glassc6a52e72024-11-15 16:19:23 -07001207 ut_assertok(run_command("bootstd images", 0));
1208 ut_assert_nextlinen("Seq");
1209 ut_assert_nextlinen("---");
1210 ut_assert_nextlinen(" 0 mmc1.bootdev.part_1 extlinux_cfg");
1211 ut_assert_nextlinen(" 1 mmc5.bootdev.part_2 x86_setup");
1212 ut_assert_nextlinen(" 1 mmc5.bootdev.part_2 cmdline");
1213 ut_assert_nextlinen(" 1 mmc5.bootdev.part_2 kernel - 4000 kernel");
1214 ut_assert_nextlinen(" 2 mmc5.bootdev.part_4 x86_setup");
1215 ut_assert_nextlinen(" 2 mmc5.bootdev.part_4 cmdline");
1216 ut_assert_nextlinen(" 2 mmc5.bootdev.part_4 kernel - 4000 kernel");
1217 ut_assert_nextlinen("---");
1218 ut_assert_nextline("(7 images)");
1219
Simon Glassfff928c2023-08-24 13:55:41 -06001220 ut_assert_console_end();
1221
1222 return 0;
1223}
Mattijs Korpershoek33342f02024-11-22 15:11:34 +01001224BOOTSTD_TEST(bootflow_cros, UTF_CONSOLE | UTF_DM | UTF_SCAN_FDT);
Mattijs Korpershoekd77f8152024-07-10 10:40:06 +02001225
Guillaume La Roque368ad9e2024-11-26 09:06:13 +01001226/* Test Android bootmeth with boot image version 4 */
1227static int bootflow_android_image_v4(struct unit_test_state *uts)
Mattijs Korpershoekd77f8152024-07-10 10:40:06 +02001228{
1229 if (!IS_ENABLED(CONFIG_BOOTMETH_ANDROID))
1230 return -EAGAIN;
1231
1232 ut_assertok(scan_mmc_android_bootdev(uts, "mmc7"));
1233 ut_assertok(run_command("bootflow list", 0));
1234
1235 ut_assert_nextlinen("Showing all");
1236 ut_assert_nextlinen("Seq");
1237 ut_assert_nextlinen("---");
1238 ut_assert_nextlinen(" 0 extlinux");
1239 ut_assert_nextlinen(" 1 android ready mmc 0 mmc7.bootdev.whole ");
1240 ut_assert_nextlinen("---");
1241 ut_assert_skip_to_line("(2 bootflows, 2 valid)");
1242
1243 ut_assert_console_end();
1244
1245 return 0;
1246}
Guillaume La Roque368ad9e2024-11-26 09:06:13 +01001247BOOTSTD_TEST(bootflow_android_image_v4, UTF_CONSOLE | UTF_DM | UTF_SCAN_FDT);
1248
1249/* Test Android bootmeth with boot image version 2 */
1250static int bootflow_android_image_v2(struct unit_test_state *uts)
1251{
1252 if (!IS_ENABLED(CONFIG_BOOTMETH_ANDROID))
1253 return -EAGAIN;
1254
1255 ut_assertok(scan_mmc_android_bootdev(uts, "mmc8"));
1256 ut_assertok(run_command("bootflow list", 0));
1257
1258 ut_assert_nextlinen("Showing all");
1259 ut_assert_nextlinen("Seq");
1260 ut_assert_nextlinen("---");
1261 ut_assert_nextlinen(" 0 extlinux");
1262 ut_assert_nextlinen(" 1 android ready mmc 0 mmc8.bootdev.whole ");
1263 ut_assert_nextlinen("---");
1264 ut_assert_skip_to_line("(2 bootflows, 2 valid)");
1265
1266 ut_assert_console_end();
1267
1268 return 0;
1269}
1270BOOTSTD_TEST(bootflow_android_image_v2, UTF_CONSOLE | UTF_DM | UTF_SCAN_FDT);
Simon Glass4f378de2024-11-07 14:31:50 -07001271
1272/* Test EFI bootmeth */
1273static int bootflow_efi(struct unit_test_state *uts)
1274{
1275 static const char *order[] = {"mmc1", "usb", NULL};
1276 struct bootstd_priv *std;
1277 struct udevice *bootstd;
1278 const char **old_order;
1279
1280 ut_assertok(uclass_first_device_err(UCLASS_BOOTSTD, &bootstd));
1281 std = dev_get_priv(bootstd);
1282 old_order = std->bootdev_order;
1283 std->bootdev_order = order;
1284
1285 /* disable ethernet since the hunter will run dhcp */
1286 test_set_eth_enable(false);
1287
1288 /* make USB scan without delays */
1289 test_set_skip_delays(true);
1290
1291 bootstd_reset_usb();
1292
1293 ut_assertok(run_command("bootflow scan", 0));
1294 ut_assert_skip_to_line(
Jerome Forissier219dade2025-04-18 16:09:41 +02001295 "Bus usb@1: 5 USB Device(s) found");
Simon Glass4f378de2024-11-07 14:31:50 -07001296
1297 ut_assertok(run_command("bootflow list", 0));
1298
1299 ut_assert_nextlinen("Showing all");
1300 ut_assert_nextlinen("Seq");
1301 ut_assert_nextlinen("---");
1302 ut_assert_nextlinen(" 0 extlinux");
1303 ut_assert_nextlinen(
1304 " 1 efi ready usb_mass_ 1 usb_mass_storage.lun0.boo /EFI/BOOT/BOOTSBOX.EFI");
1305 ut_assert_nextlinen("---");
1306 ut_assert_skip_to_line("(2 bootflows, 2 valid)");
1307 ut_assert_console_end();
1308
1309 ut_assertok(run_command("bootflow select 1", 0));
1310 ut_assert_console_end();
1311
1312 systab.fw_vendor = test_vendor;
1313
1314 ut_asserteq(1, run_command("bootflow boot", 0));
1315 ut_assert_nextline(
1316 "** Booting bootflow 'usb_mass_storage.lun0.bootdev.part_1' with efi");
1317 if (IS_ENABLED(CONFIG_LOGF_FUNC))
1318 ut_assert_skip_to_line(" efi_run_image() Booting /\\EFI\\BOOT\\BOOTSBOX.EFI");
1319 else
1320 ut_assert_skip_to_line("Booting /\\EFI\\BOOT\\BOOTSBOX.EFI");
1321
1322 /* TODO: Why the \r ? */
1323 ut_assert_nextline("U-Boot test app for EFI_LOADER\r");
1324 ut_assert_nextline("Exiting test app");
1325 ut_assert_nextline("Boot failed (err=-14)");
1326
1327 ut_assert_console_end();
1328
1329 ut_assertok(bootstd_test_drop_bootdev_order(uts));
1330
1331 return 0;
1332}
1333BOOTSTD_TEST(bootflow_efi, UTF_CONSOLE);
Simon Glassc6a52e72024-11-15 16:19:23 -07001334
1335/* Check 'bootflow scan' provides a list of images */
1336static int bootstd_images(struct unit_test_state *uts)
1337{
1338 static const char *order[] = {"mmc2", "mmc1", "mmc4", "mmc5", NULL};
1339 const struct legacy_img_hdr *hdr;
1340 const struct bootflow_img *img;
1341 const struct bootflow *bflow;
1342 struct bootstd_priv *std;
1343 const char **old_order;
1344 struct udevice *dev;
1345 ofnode root, node;
1346 ulong data, len;
1347 char *ptr;
1348
1349 /* get access to the current bootflow */
1350 ut_assertok(bootstd_get_priv(&std));
1351
1352 ut_assertok(prep_mmc_bootdev(uts, "mmc4", true, &old_order));
1353
1354 /* bind mmc5 too, for cros */
1355 root = oftree_root(oftree_default());
1356 node = ofnode_find_subnode(root, "mmc5");
1357 ut_assert(ofnode_valid(node));
1358 ut_assertok(lists_bind_fdt(gd->dm_root, node, &dev, NULL, false));
1359
1360 std->bootdev_order = order;
1361 ut_assertok(run_command("bootflow scan", 0));
1362 ut_assert_console_end();
1363 std->bootdev_order = old_order;
1364
1365 ut_assertok(run_command("bootflow list", 0));
1366 ut_assert_skip_to_line("(4 bootflows, 4 valid)");
1367
1368 ut_assertok(run_command("bootstd images", 0));
1369 ut_assert_nextlinen("Seq");
1370 ut_assert_nextlinen("---");
1371 ut_assert_nextlinen(" 0 mmc1.bootdev.part_1 extlinux_cfg");
1372 ut_assert_nextlinen(" 1 mmc4.bootdev.part_1 script");
1373 ut_assert_nextlinen(" 1 mmc4.bootdev.part_1 logo");
1374 ut_assert_nextlinen(" 2 mmc5.bootdev.part_2 x86_setup");
1375 ut_assert_nextlinen(" 2 mmc5.bootdev.part_2 cmdline");
1376 ut_assert_nextlinen(" 2 mmc5.bootdev.part_2 kernel -");
1377 ut_assert_nextlinen(" 3 mmc5.bootdev.part_4 x86_setup");
1378 ut_assert_nextlinen(" 3 mmc5.bootdev.part_4 cmdline");
1379 ut_assert_nextlinen(" 3 mmc5.bootdev.part_4 kernel -");
1380 ut_assert_nextlinen("---");
1381 ut_assert_nextline("(9 images)");
1382
1383 /* check the first image */
1384 bflow = alist_get(&std->bootflows, 0, struct bootflow);
1385 img = alist_get(&bflow->images, 0, struct bootflow_img);
1386 ut_asserteq_strn("# extlinux.conf", map_sysmem(img->addr, 0));
1387
1388 /* check the second image */
1389 bflow = alist_get(&std->bootflows, 1, struct bootflow);
1390 img = alist_get(&bflow->images, 0, struct bootflow_img);
1391
1392 /* this is the length of the script in bytes */
1393 hdr = map_sysmem(img->addr, 0);
1394 image_multi_getimg(hdr, 0, &data, &len);
1395 ptr = (void *)data;
1396 ut_asserteq_strn("# DO NOT EDIT THIS FILE", ptr);
1397
1398 /* check the ChromiumOS images */
1399 bflow = alist_get(&std->bootflows, 2, struct bootflow);
1400 img = alist_get(&bflow->images, 1, struct bootflow_img);
1401 ptr = map_sysmem(img->addr, 0);
1402 ut_asserteq_strn("BOOT_IMAGE=/vmlinuz-5.15.0-121-generic root=", ptr);
1403
1404 /*
1405 * the x86 setup is not a real binary, so just check that it is empty,
1406 * so that if this changes in the future someone will notice and update
1407 * this test
1408 */
1409 img = alist_get(&bflow->images, 0, struct bootflow_img);
1410 ptr = map_sysmem(img->addr, 0);
1411 ut_asserteq(0, *(ulong *)ptr);
1412
1413 ut_assert_console_end();
1414
1415 return 0;
1416}
1417BOOTSTD_TEST(bootstd_images, UTF_CONSOLE);