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