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