1/*  *********************************************************************
2    *  Broadcom Common Firmware Environment (CFE)
3    *
4    *  Flash Image Swapper			File: swapflashimage.c
5    *
6    *  This program updates the header and swaps the data bytes
7    *  in files generated for use with the 'flash' command
8    *  in CFE.  It is only used when in certain cases of flashing
9    *  a file intended for the opposite endian of the CFE executing
10    *  the flash command, typically when the target flash device
11    *  has a bus interface wider than 8 bits.
12    *
13    *********************************************************************
14    *
15    *  Copyright 2000,2001,2002,2003,2005
16    *  Broadcom Corporation. All rights reserved.
17    *
18    *  This software is furnished under license and may be used and
19    *  copied only in accordance with the following terms and
20    *  conditions.  Subject to these conditions, you may download,
21    *  copy, install, use, modify and distribute modified or unmodified
22    *  copies of this software in source and/or binary form.  No title
23    *  or ownership is transferred hereby.
24    *
25    *  1) Any source code used, modified or distributed must reproduce
26    *     and retain this copyright notice and list of conditions
27    *     as they appear in the source file.
28    *
29    *  2) No right is granted to use any trade name, trademark, or
30    *     logo of Broadcom Corporation.  The "Broadcom Corporation"
31    *     name may not be used to endorse or promote products derived
32    *     from this software without the prior written permission of
33    *     Broadcom Corporation.
34    *
35    *  3) THIS SOFTWARE IS PROVIDED "AS-IS" AND ANY EXPRESS OR
36    *     IMPLIED WARRANTIES, INCLUDING BUT NOT LIMITED TO, ANY IMPLIED
37    *     WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
38    *     PURPOSE, OR NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT
39    *     SHALL BROADCOM BE LIABLE FOR ANY DAMAGES WHATSOEVER, AND IN
40    *     PARTICULAR, BROADCOM SHALL NOT BE LIABLE FOR DIRECT, INDIRECT,
41    *     INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
42    *     (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
43    *     GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
44    *     BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
45    *     OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
46    *     TORT (INCLUDING NEGLIGENCE OR OTHERWISE), EVEN IF ADVISED OF
47    *     THE POSSIBILITY OF SUCH DAMAGE.
48    ********************************************************************* */
49
50#include <sys/types.h>
51#include <unistd.h>
52#include <sys/stat.h>
53
54#ifndef _SYS_INT_TYPES_H
55typedef unsigned char uint8_t;
56typedef unsigned long uint32_t;
57#endif
58
59#include "cfe_flashimage.h"
60#include <fcntl.h>
61#include <stdlib.h>
62#include <stdio.h>
63#include <string.h>
64
65
66#ifndef O_BINARY
67#define O_BINARY 0
68#endif
69
70static void usage(void)
71{
72    fprintf(stderr,"usage: swapflashimage [-(b|h|w)] flashfile outfile\n");
73    fprintf(stderr,"\n");
74    exit(1);
75}
76
77
78#define     CRC32_POLY        0xEDB88320UL    /* CRC-32 Poly */
79
80static unsigned int
81crc32(const unsigned char *databuf, unsigned int  datalen)
82{
83    unsigned int idx, bit, data, crc = 0xFFFFFFFFUL;
84
85    for (idx = 0; idx < datalen; idx++) {
86	for (data = *databuf++, bit = 0; bit < 8; bit++, data >>= 1) {
87	    crc = (crc >> 1) ^ (((crc ^ data) & 1) ? CRC32_POLY : 0);
88	    }
89	}
90
91    return crc;
92}
93
94
95static void stuff_be32(uint8_t *dest,unsigned int src)
96{
97    *dest++ = (src >> 24) & 0xFF;
98    *dest++ = (src >> 16) & 0xFF;
99    *dest++ = (src >>  8) & 0xFF;
100    *dest++ = (src >>  0) & 0xFF;
101}
102
103static uint32_t get_be32(uint8_t *src)
104{
105    return (((uint32_t) (src[0] << 24)) | \
106	    ((uint32_t) (src[1] << 16)) | \
107	    ((uint32_t) (src[2] << 8)) |  \
108	    ((uint32_t) (src[3] << 0)));
109}
110
111static int flash_validate(cfe_flashimage_t *hdr, uint8_t *code, int insize)
112{
113    uint32_t size;
114    uint32_t flags;
115    uint32_t hdrcrc;
116    uint32_t calccrc;
117
118    if (memcmp(hdr->seal,CFE_IMAGE_SEAL,sizeof(hdr->seal)) != 0) {
119	printf("Invalid header seal.  This is not a CFE flash image.\n");
120	return -1;
121	}
122
123    printf("Flash image contains CFE version %d.%d.%d for board '%s'\n",
124	   hdr->majver,hdr->minver,hdr->ecover,hdr->boardname);
125
126    size = get_be32(hdr->size);
127    flags = get_be32(hdr->flags);
128    hdrcrc = get_be32(hdr->crc);
129    printf("Flash image is %d bytes, flags %08X, CRC %08X\n",
130	   (unsigned int)size,(unsigned int)flags,(unsigned int)hdrcrc);
131
132    if (size != insize) {
133	printf("Flash image size is bogus!\n");
134	return -1;
135	}
136
137    calccrc = crc32(code,size);
138
139    if (calccrc != hdrcrc) {
140	printf("CRC is incorrect. Calculated CRC is %08X\n",
141	       (unsigned int)calccrc);
142	return -1;
143	}
144    return 0;
145}
146
147int main(int argc, char *argv[])
148{
149    int swapsize;
150    int fh;
151    int flashsize;
152    uint8_t *flashcode;
153    cfe_flashimage_t header;
154    uint32_t crc;
155    char *outfile;
156    int outsize;
157    uint8_t *ptr;
158    int i, j, k;
159    uint8_t t;
160
161    swapsize = 0;
162    while ((argc > 1) && (argv[1][0] == '-')) {
163	if (strcmp(argv[1],"-B") == 0 || strcmp(argv[1],"-b") == 0) {
164	    fprintf(stderr,"[Bytes will be not be swapped]\n");
165	    swapsize = 1;
166	    }
167	else if (strcmp(argv[1],"-H") == 0 || strcmp(argv[1],"-h") == 0) {
168	    fprintf(stderr,"[Bytes within pairs will be swapped]\n");
169	    swapsize = 2;
170	    }
171	else if (strcmp(argv[1],"-W") == 0 || strcmp(argv[1],"-w") == 0) {
172	    fprintf(stderr,"[Bytes within quads will be swapped]\n");
173	    swapsize = 4;
174	    }
175	else {
176	    fprintf(stderr,"Invalid switch: %s\n",argv[1]);
177	    exit(1);
178	    }
179	argv++;
180	argc--;
181	}
182
183    if (swapsize == 0) {
184	fprintf(stderr,"[Bytes within quads will be swapped]\n");
185	swapsize = 4;
186	}
187
188    /*
189     * We need to swap things around if the host and
190     * target are different endianness
191     */
192
193    if (argc != 3) {
194	usage();
195	}
196
197    /*
198     * Read and validate the header first.
199     */
200
201    fh = open(argv[1],O_RDONLY|O_BINARY);
202    if (fh < 0) {
203	perror(argv[1]);
204	}
205
206    flashsize = lseek(fh,0L,SEEK_END);
207    lseek(fh,0L,SEEK_SET);
208
209    if (read(fh,&header,sizeof(header)) != sizeof(header)) {
210	perror("header");
211	exit(1);
212	}
213
214    /*
215     * Force the data to be a multiple of the swap unit (or error?).
216     */
217
218    flashsize -= sizeof(header);
219    outsize = (flashsize + (swapsize-1)) & ~(swapsize-1);
220
221    flashcode = malloc(outsize);
222    if (flashcode == NULL) {
223	perror("malloc");
224	exit(1);
225	}
226
227    /*
228     * Read in the boot code
229     */
230
231    if (read(fh,flashcode,flashsize) != flashsize) {
232	perror("read");
233	exit(1);
234	}
235
236    close(fh);
237
238    if (flash_validate(&header, flashcode, flashsize) < 0) {
239	exit(1);
240	}
241
242    if (flashsize < outsize)
243	memset(flashcode+flashsize,0xFF,outsize-flashsize);
244    flashsize = outsize;
245
246    outfile = argv[2];
247
248    /*
249     * Perform the requested swap.
250     */
251
252    ptr = flashcode;
253    for (i = 0; i < flashsize; i += swapsize) {
254	for (j = 0,k = (swapsize-1); j < swapsize/2; j++,k--) {
255	    t = *(ptr+j);
256	    *(ptr+j) = *(ptr + k);
257	    *(ptr+k) = t;
258	    }
259	ptr += swapsize;
260	}
261
262    /*
263     * Update the size and CRC in the flash header
264     */
265
266    crc = crc32(flashcode,flashsize);
267
268    stuff_be32(header.size,flashsize);
269    stuff_be32(header.crc,crc);
270
271    /*
272     * Now write the output file
273     */
274
275    fh = open(outfile,O_RDWR|O_CREAT|O_TRUNC,S_IREAD|S_IWRITE|S_IRGRP|S_IWGRP|S_IROTH|O_BINARY);
276    if  (fh < 0) {
277	perror(outfile);
278	exit(1);
279	}
280    if (write(fh,&header,sizeof(header)) != sizeof(header)) {
281	perror(outfile);
282	exit(1);
283	}
284    if (write(fh,flashcode,flashsize) != flashsize) {
285	perror(outfile);
286	exit(1);
287	}
288
289    fprintf(stderr,"Wrote %d bytes to %s\n",
290	    (int)(sizeof(header)+flashsize),outfile);
291
292    close(fh);
293
294    exit(0);
295}
296