Prepare v2024.10
[platform/kernel/u-boot.git] / cmd / bootmeth.c
1 // SPDX-License-Identifier: GPL-2.0+
2 /*
3  * 'bootmeth' command
4  *
5  * Copyright 2021 Google LLC
6  * Written by Simon Glass <sjg@chromium.org>
7  */
8
9 #include <bootdev.h>
10 #include <bootmeth.h>
11 #include <bootstd.h>
12 #include <command.h>
13 #include <dm.h>
14 #include <malloc.h>
15 #include <dm/uclass-internal.h>
16
17 static int do_bootmeth_list(struct cmd_tbl *cmdtp, int flag, int argc,
18                             char *const argv[])
19 {
20         struct bootstd_priv *std;
21         struct udevice *dev;
22         bool use_order;
23         bool all = false;
24         int ret;
25         int i;
26
27         if (argc > 1 && *argv[1] == '-') {
28                 all = strchr(argv[1], 'a');
29                 argc--;
30                 argv++;
31         }
32
33         ret = bootstd_get_priv(&std);
34         if (ret) {
35                 printf("Cannot get bootstd (err=%d)\n", ret);
36                 return CMD_RET_FAILURE;
37         }
38
39         printf("Order  Seq  Name                Description\n");
40         printf("-----  ---  ------------------  ------------------\n");
41
42         /*
43          * Use the ordering if we have one, so long as we are not trying to list
44          * all bootmethds
45          */
46         use_order = std->bootmeth_count && !all;
47         if (use_order)
48                 dev = std->bootmeth_order[0];
49         else
50                 ret = uclass_find_first_device(UCLASS_BOOTMETH, &dev);
51
52         for (i = 0; dev;) {
53                 struct bootmeth_uc_plat *ucp = dev_get_uclass_plat(dev);
54                 int order = i;
55
56                 /*
57                  * With the -a flag we may list bootdevs that are not in the
58                  * ordering. Find their place in the order
59                  */
60                 if (all && std->bootmeth_count) {
61                         int j;
62
63                         /* Find the position of this bootmeth in the order */
64                         order = -1;
65                         for (j = 0; j < std->bootmeth_count; j++) {
66                                 if (std->bootmeth_order[j] == dev)
67                                         order = j;
68                         }
69                 }
70
71                 if (ucp->flags & BOOTMETHF_GLOBAL)
72                         printf("%5s", "glob");
73                 else if (order == -1)
74                         printf("%5s", "-");
75                 else
76                         printf("%5x", order);
77                 printf("  %3x  %-19.19s %s\n", dev_seq(dev), dev->name,
78                        ucp->desc);
79                 i++;
80                 if (use_order)
81                         dev = std->bootmeth_order[i];
82                 else
83                         uclass_find_next_device(&dev);
84         }
85         printf("-----  ---  ------------------  ------------------\n");
86         printf("(%d bootmeth%s)\n", i, i != 1 ? "s" : "");
87
88         return 0;
89 }
90
91 static int do_bootmeth_order(struct cmd_tbl *cmdtp, int flag, int argc,
92                              char *const argv[])
93 {
94         int ret;
95
96         ret = bootmeth_set_order(argv[1]);
97         if (ret) {
98                 printf("Failed (err=%d)\n", ret);
99                 return CMD_RET_FAILURE;
100         }
101         env_set("bootmeths", argv[1]);
102
103         return 0;
104 }
105
106 U_BOOT_LONGHELP(bootmeth,
107         "list [-a]     - list available bootmeths (-a all)\n"
108         "bootmeth order [<bd> ...]  - select bootmeth order / subset to use");
109
110 U_BOOT_CMD_WITH_SUBCMDS(bootmeth, "Boot methods", bootmeth_help_text,
111         U_BOOT_SUBCMD_MKENT(list, 2, 1, do_bootmeth_list),
112         U_BOOT_SUBCMD_MKENT(order, CONFIG_SYS_MAXARGS, 1, do_bootmeth_order));