11539Srgrimes// SPDX-License-Identifier: GPL-2.0+
21539Srgrimes/*
31539Srgrimes * Copyright (C) 2011
41539Srgrimes * Corscience GmbH & Co. KG - Simon Schwarz <schwarz@corscience.de>
51539Srgrimes */
61539Srgrimes
71539Srgrimes#include <common.h>
81539Srgrimes#include <command.h>
91539Srgrimes#include <cmd_spl.h>
101539Srgrimes#include <env.h>
111539Srgrimes#include <image.h>
121539Srgrimes#include <log.h>
131539Srgrimes#include <asm/global_data.h>
141539Srgrimes#include <linux/libfdt.h>
151539Srgrimes
161539SrgrimesDECLARE_GLOBAL_DATA_PTR;
171539Srgrimes
181539Srgrimesstatic const char **subcmd_list[] = {
191539Srgrimes
201539Srgrimes	[SPL_EXPORT_FDT] = (const char * []) {
211539Srgrimes#ifdef CONFIG_OF_LIBFDT
221539Srgrimes		"start",
231539Srgrimes		"loados",
241539Srgrimes	#ifdef CONFIG_SYS_BOOT_RAMDISK_HIGH
251539Srgrimes		"ramdisk",
261539Srgrimes	#endif
271539Srgrimes		"fdt",
281539Srgrimes		"cmdline",
291539Srgrimes		"bdt",
301539Srgrimes		"prep",
311539Srgrimes#endif
321539Srgrimes		NULL,
3323657Speter	},
341539Srgrimes	[SPL_EXPORT_ATAGS] = (const char * []) {
351539Srgrimes#ifdef CONFIG_SUPPORT_PASSING_ATAGS
361539Srgrimes		"start",
377865Sbde		"loados",
381539Srgrimes#ifdef CONFIG_SYS_BOOT_RAMDISK_HIGH
3933861Sbde		"ramdisk",
4033861Sbde#endif
411539Srgrimes		"cmdline",
4226636Sache		"bdt",
4326636Sache		"prep",
4426630Sache#endif
451539Srgrimes		NULL,
4615483Sbde	},
4715483Sbde	NULL
4815483Sbde};
4915483Sbde
5015483Sbde/* Calls bootm with the parameters given */
5115483Sbdestatic int call_bootm(int argc, char *const argv[], const char *subcommand[])
521539Srgrimes{
531539Srgrimes	char *bootm_argv[5];
541539Srgrimes
551539Srgrimes	int i = 0;
561539Srgrimes	int ret = 0;
571539Srgrimes	int j;
581539Srgrimes
591539Srgrimes	/* create paramter array */
601539Srgrimes	bootm_argv[0] = "do_bootm";
611539Srgrimes	switch (argc) {
621539Srgrimes	case 3:
631539Srgrimes		bootm_argv[4] = argv[2]; /* fdt addr */
641539Srgrimes	case 2:
651539Srgrimes		bootm_argv[3] = argv[1]; /* initrd addr */
661539Srgrimes	case 1:
671539Srgrimes		bootm_argv[2] = argv[0]; /* kernel addr */
681539Srgrimes	}
691539Srgrimes
701539Srgrimes
711539Srgrimes	/*
721539Srgrimes	 * - do the work -
731539Srgrimes	 * exec subcommands of do_bootm to init the images
741539Srgrimes	 * data structure
751539Srgrimes	 */
761539Srgrimes	while (subcommand[i] != NULL) {
771539Srgrimes		bootm_argv[1] = (char *)subcommand[i];
781539Srgrimes		debug("args %d: %s %s ", argc, bootm_argv[0], bootm_argv[1]);
791539Srgrimes		for (j = 0; j < argc; j++)
801539Srgrimes			debug("%s ", bootm_argv[j + 2]);
811539Srgrimes		debug("\n");
821539Srgrimes
831539Srgrimes		ret = do_bootm(find_cmd("do_bootm"), 0, argc+2,
841539Srgrimes			bootm_argv);
8518286Sbde		debug("Subcommand retcode: %d\n", ret);
8618286Sbde		i++;
871539Srgrimes	}
881539Srgrimes
891539Srgrimes	if (ret) {
901539Srgrimes		printf("ERROR prep subcommand failed!\n");
911539Srgrimes		return -1;
921539Srgrimes	}
931539Srgrimes
9418286Sbde	return 0;
9518286Sbde}
961539Srgrimes
971539Srgrimesstatic struct cmd_tbl cmd_spl_export_sub[] = {
9818286Sbde	U_BOOT_CMD_MKENT(fdt, 0, 1, (void *)SPL_EXPORT_FDT, "", ""),
9918286Sbde	U_BOOT_CMD_MKENT(atags, 0, 1, (void *)SPL_EXPORT_ATAGS, "", ""),
1001539Srgrimes};
1011539Srgrimes
1021539Srgrimesstatic int spl_export(struct cmd_tbl *cmdtp, int flag, int argc,
1031539Srgrimes		      char *const argv[])
1041539Srgrimes{
1051539Srgrimes	const struct cmd_tbl *c;
1061539Srgrimes
1071539Srgrimes	if (argc < 2) /* no subcommand */
1081539Srgrimes		return cmd_usage(cmdtp);
1091539Srgrimes
1101539Srgrimes	c = find_cmd_tbl(argv[1], &cmd_spl_export_sub[0],
1111539Srgrimes		ARRAY_SIZE(cmd_spl_export_sub));
1121539Srgrimes	if ((c) && ((long)c->cmd <= SPL_EXPORT_LAST)) {
1131539Srgrimes		argc -= 2;
1141539Srgrimes		argv += 2;
1151539Srgrimes		if (call_bootm(argc, argv, subcmd_list[(long)c->cmd]))
1161539Srgrimes			return -1;
1171539Srgrimes		switch ((long)c->cmd) {
1187865Sbde#ifdef CONFIG_OF_LIBFDT
1191539Srgrimes		case SPL_EXPORT_FDT:
1201539Srgrimes			printf("Argument image is now in RAM: 0x%p\n",
1211539Srgrimes				(void *)images.ft_addr);
1227865Sbde			env_set_addr("fdtargsaddr", images.ft_addr);
1237865Sbde			env_set_hex("fdtargslen", fdt_totalsize(images.ft_addr));
1247865Sbde#ifdef CONFIG_CMD_SPL_WRITE_SIZE
1257865Sbde			if (fdt_totalsize(images.ft_addr) >
1267865Sbde			    CONFIG_CMD_SPL_WRITE_SIZE)
1277865Sbde				puts("WARN: FDT size > CMD_SPL_WRITE_SIZE\n");
1287865Sbde#endif
1297865Sbde			break;
1307865Sbde#endif
1317865Sbde		case SPL_EXPORT_ATAGS:
1324749Sats			printf("Argument image is now in RAM at: 0x%p\n",
1331539Srgrimes				(void *)gd->bd->bi_boot_params);
1341539Srgrimes			break;
13526630Sache		}
13626630Sache	} else {
13726636Sache		/* Unrecognized command */
13826630Sache		return cmd_usage(cmdtp);
1391539Srgrimes	}
1401539Srgrimes
1411539Srgrimes	return 0;
1421539Srgrimes}
1431539Srgrimes
1441539Srgrimesstatic struct cmd_tbl cmd_spl_sub[] = {
1451539Srgrimes	U_BOOT_CMD_MKENT(export, 0, 1, (void *)SPL_EXPORT, "", ""),
1461539Srgrimes};
1471539Srgrimes
1481539Srgrimesstatic int do_spl(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
1491539Srgrimes{
1501539Srgrimes	const struct cmd_tbl *c;
1511539Srgrimes	int cmd;
1521539Srgrimes
1531539Srgrimes	if (argc < 2) /* no subcommand */
1541539Srgrimes		return cmd_usage(cmdtp);
1551539Srgrimes
1561539Srgrimes	c = find_cmd_tbl(argv[1], &cmd_spl_sub[0], ARRAY_SIZE(cmd_spl_sub));
1571539Srgrimes	if (c) {
15823657Speter		cmd = (long)c->cmd;
1591539Srgrimes		switch (cmd) {
1601539Srgrimes		case SPL_EXPORT:
1611539Srgrimes			argc--;
1621539Srgrimes			argv++;
1631539Srgrimes			if (spl_export(cmdtp, flag, argc, argv))
1641539Srgrimes				printf("Subcommand failed\n");
1651539Srgrimes			break;
16639191Simp		default:
1671539Srgrimes			/* unrecognized command */
1681539Srgrimes			return cmd_usage(cmdtp);
16923657Speter		}
17026624Sache	} else {
1711539Srgrimes		/* Unrecognized command */
1721539Srgrimes		return cmd_usage(cmdtp);
17335943Sjb	}
17435943Sjb	return 0;
1751539Srgrimes}
1761539Srgrimes
1771539SrgrimesU_BOOT_CMD(
1787865Sbde	spl, 6 , 1, do_spl, "SPL configuration",
1791539Srgrimes	"export <img=atags|fdt> [kernel_addr] [initrd_addr] [fdt_addr]\n"
1801539Srgrimes	"\timg\t\t\"atags\" or \"fdt\"\n"
1817865Sbde	"\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