Merge tag 'mmc-2021-4-6' of https://source.denx.de/u-boot/custodians/u-boot-mmc
[platform/kernel/u-boot.git] / cmd / spl.c
1 // SPDX-License-Identifier: GPL-2.0+
2 /*
3  * Copyright (C) 2011
4  * Corscience GmbH & Co. KG - Simon Schwarz <schwarz@corscience.de>
5  */
6
7 #include <common.h>
8 #include <command.h>
9 #include <cmd_spl.h>
10 #include <env.h>
11 #include <image.h>
12 #include <log.h>
13 #include <asm/global_data.h>
14 #include <linux/libfdt.h>
15
16 DECLARE_GLOBAL_DATA_PTR;
17
18 static const char **subcmd_list[] = {
19
20         [SPL_EXPORT_FDT] = (const char * []) {
21 #ifdef CONFIG_OF_LIBFDT
22                 "start",
23                 "loados",
24         #ifdef CONFIG_SYS_BOOT_RAMDISK_HIGH
25                 "ramdisk",
26         #endif
27                 "fdt",
28                 "cmdline",
29                 "bdt",
30                 "prep",
31 #endif
32                 NULL,
33         },
34         [SPL_EXPORT_ATAGS] = (const char * []) {
35 #if defined(CONFIG_SETUP_MEMORY_TAGS) || \
36         defined(CONFIG_CMDLINE_TAG) || \
37         defined(CONFIG_INITRD_TAG) || \
38         defined(CONFIG_SERIAL_TAG) || \
39         defined(CONFIG_REVISION_TAG)
40                 "start",
41                 "loados",
42 #ifdef CONFIG_SYS_BOOT_RAMDISK_HIGH
43                 "ramdisk",
44 #endif
45                 "cmdline",
46                 "bdt",
47                 "prep",
48 #endif
49                 NULL,
50         },
51         NULL
52 };
53
54 /* Calls bootm with the parameters given */
55 static int call_bootm(int argc, char *const argv[], const char *subcommand[])
56 {
57         char *bootm_argv[5];
58
59         int i = 0;
60         int ret = 0;
61         int j;
62
63         /* create paramter array */
64         bootm_argv[0] = "do_bootm";
65         switch (argc) {
66         case 3:
67                 bootm_argv[4] = argv[2]; /* fdt addr */
68         case 2:
69                 bootm_argv[3] = argv[1]; /* initrd addr */
70         case 1:
71                 bootm_argv[2] = argv[0]; /* kernel addr */
72         }
73
74
75         /*
76          * - do the work -
77          * exec subcommands of do_bootm to init the images
78          * data structure
79          */
80         while (subcommand[i] != NULL) {
81                 bootm_argv[1] = (char *)subcommand[i];
82                 debug("args %d: %s %s ", argc, bootm_argv[0], bootm_argv[1]);
83                 for (j = 0; j < argc; j++)
84                         debug("%s ", bootm_argv[j + 2]);
85                 debug("\n");
86
87                 ret = do_bootm(find_cmd("do_bootm"), 0, argc+2,
88                         bootm_argv);
89                 debug("Subcommand retcode: %d\n", ret);
90                 i++;
91         }
92
93         if (ret) {
94                 printf("ERROR prep subcommand failed!\n");
95                 return -1;
96         }
97
98         return 0;
99 }
100
101 static struct cmd_tbl cmd_spl_export_sub[] = {
102         U_BOOT_CMD_MKENT(fdt, 0, 1, (void *)SPL_EXPORT_FDT, "", ""),
103         U_BOOT_CMD_MKENT(atags, 0, 1, (void *)SPL_EXPORT_ATAGS, "", ""),
104 };
105
106 static int spl_export(struct cmd_tbl *cmdtp, int flag, int argc,
107                       char *const argv[])
108 {
109         const struct cmd_tbl *c;
110
111         if (argc < 2) /* no subcommand */
112                 return cmd_usage(cmdtp);
113
114         c = find_cmd_tbl(argv[1], &cmd_spl_export_sub[0],
115                 ARRAY_SIZE(cmd_spl_export_sub));
116         if ((c) && ((long)c->cmd <= SPL_EXPORT_LAST)) {
117                 argc -= 2;
118                 argv += 2;
119                 if (call_bootm(argc, argv, subcmd_list[(long)c->cmd]))
120                         return -1;
121                 switch ((long)c->cmd) {
122 #ifdef CONFIG_OF_LIBFDT
123                 case SPL_EXPORT_FDT:
124                         printf("Argument image is now in RAM: 0x%p\n",
125                                 (void *)images.ft_addr);
126                         env_set_addr("fdtargsaddr", images.ft_addr);
127                         env_set_hex("fdtargslen", fdt_totalsize(images.ft_addr));
128 #ifdef CONFIG_CMD_SPL_WRITE_SIZE
129                         if (fdt_totalsize(images.ft_addr) >
130                             CONFIG_CMD_SPL_WRITE_SIZE)
131                                 puts("WARN: FDT size > CMD_SPL_WRITE_SIZE\n");
132 #endif
133                         break;
134 #endif
135                 case SPL_EXPORT_ATAGS:
136                         printf("Argument image is now in RAM at: 0x%p\n",
137                                 (void *)gd->bd->bi_boot_params);
138                         break;
139                 }
140         } else {
141                 /* Unrecognized command */
142                 return cmd_usage(cmdtp);
143         }
144
145         return 0;
146 }
147
148 static struct cmd_tbl cmd_spl_sub[] = {
149         U_BOOT_CMD_MKENT(export, 0, 1, (void *)SPL_EXPORT, "", ""),
150 };
151
152 static int do_spl(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
153 {
154         const struct cmd_tbl *c;
155         int cmd;
156
157         if (argc < 2) /* no subcommand */
158                 return cmd_usage(cmdtp);
159
160         c = find_cmd_tbl(argv[1], &cmd_spl_sub[0], ARRAY_SIZE(cmd_spl_sub));
161         if (c) {
162                 cmd = (long)c->cmd;
163                 switch (cmd) {
164                 case SPL_EXPORT:
165                         argc--;
166                         argv++;
167                         if (spl_export(cmdtp, flag, argc, argv))
168                                 printf("Subcommand failed\n");
169                         break;
170                 default:
171                         /* unrecognized command */
172                         return cmd_usage(cmdtp);
173                 }
174         } else {
175                 /* Unrecognized command */
176                 return cmd_usage(cmdtp);
177         }
178         return 0;
179 }
180
181 U_BOOT_CMD(
182         spl, 6 , 1, do_spl, "SPL configuration",
183         "export <img=atags|fdt> [kernel_addr] [initrd_addr] [fdt_addr]\n"
184         "\timg\t\t\"atags\" or \"fdt\"\n"
185         "\tkernel_addr\taddress where a kernel image is stored.\n"
186         "\t\t\tkernel is loaded as part of the boot process, but it is not started.\n"
187         "\tinitrd_addr\taddress of initial ramdisk\n"
188         "\t\t\tcan be set to \"-\" if fdt_addr without initrd_addr is used.\n"
189         "\tfdt_addr\tin case of fdt, the address of the device tree.\n"
190         );