]> Git Repo - J-u-boot.git/blob - test/boot/bootflow.c
bootstd: Drop the system bootdev
[J-u-boot.git] / test / boot / bootflow.c
1 // 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 <[email protected]>
7  */
8
9 #include <common.h>
10 #include <bootdev.h>
11 #include <bootflow.h>
12 #include <bootstd.h>
13 #include <dm.h>
14 #include <asm/test.h>
15 #include <dm/lists.h>
16 #include <test/suites.h>
17 #include <test/ut.h>
18 #include "bootstd_common.h"
19
20 static int inject_response(struct unit_test_state *uts)
21 {
22         /*
23          * The image being booted presents a menu of options:
24          *
25          * Fedora-Workstation-armhfp-31-1.9 Boot Options.
26          * 1:   Fedora-Workstation-armhfp-31-1.9 (5.3.7-301.fc31.armv7hl)
27          * Enter choice:
28          *
29          * Provide input for this, to avoid waiting two seconds for a timeout.
30          */
31         ut_asserteq(2, console_in_puts("1\n"));
32
33         return 0;
34 }
35
36 /* Check 'bootflow scan/list' commands */
37 static int bootflow_cmd(struct unit_test_state *uts)
38 {
39         console_record_reset_enable();
40         ut_assertok(run_command("bootdev select 1", 0));
41         ut_assert_console_end();
42         ut_assertok(run_command("bootflow scan -l", 0));
43         ut_assert_nextline("Scanning for bootflows in bootdev 'mmc1.bootdev'");
44         ut_assert_nextline("Seq  Method       State   Uclass    Part  Name                      Filename");
45         ut_assert_nextlinen("---");
46         ut_assert_nextline("  0  syslinux     ready   mmc          1  mmc1.bootdev.part_1       /extlinux/extlinux.conf");
47         ut_assert_nextlinen("---");
48         ut_assert_nextline("(1 bootflow, 1 valid)");
49         ut_assert_console_end();
50
51         ut_assertok(run_command("bootflow list", 0));
52         ut_assert_nextline("Showing bootflows for bootdev 'mmc1.bootdev'");
53         ut_assert_nextline("Seq  Method       State   Uclass    Part  Name                      Filename");
54         ut_assert_nextlinen("---");
55         ut_assert_nextline("  0  syslinux     ready   mmc          1  mmc1.bootdev.part_1       /extlinux/extlinux.conf");
56         ut_assert_nextlinen("---");
57         ut_assert_nextline("(1 bootflow, 1 valid)");
58         ut_assert_console_end();
59
60         return 0;
61 }
62 BOOTSTD_TEST(bootflow_cmd, UT_TESTF_DM | UT_TESTF_SCAN_FDT);
63
64 /* Check 'bootflow scan' with a name / label / seq */
65 static int bootflow_cmd_label(struct unit_test_state *uts)
66 {
67         console_record_reset_enable();
68         ut_assertok(run_command("bootflow scan -l mmc1", 0));
69         ut_assert_nextline("Scanning for bootflows in bootdev 'mmc1.bootdev'");
70         ut_assert_skip_to_line("(1 bootflow, 1 valid)");
71         ut_assert_console_end();
72
73         ut_assertok(run_command("bootflow scan -l mmc0.bootdev", 0));
74         ut_assert_nextline("Scanning for bootflows in bootdev 'mmc0.bootdev'");
75         ut_assert_skip_to_line("(0 bootflows, 0 valid)");
76         ut_assert_console_end();
77
78         ut_assertok(run_command("bootflow scan -l 0", 0));
79         ut_assert_nextline("Scanning for bootflows in bootdev 'mmc2.bootdev'");
80         ut_assert_skip_to_line("(0 bootflows, 0 valid)");
81         ut_assert_console_end();
82
83         return 0;
84 }
85 BOOTSTD_TEST(bootflow_cmd_label, UT_TESTF_DM | UT_TESTF_SCAN_FDT);
86
87 /* Check 'bootflow scan/list' commands using all bootdevs */
88 static int bootflow_cmd_glob(struct unit_test_state *uts)
89 {
90         ut_assertok(bootstd_test_drop_bootdev_order(uts));
91
92         console_record_reset_enable();
93         ut_assertok(run_command("bootflow scan -l", 0));
94         ut_assert_nextline("Scanning for bootflows in all bootdevs");
95         ut_assert_nextline("Seq  Method       State   Uclass    Part  Name                      Filename");
96         ut_assert_nextlinen("---");
97         ut_assert_nextline("Scanning bootdev 'mmc2.bootdev':");
98         ut_assert_nextline("Scanning bootdev 'mmc1.bootdev':");
99         ut_assert_nextline("  0  syslinux     ready   mmc          1  mmc1.bootdev.part_1       /extlinux/extlinux.conf");
100         ut_assert_nextline("Scanning bootdev 'mmc0.bootdev':");
101         ut_assert_nextline("No more bootdevs");
102         ut_assert_nextlinen("---");
103         ut_assert_nextline("(1 bootflow, 1 valid)");
104         ut_assert_console_end();
105
106         ut_assertok(run_command("bootflow list", 0));
107         ut_assert_nextline("Showing all bootflows");
108         ut_assert_nextline("Seq  Method       State   Uclass    Part  Name                      Filename");
109         ut_assert_nextlinen("---");
110         ut_assert_nextline("  0  syslinux     ready   mmc          1  mmc1.bootdev.part_1       /extlinux/extlinux.conf");
111         ut_assert_nextlinen("---");
112         ut_assert_nextline("(1 bootflow, 1 valid)");
113         ut_assert_console_end();
114
115         return 0;
116 }
117 BOOTSTD_TEST(bootflow_cmd_glob, UT_TESTF_DM | UT_TESTF_SCAN_FDT);
118
119 /* Check 'bootflow scan -e' */
120 static int bootflow_cmd_scan_e(struct unit_test_state *uts)
121 {
122         ut_assertok(bootstd_test_drop_bootdev_order(uts));
123
124         console_record_reset_enable();
125         ut_assertok(run_command("bootflow scan -ale", 0));
126         ut_assert_nextline("Scanning for bootflows in all bootdevs");
127         ut_assert_nextline("Seq  Method       State   Uclass    Part  Name                      Filename");
128         ut_assert_nextlinen("---");
129         ut_assert_nextline("Scanning bootdev 'mmc2.bootdev':");
130         ut_assert_nextline("  0  syslinux     media   mmc          0  mmc2.bootdev.whole        <NULL>");
131         ut_assert_nextline("     ** No partition found, err=-93");
132         ut_assert_nextline("  1  efi          media   mmc          0  mmc2.bootdev.whole        <NULL>");
133         ut_assert_nextline("     ** No partition found, err=-93");
134
135         ut_assert_nextline("Scanning bootdev 'mmc1.bootdev':");
136         ut_assert_nextline("  2  syslinux     media   mmc          0  mmc1.bootdev.whole        <NULL>");
137         ut_assert_nextline("     ** No partition found, err=-2");
138         ut_assert_nextline("  3  efi          media   mmc          0  mmc1.bootdev.whole        <NULL>");
139         ut_assert_nextline("     ** No partition found, err=-2");
140         ut_assert_nextline("  4  syslinux     ready   mmc          1  mmc1.bootdev.part_1       /extlinux/extlinux.conf");
141         ut_assert_nextline("  5  efi          fs      mmc          1  mmc1.bootdev.part_1       efi/boot/bootsbox.efi");
142
143         ut_assert_skip_to_line("Scanning bootdev 'mmc0.bootdev':");
144         ut_assert_skip_to_line(" 3f  efi          media   mmc          0  mmc0.bootdev.whole        <NULL>");
145         ut_assert_nextline("     ** No partition found, err=-93");
146         ut_assert_nextline("No more bootdevs");
147         ut_assert_nextlinen("---");
148         ut_assert_nextline("(64 bootflows, 1 valid)");
149         ut_assert_console_end();
150
151         ut_assertok(run_command("bootflow list", 0));
152         ut_assert_nextline("Showing all bootflows");
153         ut_assert_nextline("Seq  Method       State   Uclass    Part  Name                      Filename");
154         ut_assert_nextlinen("---");
155         ut_assert_nextline("  0  syslinux     media   mmc          0  mmc2.bootdev.whole        <NULL>");
156         ut_assert_nextline("  1  efi          media   mmc          0  mmc2.bootdev.whole        <NULL>");
157         ut_assert_skip_to_line("  4  syslinux     ready   mmc          1  mmc1.bootdev.part_1       /extlinux/extlinux.conf");
158         ut_assert_skip_to_line(" 3f  efi          media   mmc          0  mmc0.bootdev.whole        <NULL>");
159         ut_assert_nextlinen("---");
160         ut_assert_nextline("(64 bootflows, 1 valid)");
161         ut_assert_console_end();
162
163         return 0;
164 }
165 BOOTSTD_TEST(bootflow_cmd_scan_e, UT_TESTF_DM | UT_TESTF_SCAN_FDT);
166
167 /* Check 'bootflow info' */
168 static int bootflow_cmd_info(struct unit_test_state *uts)
169 {
170         console_record_reset_enable();
171         ut_assertok(run_command("bootdev select 1", 0));
172         ut_assert_console_end();
173         ut_assertok(run_command("bootflow scan", 0));
174         ut_assert_console_end();
175         ut_assertok(run_command("bootflow select 0", 0));
176         ut_assert_console_end();
177         ut_assertok(run_command("bootflow info", 0));
178         ut_assert_nextline("Name:      mmc1.bootdev.part_1");
179         ut_assert_nextline("Device:    mmc1.bootdev");
180         ut_assert_nextline("Block dev: mmc1.blk");
181         ut_assert_nextline("Method:    syslinux");
182         ut_assert_nextline("State:     ready");
183         ut_assert_nextline("Partition: 1");
184         ut_assert_nextline("Subdir:    (none)");
185         ut_assert_nextline("Filename:  /extlinux/extlinux.conf");
186         ut_assert_nextlinen("Buffer:    ");
187         ut_assert_nextline("Size:      253 (595 bytes)");
188         ut_assert_nextline("Error:     0");
189         ut_assert_console_end();
190
191         ut_assertok(run_command("bootflow info -d", 0));
192         ut_assert_nextline("Name:      mmc1.bootdev.part_1");
193         ut_assert_skip_to_line("Error:     0");
194         ut_assert_nextline("Contents:");
195         ut_assert_nextline("%s", "");
196         ut_assert_nextline("# extlinux.conf generated by appliance-creator");
197         ut_assert_skip_to_line("        initrd /initramfs-5.3.7-301.fc31.armv7hl.img");
198         ut_assert_console_end();
199
200         return 0;
201 }
202 BOOTSTD_TEST(bootflow_cmd_info, UT_TESTF_DM | UT_TESTF_SCAN_FDT);
203
204 /* Check 'bootflow scan -b' to boot the first available bootdev */
205 static int bootflow_scan_boot(struct unit_test_state *uts)
206 {
207         console_record_reset_enable();
208         ut_assertok(inject_response(uts));
209         ut_assertok(run_command("bootflow scan -b", 0));
210         ut_assert_nextline(
211                 "** Booting bootflow 'mmc1.bootdev.part_1' with syslinux");
212         ut_assert_nextline("Ignoring unknown command: ui");
213
214         /*
215          * We expect it to get through to boot although sandbox always returns
216          * -EFAULT as it cannot actually boot the kernel
217          */
218         ut_assert_skip_to_line("sandbox: continuing, as we cannot run Linux");
219         ut_assert_nextline("Boot failed (err=-14)");
220         ut_assert_console_end();
221
222         return 0;
223 }
224 BOOTSTD_TEST(bootflow_scan_boot, UT_TESTF_DM | UT_TESTF_SCAN_FDT);
225
226 /* Check iterating through available bootflows */
227 static int bootflow_iter(struct unit_test_state *uts)
228 {
229         struct bootflow_iter iter;
230         struct bootflow bflow;
231
232         bootstd_clear_glob();
233
234         /* The first device is mmc2.bootdev which has no media */
235         ut_asserteq(-EPROTONOSUPPORT,
236                     bootflow_scan_first(&iter, BOOTFLOWF_ALL, &bflow));
237         ut_asserteq(2, iter.num_methods);
238         ut_asserteq(0, iter.cur_method);
239         ut_asserteq(0, iter.part);
240         ut_asserteq(0, iter.max_part);
241         ut_asserteq_str("syslinux", iter.method->name);
242         ut_asserteq(0, bflow.err);
243
244         /*
245          * This shows MEDIA even though there is none, since int
246          * bootdev_find_in_blk() we call part_get_info() which returns
247          * -EPROTONOSUPPORT. Ideally it would return -EEOPNOTSUPP and we would
248          * know.
249          */
250         ut_asserteq(BOOTFLOWST_MEDIA, bflow.state);
251
252         ut_asserteq(-EPROTONOSUPPORT, bootflow_scan_next(&iter, &bflow));
253         ut_asserteq(2, iter.num_methods);
254         ut_asserteq(1, iter.cur_method);
255         ut_asserteq(0, iter.part);
256         ut_asserteq(0, iter.max_part);
257         ut_asserteq_str("efi", iter.method->name);
258         ut_asserteq(0, bflow.err);
259         ut_asserteq(BOOTFLOWST_MEDIA, bflow.state);
260         bootflow_free(&bflow);
261
262         /* The next device is mmc1.bootdev - at first we use the whole device */
263         ut_asserteq(-ENOENT, bootflow_scan_next(&iter, &bflow));
264         ut_asserteq(2, iter.num_methods);
265         ut_asserteq(0, iter.cur_method);
266         ut_asserteq(0, iter.part);
267         ut_asserteq(0x1e, iter.max_part);
268         ut_asserteq_str("syslinux", iter.method->name);
269         ut_asserteq(0, bflow.err);
270         ut_asserteq(BOOTFLOWST_MEDIA, bflow.state);
271         bootflow_free(&bflow);
272
273         ut_asserteq(-ENOENT, bootflow_scan_next(&iter, &bflow));
274         ut_asserteq(2, iter.num_methods);
275         ut_asserteq(1, iter.cur_method);
276         ut_asserteq(0, iter.part);
277         ut_asserteq(0x1e, iter.max_part);
278         ut_asserteq_str("efi", iter.method->name);
279         ut_asserteq(0, bflow.err);
280         ut_asserteq(BOOTFLOWST_MEDIA, bflow.state);
281         bootflow_free(&bflow);
282
283         /* Then more to partition 1 where we find something */
284         ut_assertok(bootflow_scan_next(&iter, &bflow));
285         ut_asserteq(2, iter.num_methods);
286         ut_asserteq(0, iter.cur_method);
287         ut_asserteq(1, iter.part);
288         ut_asserteq(0x1e, iter.max_part);
289         ut_asserteq_str("syslinux", iter.method->name);
290         ut_asserteq(0, bflow.err);
291         ut_asserteq(BOOTFLOWST_READY, bflow.state);
292         bootflow_free(&bflow);
293
294         ut_asserteq(-ENOENT, bootflow_scan_next(&iter, &bflow));
295         ut_asserteq(2, iter.num_methods);
296         ut_asserteq(1, iter.cur_method);
297         ut_asserteq(1, iter.part);
298         ut_asserteq(0x1e, iter.max_part);
299         ut_asserteq_str("efi", iter.method->name);
300         ut_asserteq(0, bflow.err);
301         ut_asserteq(BOOTFLOWST_FS, bflow.state);
302         bootflow_free(&bflow);
303
304         /* Then more to partition 2 which doesn't exist */
305         ut_asserteq(-ENOENT, bootflow_scan_next(&iter, &bflow));
306         ut_asserteq(2, iter.num_methods);
307         ut_asserteq(0, iter.cur_method);
308         ut_asserteq(2, iter.part);
309         ut_asserteq(0x1e, iter.max_part);
310         ut_asserteq_str("syslinux", iter.method->name);
311         ut_asserteq(0, bflow.err);
312         ut_asserteq(BOOTFLOWST_MEDIA, bflow.state);
313         bootflow_free(&bflow);
314
315         bootflow_iter_uninit(&iter);
316
317         ut_assert_console_end();
318
319         return 0;
320 }
321 BOOTSTD_TEST(bootflow_iter, UT_TESTF_DM | UT_TESTF_SCAN_FDT);
322
323 /* Check using the system bootdev */
324 static int bootflow_system(struct unit_test_state *uts)
325 {
326         struct udevice *dev;
327
328         ut_assertok(uclass_get_device_by_name(UCLASS_BOOTMETH, "efi_mgr",
329                                               &dev));
330         sandbox_set_fake_efi_mgr_dev(dev, true);
331
332         /* We should get a single 'bootmgr' method right at the end */
333         bootstd_clear_glob();
334         console_record_reset_enable();
335         ut_assertok(run_command("bootflow scan -l", 0));
336         ut_assert_skip_to_line(
337                 "  0  efi_mgr      ready   (none)       0  <NULL>                    <NULL>");
338         ut_assert_skip_to_line("No more bootdevs");
339         ut_assert_skip_to_line("(5 bootflows, 5 valid)");
340         ut_assert_console_end();
341
342         return 0;
343 }
344 BOOTSTD_TEST(bootflow_system, UT_TESTF_DM | UT_TESTF_SCAN_PDATA |
345              UT_TESTF_SCAN_FDT);
346
347 /* Check disabling a bootmethod if it requests it */
348 static int bootflow_iter_disable(struct unit_test_state *uts)
349 {
350         struct udevice *bootstd, *dev;
351         struct bootflow_iter iter;
352         struct bootflow bflow;
353         int i;
354
355         /* Add the EFI bootmgr driver */
356         ut_assertok(uclass_first_device_err(UCLASS_BOOTSTD, &bootstd));
357         ut_assertok(device_bind_driver(bootstd, "bootmeth_sandbox", "sandbox",
358                                        &dev));
359
360         ut_assertok(bootstd_test_drop_bootdev_order(uts));
361
362         bootstd_clear_glob();
363         console_record_reset_enable();
364         ut_assertok(inject_response(uts));
365         ut_assertok(run_command("bootflow scan -lb", 0));
366
367         /* Try to boot the bootmgr flow, which will fail */
368         console_record_reset_enable();
369         ut_assertok(bootflow_scan_first(&iter, 0, &bflow));
370         ut_asserteq(3, iter.num_methods);
371         ut_asserteq_str("sandbox", iter.method->name);
372         ut_assertok(inject_response(uts));
373         ut_asserteq(-ENOTSUPP, bootflow_run_boot(&iter, &bflow));
374
375         ut_assert_skip_to_line("Boot method 'sandbox' failed and will not be retried");
376         ut_assert_console_end();
377
378         /* Check that the sandbox bootmeth has been removed */
379         ut_asserteq(2, iter.num_methods);
380         for (i = 0; i < iter.num_methods; i++)
381                 ut_assert(strcmp("sandbox", iter.method_order[i]->name));
382
383         return 0;
384 }
385 BOOTSTD_TEST(bootflow_iter_disable, UT_TESTF_DM | UT_TESTF_SCAN_FDT);
386
387 /* Check 'bootflow boot' to boot a selected bootflow */
388 static int bootflow_cmd_boot(struct unit_test_state *uts)
389 {
390         console_record_reset_enable();
391         ut_assertok(run_command("bootdev select 1", 0));
392         ut_assert_console_end();
393         ut_assertok(run_command("bootflow scan", 0));
394         ut_assert_console_end();
395         ut_assertok(run_command("bootflow select 0", 0));
396         ut_assert_console_end();
397
398         ut_assertok(inject_response(uts));
399         ut_asserteq(1, run_command("bootflow boot", 0));
400         ut_assert_nextline(
401                 "** Booting bootflow 'mmc1.bootdev.part_1' with syslinux");
402         ut_assert_nextline("Ignoring unknown command: ui");
403
404         /*
405          * We expect it to get through to boot although sandbox always returns
406          * -EFAULT as it cannot actually boot the kernel
407          */
408         ut_assert_skip_to_line("sandbox: continuing, as we cannot run Linux");
409         ut_assert_nextline("Boot failed (err=-14)");
410         ut_assert_console_end();
411
412         return 0;
413 }
414 BOOTSTD_TEST(bootflow_cmd_boot, UT_TESTF_DM | UT_TESTF_SCAN_FDT);
This page took 0.051539 seconds and 4 git commands to generate.