blob: 4a47265ebd5d25108d53ac0a20b681118ecd26e0 [file] [log] [blame]
Simon Glass2d653f62022-04-24 23:31:11 -06001// SPDX-License-Identifier: GPL-2.0+
2/*
3 * 'bootflow' command
4 *
5 * Copyright 2021 Google LLC
6 * Written by Simon Glass <sjg@chromium.org>
7 */
8
9#include <common.h>
10#include <bootdev.h>
11#include <bootflow.h>
Simon Glasscbb607d2023-07-30 11:17:00 -060012#include <bootm.h>
Simon Glass2d653f62022-04-24 23:31:11 -060013#include <bootstd.h>
14#include <command.h>
15#include <console.h>
16#include <dm.h>
17#include <mapmem.h>
18
19/**
20 * report_bootflow_err() - Report where a bootflow failed
21 *
22 * When a bootflow does not make it to the 'loaded' state, something went wrong.
23 * Print a helpful message if there is an error
24 *
25 * @bflow: Bootflow to process
26 * @err: Error code (0 if none)
27 */
28static void report_bootflow_err(struct bootflow *bflow, int err)
29{
30 if (!err)
31 return;
32
33 /* Indent out to 'Method' */
34 printf(" ** ");
35
36 switch (bflow->state) {
37 case BOOTFLOWST_BASE:
38 printf("No media/partition found");
39 break;
40 case BOOTFLOWST_MEDIA:
41 printf("No partition found");
42 break;
43 case BOOTFLOWST_PART:
44 printf("No filesystem found");
45 break;
46 case BOOTFLOWST_FS:
47 printf("File not found");
48 break;
49 case BOOTFLOWST_FILE:
50 printf("File cannot be loaded");
51 break;
52 case BOOTFLOWST_READY:
53 printf("Ready");
54 break;
55 case BOOTFLOWST_COUNT:
56 break;
57 }
58
Simon Glassc8894342023-05-10 16:34:26 -060059 printf(", err=%dE\n", err);
Simon Glass2d653f62022-04-24 23:31:11 -060060}
61
62/**
63 * show_bootflow() - Show the status of a bootflow
64 *
65 * @seq: Bootflow index
66 * @bflow: Bootflow to show
67 * @errors: True to show the error received, if any
68 */
69static void show_bootflow(int index, struct bootflow *bflow, bool errors)
70{
71 printf("%3x %-11s %-6s %-9.9s %4x %-25.25s %s\n", index,
72 bflow->method->name, bootflow_state_get_name(bflow->state),
Simon Glasseccb25c2022-07-30 15:52:23 -060073 bflow->dev ? dev_get_uclass_name(dev_get_parent(bflow->dev)) :
Simon Glassc3867e22023-08-24 13:55:39 -060074 "(none)", bflow->part, bflow->name, bflow->fname ?: "");
Simon Glass2d653f62022-04-24 23:31:11 -060075 if (errors)
76 report_bootflow_err(bflow, bflow->err);
77}
78
79static void show_header(void)
80{
81 printf("Seq Method State Uclass Part Name Filename\n");
82 printf("--- ----------- ------ -------- ---- ------------------------ ----------------\n");
83}
84
85static void show_footer(int count, int num_valid)
86{
87 printf("--- ----------- ------ -------- ---- ------------------------ ----------------\n");
88 printf("(%d bootflow%s, %d valid)\n", count, count != 1 ? "s" : "",
89 num_valid);
90}
91
Simon Glass3fa53b92023-10-01 19:14:38 -060092/**
93 * bootflow_handle_menu() - Handle running the menu and updating cur bootflow
94 *
95 * This shows the menu, allows the user to select something and then prints
96 * what happened
97 *
98 * @std: bootstd information
99 * @text_mode: true to run the menu in text mode
100 * @bflowp: Returns selected bootflow, on success
101 * Return: 0 on success (a bootflow was selected), -EAGAIN if nothing was
102 * chosen, other -ve value on other error
103 */
104__maybe_unused static int bootflow_handle_menu(struct bootstd_priv *std,
105 bool text_mode,
106 struct bootflow **bflowp)
107{
108 struct bootflow *bflow;
109 int ret;
110
111 ret = bootflow_menu_run(std, text_mode, &bflow);
112 if (ret) {
113 if (ret == -EAGAIN) {
114 printf("Nothing chosen\n");
115 std->cur_bootflow = NULL;
116 } else {
117 printf("Menu failed (err=%d)\n", ret);
118 }
119
120 return ret;
121 }
122
123 printf("Selected: %s\n", bflow->os_name ? bflow->os_name : bflow->name);
124 std->cur_bootflow = bflow;
125 *bflowp = bflow;
126
127 return 0;
128}
129
Simon Glass2d653f62022-04-24 23:31:11 -0600130static int do_bootflow_scan(struct cmd_tbl *cmdtp, int flag, int argc,
131 char *const argv[])
132{
133 struct bootstd_priv *std;
134 struct bootflow_iter iter;
Simon Glass91943ff2023-01-17 10:48:15 -0700135 struct udevice *dev = NULL;
Simon Glass2d653f62022-04-24 23:31:11 -0600136 struct bootflow bflow;
Simon Glass2b80bc12022-07-30 15:52:25 -0600137 bool all = false, boot = false, errors = false, no_global = false;
Simon Glassa4bee0b2023-10-01 19:15:25 -0600138 bool list = false, no_hunter = false, menu = false, text_mode = false;
Simon Glass2d653f62022-04-24 23:31:11 -0600139 int num_valid = 0;
Simon Glass91943ff2023-01-17 10:48:15 -0700140 const char *label = NULL;
Simon Glass2d653f62022-04-24 23:31:11 -0600141 bool has_args;
142 int ret, i;
143 int flags;
144
145 ret = bootstd_get_priv(&std);
146 if (ret)
147 return CMD_RET_FAILURE;
Simon Glass2d653f62022-04-24 23:31:11 -0600148
149 has_args = argc > 1 && *argv[1] == '-';
150 if (IS_ENABLED(CONFIG_CMD_BOOTFLOW_FULL)) {
151 if (has_args) {
152 all = strchr(argv[1], 'a');
153 boot = strchr(argv[1], 'b');
154 errors = strchr(argv[1], 'e');
Simon Glass2b80bc12022-07-30 15:52:25 -0600155 no_global = strchr(argv[1], 'G');
Simon Glass2d653f62022-04-24 23:31:11 -0600156 list = strchr(argv[1], 'l');
Simon Glassd73420e2023-01-17 10:48:06 -0700157 no_hunter = strchr(argv[1], 'H');
Simon Glassa4bee0b2023-10-01 19:15:25 -0600158 menu = strchr(argv[1], 'm');
159 text_mode = strchr(argv[1], 't');
Simon Glass2d653f62022-04-24 23:31:11 -0600160 argc--;
161 argv++;
162 }
Simon Glass91943ff2023-01-17 10:48:15 -0700163 if (argc > 1)
164 label = argv[1];
165 if (!label)
166 dev = std->cur_bootdev;
Simon Glass2d653f62022-04-24 23:31:11 -0600167 } else {
168 if (has_args) {
Simon Glassd8d40bc2023-05-06 08:27:09 -0600169 printf("Flags not supported: enable CONFIG_BOOTSTD_FULL\n");
Simon Glass2d653f62022-04-24 23:31:11 -0600170 return CMD_RET_USAGE;
171 }
172 boot = true;
173 }
174
175 std->cur_bootflow = NULL;
176
177 flags = 0;
178 if (list)
Simon Glass4f806f32023-02-22 12:17:03 -0700179 flags |= BOOTFLOWIF_SHOW;
Simon Glass2d653f62022-04-24 23:31:11 -0600180 if (all)
Simon Glass4f806f32023-02-22 12:17:03 -0700181 flags |= BOOTFLOWIF_ALL;
Simon Glass2b80bc12022-07-30 15:52:25 -0600182 if (no_global)
Simon Glass4f806f32023-02-22 12:17:03 -0700183 flags |= BOOTFLOWIF_SKIP_GLOBAL;
Simon Glassd73420e2023-01-17 10:48:06 -0700184 if (!no_hunter)
Simon Glass4f806f32023-02-22 12:17:03 -0700185 flags |= BOOTFLOWIF_HUNT;
Simon Glass2d653f62022-04-24 23:31:11 -0600186
187 /*
188 * If we have a device, just scan for bootflows attached to that device
189 */
Simon Glass91943ff2023-01-17 10:48:15 -0700190 if (list) {
191 printf("Scanning for bootflows ");
192 if (dev)
193 printf("in bootdev '%s'\n", dev->name);
194 else if (label)
195 printf("with label '%s'\n", label);
196 else
197 printf("in all bootdevs\n");
198 show_header();
199 }
200 if (dev)
Simon Glass2d653f62022-04-24 23:31:11 -0600201 bootdev_clear_bootflows(dev);
Simon Glass91943ff2023-01-17 10:48:15 -0700202 else
Simon Glass2d653f62022-04-24 23:31:11 -0600203 bootstd_clear_glob();
Simon Glass91943ff2023-01-17 10:48:15 -0700204 for (i = 0,
Simon Glass4b7cb052023-01-17 10:48:16 -0700205 ret = bootflow_scan_first(dev, label, &iter, flags, &bflow);
Simon Glass91943ff2023-01-17 10:48:15 -0700206 i < 1000 && ret != -ENODEV;
207 i++, ret = bootflow_scan_next(&iter, &bflow)) {
208 bflow.err = ret;
209 if (!ret)
210 num_valid++;
211 ret = bootdev_add_bootflow(&bflow);
212 if (ret) {
213 printf("Out of memory\n");
214 return CMD_RET_FAILURE;
Simon Glass2d653f62022-04-24 23:31:11 -0600215 }
Simon Glass91943ff2023-01-17 10:48:15 -0700216 if (list)
217 show_bootflow(i, &bflow, errors);
Simon Glassa4bee0b2023-10-01 19:15:25 -0600218 if (!menu && boot && !bflow.err)
Simon Glass91943ff2023-01-17 10:48:15 -0700219 bootflow_run_boot(&iter, &bflow);
Simon Glass2d653f62022-04-24 23:31:11 -0600220 }
221 bootflow_iter_uninit(&iter);
222 if (list)
223 show_footer(i, num_valid);
224
Simon Glassa4bee0b2023-10-01 19:15:25 -0600225 if (IS_ENABLED(CONFIG_CMD_BOOTFLOW_FULL) && IS_ENABLED(CONFIG_EXPO)) {
226 if (!num_valid && !list) {
227 printf("No bootflows found; try again with -l\n");
228 } else if (menu) {
229 struct bootflow *sel_bflow;
230
231 ret = bootflow_handle_menu(std, text_mode, &sel_bflow);
232 if (!ret && boot) {
233 ret = console_clear();
234 if (ret) {
235 log_err("Failed to clear console: %dE\n",
236 ret);
237 return ret;
238 }
239
240 bootflow_run_boot(NULL, sel_bflow);
241 }
242 }
243 }
Simon Glassf9fb57c2023-04-24 13:49:48 +1200244
Simon Glass2d653f62022-04-24 23:31:11 -0600245 return 0;
246}
247
248#ifdef CONFIG_CMD_BOOTFLOW_FULL
249static int do_bootflow_list(struct cmd_tbl *cmdtp, int flag, int argc,
250 char *const argv[])
251{
252 struct bootstd_priv *std;
253 struct udevice *dev;
254 struct bootflow *bflow;
255 int num_valid = 0;
256 bool errors = false;
257 int ret, i;
258
259 if (argc > 1 && *argv[1] == '-')
260 errors = strchr(argv[1], 'e');
261
262 ret = bootstd_get_priv(&std);
263 if (ret)
264 return CMD_RET_FAILURE;
265 dev = std->cur_bootdev;
266
267 /* If we have a device, just list bootflows attached to that device */
268 if (dev) {
269 printf("Showing bootflows for bootdev '%s'\n", dev->name);
270 show_header();
271 for (ret = bootdev_first_bootflow(dev, &bflow), i = 0;
272 !ret;
273 ret = bootdev_next_bootflow(&bflow), i++) {
274 num_valid += bflow->state == BOOTFLOWST_READY;
275 show_bootflow(i, bflow, errors);
276 }
277 } else {
278 printf("Showing all bootflows\n");
279 show_header();
280 for (ret = bootflow_first_glob(&bflow), i = 0;
281 !ret;
282 ret = bootflow_next_glob(&bflow), i++) {
283 num_valid += bflow->state == BOOTFLOWST_READY;
284 show_bootflow(i, bflow, errors);
285 }
286 }
287 show_footer(i, num_valid);
288
289 return 0;
290}
291
292static int do_bootflow_select(struct cmd_tbl *cmdtp, int flag, int argc,
293 char *const argv[])
294{
295 struct bootstd_priv *std;
296 struct bootflow *bflow, *found;
297 struct udevice *dev;
298 const char *name;
299 char *endp;
300 int seq, i;
301 int ret;
302
303 ret = bootstd_get_priv(&std);
304 if (ret)
305 return CMD_RET_FAILURE;
306;
307 if (argc < 2) {
308 std->cur_bootflow = NULL;
309 return 0;
310 }
311 dev = std->cur_bootdev;
312
313 name = argv[1];
314 seq = simple_strtol(name, &endp, 16);
315 found = NULL;
316
317 /*
318 * If we have a bootdev device, only allow selection of bootflows
319 * attached to that device
320 */
321 if (dev) {
322 for (ret = bootdev_first_bootflow(dev, &bflow), i = 0;
323 !ret;
324 ret = bootdev_next_bootflow(&bflow), i++) {
325 if (*endp ? !strcmp(bflow->name, name) : i == seq) {
326 found = bflow;
327 break;
328 }
329 }
330 } else {
331 for (ret = bootflow_first_glob(&bflow), i = 0;
332 !ret;
333 ret = bootflow_next_glob(&bflow), i++) {
334 if (*endp ? !strcmp(bflow->name, name) : i == seq) {
335 found = bflow;
336 break;
337 }
338 }
339 }
340
341 if (!found) {
342 printf("Cannot find bootflow '%s' ", name);
343 if (dev)
344 printf("in bootdev '%s' ", dev->name);
345 printf("(err=%d)\n", ret);
346 return CMD_RET_FAILURE;
347 }
348 std->cur_bootflow = found;
Simon Glassd42243f2023-07-12 09:04:35 -0600349 if (IS_ENABLED(CONFIG_BOOTSTD_FULL)) {
350 if (env_set("bootargs", found->cmdline)) {
351 printf("Cannot set bootargs\n");
352 return CMD_RET_FAILURE;
353 }
354 }
Simon Glass2d653f62022-04-24 23:31:11 -0600355
356 return 0;
357}
358
359static int do_bootflow_info(struct cmd_tbl *cmdtp, int flag, int argc,
360 char *const argv[])
361{
362 struct bootstd_priv *std;
363 struct bootflow *bflow;
Simon Glasscbb607d2023-07-30 11:17:00 -0600364 bool x86_setup = false;
Simon Glass2d653f62022-04-24 23:31:11 -0600365 bool dump = false;
366 int ret;
367
Simon Glasscbb607d2023-07-30 11:17:00 -0600368 if (argc > 1 && *argv[1] == '-') {
Simon Glass2d653f62022-04-24 23:31:11 -0600369 dump = strchr(argv[1], 'd');
Simon Glasscbb607d2023-07-30 11:17:00 -0600370 x86_setup = strchr(argv[1], 's');
371 }
Simon Glass2d653f62022-04-24 23:31:11 -0600372
373 ret = bootstd_get_priv(&std);
374 if (ret)
375 return CMD_RET_FAILURE;
376
377 if (!std->cur_bootflow) {
378 printf("No bootflow selected\n");
379 return CMD_RET_FAILURE;
380 }
381 bflow = std->cur_bootflow;
382
Simon Glasscbb607d2023-07-30 11:17:00 -0600383 if (IS_ENABLED(CONFIG_X86) && x86_setup) {
384 zimage_dump(bflow->x86_setup, false);
385
386 return 0;
387 }
388
Simon Glass2d653f62022-04-24 23:31:11 -0600389 printf("Name: %s\n", bflow->name);
390 printf("Device: %s\n", bflow->dev->name);
391 printf("Block dev: %s\n", bflow->blk ? bflow->blk->name : "(none)");
392 printf("Method: %s\n", bflow->method->name);
393 printf("State: %s\n", bootflow_state_get_name(bflow->state));
394 printf("Partition: %d\n", bflow->part);
395 printf("Subdir: %s\n", bflow->subdir ? bflow->subdir : "(none)");
396 printf("Filename: %s\n", bflow->fname);
397 printf("Buffer: %lx\n", (ulong)map_to_sysmem(bflow->buf));
398 printf("Size: %x (%d bytes)\n", bflow->size, bflow->size);
Simon Glass2175e762023-01-06 08:52:33 -0600399 printf("OS: %s\n", bflow->os_name ? bflow->os_name : "(none)");
Simon Glassf4a91652023-07-12 09:04:34 -0600400 printf("Cmdline: ");
401 if (bflow->cmdline)
402 puts(bflow->cmdline);
403 else
404 puts("(none)");
405 putc('\n');
Simon Glass43b6fa92023-07-12 09:04:36 -0600406 if (bflow->x86_setup)
407 printf("X86 setup: %p\n", bflow->x86_setup);
Simon Glass24d8e1b2023-01-06 08:52:34 -0600408 printf("Logo: %s\n", bflow->logo ?
409 simple_xtoa((ulong)map_to_sysmem(bflow->logo)) : "(none)");
410 if (bflow->logo) {
411 printf("Logo size: %x (%d bytes)\n", bflow->logo_size,
412 bflow->logo_size);
413 }
Simon Glass7638c852023-01-17 10:47:56 -0700414 printf("FDT: %s\n", bflow->fdt_fname);
415 if (bflow->fdt_fname) {
416 printf("FDT size: %x (%d bytes)\n", bflow->fdt_size,
417 bflow->fdt_size);
418 printf("FDT addr: %lx\n", bflow->fdt_addr);
419 }
Simon Glass2d653f62022-04-24 23:31:11 -0600420 printf("Error: %d\n", bflow->err);
421 if (dump && bflow->buf) {
422 /* Set some sort of maximum on the size */
423 int size = min(bflow->size, 10 << 10);
424 int i;
425
426 printf("Contents:\n\n");
427 for (i = 0; i < size; i++) {
428 putc(bflow->buf[i]);
429 if (!(i % 128) && ctrlc()) {
430 printf("...interrupted\n");
431 break;
432 }
433 }
434 }
435
436 return 0;
437}
438
Simon Glassc2792242023-08-10 19:33:18 -0600439static int do_bootflow_read(struct cmd_tbl *cmdtp, int flag, int argc,
440 char *const argv[])
441{
442 struct bootstd_priv *std;
443 struct bootflow *bflow;
444 int ret;
445
446 ret = bootstd_get_priv(&std);
447 if (ret)
448 return CMD_RET_FAILURE;
449
450 /*
451 * Require a current bootflow. Users can use 'bootflow scan -b' to
452 * automatically scan and boot, if needed.
453 */
454 if (!std->cur_bootflow) {
455 printf("No bootflow selected\n");
456 return CMD_RET_FAILURE;
457 }
458 bflow = std->cur_bootflow;
459 ret = bootflow_read_all(bflow);
460 if (ret) {
461 printf("Failed: err=%dE\n", ret);
462 return CMD_RET_FAILURE;
463 }
464
465 return 0;
466}
467
Simon Glass2d653f62022-04-24 23:31:11 -0600468static int do_bootflow_boot(struct cmd_tbl *cmdtp, int flag, int argc,
469 char *const argv[])
470{
471 struct bootstd_priv *std;
472 struct bootflow *bflow;
473 int ret;
474
475 ret = bootstd_get_priv(&std);
476 if (ret)
477 return CMD_RET_FAILURE;
478
479 /*
480 * Require a current bootflow. Users can use 'bootflow scan -b' to
481 * automatically scan and boot, if needed.
482 */
483 if (!std->cur_bootflow) {
484 printf("No bootflow selected\n");
485 return CMD_RET_FAILURE;
486 }
487 bflow = std->cur_bootflow;
488 ret = bootflow_run_boot(NULL, bflow);
489 if (ret)
490 return CMD_RET_FAILURE;
491
492 return 0;
493}
Simon Glass02d929b2023-01-06 08:52:40 -0600494
495static int do_bootflow_menu(struct cmd_tbl *cmdtp, int flag, int argc,
496 char *const argv[])
497{
498 struct bootstd_priv *std;
499 struct bootflow *bflow;
500 bool text_mode = false;
501 int ret;
502
Tom Rinie0dda262023-04-06 10:03:33 -0400503 if (!IS_ENABLED(CONFIG_EXPO)) {
504 printf("Menu not supported\n");
505 return CMD_RET_FAILURE;
506 }
507
Simon Glass02d929b2023-01-06 08:52:40 -0600508 if (argc > 1 && *argv[1] == '-')
509 text_mode = strchr(argv[1], 't');
510
511 ret = bootstd_get_priv(&std);
512 if (ret)
513 return CMD_RET_FAILURE;
514
Simon Glass3fa53b92023-10-01 19:14:38 -0600515 ret = bootflow_handle_menu(std, text_mode, &bflow);
516 if (ret)
517 return CMD_RET_FAILURE;
Simon Glass02d929b2023-01-06 08:52:40 -0600518
519 return 0;
520}
Simon Glass82c09382023-07-12 09:04:39 -0600521
522static int do_bootflow_cmdline(struct cmd_tbl *cmdtp, int flag, int argc,
523 char *const argv[])
524{
525 struct bootstd_priv *std;
526 struct bootflow *bflow;
527 const char *op, *arg, *val = NULL;
528 int ret;
529
530 if (argc < 3)
531 return CMD_RET_USAGE;
532
533 ret = bootstd_get_priv(&std);
534 if (ret)
535 return CMD_RET_FAILURE;
536
537 bflow = std->cur_bootflow;
538 if (!bflow) {
539 printf("No bootflow selected\n");
540 return CMD_RET_FAILURE;
541 }
542
543 op = argv[1];
544 arg = argv[2];
545 if (*op == 's') {
546 if (argc < 4)
547 return CMD_RET_USAGE;
548 val = argv[3];
549 }
550
551 switch (*op) {
552 case 'c': /* clear */
553 val = "";
554 fallthrough;
555 case 's': /* set */
556 case 'd': /* delete */
557 ret = bootflow_cmdline_set_arg(bflow, arg, val, true);
558 break;
559 case 'g': /* get */
560 ret = bootflow_cmdline_get_arg(bflow, arg, &val);
561 if (ret >= 0)
562 printf("%.*s\n", ret, val);
563 break;
Simon Glass33ebcb42023-07-12 09:04:42 -0600564 case 'a': /* auto */
565 ret = bootflow_cmdline_auto(bflow, arg);
566 break;
Simon Glass82c09382023-07-12 09:04:39 -0600567 }
568 switch (ret) {
569 case -E2BIG:
570 printf("Argument too long\n");
571 break;
572 case -ENOENT:
573 printf("Argument not found\n");
574 break;
575 case -EINVAL:
576 printf("Mismatched quotes\n");
577 break;
578 case -EBADF:
579 printf("Value must be quoted\n");
580 break;
581 default:
582 if (ret < 0)
583 printf("Unknown error: %dE\n", ret);
584 }
585 if (ret < 0)
586 return CMD_RET_FAILURE;
587
588 return 0;
589}
Simon Glass2d653f62022-04-24 23:31:11 -0600590#endif /* CONFIG_CMD_BOOTFLOW_FULL */
591
Tom Rini36162182023-10-07 15:13:08 -0400592U_BOOT_LONGHELP(bootflow,
Simon Glass2d653f62022-04-24 23:31:11 -0600593#ifdef CONFIG_CMD_BOOTFLOW_FULL
Simon Glass2b80bc12022-07-30 15:52:25 -0600594 "scan [-abeGl] [bdev] - scan for valid bootflows (-l list, -a all, -e errors, -b boot, -G no global)\n"
Simon Glass2d653f62022-04-24 23:31:11 -0600595 "bootflow list [-e] - list scanned bootflows (-e errors)\n"
596 "bootflow select [<num>|<name>] - select a bootflow\n"
Simon Glasscbb607d2023-07-30 11:17:00 -0600597 "bootflow info [-ds] - show info on current bootflow (-d dump bootflow)\n"
Simon Glassc2792242023-08-10 19:33:18 -0600598 "bootflow read - read all current-bootflow files\n"
599 "bootflow boot - boot current bootflow\n"
Simon Glass82c09382023-07-12 09:04:39 -0600600 "bootflow menu [-t] - show a menu of available bootflows\n"
Tom Rini36162182023-10-07 15:13:08 -0400601 "bootflow cmdline [set|get|clear|delete|auto] <param> [<value>] - update cmdline"
Simon Glass2d653f62022-04-24 23:31:11 -0600602#else
Tom Rini36162182023-10-07 15:13:08 -0400603 "scan - boot first available bootflow\n"
Simon Glass2d653f62022-04-24 23:31:11 -0600604#endif
Tom Rini36162182023-10-07 15:13:08 -0400605 );
Simon Glass2d653f62022-04-24 23:31:11 -0600606
607U_BOOT_CMD_WITH_SUBCMDS(bootflow, "Boot flows", bootflow_help_text,
608 U_BOOT_SUBCMD_MKENT(scan, 3, 1, do_bootflow_scan),
609#ifdef CONFIG_CMD_BOOTFLOW_FULL
610 U_BOOT_SUBCMD_MKENT(list, 2, 1, do_bootflow_list),
611 U_BOOT_SUBCMD_MKENT(select, 2, 1, do_bootflow_select),
612 U_BOOT_SUBCMD_MKENT(info, 2, 1, do_bootflow_info),
Simon Glassc2792242023-08-10 19:33:18 -0600613 U_BOOT_SUBCMD_MKENT(read, 1, 1, do_bootflow_read),
Simon Glass02d929b2023-01-06 08:52:40 -0600614 U_BOOT_SUBCMD_MKENT(boot, 1, 1, do_bootflow_boot),
615 U_BOOT_SUBCMD_MKENT(menu, 2, 1, do_bootflow_menu),
Simon Glass82c09382023-07-12 09:04:39 -0600616 U_BOOT_SUBCMD_MKENT(cmdline, 4, 1, do_bootflow_cmdline),
Simon Glass2d653f62022-04-24 23:31:11 -0600617#endif
618);