blob: 72b06a42e4dfcf92ea50fc29cd9178b6809b9c10 [file] [log] [blame]
Simon Glass7617f492022-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
Simon Glass7617f492022-04-24 23:31:11 -06009#include <bootdev.h>
10#include <bootflow.h>
Simon Glass5495aaf2023-07-30 11:17:00 -060011#include <bootm.h>
Simon Glass7617f492022-04-24 23:31:11 -060012#include <bootstd.h>
13#include <command.h>
14#include <console.h>
15#include <dm.h>
16#include <mapmem.h>
17
18/**
19 * report_bootflow_err() - Report where a bootflow failed
20 *
21 * When a bootflow does not make it to the 'loaded' state, something went wrong.
22 * Print a helpful message if there is an error
23 *
24 * @bflow: Bootflow to process
25 * @err: Error code (0 if none)
26 */
27static void report_bootflow_err(struct bootflow *bflow, int err)
28{
29 if (!err)
30 return;
31
32 /* Indent out to 'Method' */
33 printf(" ** ");
34
35 switch (bflow->state) {
36 case BOOTFLOWST_BASE:
37 printf("No media/partition found");
38 break;
39 case BOOTFLOWST_MEDIA:
40 printf("No partition found");
41 break;
42 case BOOTFLOWST_PART:
43 printf("No filesystem found");
44 break;
45 case BOOTFLOWST_FS:
46 printf("File not found");
47 break;
48 case BOOTFLOWST_FILE:
49 printf("File cannot be loaded");
50 break;
51 case BOOTFLOWST_READY:
52 printf("Ready");
53 break;
54 case BOOTFLOWST_COUNT:
55 break;
56 }
57
Simon Glass9482fdf2023-05-10 16:34:26 -060058 printf(", err=%dE\n", err);
Simon Glass7617f492022-04-24 23:31:11 -060059}
60
61/**
62 * show_bootflow() - Show the status of a bootflow
63 *
64 * @seq: Bootflow index
65 * @bflow: Bootflow to show
66 * @errors: True to show the error received, if any
67 */
68static void show_bootflow(int index, struct bootflow *bflow, bool errors)
69{
70 printf("%3x %-11s %-6s %-9.9s %4x %-25.25s %s\n", index,
71 bflow->method->name, bootflow_state_get_name(bflow->state),
Simon Glassdee4d642022-07-30 15:52:23 -060072 bflow->dev ? dev_get_uclass_name(dev_get_parent(bflow->dev)) :
Simon Glassd465ad52023-08-24 13:55:39 -060073 "(none)", bflow->part, bflow->name, bflow->fname ?: "");
Simon Glass7617f492022-04-24 23:31:11 -060074 if (errors)
75 report_bootflow_err(bflow, bflow->err);
76}
77
78static void show_header(void)
79{
80 printf("Seq Method State Uclass Part Name Filename\n");
81 printf("--- ----------- ------ -------- ---- ------------------------ ----------------\n");
82}
83
84static void show_footer(int count, int num_valid)
85{
86 printf("--- ----------- ------ -------- ---- ------------------------ ----------------\n");
87 printf("(%d bootflow%s, %d valid)\n", count, count != 1 ? "s" : "",
88 num_valid);
89}
90
Simon Glass6d5083b2023-10-01 19:14:38 -060091/**
92 * bootflow_handle_menu() - Handle running the menu and updating cur bootflow
93 *
94 * This shows the menu, allows the user to select something and then prints
95 * what happened
96 *
97 * @std: bootstd information
98 * @text_mode: true to run the menu in text mode
99 * @bflowp: Returns selected bootflow, on success
100 * Return: 0 on success (a bootflow was selected), -EAGAIN if nothing was
101 * chosen, other -ve value on other error
102 */
103__maybe_unused static int bootflow_handle_menu(struct bootstd_priv *std,
104 bool text_mode,
105 struct bootflow **bflowp)
106{
107 struct bootflow *bflow;
108 int ret;
109
110 ret = bootflow_menu_run(std, text_mode, &bflow);
111 if (ret) {
112 if (ret == -EAGAIN) {
113 printf("Nothing chosen\n");
114 std->cur_bootflow = NULL;
115 } else {
116 printf("Menu failed (err=%d)\n", ret);
117 }
118
119 return ret;
120 }
121
122 printf("Selected: %s\n", bflow->os_name ? bflow->os_name : bflow->name);
123 std->cur_bootflow = bflow;
124 *bflowp = bflow;
125
126 return 0;
127}
128
Simon Glass7617f492022-04-24 23:31:11 -0600129static int do_bootflow_scan(struct cmd_tbl *cmdtp, int flag, int argc,
130 char *const argv[])
131{
132 struct bootstd_priv *std;
133 struct bootflow_iter iter;
Simon Glassba3d5372023-01-17 10:48:15 -0700134 struct udevice *dev = NULL;
Simon Glass7617f492022-04-24 23:31:11 -0600135 struct bootflow bflow;
Simon Glass73fcf512022-07-30 15:52:25 -0600136 bool all = false, boot = false, errors = false, no_global = false;
Simon Glass9bf27862023-10-01 19:15:25 -0600137 bool list = false, no_hunter = false, menu = false, text_mode = false;
Simon Glass7617f492022-04-24 23:31:11 -0600138 int num_valid = 0;
Simon Glassba3d5372023-01-17 10:48:15 -0700139 const char *label = NULL;
Simon Glass7617f492022-04-24 23:31:11 -0600140 bool has_args;
141 int ret, i;
142 int flags;
143
144 ret = bootstd_get_priv(&std);
145 if (ret)
146 return CMD_RET_FAILURE;
Simon Glass7617f492022-04-24 23:31:11 -0600147
148 has_args = argc > 1 && *argv[1] == '-';
149 if (IS_ENABLED(CONFIG_CMD_BOOTFLOW_FULL)) {
150 if (has_args) {
151 all = strchr(argv[1], 'a');
152 boot = strchr(argv[1], 'b');
153 errors = strchr(argv[1], 'e');
Simon Glass73fcf512022-07-30 15:52:25 -0600154 no_global = strchr(argv[1], 'G');
Simon Glass7617f492022-04-24 23:31:11 -0600155 list = strchr(argv[1], 'l');
Simon Glassa21e7752023-01-17 10:48:06 -0700156 no_hunter = strchr(argv[1], 'H');
Simon Glass9bf27862023-10-01 19:15:25 -0600157 menu = strchr(argv[1], 'm');
158 text_mode = strchr(argv[1], 't');
Simon Glass7617f492022-04-24 23:31:11 -0600159 argc--;
160 argv++;
161 }
Simon Glassba3d5372023-01-17 10:48:15 -0700162 if (argc > 1)
163 label = argv[1];
164 if (!label)
165 dev = std->cur_bootdev;
Simon Glass7617f492022-04-24 23:31:11 -0600166 } else {
167 if (has_args) {
Simon Glass2d5a8e12023-05-06 08:27:09 -0600168 printf("Flags not supported: enable CONFIG_BOOTSTD_FULL\n");
Simon Glass7617f492022-04-24 23:31:11 -0600169 return CMD_RET_USAGE;
170 }
171 boot = true;
172 }
173
174 std->cur_bootflow = NULL;
175
176 flags = 0;
177 if (list)
Simon Glass99e68182023-02-22 12:17:03 -0700178 flags |= BOOTFLOWIF_SHOW;
Simon Glass7617f492022-04-24 23:31:11 -0600179 if (all)
Simon Glass99e68182023-02-22 12:17:03 -0700180 flags |= BOOTFLOWIF_ALL;
Simon Glass73fcf512022-07-30 15:52:25 -0600181 if (no_global)
Simon Glass99e68182023-02-22 12:17:03 -0700182 flags |= BOOTFLOWIF_SKIP_GLOBAL;
Simon Glassa21e7752023-01-17 10:48:06 -0700183 if (!no_hunter)
Simon Glass99e68182023-02-22 12:17:03 -0700184 flags |= BOOTFLOWIF_HUNT;
Simon Glass7617f492022-04-24 23:31:11 -0600185
186 /*
187 * If we have a device, just scan for bootflows attached to that device
188 */
Simon Glassba3d5372023-01-17 10:48:15 -0700189 if (list) {
190 printf("Scanning for bootflows ");
191 if (dev)
192 printf("in bootdev '%s'\n", dev->name);
193 else if (label)
194 printf("with label '%s'\n", label);
195 else
196 printf("in all bootdevs\n");
197 show_header();
198 }
199 if (dev)
Simon Glass346ab5d2024-11-15 16:19:09 -0700200 bootstd_clear_bootflows_for_bootdev(dev);
Simon Glassba3d5372023-01-17 10:48:15 -0700201 else
Simon Glass7617f492022-04-24 23:31:11 -0600202 bootstd_clear_glob();
Simon Glassba3d5372023-01-17 10:48:15 -0700203 for (i = 0,
Simon Glass5d3d44f2023-01-17 10:48:16 -0700204 ret = bootflow_scan_first(dev, label, &iter, flags, &bflow);
Simon Glassba3d5372023-01-17 10:48:15 -0700205 i < 1000 && ret != -ENODEV;
206 i++, ret = bootflow_scan_next(&iter, &bflow)) {
207 bflow.err = ret;
208 if (!ret)
209 num_valid++;
Simon Glassc01d83f2024-11-15 16:19:08 -0700210 ret = bootstd_add_bootflow(&bflow);
Simon Glass199f5882024-11-15 16:19:12 -0700211 if (ret < 0) {
Simon Glassba3d5372023-01-17 10:48:15 -0700212 printf("Out of memory\n");
213 return CMD_RET_FAILURE;
Simon Glass7617f492022-04-24 23:31:11 -0600214 }
Simon Glassba3d5372023-01-17 10:48:15 -0700215 if (list)
216 show_bootflow(i, &bflow, errors);
Simon Glass9bf27862023-10-01 19:15:25 -0600217 if (!menu && boot && !bflow.err)
Simon Glassba3d5372023-01-17 10:48:15 -0700218 bootflow_run_boot(&iter, &bflow);
Simon Glass7617f492022-04-24 23:31:11 -0600219 }
220 bootflow_iter_uninit(&iter);
221 if (list)
222 show_footer(i, num_valid);
223
Simon Glass9bf27862023-10-01 19:15:25 -0600224 if (IS_ENABLED(CONFIG_CMD_BOOTFLOW_FULL) && IS_ENABLED(CONFIG_EXPO)) {
225 if (!num_valid && !list) {
226 printf("No bootflows found; try again with -l\n");
227 } else if (menu) {
228 struct bootflow *sel_bflow;
229
230 ret = bootflow_handle_menu(std, text_mode, &sel_bflow);
231 if (!ret && boot) {
232 ret = console_clear();
233 if (ret) {
234 log_err("Failed to clear console: %dE\n",
235 ret);
236 return ret;
237 }
238
239 bootflow_run_boot(NULL, sel_bflow);
240 }
241 }
242 }
Simon Glass8f97c672023-04-24 13:49:48 +1200243
Simon Glass7617f492022-04-24 23:31:11 -0600244 return 0;
245}
246
247#ifdef CONFIG_CMD_BOOTFLOW_FULL
248static int do_bootflow_list(struct cmd_tbl *cmdtp, int flag, int argc,
249 char *const argv[])
250{
251 struct bootstd_priv *std;
252 struct udevice *dev;
253 struct bootflow *bflow;
254 int num_valid = 0;
255 bool errors = false;
256 int ret, i;
257
258 if (argc > 1 && *argv[1] == '-')
259 errors = strchr(argv[1], 'e');
260
261 ret = bootstd_get_priv(&std);
262 if (ret)
263 return CMD_RET_FAILURE;
264 dev = std->cur_bootdev;
265
266 /* If we have a device, just list bootflows attached to that device */
267 if (dev) {
268 printf("Showing bootflows for bootdev '%s'\n", dev->name);
269 show_header();
270 for (ret = bootdev_first_bootflow(dev, &bflow), i = 0;
271 !ret;
272 ret = bootdev_next_bootflow(&bflow), i++) {
273 num_valid += bflow->state == BOOTFLOWST_READY;
274 show_bootflow(i, bflow, errors);
275 }
276 } else {
277 printf("Showing all bootflows\n");
278 show_header();
279 for (ret = bootflow_first_glob(&bflow), i = 0;
280 !ret;
281 ret = bootflow_next_glob(&bflow), i++) {
282 num_valid += bflow->state == BOOTFLOWST_READY;
283 show_bootflow(i, bflow, errors);
284 }
285 }
286 show_footer(i, num_valid);
287
288 return 0;
289}
290
291static int do_bootflow_select(struct cmd_tbl *cmdtp, int flag, int argc,
292 char *const argv[])
293{
294 struct bootstd_priv *std;
295 struct bootflow *bflow, *found;
296 struct udevice *dev;
297 const char *name;
298 char *endp;
299 int seq, i;
300 int ret;
301
302 ret = bootstd_get_priv(&std);
303 if (ret)
304 return CMD_RET_FAILURE;
305;
306 if (argc < 2) {
307 std->cur_bootflow = NULL;
308 return 0;
309 }
310 dev = std->cur_bootdev;
311
312 name = argv[1];
313 seq = simple_strtol(name, &endp, 16);
314 found = NULL;
315
316 /*
317 * If we have a bootdev device, only allow selection of bootflows
318 * attached to that device
319 */
320 if (dev) {
321 for (ret = bootdev_first_bootflow(dev, &bflow), i = 0;
322 !ret;
323 ret = bootdev_next_bootflow(&bflow), i++) {
324 if (*endp ? !strcmp(bflow->name, name) : i == seq) {
325 found = bflow;
326 break;
327 }
328 }
329 } else {
330 for (ret = bootflow_first_glob(&bflow), i = 0;
331 !ret;
332 ret = bootflow_next_glob(&bflow), i++) {
333 if (*endp ? !strcmp(bflow->name, name) : i == seq) {
334 found = bflow;
335 break;
336 }
337 }
338 }
339
340 if (!found) {
341 printf("Cannot find bootflow '%s' ", name);
342 if (dev)
343 printf("in bootdev '%s' ", dev->name);
344 printf("(err=%d)\n", ret);
345 return CMD_RET_FAILURE;
346 }
347 std->cur_bootflow = found;
Simon Glassb35513a2023-07-12 09:04:35 -0600348 if (IS_ENABLED(CONFIG_BOOTSTD_FULL)) {
349 if (env_set("bootargs", found->cmdline)) {
350 printf("Cannot set bootargs\n");
351 return CMD_RET_FAILURE;
352 }
353 }
Simon Glass7617f492022-04-24 23:31:11 -0600354
355 return 0;
356}
357
358static int do_bootflow_info(struct cmd_tbl *cmdtp, int flag, int argc,
359 char *const argv[])
360{
361 struct bootstd_priv *std;
362 struct bootflow *bflow;
Simon Glass5495aaf2023-07-30 11:17:00 -0600363 bool x86_setup = false;
Simon Glass7617f492022-04-24 23:31:11 -0600364 bool dump = false;
365 int ret;
366
Simon Glass5495aaf2023-07-30 11:17:00 -0600367 if (argc > 1 && *argv[1] == '-') {
Simon Glass7617f492022-04-24 23:31:11 -0600368 dump = strchr(argv[1], 'd');
Simon Glass5495aaf2023-07-30 11:17:00 -0600369 x86_setup = strchr(argv[1], 's');
370 }
Simon Glass7617f492022-04-24 23:31:11 -0600371
372 ret = bootstd_get_priv(&std);
373 if (ret)
374 return CMD_RET_FAILURE;
375
376 if (!std->cur_bootflow) {
377 printf("No bootflow selected\n");
378 return CMD_RET_FAILURE;
379 }
380 bflow = std->cur_bootflow;
381
Simon Glass5495aaf2023-07-30 11:17:00 -0600382 if (IS_ENABLED(CONFIG_X86) && x86_setup) {
Simon Glass7b15c572025-03-05 17:25:00 -0700383 struct bootm_info bmi;
384
385 bootm_init(&bmi);
386 zimage_dump(&bmi, bflow->x86_setup, false);
Simon Glass5495aaf2023-07-30 11:17:00 -0600387
388 return 0;
389 }
390
Simon Glass7617f492022-04-24 23:31:11 -0600391 printf("Name: %s\n", bflow->name);
392 printf("Device: %s\n", bflow->dev->name);
393 printf("Block dev: %s\n", bflow->blk ? bflow->blk->name : "(none)");
394 printf("Method: %s\n", bflow->method->name);
395 printf("State: %s\n", bootflow_state_get_name(bflow->state));
396 printf("Partition: %d\n", bflow->part);
397 printf("Subdir: %s\n", bflow->subdir ? bflow->subdir : "(none)");
398 printf("Filename: %s\n", bflow->fname);
Simon Glasscdf83fd22024-10-19 09:22:09 -0600399 printf("Buffer: ");
400 if (bflow->buf)
401 printf("%lx\n", (ulong)map_to_sysmem(bflow->buf));
402 else
403 printf("(not loaded)\n");
Simon Glass7617f492022-04-24 23:31:11 -0600404 printf("Size: %x (%d bytes)\n", bflow->size, bflow->size);
Simon Glass72b7b192023-01-06 08:52:33 -0600405 printf("OS: %s\n", bflow->os_name ? bflow->os_name : "(none)");
Simon Glass33927522023-07-12 09:04:34 -0600406 printf("Cmdline: ");
407 if (bflow->cmdline)
408 puts(bflow->cmdline);
409 else
410 puts("(none)");
411 putc('\n');
Simon Glass63398b02023-07-12 09:04:36 -0600412 if (bflow->x86_setup)
Simon Glass2f0128f2024-10-19 09:21:59 -0600413 printf("X86 setup: %lx\n",
414 (ulong)map_to_sysmem(bflow->x86_setup));
Simon Glass612b9cc2023-01-06 08:52:34 -0600415 printf("Logo: %s\n", bflow->logo ?
416 simple_xtoa((ulong)map_to_sysmem(bflow->logo)) : "(none)");
417 if (bflow->logo) {
418 printf("Logo size: %x (%d bytes)\n", bflow->logo_size,
419 bflow->logo_size);
420 }
Simon Glass7b8c6342023-01-17 10:47:56 -0700421 printf("FDT: %s\n", bflow->fdt_fname);
422 if (bflow->fdt_fname) {
423 printf("FDT size: %x (%d bytes)\n", bflow->fdt_size,
424 bflow->fdt_size);
425 printf("FDT addr: %lx\n", bflow->fdt_addr);
426 }
Simon Glass7617f492022-04-24 23:31:11 -0600427 printf("Error: %d\n", bflow->err);
428 if (dump && bflow->buf) {
429 /* Set some sort of maximum on the size */
430 int size = min(bflow->size, 10 << 10);
431 int i;
432
433 printf("Contents:\n\n");
434 for (i = 0; i < size; i++) {
435 putc(bflow->buf[i]);
436 if (!(i % 128) && ctrlc()) {
437 printf("...interrupted\n");
438 break;
439 }
440 }
441 }
442
443 return 0;
444}
445
Simon Glass6d8f95b2023-08-10 19:33:18 -0600446static int do_bootflow_read(struct cmd_tbl *cmdtp, int flag, int argc,
447 char *const argv[])
448{
449 struct bootstd_priv *std;
450 struct bootflow *bflow;
451 int ret;
452
453 ret = bootstd_get_priv(&std);
454 if (ret)
455 return CMD_RET_FAILURE;
456
457 /*
458 * Require a current bootflow. Users can use 'bootflow scan -b' to
459 * automatically scan and boot, if needed.
460 */
461 if (!std->cur_bootflow) {
462 printf("No bootflow selected\n");
463 return CMD_RET_FAILURE;
464 }
465 bflow = std->cur_bootflow;
466 ret = bootflow_read_all(bflow);
467 if (ret) {
468 printf("Failed: err=%dE\n", ret);
469 return CMD_RET_FAILURE;
470 }
471
472 return 0;
473}
474
Simon Glass7617f492022-04-24 23:31:11 -0600475static int do_bootflow_boot(struct cmd_tbl *cmdtp, int flag, int argc,
476 char *const argv[])
477{
478 struct bootstd_priv *std;
479 struct bootflow *bflow;
480 int ret;
481
482 ret = bootstd_get_priv(&std);
483 if (ret)
484 return CMD_RET_FAILURE;
485
486 /*
487 * Require a current bootflow. Users can use 'bootflow scan -b' to
488 * automatically scan and boot, if needed.
489 */
490 if (!std->cur_bootflow) {
491 printf("No bootflow selected\n");
492 return CMD_RET_FAILURE;
493 }
494 bflow = std->cur_bootflow;
495 ret = bootflow_run_boot(NULL, bflow);
496 if (ret)
497 return CMD_RET_FAILURE;
498
499 return 0;
500}
Simon Glass0a2f6a32023-01-06 08:52:40 -0600501
502static int do_bootflow_menu(struct cmd_tbl *cmdtp, int flag, int argc,
503 char *const argv[])
504{
505 struct bootstd_priv *std;
506 struct bootflow *bflow;
507 bool text_mode = false;
508 int ret;
509
Tom Rinif2d51362023-04-06 10:03:33 -0400510 if (!IS_ENABLED(CONFIG_EXPO)) {
511 printf("Menu not supported\n");
512 return CMD_RET_FAILURE;
513 }
514
Simon Glass0a2f6a32023-01-06 08:52:40 -0600515 if (argc > 1 && *argv[1] == '-')
516 text_mode = strchr(argv[1], 't');
517
518 ret = bootstd_get_priv(&std);
519 if (ret)
520 return CMD_RET_FAILURE;
521
Simon Glass6d5083b2023-10-01 19:14:38 -0600522 ret = bootflow_handle_menu(std, text_mode, &bflow);
523 if (ret)
524 return CMD_RET_FAILURE;
Simon Glass0a2f6a32023-01-06 08:52:40 -0600525
526 return 0;
527}
Simon Glass55a2da32023-07-12 09:04:39 -0600528
529static int do_bootflow_cmdline(struct cmd_tbl *cmdtp, int flag, int argc,
530 char *const argv[])
531{
532 struct bootstd_priv *std;
533 struct bootflow *bflow;
534 const char *op, *arg, *val = NULL;
535 int ret;
536
537 if (argc < 3)
538 return CMD_RET_USAGE;
539
540 ret = bootstd_get_priv(&std);
541 if (ret)
542 return CMD_RET_FAILURE;
543
544 bflow = std->cur_bootflow;
545 if (!bflow) {
546 printf("No bootflow selected\n");
547 return CMD_RET_FAILURE;
548 }
549
550 op = argv[1];
551 arg = argv[2];
552 if (*op == 's') {
Simon Glass7a164f82023-11-29 10:31:19 -0700553 val = argv[3] ?: (const char *)BOOTFLOWCL_EMPTY;
Simon Glass55a2da32023-07-12 09:04:39 -0600554 }
555
556 switch (*op) {
557 case 'c': /* clear */
558 val = "";
559 fallthrough;
560 case 's': /* set */
561 case 'd': /* delete */
562 ret = bootflow_cmdline_set_arg(bflow, arg, val, true);
563 break;
564 case 'g': /* get */
565 ret = bootflow_cmdline_get_arg(bflow, arg, &val);
566 if (ret >= 0)
567 printf("%.*s\n", ret, val);
568 break;
Simon Glasscd91e992023-07-12 09:04:42 -0600569 case 'a': /* auto */
570 ret = bootflow_cmdline_auto(bflow, arg);
571 break;
Simon Glass55a2da32023-07-12 09:04:39 -0600572 }
573 switch (ret) {
574 case -E2BIG:
575 printf("Argument too long\n");
576 break;
577 case -ENOENT:
578 printf("Argument not found\n");
579 break;
580 case -EINVAL:
581 printf("Mismatched quotes\n");
582 break;
583 case -EBADF:
584 printf("Value must be quoted\n");
585 break;
586 default:
587 if (ret < 0)
588 printf("Unknown error: %dE\n", ret);
589 }
590 if (ret < 0)
591 return CMD_RET_FAILURE;
592
593 return 0;
594}
Simon Glass7617f492022-04-24 23:31:11 -0600595#endif /* CONFIG_CMD_BOOTFLOW_FULL */
596
Tom Rini03f146c2023-10-07 15:13:08 -0400597U_BOOT_LONGHELP(bootflow,
Simon Glass7617f492022-04-24 23:31:11 -0600598#ifdef CONFIG_CMD_BOOTFLOW_FULL
Simon Glass73fcf512022-07-30 15:52:25 -0600599 "scan [-abeGl] [bdev] - scan for valid bootflows (-l list, -a all, -e errors, -b boot, -G no global)\n"
Simon Glass7617f492022-04-24 23:31:11 -0600600 "bootflow list [-e] - list scanned bootflows (-e errors)\n"
601 "bootflow select [<num>|<name>] - select a bootflow\n"
Simon Glass5495aaf2023-07-30 11:17:00 -0600602 "bootflow info [-ds] - show info on current bootflow (-d dump bootflow)\n"
Simon Glass6d8f95b2023-08-10 19:33:18 -0600603 "bootflow read - read all current-bootflow files\n"
604 "bootflow boot - boot current bootflow\n"
Simon Glass55a2da32023-07-12 09:04:39 -0600605 "bootflow menu [-t] - show a menu of available bootflows\n"
Tom Rini03f146c2023-10-07 15:13:08 -0400606 "bootflow cmdline [set|get|clear|delete|auto] <param> [<value>] - update cmdline"
Simon Glass7617f492022-04-24 23:31:11 -0600607#else
Tom Rini03f146c2023-10-07 15:13:08 -0400608 "scan - boot first available bootflow\n"
Simon Glass7617f492022-04-24 23:31:11 -0600609#endif
Tom Rini03f146c2023-10-07 15:13:08 -0400610 );
Simon Glass7617f492022-04-24 23:31:11 -0600611
612U_BOOT_CMD_WITH_SUBCMDS(bootflow, "Boot flows", bootflow_help_text,
613 U_BOOT_SUBCMD_MKENT(scan, 3, 1, do_bootflow_scan),
614#ifdef CONFIG_CMD_BOOTFLOW_FULL
615 U_BOOT_SUBCMD_MKENT(list, 2, 1, do_bootflow_list),
616 U_BOOT_SUBCMD_MKENT(select, 2, 1, do_bootflow_select),
617 U_BOOT_SUBCMD_MKENT(info, 2, 1, do_bootflow_info),
Simon Glass6d8f95b2023-08-10 19:33:18 -0600618 U_BOOT_SUBCMD_MKENT(read, 1, 1, do_bootflow_read),
Simon Glass0a2f6a32023-01-06 08:52:40 -0600619 U_BOOT_SUBCMD_MKENT(boot, 1, 1, do_bootflow_boot),
620 U_BOOT_SUBCMD_MKENT(menu, 2, 1, do_bootflow_menu),
Simon Glass55a2da32023-07-12 09:04:39 -0600621 U_BOOT_SUBCMD_MKENT(cmdline, 4, 1, do_bootflow_cmdline),
Simon Glass7617f492022-04-24 23:31:11 -0600622#endif
623);