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