1 // SPDX-License-Identifier: GPL-2.0+
3 * Test for bootdev functions. All start with 'bootdev'
5 * Copyright 2021 Google LLC
15 #include <test/suites.h>
17 #include "bootstd_common.h"
19 /* Check 'bootflow scan/list' commands */
20 static int bootflow_cmd(struct unit_test_state *uts)
22 console_record_reset_enable();
23 ut_assertok(run_command("bootdev select 1", 0));
24 ut_assert_console_end();
25 ut_assertok(run_command("bootflow scan -l", 0));
26 ut_assert_nextline("Scanning for bootflows in bootdev 'mmc1.bootdev'");
27 ut_assert_nextline("Seq Method State Uclass Part Name Filename");
28 ut_assert_nextlinen("---");
29 ut_assert_nextline(" 0 syslinux ready mmc 1 mmc1.bootdev.part_1 /extlinux/extlinux.conf");
30 ut_assert_nextlinen("---");
31 ut_assert_nextline("(1 bootflow, 1 valid)");
32 ut_assert_console_end();
34 ut_assertok(run_command("bootflow list", 0));
35 ut_assert_nextline("Showing bootflows for bootdev 'mmc1.bootdev'");
36 ut_assert_nextline("Seq Method State Uclass Part Name Filename");
37 ut_assert_nextlinen("---");
38 ut_assert_nextline(" 0 syslinux ready mmc 1 mmc1.bootdev.part_1 /extlinux/extlinux.conf");
39 ut_assert_nextlinen("---");
40 ut_assert_nextline("(1 bootflow, 1 valid)");
41 ut_assert_console_end();
45 BOOTSTD_TEST(bootflow_cmd, UT_TESTF_DM | UT_TESTF_SCAN_FDT);
47 /* Check 'bootflow scan' with a name / label / seq */
48 static int bootflow_cmd_label(struct unit_test_state *uts)
50 console_record_reset_enable();
51 ut_assertok(run_command("bootflow scan -l mmc1", 0));
52 ut_assert_nextline("Scanning for bootflows in bootdev 'mmc1.bootdev'");
53 ut_assert_skip_to_line("(1 bootflow, 1 valid)");
54 ut_assert_console_end();
56 ut_assertok(run_command("bootflow scan -l mmc0.bootdev", 0));
57 ut_assert_nextline("Scanning for bootflows in bootdev 'mmc0.bootdev'");
58 ut_assert_skip_to_line("(0 bootflows, 0 valid)");
59 ut_assert_console_end();
61 ut_assertok(run_command("bootflow scan -l 0", 0));
62 ut_assert_nextline("Scanning for bootflows in bootdev 'mmc2.bootdev'");
63 ut_assert_skip_to_line("(0 bootflows, 0 valid)");
64 ut_assert_console_end();
68 BOOTSTD_TEST(bootflow_cmd_label, UT_TESTF_DM | UT_TESTF_SCAN_FDT);
70 /* Check 'bootflow scan/list' commands using all bootdevs */
71 static int bootflow_cmd_glob(struct unit_test_state *uts)
73 ut_assertok(bootstd_test_drop_bootdev_order(uts));
75 console_record_reset_enable();
76 ut_assertok(run_command("bootflow scan -l", 0));
77 ut_assert_nextline("Scanning for bootflows in all bootdevs");
78 ut_assert_nextline("Seq Method State Uclass Part Name Filename");
79 ut_assert_nextlinen("---");
80 ut_assert_nextline("Scanning bootdev 'mmc2.bootdev':");
81 ut_assert_nextline("Scanning bootdev 'mmc1.bootdev':");
82 ut_assert_nextline(" 0 syslinux ready mmc 1 mmc1.bootdev.part_1 /extlinux/extlinux.conf");
83 ut_assert_nextline("Scanning bootdev 'mmc0.bootdev':");
84 ut_assert_nextline("No more bootdevs");
85 ut_assert_nextlinen("---");
86 ut_assert_nextline("(1 bootflow, 1 valid)");
87 ut_assert_console_end();
89 ut_assertok(run_command("bootflow list", 0));
90 ut_assert_nextline("Showing all bootflows");
91 ut_assert_nextline("Seq Method State Uclass Part Name Filename");
92 ut_assert_nextlinen("---");
93 ut_assert_nextline(" 0 syslinux ready mmc 1 mmc1.bootdev.part_1 /extlinux/extlinux.conf");
94 ut_assert_nextlinen("---");
95 ut_assert_nextline("(1 bootflow, 1 valid)");
96 ut_assert_console_end();
100 BOOTSTD_TEST(bootflow_cmd_glob, UT_TESTF_DM | UT_TESTF_SCAN_FDT);
102 /* Check 'bootflow scan -e' */
103 static int bootflow_cmd_scan_e(struct unit_test_state *uts)
105 ut_assertok(bootstd_test_drop_bootdev_order(uts));
107 console_record_reset_enable();
108 ut_assertok(run_command("bootflow scan -ale", 0));
109 ut_assert_nextline("Scanning for bootflows in all bootdevs");
110 ut_assert_nextline("Seq Method State Uclass Part Name Filename");
111 ut_assert_nextlinen("---");
112 ut_assert_nextline("Scanning bootdev 'mmc2.bootdev':");
113 ut_assert_nextline(" 0 syslinux media mmc 0 mmc2.bootdev.whole <NULL>");
114 ut_assert_nextline(" ** No partition found, err=-93");
115 ut_assert_nextline(" 1 efi media mmc 0 mmc2.bootdev.whole <NULL>");
116 ut_assert_nextline(" ** No partition found, err=-93");
118 ut_assert_nextline("Scanning bootdev 'mmc1.bootdev':");
119 ut_assert_nextline(" 2 syslinux media mmc 0 mmc1.bootdev.whole <NULL>");
120 ut_assert_nextline(" ** No partition found, err=-2");
121 ut_assert_nextline(" 3 efi media mmc 0 mmc1.bootdev.whole <NULL>");
122 ut_assert_nextline(" ** No partition found, err=-2");
123 ut_assert_nextline(" 4 syslinux ready mmc 1 mmc1.bootdev.part_1 /extlinux/extlinux.conf");
124 ut_assert_nextline(" 5 efi fs mmc 1 mmc1.bootdev.part_1 efi/boot/bootsbox.efi");
126 ut_assert_skip_to_line("Scanning bootdev 'mmc0.bootdev':");
127 ut_assert_skip_to_line(" 3f efi media mmc 0 mmc0.bootdev.whole <NULL>");
128 ut_assert_nextline(" ** No partition found, err=-93");
129 ut_assert_nextline("No more bootdevs");
130 ut_assert_nextlinen("---");
131 ut_assert_nextline("(64 bootflows, 1 valid)");
132 ut_assert_console_end();
134 ut_assertok(run_command("bootflow list", 0));
135 ut_assert_nextline("Showing all bootflows");
136 ut_assert_nextline("Seq Method State Uclass Part Name Filename");
137 ut_assert_nextlinen("---");
138 ut_assert_nextline(" 0 syslinux media mmc 0 mmc2.bootdev.whole <NULL>");
139 ut_assert_nextline(" 1 efi media mmc 0 mmc2.bootdev.whole <NULL>");
140 ut_assert_skip_to_line(" 4 syslinux ready mmc 1 mmc1.bootdev.part_1 /extlinux/extlinux.conf");
141 ut_assert_skip_to_line(" 3f efi media mmc 0 mmc0.bootdev.whole <NULL>");
142 ut_assert_nextlinen("---");
143 ut_assert_nextline("(64 bootflows, 1 valid)");
144 ut_assert_console_end();
148 BOOTSTD_TEST(bootflow_cmd_scan_e, UT_TESTF_DM | UT_TESTF_SCAN_FDT);
150 /* Check 'bootflow info' */
151 static int bootflow_cmd_info(struct unit_test_state *uts)
153 console_record_reset_enable();
154 ut_assertok(run_command("bootdev select 1", 0));
155 ut_assert_console_end();
156 ut_assertok(run_command("bootflow scan", 0));
157 ut_assert_console_end();
158 ut_assertok(run_command("bootflow select 0", 0));
159 ut_assert_console_end();
160 ut_assertok(run_command("bootflow info", 0));
161 ut_assert_nextline("Name: mmc1.bootdev.part_1");
162 ut_assert_nextline("Device: mmc1.bootdev");
163 ut_assert_nextline("Block dev: mmc1.blk");
164 ut_assert_nextline("Method: syslinux");
165 ut_assert_nextline("State: ready");
166 ut_assert_nextline("Partition: 1");
167 ut_assert_nextline("Subdir: (none)");
168 ut_assert_nextline("Filename: /extlinux/extlinux.conf");
169 ut_assert_nextlinen("Buffer: ");
170 ut_assert_nextline("Size: 253 (595 bytes)");
171 ut_assert_nextline("Error: 0");
172 ut_assert_console_end();
174 ut_assertok(run_command("bootflow info -d", 0));
175 ut_assert_nextline("Name: mmc1.bootdev.part_1");
176 ut_assert_skip_to_line("Error: 0");
177 ut_assert_nextline("Contents:");
178 ut_assert_nextline("%s", "");
179 ut_assert_nextline("# extlinux.conf generated by appliance-creator");
180 ut_assert_skip_to_line(" initrd /initramfs-5.3.7-301.fc31.armv7hl.img");
181 ut_assert_console_end();
185 BOOTSTD_TEST(bootflow_cmd_info, UT_TESTF_DM | UT_TESTF_SCAN_FDT);
187 /* Check 'bootflow scan -b' to boot the first available bootdev */
188 static int bootflow_scan_boot(struct unit_test_state *uts)
190 console_record_reset_enable();
191 ut_assertok(run_command("bootflow scan -b", 0));
193 "** Booting bootflow 'mmc1.bootdev.part_1' with syslinux");
194 ut_assert_nextline("Ignoring unknown command: ui");
197 * We expect it to get through to boot although sandbox always returns
198 * -EFAULT as it cannot actually boot the kernel
200 ut_assert_skip_to_line("sandbox: continuing, as we cannot run Linux");
201 ut_assert_nextline("Boot failed (err=-14)");
202 ut_assert_console_end();
206 BOOTSTD_TEST(bootflow_scan_boot, UT_TESTF_DM | UT_TESTF_SCAN_FDT);
208 /* Check iterating through available bootflows */
209 static int bootflow_iter(struct unit_test_state *uts)
211 struct bootflow_iter iter;
212 struct bootflow bflow;
214 bootstd_clear_glob();
216 /* The first device is mmc2.bootdev which has no media */
217 ut_asserteq(-EPROTONOSUPPORT,
218 bootflow_scan_first(&iter, BOOTFLOWF_ALL, &bflow));
219 ut_asserteq(2, iter.num_methods);
220 ut_asserteq(0, iter.cur_method);
221 ut_asserteq(0, iter.part);
222 ut_asserteq(0, iter.max_part);
223 ut_asserteq_str("syslinux", iter.method->name);
224 ut_asserteq(0, bflow.err);
227 * This shows MEDIA even though there is none, since int
228 * bootdev_find_in_blk() we call part_get_info() which returns
229 * -EPROTONOSUPPORT. Ideally it would return -EEOPNOTSUPP and we would
232 ut_asserteq(BOOTFLOWST_MEDIA, bflow.state);
234 ut_asserteq(-EPROTONOSUPPORT, bootflow_scan_next(&iter, &bflow));
235 ut_asserteq(2, iter.num_methods);
236 ut_asserteq(1, iter.cur_method);
237 ut_asserteq(0, iter.part);
238 ut_asserteq(0, iter.max_part);
239 ut_asserteq_str("efi", iter.method->name);
240 ut_asserteq(0, bflow.err);
241 ut_asserteq(BOOTFLOWST_MEDIA, bflow.state);
242 bootflow_free(&bflow);
244 /* The next device is mmc1.bootdev - at first we use the whole device */
245 ut_asserteq(-ENOENT, bootflow_scan_next(&iter, &bflow));
246 ut_asserteq(2, iter.num_methods);
247 ut_asserteq(0, iter.cur_method);
248 ut_asserteq(0, iter.part);
249 ut_asserteq(0x1e, iter.max_part);
250 ut_asserteq_str("syslinux", iter.method->name);
251 ut_asserteq(0, bflow.err);
252 ut_asserteq(BOOTFLOWST_MEDIA, bflow.state);
253 bootflow_free(&bflow);
255 ut_asserteq(-ENOENT, bootflow_scan_next(&iter, &bflow));
256 ut_asserteq(2, iter.num_methods);
257 ut_asserteq(1, iter.cur_method);
258 ut_asserteq(0, iter.part);
259 ut_asserteq(0x1e, iter.max_part);
260 ut_asserteq_str("efi", iter.method->name);
261 ut_asserteq(0, bflow.err);
262 ut_asserteq(BOOTFLOWST_MEDIA, bflow.state);
263 bootflow_free(&bflow);
265 /* Then more to partition 1 where we find something */
266 ut_assertok(bootflow_scan_next(&iter, &bflow));
267 ut_asserteq(2, iter.num_methods);
268 ut_asserteq(0, iter.cur_method);
269 ut_asserteq(1, iter.part);
270 ut_asserteq(0x1e, iter.max_part);
271 ut_asserteq_str("syslinux", iter.method->name);
272 ut_asserteq(0, bflow.err);
273 ut_asserteq(BOOTFLOWST_READY, bflow.state);
274 bootflow_free(&bflow);
276 ut_asserteq(-ENOENT, bootflow_scan_next(&iter, &bflow));
277 ut_asserteq(2, iter.num_methods);
278 ut_asserteq(1, iter.cur_method);
279 ut_asserteq(1, iter.part);
280 ut_asserteq(0x1e, iter.max_part);
281 ut_asserteq_str("efi", iter.method->name);
282 ut_asserteq(0, bflow.err);
283 ut_asserteq(BOOTFLOWST_FS, bflow.state);
284 bootflow_free(&bflow);
286 /* Then more to partition 2 which doesn't exist */
287 ut_asserteq(-ENOENT, bootflow_scan_next(&iter, &bflow));
288 ut_asserteq(2, iter.num_methods);
289 ut_asserteq(0, iter.cur_method);
290 ut_asserteq(2, iter.part);
291 ut_asserteq(0x1e, iter.max_part);
292 ut_asserteq_str("syslinux", iter.method->name);
293 ut_asserteq(0, bflow.err);
294 ut_asserteq(BOOTFLOWST_MEDIA, bflow.state);
295 bootflow_free(&bflow);
297 bootflow_iter_uninit(&iter);
299 ut_assert_console_end();
303 BOOTSTD_TEST(bootflow_iter, UT_TESTF_DM | UT_TESTF_SCAN_FDT);
305 /* Check using the system bootdev */
306 static int bootflow_system(struct unit_test_state *uts)
308 struct udevice *bootstd, *dev;
310 /* Add the EFI bootmgr driver */
311 ut_assertok(uclass_first_device_err(UCLASS_BOOTSTD, &bootstd));
312 ut_assertok(device_bind_driver(bootstd, "bootmeth_efi_mgr", "bootmgr",
315 /* Add the system bootdev that it uses */
316 ut_assertok(device_bind_driver(bootstd, "system_bootdev",
317 "system-bootdev", &dev));
319 ut_assertok(bootstd_test_drop_bootdev_order(uts));
321 /* We should get a single 'bootmgr' method right at the end */
322 bootstd_clear_glob();
323 console_record_reset_enable();
324 ut_assertok(run_command("bootflow scan -l", 0));
325 ut_assert_skip_to_line(" 1 bootmgr ready bootstd 0 <NULL> <NULL>");
326 ut_assert_nextline("No more bootdevs");
327 ut_assert_skip_to_line("(2 bootflows, 2 valid)");
328 ut_assert_console_end();
332 BOOTSTD_TEST(bootflow_system, UT_TESTF_DM | UT_TESTF_SCAN_FDT);
334 /* Check disabling a bootmethod if it requests it */
335 static int bootflow_iter_disable(struct unit_test_state *uts)
337 struct udevice *bootstd, *dev;
338 struct bootflow_iter iter;
339 struct bootflow bflow;
342 /* Add the EFI bootmgr driver */
343 ut_assertok(uclass_first_device_err(UCLASS_BOOTSTD, &bootstd));
344 ut_assertok(device_bind_driver(bootstd, "bootmeth_sandbox", "sandbox",
347 /* Add the system bootdev that it uses */
348 ut_assertok(device_bind_driver(bootstd, "system_bootdev",
349 "system-bootdev", &dev));
351 ut_assertok(bootstd_test_drop_bootdev_order(uts));
353 bootstd_clear_glob();
354 ut_assertok(run_command("bootflow scan -lb", 0));
356 /* Try to boot the bootmgr flow, which will fail */
357 console_record_reset_enable();
358 ut_assertok(bootflow_scan_first(&iter, 0, &bflow));
359 ut_asserteq(3, iter.num_methods);
360 ut_asserteq_str("sandbox", iter.method->name);
361 ut_asserteq(-ENOTSUPP, bootflow_run_boot(&iter, &bflow));
363 ut_assert_skip_to_line("Boot method 'sandbox' failed and will not be retried");
364 ut_assert_console_end();
366 /* Check that the sandbox bootmeth has been removed */
367 ut_asserteq(2, iter.num_methods);
368 for (i = 0; i < iter.num_methods; i++)
369 ut_assert(strcmp("sandbox", iter.method_order[i]->name));
373 BOOTSTD_TEST(bootflow_iter_disable, UT_TESTF_DM | UT_TESTF_SCAN_FDT);
375 /* Check 'bootflow boot' to boot a selected bootflow */
376 static int bootflow_cmd_boot(struct unit_test_state *uts)
378 console_record_reset_enable();
379 ut_assertok(run_command("bootdev select 1", 0));
380 ut_assert_console_end();
381 ut_assertok(run_command("bootflow scan", 0));
382 ut_assert_console_end();
383 ut_assertok(run_command("bootflow select 0", 0));
384 ut_assert_console_end();
385 ut_asserteq(1, run_command("bootflow boot", 0));
387 "** Booting bootflow 'mmc1.bootdev.part_1' with syslinux");
388 ut_assert_nextline("Ignoring unknown command: ui");
391 * We expect it to get through to boot although sandbox always returns
392 * -EFAULT as it cannot actually boot the kernel
394 ut_assert_skip_to_line("sandbox: continuing, as we cannot run Linux");
395 ut_assert_nextline("Boot failed (err=-14)");
396 ut_assert_console_end();
400 BOOTSTD_TEST(bootflow_cmd_boot, UT_TESTF_DM | UT_TESTF_SCAN_FDT);