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