1/* ********************************************************************* 2 * Broadcom Common Firmware Environment (CFE) 3 * 4 * Boot block generator File: mkbootimage.c 5 * 6 * Author: Mitch Lichtenberg (mpl@broadcom.com) 7 * 8 * This program converts a binary file (bootstrap program) 9 * into a boot block by prepending the boot block sector 10 * to the program. It generates the appropriate 11 * boot block checksums and such. The resulting file may 12 * be used by installboot (for example) to put into a disk 13 * image for the simulator. 14 * 15 ********************************************************************* 16 * 17 * Copyright 2000,2001,2002,2003 18 * Broadcom Corporation. All rights reserved. 19 * 20 * This software is furnished under license and may be used and 21 * copied only in accordance with the following terms and 22 * conditions. Subject to these conditions, you may download, 23 * copy, install, use, modify and distribute modified or unmodified 24 * copies of this software in source and/or binary form. No title 25 * or ownership is transferred hereby. 26 * 27 * 1) Any source code used, modified or distributed must reproduce 28 * and retain this copyright notice and list of conditions 29 * as they appear in the source file. 30 * 31 * 2) No right is granted to use any trade name, trademark, or 32 * logo of Broadcom Corporation. The "Broadcom Corporation" 33 * name may not be used to endorse or promote products derived 34 * from this software without the prior written permission of 35 * Broadcom Corporation. 36 * 37 * 3) THIS SOFTWARE IS PROVIDED "AS-IS" AND ANY EXPRESS OR 38 * IMPLIED WARRANTIES, INCLUDING BUT NOT LIMITED TO, ANY IMPLIED 39 * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR 40 * PURPOSE, OR NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT 41 * SHALL BROADCOM BE LIABLE FOR ANY DAMAGES WHATSOEVER, AND IN 42 * PARTICULAR, BROADCOM SHALL NOT BE LIABLE FOR DIRECT, INDIRECT, 43 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 44 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE 45 * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR 46 * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY 47 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR 48 * TORT (INCLUDING NEGLIGENCE OR OTHERWISE), EVEN IF ADVISED OF 49 * THE POSSIBILITY OF SUCH DAMAGE. 50 ********************************************************************* */ 51 52#include <sys/types.h> 53#include <sys/stat.h> 54 55typedef unsigned long long uint64_t; 56typedef unsigned long uint32_t; 57 58#include "cfe_bootblock.h" 59#include <fcntl.h> 60#include <stdlib.h> 61#include <stdio.h> 62#include <string.h> 63 64#define roundup(x,align) (((x)+(align)-1)&~((align)-1)) 65#define howmany(x,align) (((x)+(align)-1)/(align)) 66 67static int verbose = 0; 68static int big_endian = 1; 69static int swapflg = 1; 70static unsigned long sector_offset = 0; 71 72static void usage(void) 73{ 74 fprintf(stderr,"usage: mkbootimage [-S <sector offset>] [-v] [-EB] [-EL] inputfile outputfile\n"); 75 exit(1); 76} 77 78static void bswap32(uint32_t *ptr) 79{ 80 unsigned char b; 81 unsigned char *bptr; 82 83 if (swapflg) { 84 bptr = (unsigned char *) ptr; 85 b = bptr[0]; bptr[0] = bptr[3]; bptr[3] = b; 86 b = bptr[1]; bptr[1] = bptr[2]; bptr[2] = b; 87 } 88} 89 90static void bswap64(uint64_t *ptr) 91{ 92 unsigned char b; 93 unsigned char *bptr; 94 95 bptr = (unsigned char *) ptr; 96 97 if (swapflg) { 98 b = bptr[0]; bptr[0] = bptr[7]; bptr[7] = b; 99 b = bptr[1]; bptr[1] = bptr[6]; bptr[6] = b; 100 b = bptr[2]; bptr[2] = bptr[5]; bptr[5] = b; 101 b = bptr[3]; bptr[3] = bptr[4]; bptr[4] = b; 102 } 103} 104 105 106static void bswap_bootblock(struct boot_block *bb) 107{ 108 int idx; 109 110 for (idx = 59; idx <= 63; idx++) { 111 bswap64(&(bb->bb_data[idx])); 112 } 113} 114 115static void do_checksum(void *ptr,int length,uint32_t *csptr,int swap) 116{ 117 uint32_t *p; 118 uint32_t chksum = 0; 119 uint32_t d; 120 121 p = (uint32_t *) ptr; 122 123 length /= sizeof(uint32_t); 124 125 while (length) { 126 d = *p; 127 if (swap) bswap32(&d); 128 chksum += d; 129 p++; 130 length--; 131 } 132 133 if (swap) bswap32(&chksum); 134 135 *csptr = chksum; 136} 137 138 139static void dumpbootblock(struct boot_block *bb) 140{ 141 int idx; 142 143 fprintf(stderr,"Magic Number: %016llX\n", 144 bb->bb_magic); 145 fprintf(stderr,"Boot code offset: %llu\n", 146 (unsigned long long)bb->bb_secstart); 147 fprintf(stderr,"Boot code size: %u\n", 148 (uint32_t) (bb->bb_secsize & BOOT_SECSIZE_MASK)); 149 fprintf(stderr,"Header checksum: %08X\n", 150 (uint32_t) (bb->bb_hdrinfo & BOOT_HDR_CHECKSUM_MASK)); 151 fprintf(stderr,"Header version: %d\n", 152 (uint32_t) ((bb->bb_hdrinfo & BOOT_HDR_VER_MASK) >> BOOT_HDR_VER_SHIFT)); 153 fprintf(stderr,"Data checksum: %08X\n", 154 (uint32_t) ((bb->bb_secsize & BOOT_DATA_CHECKSUM_MASK) >> BOOT_DATA_CHECKSUM_SHIFT)); 155 fprintf(stderr,"Architecture info: %08X\n", 156 (uint32_t) (bb->bb_archinfo & BOOT_ARCHINFO_MASK)); 157 fprintf(stderr,"\n"); 158 159 for (idx = 59; idx <= 63; idx++) { 160 fprintf(stderr,"Word %d = %016llX\n",idx,bb->bb_data[idx]); 161 } 162} 163 164static int host_is_little(void) 165{ 166 unsigned long var = 1; 167 unsigned char *pvar = (unsigned char *) &var; 168 169 return (*pvar == 1); 170} 171 172int main(int argc, char *argv[]) 173{ 174 int fh; 175 long bootsize; 176 long bootbufsize; 177 unsigned char *bootcode; 178 struct boot_block bootblock; 179 uint32_t datacsum,hdrcsum; 180 int host_le; 181 182 while ((argc > 1) && (argv[1][0] == '-')) { 183 if (strcmp(argv[1],"-v") == 0) { 184 verbose = 1; 185 } 186 else if (strcmp(argv[1],"-EB") == 0) { 187 big_endian = 1; 188 } 189 else if (strcmp(argv[1],"-EL") == 0) { 190 big_endian = 0; 191 } 192 else if (strcmp(argv[1],"-S") == 0) { 193 char *tmp_ptr; 194 argv++; 195 argc--; 196 if (argc == 1) { 197 fprintf(stderr,"-S requires an argument\n"); 198 exit(1); 199 } 200 sector_offset = strtoul(argv[1], &tmp_ptr, 0); 201 if (*tmp_ptr) { 202 fprintf(stderr,"Unable to parse %s as a sector offset\n", argv[1]); 203 exit(1); 204 } 205 } 206 else { 207 fprintf(stderr,"Invalid switch: %s\n",argv[1]); 208 exit(1); 209 } 210 argv++; 211 argc--; 212 } 213 214 /* 215 * We need to swap things around if the host and 216 * target are different endianness 217 */ 218 219 swapflg = 0; 220 host_le = host_is_little(); 221 222 if (big_endian && host_is_little()) swapflg = 1; 223 if ((big_endian == 0) && !(host_is_little())) swapflg = 1; 224 225 fprintf(stderr,"Host is %s-endian.\n",host_le ? "little" : "big"); 226 fprintf(stderr,"Target is %s-endian.\n",big_endian ? "big" : "little"); 227 228 if (argc != 3) { 229 usage(); 230 } 231 232 /* 233 * Read in the boot file 234 */ 235 236 fh = open(argv[1],O_RDONLY); 237 if (fh < 0) { 238 perror(argv[1]); 239 } 240 241 bootsize = lseek(fh,0L,SEEK_END); 242 lseek(fh,0L,SEEK_SET); 243 244 bootbufsize = roundup(bootsize,BOOT_BLOCK_BLOCKSIZE); 245 246 bootcode = malloc(bootbufsize); 247 if (bootcode == NULL) { 248 perror("malloc"); 249 exit(1); 250 } 251 memset(bootcode,0,bootbufsize); 252 if (read(fh,bootcode,bootsize) != bootsize) { 253 perror("read"); 254 exit(1); 255 } 256 257 close(fh); 258 259 /* 260 * Construct the boot block 261 */ 262 263 264 /* Checksum the boot code */ 265 do_checksum(bootcode,bootbufsize,&datacsum,1); 266 bswap32(&datacsum); 267 268 269 /* fill in the boot block fields, and checksum the boot block */ 270 bootblock.bb_magic = BOOT_MAGIC_NUMBER; 271 bootblock.bb_hdrinfo = (((uint64_t) BOOT_HDR_VERSION) << BOOT_HDR_VER_SHIFT); 272 bootblock.bb_secstart = BOOT_BLOCK_BLOCKSIZE + (sector_offset * 512); 273 bootblock.bb_secsize = ((uint64_t) bootbufsize) | 274 (((uint64_t) datacsum) << BOOT_DATA_CHECKSUM_SHIFT); 275 bootblock.bb_archinfo = 0; 276 277 do_checksum(&(bootblock.bb_magic),BOOT_BLOCK_SIZE,&hdrcsum,0); 278 bootblock.bb_hdrinfo |= (uint64_t) hdrcsum; 279 280 if (verbose) dumpbootblock(&bootblock); 281 282 bswap_bootblock(&bootblock); 283 284 /* 285 * Now write the output file 286 */ 287 288 fh = open(argv[2],O_RDWR|O_CREAT,S_IREAD|S_IWRITE); 289 if (fh < 0) { 290 perror(argv[2]); 291 exit(1); 292 } 293 if (lseek(fh, sector_offset * 512, SEEK_SET) != (sector_offset * 512)) { 294 perror(argv[2]); 295 exit(1); 296 } 297 if (write(fh,&bootblock,sizeof(bootblock)) != sizeof(bootblock)) { 298 perror(argv[2]); 299 exit(1); 300 } 301 if (write(fh,bootcode,bootbufsize) != bootbufsize) { 302 perror(argv[2]); 303 exit(1); 304 } 305 306 close(fh); 307 308 fprintf(stderr,"%s -> %s : OK\n",argv[1],argv[2]); 309 310 exit(0); 311 312 313} 314