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 */
47 static void fpga_usage (cmd_tbl_t * cmdtp);
48 static 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 */
fpga_loadbitstream(unsigned long dev,char * fpgadata,size_t size)59 int 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  */
do_fpga(cmd_tbl_t * cmdtp,int flag,int argc,char * argv[])159 int 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 
fpga_usage(cmd_tbl_t * cmdtp)321 static 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  */
fpga_get_op(char * opstr)330 static 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 
352 U_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"
361 #if defined(CONFIG_FIT)
362 	    "\n"
363 	    "\tFor loadmk operating on FIT format uImage address must include\n"
364 	    "\tsubimage unit name in the form of addr:<subimg_uname>"
365 #endif
366 );
367