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