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