1 // SPDX-License-Identifier: GPL-2.0+
2 /*
3  * Test for bootdev functions. All start with 'bootmeth'
4  *
5  * Copyright 2021 Google LLC
6  * Written by Simon Glass <sjg@chromium.org>
7  */
8 
9 #include <bootmeth.h>
10 #include <bootstd.h>
11 #include <dm.h>
12 #include <env.h>
13 #include <test/ut.h>
14 #include "bootstd_common.h"
15 
16 /* Check 'bootmeth list' command */
bootmeth_cmd_list(struct unit_test_state * uts)17 static int bootmeth_cmd_list(struct unit_test_state *uts)
18 {
19 	ut_assertok(run_command("bootmeth list", 0));
20 	ut_assert_nextline("Order  Seq  Name                Description");
21 	ut_assert_nextlinen("---");
22 	ut_assert_nextline("    0    0  extlinux            Extlinux boot from a block device");
23 	ut_assert_nextline("    1    1  efi                 EFI boot from an .efi file");
24 	if (IS_ENABLED(CONFIG_BOOTMETH_GLOBAL))
25 		ut_assert_nextline(" glob    2  firmware0           VBE simple");
26 	ut_assert_nextlinen("---");
27 	ut_assert_nextline(IS_ENABLED(CONFIG_BOOTMETH_GLOBAL) ?
28 		 "(3 bootmeths)" : "(2 bootmeths)");
29 	ut_assert_console_end();
30 
31 	return 0;
32 }
33 BOOTSTD_TEST(bootmeth_cmd_list, UTF_DM | UTF_SCAN_FDT | UTF_CONSOLE);
34 
35 /* Check 'bootmeth order' command */
bootmeth_cmd_order(struct unit_test_state * uts)36 static int bootmeth_cmd_order(struct unit_test_state *uts)
37 {
38 	/* Select just one bootmethod */
39 	ut_assertok(run_command("bootmeth order extlinux", 0));
40 	ut_assert_console_end();
41 	ut_assertnonnull(env_get("bootmeths"));
42 	ut_asserteq_str("extlinux", env_get("bootmeths"));
43 
44 	/* Only that one should be listed */
45 	ut_assertok(run_command("bootmeth list", 0));
46 	ut_assert_nextline("Order  Seq  Name                Description");
47 	ut_assert_nextlinen("---");
48 	ut_assert_nextline("    0    0  extlinux            Extlinux boot from a block device");
49 	ut_assert_nextlinen("---");
50 	ut_assert_nextline("(1 bootmeth)");
51 	ut_assert_console_end();
52 
53 	/* Check the -a flag, efi should show as not in the order ("-") */
54 	ut_assertok(run_command("bootmeth list -a", 0));
55 	ut_assert_nextline("Order  Seq  Name                Description");
56 	ut_assert_nextlinen("---");
57 	ut_assert_nextline("    0    0  extlinux            Extlinux boot from a block device");
58 	ut_assert_nextline("    -    1  efi                 EFI boot from an .efi file");
59 	if (IS_ENABLED(CONFIG_BOOTMETH_GLOBAL))
60 		ut_assert_nextline(" glob    2  firmware0           VBE simple");
61 	ut_assert_nextlinen("---");
62 	ut_assert_nextline(IS_ENABLED(CONFIG_BOOTMETH_GLOBAL) ?
63 		 "(3 bootmeths)" : "(2 bootmeths)");
64 	ut_assert_console_end();
65 
66 	/* Check the -a flag with the reverse order */
67 	ut_assertok(run_command("bootmeth order \"efi extlinux\"", 0));
68 	ut_assert_console_end();
69 	ut_assertok(run_command("bootmeth list -a", 0));
70 	ut_assert_nextline("Order  Seq  Name                Description");
71 	ut_assert_nextlinen("---");
72 	ut_assert_nextline("    1    0  extlinux            Extlinux boot from a block device");
73 	ut_assert_nextline("    0    1  efi                 EFI boot from an .efi file");
74 	if (IS_ENABLED(CONFIG_BOOTMETH_GLOBAL))
75 		ut_assert_nextline(" glob    2  firmware0           VBE simple");
76 	ut_assert_nextlinen("---");
77 	ut_assert_nextline(IS_ENABLED(CONFIG_BOOTMETH_GLOBAL) ?
78 		 "(3 bootmeths)" : "(2 bootmeths)");
79 	ut_assert_console_end();
80 
81 	/* Now reset the order to empty, which should show all of them again */
82 	ut_assertok(run_command("bootmeth order", 0));
83 	ut_assert_console_end();
84 	ut_assertnull(env_get("bootmeths"));
85 	ut_assertok(run_command("bootmeth list", 0));
86 	ut_assert_skip_to_line(IS_ENABLED(CONFIG_BOOTMETH_GLOBAL) ?
87 		 "(3 bootmeths)" : "(2 bootmeths)");
88 
89 	/* Try reverse order */
90 	ut_assertok(run_command("bootmeth order \"efi extlinux\"", 0));
91 	ut_assert_console_end();
92 	ut_assertok(run_command("bootmeth list", 0));
93 	ut_assert_nextline("Order  Seq  Name                Description");
94 	ut_assert_nextlinen("---");
95 	ut_assert_nextline("    0    1  efi                 EFI boot from an .efi file");
96 	ut_assert_nextline("    1    0  extlinux            Extlinux boot from a block device");
97 	ut_assert_nextlinen("---");
98 	ut_assert_nextline("(2 bootmeths)");
99 	ut_assertnonnull(env_get("bootmeths"));
100 	ut_asserteq_str("efi extlinux", env_get("bootmeths"));
101 	ut_assert_console_end();
102 
103 	return 0;
104 }
105 BOOTSTD_TEST(bootmeth_cmd_order, UTF_DM | UTF_SCAN_FDT | UTF_CONSOLE);
106 
107 /* Check 'bootmeth order' command with global bootmeths */
bootmeth_cmd_order_glob(struct unit_test_state * uts)108 static int bootmeth_cmd_order_glob(struct unit_test_state *uts)
109 {
110 	if (!IS_ENABLED(CONFIG_BOOTMETH_GLOBAL))
111 		return -EAGAIN;
112 
113 	ut_assertok(run_command("bootmeth order \"efi firmware0\"", 0));
114 	ut_assert_console_end();
115 	ut_assertok(run_command("bootmeth list", 0));
116 	ut_assert_nextline("Order  Seq  Name                Description");
117 	ut_assert_nextlinen("---");
118 	ut_assert_nextline("    0    1  efi                 EFI boot from an .efi file");
119 	ut_assert_nextline(" glob    2  firmware0           VBE simple");
120 	ut_assert_nextlinen("---");
121 	ut_assert_nextline("(2 bootmeths)");
122 	ut_assertnonnull(env_get("bootmeths"));
123 	ut_asserteq_str("efi firmware0", env_get("bootmeths"));
124 	ut_assert_console_end();
125 
126 	return 0;
127 }
128 BOOTSTD_TEST(bootmeth_cmd_order_glob, UTF_DM | UTF_SCAN_FDT | UTF_CONSOLE);
129 
130 /* Check 'bootmeth set' command */
bootmeth_cmd_set(struct unit_test_state * uts)131 static int bootmeth_cmd_set(struct unit_test_state *uts)
132 {
133 	/* Check we can enable extlinux fallback */
134 	console_record_reset_enable();
135 	ut_assertok(run_command("bootmeth set extlinux fallback 1", 0));
136 	ut_assert_console_end();
137 
138 	/* Check we can disable extlinux fallback */
139 	console_record_reset_enable();
140 	ut_assertok(run_command("bootmeth set extlinux fallback 0", 0));
141 	ut_assert_console_end();
142 
143 	/* Check extlinux fallback unexpected value */
144 	console_record_reset_enable();
145 	ut_asserteq(1, run_command("bootmeth set extlinux fallback fred", 0));
146 	ut_assert_nextline("Unexpected value 'fred'");
147 	ut_assert_nextline("Failed (err=-22)");
148 	ut_assert_console_end();
149 
150 	/* Check that we need to provide right number of parameters */
151 	ut_asserteq(1, run_command("bootmeth set extlinux fallback", 0));
152 	ut_assert_nextline("Required parameters not provided");
153 	ut_assert_console_end();
154 
155 	/* Check that we need to provide a valid bootmethod */
156 	ut_asserteq(1, run_command("bootmeth set fred fallback 0", 0));
157 	ut_assert_nextline("Unknown bootmeth 'fred'");
158 	ut_assert_nextline("Failed (err=-19)");
159 	ut_assert_console_end();
160 
161 	/* Check that we need to provide a valid property */
162 	ut_asserteq(1, run_command("bootmeth set extlinux fred 0", 0));
163 	ut_assert_nextline("Invalid option");
164 	ut_assert_nextline("Failed (err=-22)");
165 	ut_assert_console_end();
166 
167 	/* Check that we need to provide a bootmeth that supports properties */
168 	ut_asserteq(1, run_command("bootmeth set efi fallback 0", 0));
169 	ut_assert_nextline("set_property not found");
170 	ut_assert_nextline("Failed (err=-19)");
171 	ut_assert_console_end();
172 
173 	return 0;
174 }
175 BOOTSTD_TEST(bootmeth_cmd_set, UTF_DM | UTF_SCAN_FDT);
176 
177 /* Check 'bootmeths' env var */
bootmeth_env(struct unit_test_state * uts)178 static int bootmeth_env(struct unit_test_state *uts)
179 {
180 	struct bootstd_priv *std;
181 
182 	ut_assertok(bootstd_get_priv(&std));
183 
184 	/* Select just one bootmethod */
185 	ut_assertok(env_set("bootmeths", "extlinux"));
186 	ut_asserteq(1, std->bootmeth_count);
187 
188 	/* Select an invalid bootmethod */
189 	ut_asserteq(1, run_command("setenv bootmeths fred", 0));
190 	ut_assert_nextline("Unknown bootmeth 'fred'");
191 	ut_assert_nextlinen("## Error inserting");
192 	ut_assert_console_end();
193 
194 	ut_assertok(env_set("bootmeths", "efi extlinux"));
195 	ut_asserteq(2, std->bootmeth_count);
196 	ut_assert_console_end();
197 
198 	return 0;
199 }
200 BOOTSTD_TEST(bootmeth_env, UTF_DM | UTF_SCAN_FDT | UTF_CONSOLE);
201 
202 /* Check the get_state_desc() method */
bootmeth_state(struct unit_test_state * uts)203 static int bootmeth_state(struct unit_test_state *uts)
204 {
205 	struct udevice *dev;
206 	char buf[50];
207 
208 	ut_assertok(uclass_first_device_err(UCLASS_BOOTMETH, &dev));
209 	ut_assertnonnull(dev);
210 
211 	ut_assertok(bootmeth_get_state_desc(dev, buf, sizeof(buf)));
212 	ut_asserteq_str("OK", buf);
213 
214 	return 0;
215 }
216 BOOTSTD_TEST(bootmeth_state, UTF_DM | UTF_SCAN_FDT);
217