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 <linux/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