uboot/common/cmd_fpga.c
<<
>>
Prefs
   1/*
   2 * (C) Copyright 2000, 2001
   3 * Rich Ireland, Enterasys Networks, rireland@enterasys.com.
   4 *
   5 * See file CREDITS for list of people who contributed to this
   6 * project.
   7 *
   8 * This program is free software; you can redistribute it and/or
   9 * modify it under the terms of the GNU General Public License as
  10 * published by the Free Software Foundation; either version 2 of
  11 * the License, or (at your option) any later version.
  12 *
  13 * This program is distributed in the hope that it will be useful,
  14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
  15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  16 * GNU General Public License for more details.
  17 *
  18 * You should have received a copy of the GNU General Public License
  19 * along with this program; if not, write to the Free Software
  20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
  21 * MA 02111-1307 USA
  22 *
  23 */
  24
  25/*
  26 *  FPGA support
  27 */
  28#include <common.h>
  29#include <command.h>
  30#if defined(CONFIG_CMD_NET)
  31#include <net.h>
  32#endif
  33#include <fpga.h>
  34#include <malloc.h>
  35
  36#if 0
  37#define FPGA_DEBUG
  38#endif
  39
  40#ifdef  FPGA_DEBUG
  41#define PRINTF(fmt,args...)     printf (fmt ,##args)
  42#else
  43#define PRINTF(fmt,args...)
  44#endif
  45
  46/* Local functions */
  47static void fpga_usage (cmd_tbl_t * cmdtp);
  48static int fpga_get_op (char *opstr);
  49
  50/* Local defines */
  51#define FPGA_NONE   -1
  52#define FPGA_INFO   0
  53#define FPGA_LOAD   1
  54#define FPGA_LOADB  2
  55#define FPGA_DUMP   3
  56#define FPGA_LOADMK 4
  57
  58/* Convert bitstream data and load into the fpga */
  59int fpga_loadbitstream(unsigned long dev, char* fpgadata, size_t size)
  60{
  61#if defined(CONFIG_FPGA_XILINX)
  62        unsigned int length;
  63        unsigned int swapsize;
  64        char buffer[80];
  65        unsigned char *dataptr;
  66        unsigned int i;
  67        int rc;
  68
  69        dataptr = (unsigned char *)fpgadata;
  70
  71        /* skip the first bytes of the bitsteam, their meaning is unknown */
  72        length = (*dataptr << 8) + *(dataptr+1);
  73        dataptr+=2;
  74        dataptr+=length;
  75
  76        /* get design name (identifier, length, string) */
  77        length = (*dataptr << 8) + *(dataptr+1);
  78        dataptr+=2;
  79        if (*dataptr++ != 0x61) {
  80                PRINTF ("%s: Design name identifier not recognized in bitstream\n",
  81                        __FUNCTION__ );
  82                return FPGA_FAIL;
  83        }
  84
  85        length = (*dataptr << 8) + *(dataptr+1);
  86        dataptr+=2;
  87        for(i=0;i<length;i++)
  88                buffer[i] = *dataptr++;
  89
  90        printf("  design filename = \"%s\"\n", buffer);
  91
  92        /* get part number (identifier, length, string) */
  93        if (*dataptr++ != 0x62) {
  94                printf("%s: Part number identifier not recognized in bitstream\n",
  95                        __FUNCTION__ );
  96                return FPGA_FAIL;
  97        }
  98
  99        length = (*dataptr << 8) + *(dataptr+1);
 100        dataptr+=2;
 101        for(i=0;i<length;i++)
 102                buffer[i] = *dataptr++;
 103        printf("  part number = \"%s\"\n", buffer);
 104
 105        /* get date (identifier, length, string) */
 106        if (*dataptr++ != 0x63) {
 107                printf("%s: Date identifier not recognized in bitstream\n",
 108                       __FUNCTION__);
 109                return FPGA_FAIL;
 110        }
 111
 112        length = (*dataptr << 8) + *(dataptr+1);
 113        dataptr+=2;
 114        for(i=0;i<length;i++)
 115                buffer[i] = *dataptr++;
 116        printf("  date = \"%s\"\n", buffer);
 117
 118        /* get time (identifier, length, string) */
 119        if (*dataptr++ != 0x64) {
 120                printf("%s: Time identifier not recognized in bitstream\n",__FUNCTION__);
 121                return FPGA_FAIL;
 122        }
 123
 124        length = (*dataptr << 8) + *(dataptr+1);
 125        dataptr+=2;
 126        for(i=0;i<length;i++)
 127                buffer[i] = *dataptr++;
 128        printf("  time = \"%s\"\n", buffer);
 129
 130        /* get fpga data length (identifier, length) */
 131        if (*dataptr++ != 0x65) {
 132                printf("%s: Data length identifier not recognized in bitstream\n",
 133                        __FUNCTION__);
 134                return FPGA_FAIL;
 135        }
 136        swapsize = ((unsigned int) *dataptr     <<24) +
 137                   ((unsigned int) *(dataptr+1) <<16) +
 138                   ((unsigned int) *(dataptr+2) <<8 ) +
 139                   ((unsigned int) *(dataptr+3)     ) ;
 140        dataptr+=4;
 141        printf("  bytes in bitstream = %d\n", swapsize);
 142
 143        rc = fpga_load(dev, dataptr, swapsize);
 144        return rc;
 145#else
 146        printf("Bitstream support only for Xilinx devices\n");
 147        return FPGA_FAIL;
 148#endif
 149}
 150
 151/* ------------------------------------------------------------------------- */
 152/* command form:
 153 *   fpga <op> <device number> <data addr> <datasize>
 154 * where op is 'load', 'dump', or 'info'
 155 * If there is no device number field, the fpga environment variable is used.
 156 * If there is no data addr field, the fpgadata environment variable is used.
 157 * The info command requires no data address field.
 158 */
 159int do_fpga (cmd_tbl_t * cmdtp, int flag, int argc, char *argv[])
 160{
 161        int op, dev = FPGA_INVALID_DEVICE;
 162        size_t data_size = 0;
 163        void *fpga_data = NULL;
 164        char *devstr = getenv ("fpga");
 165        char *datastr = getenv ("fpgadata");
 166        int rc = FPGA_FAIL;
 167#if defined (CONFIG_FIT)
 168        const char *fit_uname = NULL;
 169        ulong fit_addr;
 170#endif
 171
 172        if (devstr)
 173                dev = (int) simple_strtoul (devstr, NULL, 16);
 174        if (datastr)
 175                fpga_data = (void *) simple_strtoul (datastr, NULL, 16);
 176
 177        switch (argc) {
 178        case 5:         /* fpga <op> <dev> <data> <datasize> */
 179                data_size = simple_strtoul (argv[4], NULL, 16);
 180
 181        case 4:         /* fpga <op> <dev> <data> */
 182#if defined(CONFIG_FIT)
 183                if (fit_parse_subimage (argv[3], (ulong)fpga_data,
 184                                        &fit_addr, &fit_uname)) {
 185                        fpga_data = (void *)fit_addr;
 186                        debug ("*  fpga: subimage '%s' from FIT image at 0x%08lx\n",
 187                                        fit_uname, fit_addr);
 188                } else
 189#endif
 190                {
 191                        fpga_data = (void *) simple_strtoul (argv[3], NULL, 16);
 192                        debug ("*  fpga: cmdline image address = 0x%08lx\n", (ulong)fpga_data);
 193                }
 194                PRINTF ("%s: fpga_data = 0x%x\n", __FUNCTION__, (uint) fpga_data);
 195
 196        case 3:         /* fpga <op> <dev | data addr> */
 197                dev = (int) simple_strtoul (argv[2], NULL, 16);
 198                PRINTF ("%s: device = %d\n", __FUNCTION__, dev);
 199                /* FIXME - this is a really weak test */
 200                if ((argc == 3) && (dev > fpga_count ())) {     /* must be buffer ptr */
 201                        PRINTF ("%s: Assuming buffer pointer in arg 3\n",
 202                                __FUNCTION__);
 203
 204#if defined(CONFIG_FIT)
 205                        if (fit_parse_subimage (argv[2], (ulong)fpga_data,
 206                                                &fit_addr, &fit_uname)) {
 207                                fpga_data = (void *)fit_addr;
 208                                debug ("*  fpga: subimage '%s' from FIT image at 0x%08lx\n",
 209                                                fit_uname, fit_addr);
 210                        } else
 211#endif
 212                        {
 213                                fpga_data = (void *) dev;
 214                                debug ("*  fpga: cmdline image address = 0x%08lx\n", (ulong)fpga_data);
 215                        }
 216
 217                        PRINTF ("%s: fpga_data = 0x%x\n",
 218                                __FUNCTION__, (uint) fpga_data);
 219                        dev = FPGA_INVALID_DEVICE;      /* reset device num */
 220                }
 221
 222        case 2:         /* fpga <op> */
 223                op = (int) fpga_get_op (argv[1]);
 224                break;
 225
 226        default:
 227                PRINTF ("%s: Too many or too few args (%d)\n",
 228                        __FUNCTION__, argc);
 229                op = FPGA_NONE; /* force usage display */
 230                break;
 231        }
 232
 233        switch (op) {
 234        case FPGA_NONE:
 235                fpga_usage (cmdtp);
 236                break;
 237
 238        case FPGA_INFO:
 239                rc = fpga_info (dev);
 240                break;
 241
 242        case FPGA_LOAD:
 243                rc = fpga_load (dev, fpga_data, data_size);
 244                break;
 245
 246        case FPGA_LOADB:
 247                rc = fpga_loadbitstream(dev, fpga_data, data_size);
 248                break;
 249
 250        case FPGA_LOADMK:
 251                switch (genimg_get_format (fpga_data)) {
 252                case IMAGE_FORMAT_LEGACY:
 253                        {
 254                                image_header_t *hdr = (image_header_t *)fpga_data;
 255                                ulong   data;
 256
 257                                data = (ulong)image_get_data (hdr);
 258                                data_size = image_get_data_size (hdr);
 259                                rc = fpga_load (dev, (void *)data, data_size);
 260                        }
 261                        break;
 262#if defined(CONFIG_FIT)
 263                case IMAGE_FORMAT_FIT:
 264                        {
 265                                const void *fit_hdr = (const void *)fpga_data;
 266                                int noffset;
 267                                void *fit_data;
 268
 269                                if (fit_uname == NULL) {
 270                                        puts ("No FIT subimage unit name\n");
 271                                        return 1;
 272                                }
 273
 274                                if (!fit_check_format (fit_hdr)) {
 275                                        puts ("Bad FIT image format\n");
 276                                        return 1;
 277                                }
 278
 279                                /* get fpga component image node offset */
 280                                noffset = fit_image_get_node (fit_hdr, fit_uname);
 281                                if (noffset < 0) {
 282                                        printf ("Can't find '%s' FIT subimage\n", fit_uname);
 283                                        return 1;
 284                                }
 285
 286                                /* verify integrity */
 287                                if (!fit_image_check_hashes (fit_hdr, noffset)) {
 288                                        puts ("Bad Data Hash\n");
 289                                        return 1;
 290                                }
 291
 292                                /* get fpga subimage data address and length */
 293                                if (fit_image_get_data (fit_hdr, noffset, &fit_data, &data_size)) {
 294                                        puts ("Could not find fpga subimage data\n");
 295                                        return 1;
 296                                }
 297
 298                                rc = fpga_load (dev, fit_data, data_size);
 299                        }
 300                        break;
 301#endif
 302                default:
 303                        puts ("** Unknown image type\n");
 304                        rc = FPGA_FAIL;
 305                        break;
 306                }
 307                break;
 308
 309        case FPGA_DUMP:
 310                rc = fpga_dump (dev, fpga_data, data_size);
 311                break;
 312
 313        default:
 314                printf ("Unknown operation\n");
 315                fpga_usage (cmdtp);
 316                break;
 317        }
 318        return (rc);
 319}
 320
 321static void fpga_usage (cmd_tbl_t * cmdtp)
 322{
 323        cmd_usage(cmdtp);
 324}
 325
 326/*
 327 * Map op to supported operations.  We don't use a table since we
 328 * would just have to relocate it from flash anyway.
 329 */
 330static int fpga_get_op (char *opstr)
 331{
 332        int op = FPGA_NONE;
 333
 334        if (!strcmp ("info", opstr)) {
 335                op = FPGA_INFO;
 336        } else if (!strcmp ("loadb", opstr)) {
 337                op = FPGA_LOADB;
 338        } else if (!strcmp ("load", opstr)) {
 339                op = FPGA_LOAD;
 340        } else if (!strcmp ("loadmk", opstr)) {
 341                op = FPGA_LOADMK;
 342        } else if (!strcmp ("dump", opstr)) {
 343                op = FPGA_DUMP;
 344        }
 345
 346        if (op == FPGA_NONE) {
 347                printf ("Unknown fpga operation \"%s\"\n", opstr);
 348        }
 349        return op;
 350}
 351
 352U_BOOT_CMD (fpga, 6, 1, do_fpga,
 353            "loadable FPGA image support",
 354            "fpga [operation type] [device number] [image address] [image size]\n"
 355            "fpga operations:\n"
 356            "\tinfo\tlist known device information\n"
 357            "\tload\tLoad device from memory buffer\n"
 358            "\tloadb\tLoad device from bitstream buffer (Xilinx devices only)\n"
 359            "\tloadmk\tLoad device generated with mkimage\n"
 360            "\tdump\tLoad device to memory buffer\n"
 361#if defined(CONFIG_FIT)
 362            "\tFor loadmk operating on FIT format uImage address must include\n"
 363            "\tsubimage unit name in the form of addr:<subimg_uname>\n"
 364#endif
 365);
 366