1/* ********************************************************************* 2 * Broadcom Common Firmware Environment (CFE) 3 * 4 * Boot block generator File: mkbootimage.c 5 * 6 * Author: Mitch Lichtenberg 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#include <unistd.h> 64 65#define roundup(x,align) (((x)+(align)-1)&~((align)-1)) 66#define howmany(x,align) (((x)+(align)-1)/(align)) 67 68static int verbose = 0; 69static int big_endian = 1; 70static int swapflg = 1; 71static unsigned long sector_offset = 0; 72 73static void usage(void) 74{ 75 fprintf(stderr,"usage: mkbootimage [-S <sector offset>] [-v] [-EB] [-EL] inputfile outputfile\n"); 76 exit(1); 77} 78 79static void bswap32(uint32_t *ptr) 80{ 81 unsigned char b; 82 unsigned char *bptr; 83 84 if (swapflg) { 85 bptr = (unsigned char *) ptr; 86 b = bptr[0]; bptr[0] = bptr[3]; bptr[3] = b; 87 b = bptr[1]; bptr[1] = bptr[2]; bptr[2] = b; 88 } 89} 90 91static void bswap64(uint64_t *ptr) 92{ 93 unsigned char b; 94 unsigned char *bptr; 95 96 bptr = (unsigned char *) ptr; 97 98 if (swapflg) { 99 b = bptr[0]; bptr[0] = bptr[7]; bptr[7] = b; 100 b = bptr[1]; bptr[1] = bptr[6]; bptr[6] = b; 101 b = bptr[2]; bptr[2] = bptr[5]; bptr[5] = b; 102 b = bptr[3]; bptr[3] = bptr[4]; bptr[4] = b; 103 } 104} 105 106 107static void bswap_bootblock(struct boot_block *bb) 108{ 109 int idx; 110 111 for (idx = 59; idx <= 63; idx++) { 112 bswap64(&(bb->bb_data[idx])); 113 } 114} 115 116static void do_checksum(void *ptr,int length,uint32_t *csptr,int swap) 117{ 118 uint32_t *p; 119 uint32_t chksum = 0; 120 uint32_t d; 121 122 p = (uint32_t *) ptr; 123 124 length /= sizeof(uint32_t); 125 126 while (length) { 127 d = *p; 128 if (swap) bswap32(&d); 129 chksum += d; 130 p++; 131 length--; 132 } 133 134 if (swap) bswap32(&chksum); 135 136 *csptr = chksum; 137} 138 139 140static void dumpbootblock(struct boot_block *bb) 141{ 142 int idx; 143 144 fprintf(stderr,"Magic Number: %016llX\n", 145 bb->bb_magic); 146 fprintf(stderr,"Boot code offset: %llu\n", 147 (unsigned long long)bb->bb_secstart); 148 fprintf(stderr,"Boot code size: %lu\n", 149 (unsigned long) (uint32_t) (bb->bb_secsize & BOOT_SECSIZE_MASK)); 150 fprintf(stderr,"Header checksum: %08lX\n", 151 (unsigned long) (uint32_t) (bb->bb_hdrinfo & BOOT_HDR_CHECKSUM_MASK)); 152 fprintf(stderr,"Header version: %ld\n", 153 (unsigned long) (uint32_t) ((bb->bb_hdrinfo & BOOT_HDR_VER_MASK) >> BOOT_HDR_VER_SHIFT)); 154 fprintf(stderr,"Data checksum: %08lX\n", 155 (unsigned long) (uint32_t) ((bb->bb_secsize & BOOT_DATA_CHECKSUM_MASK) >> BOOT_DATA_CHECKSUM_SHIFT)); 156 fprintf(stderr,"Architecture info: %08lX\n", 157 (unsigned long) (uint32_t) (bb->bb_archinfo & BOOT_ARCHINFO_MASK)); 158 fprintf(stderr,"\n"); 159 160 for (idx = 59; idx <= 63; idx++) { 161 fprintf(stderr,"Word %d = %016llX\n",idx,bb->bb_data[idx]); 162 } 163} 164 165static int host_is_little(void) 166{ 167 unsigned long var = 1; 168 unsigned char *pvar = (unsigned char *) &var; 169 170 return (*pvar == 1); 171} 172 173int main(int argc, char *argv[]) 174{ 175 int fh; 176 long bootsize; 177 long bootbufsize; 178 unsigned char *bootcode; 179 struct boot_block bootblock; 180 uint32_t datacsum,hdrcsum; 181 int host_le; 182 183 while ((argc > 1) && (argv[1][0] == '-')) { 184 if (strcmp(argv[1],"-v") == 0) { 185 verbose = 1; 186 } 187 else if (strcmp(argv[1],"-EB") == 0) { 188 big_endian = 1; 189 } 190 else if (strcmp(argv[1],"-EL") == 0) { 191 big_endian = 0; 192 } 193 else if (strcmp(argv[1],"-S") == 0) { 194 char *tmp_ptr; 195 argv++; 196 argc--; 197 if (argc == 1) { 198 fprintf(stderr,"-S requires an argument\n"); 199 exit(1); 200 } 201 sector_offset = strtoul(argv[1], &tmp_ptr, 0); 202 if (*tmp_ptr) { 203 fprintf(stderr,"Unable to parse %s as a sector offset\n", argv[1]); 204 exit(1); 205 } 206 } 207 else { 208 fprintf(stderr,"Invalid switch: %s\n",argv[1]); 209 exit(1); 210 } 211 argv++; 212 argc--; 213 } 214 215 /* 216 * We need to swap things around if the host and 217 * target are different endianness 218 */ 219 220 swapflg = 0; 221 host_le = host_is_little(); 222 223 if (big_endian && host_is_little()) swapflg = 1; 224 if ((big_endian == 0) && !(host_is_little())) swapflg = 1; 225 226 fprintf(stderr,"Host is %s-endian.\n",host_le ? "little" : "big"); 227 fprintf(stderr,"Target is %s-endian.\n",big_endian ? "big" : "little"); 228 229 if (argc != 3) { 230 usage(); 231 } 232 233 /* 234 * Read in the boot file 235 */ 236 237 fh = open(argv[1],O_RDONLY); 238 if (fh < 0) { 239 perror(argv[1]); 240 } 241 242 bootsize = lseek(fh,0L,SEEK_END); 243 lseek(fh,0L,SEEK_SET); 244 245 bootbufsize = roundup(bootsize,BOOT_BLOCK_BLOCKSIZE); 246 247 bootcode = malloc(bootbufsize); 248 if (bootcode == NULL) { 249 perror("malloc"); 250 exit(1); 251 } 252 memset(bootcode,0,bootbufsize); 253 if (read(fh,bootcode,bootsize) != bootsize) { 254 perror("read"); 255 exit(1); 256 } 257 258 close(fh); 259 260 /* 261 * Construct the boot block 262 */ 263 264 265 /* Checksum the boot code */ 266 do_checksum(bootcode,bootbufsize,&datacsum,1); 267 bswap32(&datacsum); 268 269 270 /* fill in the boot block fields, and checksum the boot block */ 271 bootblock.bb_magic = BOOT_MAGIC_NUMBER; 272 bootblock.bb_hdrinfo = (((uint64_t) BOOT_HDR_VERSION) << BOOT_HDR_VER_SHIFT); 273 bootblock.bb_secstart = BOOT_BLOCK_BLOCKSIZE + (sector_offset * 512); 274 bootblock.bb_secsize = ((uint64_t) bootbufsize) | 275 (((uint64_t) datacsum) << BOOT_DATA_CHECKSUM_SHIFT); 276 bootblock.bb_archinfo = 0; /* XXX */ 277 278 do_checksum(&(bootblock.bb_magic),BOOT_BLOCK_SIZE,&hdrcsum,0); 279 bootblock.bb_hdrinfo |= (uint64_t) hdrcsum; 280 281 if (verbose) dumpbootblock(&bootblock); 282 283 bswap_bootblock(&bootblock); 284 285 /* 286 * Now write the output file 287 */ 288 289 fh = open(argv[2],O_RDWR|O_CREAT,S_IREAD|S_IWRITE); 290 if (fh < 0) { 291 perror(argv[2]); 292 exit(1); 293 } 294 if (lseek(fh, sector_offset * 512, SEEK_SET) != (sector_offset * 512)) { 295 perror(argv[2]); 296 exit(1); 297 } 298 if (write(fh,&bootblock,sizeof(bootblock)) != sizeof(bootblock)) { 299 perror(argv[2]); 300 exit(1); 301 } 302 if (write(fh,bootcode,bootbufsize) != bootbufsize) { 303 perror(argv[2]); 304 exit(1); 305 } 306 307 close(fh); 308 309 fprintf(stderr,"%s -> %s : OK\n",argv[1],argv[2]); 310 311 exit(0); 312 313 314} 315 316