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) && ((int)c->cmd <= SPL_EXPORT_LAST)) { 113 argc -= 2; 114 argv += 2; 115 if (call_bootm(argc, argv, subcmd_list[(int)c->cmd])) 116 return -1; 117 switch ((int)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 if (fdt_totalsize(images.ft_addr) > 125 CONFIG_CMD_SPL_WRITE_SIZE) 126 puts("WARN: FDT size > CMD_SPL_WRITE_SIZE\n"); 127 break; 128 #endif 129 case SPL_EXPORT_ATAGS: 130 printf("Argument image is now in RAM at: 0x%p\n", 131 (void *)gd->bd->bi_boot_params); 132 break; 133 } 134 } else { 135 /* Unrecognized command */ 136 return cmd_usage(cmdtp); 137 } 138 139 return 0; 140 } 141 142 static cmd_tbl_t cmd_spl_sub[] = { 143 U_BOOT_CMD_MKENT(export, 0, 1, (void *)SPL_EXPORT, "", ""), 144 }; 145 146 static int do_spl(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) 147 { 148 const cmd_tbl_t *c; 149 int cmd; 150 151 if (argc < 2) /* no subcommand */ 152 return cmd_usage(cmdtp); 153 154 c = find_cmd_tbl(argv[1], &cmd_spl_sub[0], ARRAY_SIZE(cmd_spl_sub)); 155 if (c) { 156 cmd = (int)c->cmd; 157 switch (cmd) { 158 case SPL_EXPORT: 159 argc--; 160 argv++; 161 if (spl_export(cmdtp, flag, argc, argv)) 162 printf("Subcommand failed\n"); 163 break; 164 default: 165 /* unrecognized command */ 166 return cmd_usage(cmdtp); 167 } 168 } else { 169 /* Unrecognized command */ 170 return cmd_usage(cmdtp); 171 } 172 return 0; 173 } 174 175 U_BOOT_CMD( 176 spl, 6 , 1, do_spl, "SPL configuration", 177 "export <img=atags|fdt> [kernel_addr] [initrd_addr] [fdt_addr]\n" 178 "\timg\t\t\"atags\" or \"fdt\"\n" 179 "\tkernel_addr\taddress where a kernel image is stored.\n" 180 "\t\t\tkernel is loaded as part of the boot process, but it is not started.\n" 181 "\tinitrd_addr\taddress of initial ramdisk\n" 182 "\t\t\tcan be set to \"-\" if fdt_addr without initrd_addr is used.\n" 183 "\tfdt_addr\tin case of fdt, the address of the device tree.\n" 184 ); 185