1/*  *********************************************************************
2    *  Broadcom Common Firmware Environment (CFE)
3    *
4    *  Flash Image generator			File: mkflashimage.c
5    *
6    *  Author:  Mitch Lichtenberg (mpl@broadcom.com)
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
66
67static int verbose = 0;
68static int big_endian = 1;
69static int both_endian = 0;
70int mlong64 = 0;
71char boardname[32];
72
73/*
74 * This is the offset in the flash where the little-endian image goes
75 * if we're making a bi-endian flash.
76 */
77
78#define CFE_BIENDIAN_LE_OFFSET	(1024*1024)
79
80static void usage(void)
81{
82    fprintf(stderr,"usage: mkflashimage [-v] [-EB] [-EL] [-64] [-B boardname] [-V v.v.v] binfile outfile\n");
83    fprintf(stderr,"\n");
84    fprintf(stderr,"       mkflashimage [-v] -EX [-64] [-B boardname] [-V v.v.v] BE-binfile LE-binfile outfile\n");
85    fprintf(stderr,"       (this variant used for making bi-endian flash files)\n");
86    exit(1);
87}
88
89
90static int host_is_little(void)
91{
92    unsigned long var = 1;
93    unsigned char *pvar = (unsigned char *) &var;
94
95    return (*pvar == 1);
96}
97
98#define     CRC32_POLY        0xEDB88320UL    /* CRC-32 Poly */
99
100static unsigned int
101crc32(const unsigned char *databuf, unsigned int  datalen)
102{
103    unsigned int idx, bit, data, crc = 0xFFFFFFFFUL;
104
105    for (idx = 0; idx < datalen; idx++) {
106	for (data = *databuf++, bit = 0; bit < 8; bit++, data >>= 1) {
107	    crc = (crc >> 1) ^ (((crc ^ data) & 1) ? CRC32_POLY : 0);
108	    }
109	}
110
111    return crc;
112}
113
114
115void stuff_be32(uint8_t *dest,unsigned int src)
116{
117    *dest++ = (src >> 24) & 0xFF;
118    *dest++ = (src >> 16) & 0xFF;
119    *dest++ = (src >>  8) & 0xFF;
120    *dest++ = (src >>  0) & 0xFF;
121}
122
123int main(int argc, char *argv[])
124{
125    int fh;
126    int flashsize;
127    unsigned char *flashcode;
128    cfe_flashimage_t header;
129    int host_le;
130    int majver,minver,ecover;
131    uint32_t crc;
132    uint32_t flags;
133    char *outfile;
134
135    majver = minver = ecover = 0;
136    boardname[0] = 0;
137
138    while ((argc > 1) && (argv[1][0] == '-')) {
139	if (strcmp(argv[1],"-v") == 0) {
140	    verbose = 1;
141	    }
142	else if (strcmp(argv[1],"-EX") == 0) {
143	    if (verbose) fprintf(stderr,"[Image file will be marked Bi-Endian]\n");
144	    both_endian = 1;
145	    }
146	else if (strcmp(argv[1],"-EB") == 0) {
147	    if (verbose) fprintf(stderr,"[Image file will be marked Big-Endian]\n");
148	    big_endian = 1;
149	    }
150	else if (strcmp(argv[1],"-EL") == 0) {
151	    if (verbose) fprintf(stderr,"[Image file will be marked Little-Endian]\n");
152	    big_endian = 0;
153	    }
154	else if (strcmp(argv[1],"-64") == 0) {
155	    if (verbose) fprintf(stderr,"[Image file will be marked 64-bit]\n");
156	    mlong64 = 1;
157	    }
158	else if (strcmp(argv[1],"-B") == 0) {
159	    argc--;
160	    argv++;
161	    strcpy(boardname,argv[1]);
162	    if (verbose) fprintf(stderr,"[Board name: %s]\n",boardname);
163	    }
164	else if (strcmp(argv[1],"-V") == 0) {
165	    argc--;
166	    argv++;
167	    sscanf(argv[1],"%d.%d.%d",&majver,&minver,&ecover);
168	    if (verbose) fprintf(stderr,"[Image version: %d.%d.%d]\n",majver,minver,ecover);
169	    }
170	else {
171	    fprintf(stderr,"Invalid switch: %s\n",argv[1]);
172	    exit(1);
173	    }
174	argv++;
175	argc--;
176	}
177
178    /*
179     * We need to swap things around if the host and
180     * target are different endianness
181     */
182
183    host_le = host_is_little();
184
185    if (verbose) {
186	fprintf(stderr,"Host is %s-endian.\n",host_le ? "little" : "big");
187	if (both_endian) {
188	    fprintf(stderr,"Target is bi-endian.\n");
189	    }
190	else {
191	    fprintf(stderr,"Target is %s-endian.\n",big_endian ? "big" : "little");
192	    }
193	}
194
195    if ((both_endian && (argc != 4)) || (!both_endian && (argc != 3))) {
196	usage();
197	}
198
199    /*
200     * Read in the boot file(s)
201     */
202
203    flags = 0;
204
205    if (both_endian) {
206	int be_size;
207
208	flags |= (CFE_IMAGE_EB | CFE_IMAGE_EL);
209
210	if (verbose) fprintf(stderr,"Reading: %s\n",argv[2]);
211
212	fh = open(argv[2],O_RDONLY);
213	if (fh < 0) {
214	    perror(argv[2]);
215	    }
216
217	flashsize = lseek(fh,0L,SEEK_END);
218	lseek(fh,0L,SEEK_SET);
219
220	flashcode = malloc(flashsize+CFE_BIENDIAN_LE_OFFSET);
221	if (flashcode == NULL) {
222	    perror("malloc");
223	    exit(1);
224	    }
225	memset(flashcode,0xFF,flashsize+CFE_BIENDIAN_LE_OFFSET);
226
227	if (read(fh,flashcode+CFE_BIENDIAN_LE_OFFSET,flashsize) != flashsize) {
228	    perror("read");
229	    exit(1);
230	    }
231
232	close(fh);
233
234	if (memcmp(flashcode+CFE_BIENDIAN_LE_OFFSET,CFE_IMAGE_SEAL,4) == 0) {
235	    fprintf(stderr,"File '%s' already has an image header.\n",argv[2]);
236	    exit(1);
237	    }
238
239	flashsize += CFE_BIENDIAN_LE_OFFSET;	/* actual file size */
240
241	if (verbose) fprintf(stderr,"Reading: %s\n",argv[1]);
242
243	fh = open(argv[1],O_RDONLY);
244	if (fh < 0) {
245	    perror(argv[1]);
246	    exit(1);
247	    }
248
249	be_size = lseek(fh,0L,SEEK_END);
250	lseek(fh,0L,SEEK_SET);
251	if (be_size > CFE_BIENDIAN_LE_OFFSET) {
252	    fprintf(stderr,"File '%s' will not fit within first %d bytes of flash image\n",
253		    argv[1],CFE_BIENDIAN_LE_OFFSET);
254	    close(fh);
255	    exit(1);
256	    }
257
258	if (read(fh,flashcode,be_size) != be_size) {
259	    perror("read");
260	    exit(1);
261	    }
262
263	close(fh);
264
265	outfile = argv[3];
266
267	}
268    else {
269	if (big_endian) flags |= CFE_IMAGE_EB;
270	else flags |= CFE_IMAGE_EL;
271
272	fh = open(argv[1],O_RDONLY);
273	if (fh < 0) {
274	    perror(argv[1]);
275	    exit(1);
276	    }
277
278	flashsize = lseek(fh,0L,SEEK_END);
279	lseek(fh,0L,SEEK_SET);
280
281	flashcode = malloc(flashsize);
282	if (flashcode == NULL) {
283	    perror("malloc");
284	    exit(1);
285	    }
286	memset(flashcode,0,flashsize);
287	if (read(fh,flashcode,flashsize) != flashsize) {
288	    perror("read");
289	    exit(1);
290	    }
291
292	close(fh);
293
294	if (memcmp(flashcode,CFE_IMAGE_SEAL,4) == 0) {
295	    fprintf(stderr,"File '%s' already has an image header.\n",argv[1]);
296	    exit(1);
297	    }
298
299	outfile = argv[2];
300	}
301
302
303    /*
304     * Construct the flash header
305     */
306
307    if (mlong64) flags |= CFE_IMAGE_MLONG64;
308    crc = crc32(flashcode,flashsize);
309
310    memset(&header,0,sizeof(header));
311    memcpy(header.seal,CFE_IMAGE_SEAL,sizeof(header.seal));
312    stuff_be32(header.flags,flags);
313    stuff_be32(header.size,flashsize);
314    stuff_be32(header.crc,crc);
315    header.majver = majver;
316    header.minver = minver;
317    header.ecover = ecover;
318    header.miscver = 0;
319    strcpy(header.boardname,boardname);
320
321    /*
322     * Now write the output file
323     */
324
325    fh = open(outfile,O_RDWR|O_CREAT|O_TRUNC,S_IREAD|S_IWRITE|S_IRGRP|S_IWGRP|S_IROTH);
326    if  (fh < 0) {
327	perror(outfile);
328	exit(1);
329	}
330    if (write(fh,&header,sizeof(header)) != sizeof(header)) {
331	perror(outfile);
332	exit(1);
333	}
334    if (write(fh,flashcode,flashsize) != flashsize) {
335	perror(outfile);
336	exit(1);
337	}
338
339    fprintf(stderr,"Wrote %d bytes to %s\n",sizeof(header)+flashsize,outfile);
340
341    close(fh);
342
343    exit(0);
344
345
346}
347
348