1/*  *********************************************************************
2    *  Broadcom Common Firmware Environment (CFE)
3    *
4    *  Flash Image generator			File: mkflashimage.c
5    *
6    *  Author:  Mitch Lichtenberg
7    *
8    *  This program sticks a header on the front of a binary
9    *  file making it suitable for use with the 'flash' command
10    *  in CFE.  The header contains the CFE version # and board
11    *  type, a CRC, and other info to help prevent us from
12    *  flashing bad stuff onto a board.
13    *
14    *********************************************************************
15    *
16    *  Copyright 2000,2001,2002,2003
17    *  Broadcom Corporation. All rights reserved.
18    *
19    *  This software is furnished under license and may be used and
20    *  copied only in accordance with the following terms and
21    *  conditions.  Subject to these conditions, you may download,
22    *  copy, install, use, modify and distribute modified or unmodified
23    *  copies of this software in source and/or binary form.  No title
24    *  or ownership is transferred hereby.
25    *
26    *  1) Any source code used, modified or distributed must reproduce
27    *     and retain this copyright notice and list of conditions
28    *     as they appear in the source file.
29    *
30    *  2) No right is granted to use any trade name, trademark, or
31    *     logo of Broadcom Corporation.  The "Broadcom Corporation"
32    *     name may not be used to endorse or promote products derived
33    *     from this software without the prior written permission of
34    *     Broadcom Corporation.
35    *
36    *  3) THIS SOFTWARE IS PROVIDED "AS-IS" AND ANY EXPRESS OR
37    *     IMPLIED WARRANTIES, INCLUDING BUT NOT LIMITED TO, ANY IMPLIED
38    *     WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
39    *     PURPOSE, OR NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT
40    *     SHALL BROADCOM BE LIABLE FOR ANY DAMAGES WHATSOEVER, AND IN
41    *     PARTICULAR, BROADCOM SHALL NOT BE LIABLE FOR DIRECT, INDIRECT,
42    *     INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
43    *     (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
44    *     GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
45    *     BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
46    *     OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
47    *     TORT (INCLUDING NEGLIGENCE OR OTHERWISE), EVEN IF ADVISED OF
48    *     THE POSSIBILITY OF SUCH DAMAGE.
49    ********************************************************************* */
50
51#include <sys/types.h>
52#include <sys/stat.h>
53
54#ifndef _SYS_INT_TYPES_H
55typedef unsigned char uint8_t;
56typedef unsigned long long uint64_t;
57typedef unsigned long uint32_t;
58#endif
59
60#include "cfe_flashimage.h"
61#include <fcntl.h>
62#include <stdlib.h>
63#include <stdio.h>
64#include <string.h>
65#include <unistd.h>
66
67
68static int verbose = 0;
69static int big_endian = 1;
70static int both_endian = 0;
71int mlong64 = 0;
72char boardname[32];
73
74#ifndef O_BINARY
75#define O_BINARY 0
76#endif
77
78/*
79 * This is the offset in the flash where the little-endian image goes
80 * if we're making a bi-endian flash.
81 */
82
83#define CFE_BIENDIAN_LE_OFFSET	(1024*1024)
84
85static void usage(void)
86{
87    fprintf(stderr,"usage: mkflashimage [-v] [-EB] [-EL] [-64] [-B boardname] [-V v.v.v] binfile outfile\n");
88    fprintf(stderr,"\n");
89    fprintf(stderr,"       mkflashimage [-v] -EX [-64] [-B boardname] [-V v.v.v] BE-binfile LE-binfile outfile\n");
90    fprintf(stderr,"       (this variant used for making bi-endian flash files)\n");
91    exit(1);
92}
93
94
95static int host_is_little(void)
96{
97    unsigned long var = 1;
98    unsigned char *pvar = (unsigned char *) &var;
99
100    return (*pvar == 1);
101}
102
103#define     CRC32_POLY        0xEDB88320UL    /* CRC-32 Poly */
104
105static unsigned int
106crc32(const unsigned char *databuf, unsigned int  datalen)
107{
108    unsigned int idx, bit, data, crc = 0xFFFFFFFFUL;
109
110    for (idx = 0; idx < datalen; idx++) {
111	for (data = *databuf++, bit = 0; bit < 8; bit++, data >>= 1) {
112	    crc = (crc >> 1) ^ (((crc ^ data) & 1) ? CRC32_POLY : 0);
113	    }
114	}
115
116    return crc;
117}
118
119
120static void stuff_be32(uint8_t *dest,unsigned int src)
121{
122    *dest++ = (src >> 24) & 0xFF;
123    *dest++ = (src >> 16) & 0xFF;
124    *dest++ = (src >>  8) & 0xFF;
125    *dest++ = (src >>  0) & 0xFF;
126}
127
128int main(int argc, char *argv[])
129{
130    int fh;
131    int flashsize;
132    unsigned char *flashcode;
133    cfe_flashimage_t header;
134    int host_le;
135    int majver,minver,ecover;
136    uint32_t crc;
137    uint32_t flags;
138    char *outfile;
139
140    majver = minver = ecover = 0;
141    boardname[0] = 0;
142
143    while ((argc > 1) && (argv[1][0] == '-')) {
144	if (strcmp(argv[1],"-v") == 0) {
145	    verbose = 1;
146	    }
147	else if (strcmp(argv[1],"-EX") == 0) {
148	    if (verbose) fprintf(stderr,"[Image file will be marked Bi-Endian]\n");
149	    both_endian = 1;
150	    }
151	else if (strcmp(argv[1],"-EB") == 0) {
152	    if (verbose) fprintf(stderr,"[Image file will be marked Big-Endian]\n");
153	    big_endian = 1;
154	    }
155	else if (strcmp(argv[1],"-EL") == 0) {
156	    if (verbose) fprintf(stderr,"[Image file will be marked Little-Endian]\n");
157	    big_endian = 0;
158	    }
159	else if (strcmp(argv[1],"-64") == 0) {
160	    if (verbose) fprintf(stderr,"[Image file will be marked 64-bit]\n");
161	    mlong64 = 1;
162	    }
163	else if (strcmp(argv[1],"-B") == 0) {
164	    argc--;
165	    argv++;
166	    strcpy(boardname,argv[1]);
167	    if (verbose) fprintf(stderr,"[Board name: %s]\n",boardname);
168	    }
169	else if (strcmp(argv[1],"-V") == 0) {
170	    argc--;
171	    argv++;
172	    sscanf(argv[1],"%d.%d.%d",&majver,&minver,&ecover);
173	    if (verbose) fprintf(stderr,"[Image version: %d.%d.%d]\n",majver,minver,ecover);
174	    }
175	else {
176	    fprintf(stderr,"Invalid switch: %s\n",argv[1]);
177	    exit(1);
178	    }
179	argv++;
180	argc--;
181	}
182
183    /*
184     * We need to swap things around if the host and
185     * target are different endianness
186     */
187
188    host_le = host_is_little();
189
190    if (verbose) {
191	fprintf(stderr,"Host is %s-endian.\n",host_le ? "little" : "big");
192	if (both_endian) {
193	    fprintf(stderr,"Target is bi-endian.\n");
194	    }
195	else {
196	    fprintf(stderr,"Target is %s-endian.\n",big_endian ? "big" : "little");
197	    }
198	}
199
200    if ((both_endian && (argc != 4)) || (!both_endian && (argc != 3))) {
201	usage();
202	}
203
204    /*
205     * Read in the boot file(s)
206     */
207
208    flags = 0;
209
210    if (both_endian) {
211	int be_size;
212
213	flags |= (CFE_IMAGE_EB | CFE_IMAGE_EL);
214
215	if (verbose) fprintf(stderr,"Reading: %s\n",argv[2]);
216
217	fh = open(argv[2],O_RDONLY|O_BINARY);
218	if (fh < 0) {
219	    perror(argv[2]);
220	    }
221
222	flashsize = lseek(fh,0L,SEEK_END);
223	lseek(fh,0L,SEEK_SET);
224
225	flashcode = malloc(flashsize+CFE_BIENDIAN_LE_OFFSET);
226	if (flashcode == NULL) {
227	    perror("malloc");
228	    exit(1);
229	    }
230	memset(flashcode,0xFF,flashsize+CFE_BIENDIAN_LE_OFFSET);
231
232	if (read(fh,flashcode+CFE_BIENDIAN_LE_OFFSET,flashsize) != flashsize) {
233	    perror("read");
234	    exit(1);
235	    }
236
237	close(fh);
238
239	if (memcmp(flashcode+CFE_BIENDIAN_LE_OFFSET,CFE_IMAGE_SEAL,4) == 0) {
240	    fprintf(stderr,"File '%s' already has an image header.\n",argv[2]);
241	    exit(1);
242	    }
243
244	flashsize += CFE_BIENDIAN_LE_OFFSET;	/* actual file size */
245
246	if (verbose) fprintf(stderr,"Reading: %s\n",argv[1]);
247
248	fh = open(argv[1],O_RDONLY|O_BINARY);
249	if (fh < 0) {
250	    perror(argv[1]);
251	    exit(1);
252	    }
253
254	be_size = lseek(fh,0L,SEEK_END);
255	lseek(fh,0L,SEEK_SET);
256	if (be_size > CFE_BIENDIAN_LE_OFFSET) {
257	    fprintf(stderr,"File '%s' will not fit within first %d bytes of flash image\n",
258		    argv[1],CFE_BIENDIAN_LE_OFFSET);
259	    close(fh);
260	    exit(1);
261	    }
262
263	if (read(fh,flashcode,be_size) != be_size) {
264	    perror("read");
265	    exit(1);
266	    }
267
268	close(fh);
269
270	outfile = argv[3];
271
272	}
273    else {
274	if (big_endian) flags |= CFE_IMAGE_EB;
275	else flags |= CFE_IMAGE_EL;
276
277	fh = open(argv[1],O_RDONLY|O_BINARY);
278	if (fh < 0) {
279	    perror(argv[1]);
280	    exit(1);
281	    }
282
283	flashsize = lseek(fh,0L,SEEK_END);
284	lseek(fh,0L,SEEK_SET);
285
286	flashcode = malloc(flashsize);
287	if (flashcode == NULL) {
288	    perror("malloc");
289	    exit(1);
290	    }
291	memset(flashcode,0,flashsize);
292	if (read(fh,flashcode,flashsize) != flashsize) {
293	    perror("read");
294	    exit(1);
295	    }
296
297	close(fh);
298
299	if (memcmp(flashcode,CFE_IMAGE_SEAL,4) == 0) {
300	    fprintf(stderr,"File '%s' already has an image header.\n",argv[1]);
301	    exit(1);
302	    }
303
304	outfile = argv[2];
305	}
306
307
308    /*
309     * Construct the flash header
310     */
311
312    if (mlong64) flags |= CFE_IMAGE_MLONG64;
313    crc = crc32(flashcode,flashsize);
314
315    memset(&header,0,sizeof(header));
316    memcpy(header.seal,CFE_IMAGE_SEAL,sizeof(header.seal));
317    stuff_be32(header.flags,flags);
318    stuff_be32(header.size,flashsize);
319    stuff_be32(header.crc,crc);
320    header.majver = majver;
321    header.minver = minver;
322    header.ecover = ecover;
323    header.miscver = 0;
324    strcpy(header.boardname,boardname);
325
326    /*
327     * Now write the output file
328     */
329
330    fh = open(outfile,O_RDWR|O_CREAT|O_TRUNC,S_IREAD|S_IWRITE|S_IRGRP|S_IWGRP|S_IROTH|O_BINARY);
331    if  (fh < 0) {
332	perror(outfile);
333	exit(1);
334	}
335    if (write(fh,&header,sizeof(header)) != sizeof(header)) {
336	perror(outfile);
337	exit(1);
338	}
339    if (write(fh,flashcode,flashsize) != flashsize) {
340	perror(outfile);
341	exit(1);
342	}
343
344    fprintf(stderr,"Wrote %d bytes to %s\n",(int)sizeof(header)+flashsize,outfile);
345
346    close(fh);
347
348    exit(0);
349
350
351}
352
353