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