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