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 16DECLARE_GLOBAL_DATA_PTR; 17 18static 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#ifdef CONFIG_SUPPORT_PASSING_ATAGS 36 "start", 37 "loados", 38#ifdef CONFIG_SYS_BOOT_RAMDISK_HIGH 39 "ramdisk", 40#endif 41 "cmdline", 42 "bdt", 43 "prep", 44#endif 45 NULL, 46 }, 47 NULL 48}; 49 50/* Calls bootm with the parameters given */ 51static int call_bootm(int argc, char *const argv[], const char *subcommand[]) 52{ 53 char *bootm_argv[5]; 54 55 int i = 0; 56 int ret = 0; 57 int j; 58 59 /* create paramter array */ 60 bootm_argv[0] = "do_bootm"; 61 switch (argc) { 62 case 3: 63 bootm_argv[4] = argv[2]; /* fdt addr */ 64 case 2: 65 bootm_argv[3] = argv[1]; /* initrd addr */ 66 case 1: 67 bootm_argv[2] = argv[0]; /* kernel addr */ 68 } 69 70 71 /* 72 * - do the work - 73 * exec subcommands of do_bootm to init the images 74 * data structure 75 */ 76 while (subcommand[i] != NULL) { 77 bootm_argv[1] = (char *)subcommand[i]; 78 debug("args %d: %s %s ", argc, bootm_argv[0], bootm_argv[1]); 79 for (j = 0; j < argc; j++) 80 debug("%s ", bootm_argv[j + 2]); 81 debug("\n"); 82 83 ret = do_bootm(find_cmd("do_bootm"), 0, argc+2, 84 bootm_argv); 85 debug("Subcommand retcode: %d\n", ret); 86 i++; 87 } 88 89 if (ret) { 90 printf("ERROR prep subcommand failed!\n"); 91 return -1; 92 } 93 94 return 0; 95} 96 97static struct cmd_tbl cmd_spl_export_sub[] = { 98 U_BOOT_CMD_MKENT(fdt, 0, 1, (void *)SPL_EXPORT_FDT, "", ""), 99 U_BOOT_CMD_MKENT(atags, 0, 1, (void *)SPL_EXPORT_ATAGS, "", ""), 100}; 101 102static int spl_export(struct cmd_tbl *cmdtp, int flag, int argc, 103 char *const argv[]) 104{ 105 const struct cmd_tbl *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 144static struct cmd_tbl cmd_spl_sub[] = { 145 U_BOOT_CMD_MKENT(export, 0, 1, (void *)SPL_EXPORT, "", ""), 146}; 147 148static int do_spl(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]) 149{ 150 const struct cmd_tbl *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 177U_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