1 /* 2 * (C) Copyright 2000, 2001 3 * Rich Ireland, Enterasys Networks, rireland@enterasys.com. 4 * 5 * SPDX-License-Identifier: GPL-2.0+ 6 */ 7 8 /* 9 * FPGA support 10 */ 11 #include <common.h> 12 #include <command.h> 13 #include <fpga.h> 14 #include <fs.h> 15 #include <malloc.h> 16 17 /* Local functions */ 18 static int fpga_get_op(char *opstr); 19 20 /* Local defines */ 21 #define FPGA_NONE -1 22 #define FPGA_INFO 0 23 #define FPGA_LOAD 1 24 #define FPGA_LOADB 2 25 #define FPGA_DUMP 3 26 #define FPGA_LOADMK 4 27 #define FPGA_LOADP 5 28 #define FPGA_LOADBP 6 29 #define FPGA_LOADFS 7 30 31 /* ------------------------------------------------------------------------- */ 32 /* command form: 33 * fpga <op> <device number> <data addr> <datasize> 34 * where op is 'load', 'dump', or 'info' 35 * If there is no device number field, the fpga environment variable is used. 36 * If there is no data addr field, the fpgadata environment variable is used. 37 * The info command requires no data address field. 38 */ 39 int do_fpga(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[]) 40 { 41 int op, dev = FPGA_INVALID_DEVICE; 42 size_t data_size = 0; 43 void *fpga_data = NULL; 44 char *devstr = getenv("fpga"); 45 char *datastr = getenv("fpgadata"); 46 int rc = FPGA_FAIL; 47 int wrong_parms = 0; 48 #if defined(CONFIG_FIT) 49 const char *fit_uname = NULL; 50 ulong fit_addr; 51 #endif 52 #if defined(CONFIG_CMD_FPGA_LOADFS) 53 fpga_fs_info fpga_fsinfo; 54 fpga_fsinfo.fstype = FS_TYPE_ANY; 55 #endif 56 57 if (devstr) 58 dev = (int) simple_strtoul(devstr, NULL, 16); 59 if (datastr) 60 fpga_data = (void *)simple_strtoul(datastr, NULL, 16); 61 62 switch (argc) { 63 #if defined(CONFIG_CMD_FPGA_LOADFS) 64 case 9: 65 fpga_fsinfo.blocksize = (unsigned int) 66 simple_strtoul(argv[5], NULL, 16); 67 fpga_fsinfo.interface = argv[6]; 68 fpga_fsinfo.dev_part = argv[7]; 69 fpga_fsinfo.filename = argv[8]; 70 #endif 71 case 5: /* fpga <op> <dev> <data> <datasize> */ 72 data_size = simple_strtoul(argv[4], NULL, 16); 73 74 case 4: /* fpga <op> <dev> <data> */ 75 #if defined(CONFIG_FIT) 76 if (fit_parse_subimage(argv[3], (ulong)fpga_data, 77 &fit_addr, &fit_uname)) { 78 fpga_data = (void *)fit_addr; 79 debug("* fpga: subimage '%s' from FIT image ", 80 fit_uname); 81 debug("at 0x%08lx\n", fit_addr); 82 } else 83 #endif 84 { 85 fpga_data = (void *)simple_strtoul(argv[3], NULL, 16); 86 debug("* fpga: cmdline image address = 0x%08lx\n", 87 (ulong)fpga_data); 88 } 89 debug("%s: fpga_data = 0x%lx\n", __func__, (ulong)fpga_data); 90 91 case 3: /* fpga <op> <dev | data addr> */ 92 dev = (int)simple_strtoul(argv[2], NULL, 16); 93 debug("%s: device = %d\n", __func__, dev); 94 /* FIXME - this is a really weak test */ 95 if ((argc == 3) && (dev > fpga_count())) { 96 /* must be buffer ptr */ 97 debug("%s: Assuming buffer pointer in arg 3\n", 98 __func__); 99 100 #if defined(CONFIG_FIT) 101 if (fit_parse_subimage(argv[2], (ulong)fpga_data, 102 &fit_addr, &fit_uname)) { 103 fpga_data = (void *)fit_addr; 104 debug("* fpga: subimage '%s' from FIT image ", 105 fit_uname); 106 debug("at 0x%08lx\n", fit_addr); 107 } else 108 #endif 109 { 110 fpga_data = (void *)(uintptr_t)dev; 111 debug("* fpga: cmdline image addr = 0x%08lx\n", 112 (ulong)fpga_data); 113 } 114 115 debug("%s: fpga_data = 0x%lx\n", 116 __func__, (ulong)fpga_data); 117 dev = FPGA_INVALID_DEVICE; /* reset device num */ 118 } 119 120 case 2: /* fpga <op> */ 121 op = (int)fpga_get_op(argv[1]); 122 break; 123 124 default: 125 debug("%s: Too many or too few args (%d)\n", __func__, argc); 126 op = FPGA_NONE; /* force usage display */ 127 break; 128 } 129 130 if (dev == FPGA_INVALID_DEVICE) { 131 puts("FPGA device not specified\n"); 132 op = FPGA_NONE; 133 } 134 135 switch (op) { 136 case FPGA_NONE: 137 case FPGA_INFO: 138 break; 139 #if defined(CONFIG_CMD_FPGA_LOADFS) 140 case FPGA_LOADFS: 141 /* Blocksize can be zero */ 142 if (!fpga_fsinfo.interface || !fpga_fsinfo.dev_part || 143 !fpga_fsinfo.filename) 144 wrong_parms = 1; 145 #endif 146 case FPGA_LOAD: 147 case FPGA_LOADP: 148 case FPGA_LOADB: 149 case FPGA_LOADBP: 150 case FPGA_DUMP: 151 if (!fpga_data || !data_size) 152 wrong_parms = 1; 153 break; 154 #if defined(CONFIG_CMD_FPGA_LOADMK) 155 case FPGA_LOADMK: 156 if (!fpga_data) 157 wrong_parms = 1; 158 break; 159 #endif 160 } 161 162 if (wrong_parms) { 163 puts("Wrong parameters for FPGA request\n"); 164 op = FPGA_NONE; 165 } 166 167 switch (op) { 168 case FPGA_NONE: 169 return CMD_RET_USAGE; 170 171 case FPGA_INFO: 172 rc = fpga_info(dev); 173 break; 174 175 case FPGA_LOAD: 176 rc = fpga_load(dev, fpga_data, data_size, BIT_FULL); 177 break; 178 179 #if defined(CONFIG_CMD_FPGA_LOADP) 180 case FPGA_LOADP: 181 rc = fpga_load(dev, fpga_data, data_size, BIT_PARTIAL); 182 break; 183 #endif 184 185 case FPGA_LOADB: 186 rc = fpga_loadbitstream(dev, fpga_data, data_size, BIT_FULL); 187 break; 188 189 #if defined(CONFIG_CMD_FPGA_LOADBP) 190 case FPGA_LOADBP: 191 rc = fpga_loadbitstream(dev, fpga_data, data_size, BIT_PARTIAL); 192 break; 193 #endif 194 195 #if defined(CONFIG_CMD_FPGA_LOADFS) 196 case FPGA_LOADFS: 197 rc = fpga_fsload(dev, fpga_data, data_size, &fpga_fsinfo); 198 break; 199 #endif 200 201 #if defined(CONFIG_CMD_FPGA_LOADMK) 202 case FPGA_LOADMK: 203 switch (genimg_get_format(fpga_data)) { 204 #if defined(CONFIG_IMAGE_FORMAT_LEGACY) 205 case IMAGE_FORMAT_LEGACY: 206 { 207 image_header_t *hdr = 208 (image_header_t *)fpga_data; 209 ulong data; 210 uint8_t comp; 211 212 comp = image_get_comp(hdr); 213 if (comp == IH_COMP_GZIP) { 214 #if defined(CONFIG_GZIP) 215 ulong image_buf = image_get_data(hdr); 216 data = image_get_load(hdr); 217 ulong image_size = ~0UL; 218 219 if (gunzip((void *)data, ~0UL, 220 (void *)image_buf, 221 &image_size) != 0) { 222 puts("GUNZIP: error\n"); 223 return 1; 224 } 225 data_size = image_size; 226 #else 227 puts("Gunzip image is not supported\n"); 228 return 1; 229 #endif 230 } else { 231 data = (ulong)image_get_data(hdr); 232 data_size = image_get_data_size(hdr); 233 } 234 rc = fpga_load(dev, (void *)data, data_size, 235 BIT_FULL); 236 } 237 break; 238 #endif 239 #if defined(CONFIG_FIT) 240 case IMAGE_FORMAT_FIT: 241 { 242 const void *fit_hdr = (const void *)fpga_data; 243 int noffset; 244 const void *fit_data; 245 246 if (fit_uname == NULL) { 247 puts("No FIT subimage unit name\n"); 248 return 1; 249 } 250 251 if (!fit_check_format(fit_hdr)) { 252 puts("Bad FIT image format\n"); 253 return 1; 254 } 255 256 /* get fpga component image node offset */ 257 noffset = fit_image_get_node(fit_hdr, 258 fit_uname); 259 if (noffset < 0) { 260 printf("Can't find '%s' FIT subimage\n", 261 fit_uname); 262 return 1; 263 } 264 265 /* verify integrity */ 266 if (!fit_image_verify(fit_hdr, noffset)) { 267 puts ("Bad Data Hash\n"); 268 return 1; 269 } 270 271 /* get fpga subimage data address and length */ 272 if (fit_image_get_data(fit_hdr, noffset, 273 &fit_data, &data_size)) { 274 puts("Fpga subimage data not found\n"); 275 return 1; 276 } 277 278 rc = fpga_load(dev, fit_data, data_size, 279 BIT_FULL); 280 } 281 break; 282 #endif 283 default: 284 puts("** Unknown image type\n"); 285 rc = FPGA_FAIL; 286 break; 287 } 288 break; 289 #endif 290 291 case FPGA_DUMP: 292 rc = fpga_dump(dev, fpga_data, data_size); 293 break; 294 295 default: 296 printf("Unknown operation\n"); 297 return CMD_RET_USAGE; 298 } 299 return rc; 300 } 301 302 /* 303 * Map op to supported operations. We don't use a table since we 304 * would just have to relocate it from flash anyway. 305 */ 306 static int fpga_get_op(char *opstr) 307 { 308 int op = FPGA_NONE; 309 310 if (!strcmp("info", opstr)) 311 op = FPGA_INFO; 312 else if (!strcmp("loadb", opstr)) 313 op = FPGA_LOADB; 314 else if (!strcmp("load", opstr)) 315 op = FPGA_LOAD; 316 #if defined(CONFIG_CMD_FPGA_LOADP) 317 else if (!strcmp("loadp", opstr)) 318 op = FPGA_LOADP; 319 #endif 320 #if defined(CONFIG_CMD_FPGA_LOADBP) 321 else if (!strcmp("loadbp", opstr)) 322 op = FPGA_LOADBP; 323 #endif 324 #if defined(CONFIG_CMD_FPGA_LOADFS) 325 else if (!strcmp("loadfs", opstr)) 326 op = FPGA_LOADFS; 327 #endif 328 #if defined(CONFIG_CMD_FPGA_LOADMK) 329 else if (!strcmp("loadmk", opstr)) 330 op = FPGA_LOADMK; 331 #endif 332 else if (!strcmp("dump", opstr)) 333 op = FPGA_DUMP; 334 335 if (op == FPGA_NONE) 336 printf("Unknown fpga operation \"%s\"\n", opstr); 337 338 return op; 339 } 340 341 #if defined(CONFIG_CMD_FPGA_LOADFS) 342 U_BOOT_CMD(fpga, 9, 1, do_fpga, 343 #else 344 U_BOOT_CMD(fpga, 6, 1, do_fpga, 345 #endif 346 "loadable FPGA image support", 347 "[operation type] [device number] [image address] [image size]\n" 348 "fpga operations:\n" 349 " dump\t[dev] [address] [size]\tLoad device to memory buffer\n" 350 " info\t[dev]\t\t\tlist known device information\n" 351 " load\t[dev] [address] [size]\tLoad device from memory buffer\n" 352 #if defined(CONFIG_CMD_FPGA_LOADP) 353 " loadp\t[dev] [address] [size]\t" 354 "Load device from memory buffer with partial bitstream\n" 355 #endif 356 " loadb\t[dev] [address] [size]\t" 357 "Load device from bitstream buffer (Xilinx only)\n" 358 #if defined(CONFIG_CMD_FPGA_LOADBP) 359 " loadbp\t[dev] [address] [size]\t" 360 "Load device from bitstream buffer with partial bitstream" 361 "(Xilinx only)\n" 362 #endif 363 #if defined(CONFIG_CMD_FPGA_LOADFS) 364 "Load device from filesystem (FAT by default) (Xilinx only)\n" 365 " loadfs [dev] [address] [image size] [blocksize] <interface>\n" 366 " [<dev[:part]>] <filename>\n" 367 #endif 368 #if defined(CONFIG_CMD_FPGA_LOADMK) 369 " loadmk [dev] [address]\tLoad device generated with mkimage" 370 #if defined(CONFIG_FIT) 371 "\n" 372 "\tFor loadmk operating on FIT format uImage address must include\n" 373 "\tsubimage unit name in the form of addr:<subimg_uname>" 374 #endif 375 #endif 376 ); 377