1/* ********************************************************************* 2 * Broadcom Common Firmware Environment (CFE) 3 * 4 * Boot program installer File: installboot.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 bootcode_offset = 2; 71static unsigned long bootsect_offset = 1; 72 73static void usage(void) 74{ 75 fprintf(stderr,"usage: installboot [-bootsect <sector offset>] [-bootcode <sector offset>]\n" 76 " [-v] [-EB] [-EL] bootloaderfile.bin devicefile\n\n"); 77 fprintf(stderr,"This program installs a boot block onto a disk. Typically, installboot\n" 78 "is used to install sibyl or other OS bootloaders. The binary you install\n" 79 "should be a raw program (not ELF) located to run in CFE's boot area\n" 80 "at address 0x2000_0000. The devicefile should be the name of the raw device\n" 81 "such as /dev/hda on Linux.\n\n" 82 "Care must be taken when choosing the values for -bootsect and -bootcode\n" 83 "not to interfere with other partitions on your disk. When partitioning,\n" 84 "it's a good idea to reserve 3 cylinders at the beginning of the disk for\n" 85 "the boot loader.\n\n" 86 "-bootsect nn specifies that the boot sector will be placed on sector 'nn'\n" 87 "-bootcode nn specifies that the boot program itself will be placed\n" 88 " on sectors starting with 'nn'. The boot sector will point\n" 89 " to this sector.\n"); 90 91 exit(1); 92} 93 94static void bswap32(uint32_t *ptr) 95{ 96 unsigned char b; 97 unsigned char *bptr; 98 99 if (swapflg) { 100 bptr = (unsigned char *) ptr; 101 b = bptr[0]; bptr[0] = bptr[3]; bptr[3] = b; 102 b = bptr[1]; bptr[1] = bptr[2]; bptr[2] = b; 103 } 104} 105 106static void bswap64(uint64_t *ptr) 107{ 108 unsigned char b; 109 unsigned char *bptr; 110 111 bptr = (unsigned char *) ptr; 112 113 if (swapflg) { 114 b = bptr[0]; bptr[0] = bptr[7]; bptr[7] = b; 115 b = bptr[1]; bptr[1] = bptr[6]; bptr[6] = b; 116 b = bptr[2]; bptr[2] = bptr[5]; bptr[5] = b; 117 b = bptr[3]; bptr[3] = bptr[4]; bptr[4] = b; 118 } 119} 120 121 122static void bswap_bootblock(struct boot_block *bb) 123{ 124 int idx; 125 126 for (idx = 59; idx <= 63; idx++) { 127 bswap64(&(bb->bb_data[idx])); 128 } 129} 130 131static void do_checksum(void *ptr,int length,uint32_t *csptr,int swap) 132{ 133 uint32_t *p; 134 uint32_t chksum = 0; 135 uint32_t d; 136 137 p = (uint32_t *) ptr; 138 139 length /= sizeof(uint32_t); 140 141 while (length) { 142 d = *p; 143 if (swap) bswap32(&d); 144 chksum += d; 145 p++; 146 length--; 147 } 148 149 if (swap) bswap32(&chksum); 150 151 *csptr = chksum; 152} 153 154 155static void dumpbootblock(struct boot_block *bb) 156{ 157 int idx; 158 159 fprintf(stderr,"Magic Number: %016llX\n", 160 bb->bb_magic); 161 fprintf(stderr,"Boot code offset: %llu\n", 162 (unsigned long long)bb->bb_secstart); 163 fprintf(stderr,"Boot code size: %u\n", 164 (uint32_t) (bb->bb_secsize & BOOT_SECSIZE_MASK)); 165 fprintf(stderr,"Header checksum: %08X\n", 166 (uint32_t) (bb->bb_hdrinfo & BOOT_HDR_CHECKSUM_MASK)); 167 fprintf(stderr,"Header version: %d\n", 168 (uint32_t) ((bb->bb_hdrinfo & BOOT_HDR_VER_MASK) >> BOOT_HDR_VER_SHIFT)); 169 fprintf(stderr,"Data checksum: %08X\n", 170 (uint32_t) ((bb->bb_secsize & BOOT_DATA_CHECKSUM_MASK) >> BOOT_DATA_CHECKSUM_SHIFT)); 171 fprintf(stderr,"Architecture info: %08X\n", 172 (uint32_t) (bb->bb_archinfo & BOOT_ARCHINFO_MASK)); 173 fprintf(stderr,"\n"); 174 175 for (idx = 59; idx <= 63; idx++) { 176 fprintf(stderr,"Word %d = %016llX\n",idx,bb->bb_data[idx]); 177 } 178} 179 180static int host_is_little(void) 181{ 182 unsigned long var = 1; 183 unsigned char *pvar = (unsigned char *) &var; 184 185 return (*pvar == 1); 186} 187 188int main(int argc, char *argv[]) 189{ 190 int fh; 191 long bootsize; 192 long bootbufsize; 193 unsigned char *bootcode; 194 struct boot_block bootblock; 195 uint32_t datacsum,hdrcsum; 196 int host_le; 197 198 while ((argc > 1) && (argv[1][0] == '-')) { 199 if (strcmp(argv[1],"-v") == 0) { 200 verbose = 1; 201 } 202 else if (strcmp(argv[1],"-EB") == 0) { 203 big_endian = 1; 204 } 205 else if (strcmp(argv[1],"-EL") == 0) { 206 big_endian = 0; 207 } 208 else if (strcmp(argv[1],"-bootsect") == 0) { 209 char *tmp_ptr; 210 argv++; 211 argc--; 212 if (argc == 1) { 213 fprintf(stderr,"-bootsect requires an argument\n"); 214 exit(1); 215 } 216 bootsect_offset = strtoul(argv[1], &tmp_ptr, 0); 217 bootcode_offset = bootsect_offset + 1; /* default if -bootcode not specified */ 218 if (*tmp_ptr) { 219 fprintf(stderr,"Unable to parse %s as a sector offset\n", argv[1]); 220 exit(1); 221 } 222 } 223 else if (strcmp(argv[1],"-bootcode") == 0) { 224 char *tmp_ptr; 225 argv++; 226 argc--; 227 if (argc == 1) { 228 fprintf(stderr,"-bootcode requires an argument\n"); 229 exit(1); 230 } 231 bootcode_offset = strtoul(argv[1], &tmp_ptr, 0); 232 if (*tmp_ptr) { 233 fprintf(stderr,"Unable to parse %s as a sector offset\n", argv[1]); 234 exit(1); 235 } 236 } 237 else { 238 fprintf(stderr,"Invalid switch: %s\n",argv[1]); 239 exit(1); 240 } 241 argv++; 242 argc--; 243 } 244 245 /* 246 * We need to swap things around if the host and 247 * target are different endianness 248 */ 249 250 swapflg = 0; 251 host_le = host_is_little(); 252 253 if (big_endian && host_is_little()) swapflg = 1; 254 if ((big_endian == 0) && !(host_is_little())) swapflg = 1; 255 256 fprintf(stderr,"Host is %s-endian.\n",host_le ? "little" : "big"); 257 fprintf(stderr,"Target is %s-endian.\n",big_endian ? "big" : "little"); 258 259 if (argc != 3) { 260 usage(); 261 } 262 263 /* 264 * Read in the boot file 265 */ 266 267 fh = open(argv[1],O_RDONLY); 268 if (fh < 0) { 269 perror(argv[1]); 270 } 271 272 bootsize = lseek(fh,0L,SEEK_END); 273 lseek(fh,0L,SEEK_SET); 274 275 bootbufsize = roundup(bootsize,BOOT_BLOCK_BLOCKSIZE); 276 277 bootcode = malloc(bootbufsize); 278 if (bootcode == NULL) { 279 perror("malloc"); 280 exit(1); 281 } 282 memset(bootcode,0,bootbufsize); 283 if (read(fh,bootcode,bootsize) != bootsize) { 284 perror("read"); 285 exit(1); 286 } 287 288 close(fh); 289 290 /* 291 * Construct the boot block 292 */ 293 294 295 /* Checksum the boot code */ 296 do_checksum(bootcode,bootbufsize,&datacsum,1); 297 bswap32(&datacsum); 298 299 300 /* fill in the boot block fields, and checksum the boot block */ 301 bootblock.bb_magic = BOOT_MAGIC_NUMBER; 302 bootblock.bb_hdrinfo = (((uint64_t) BOOT_HDR_VERSION) << BOOT_HDR_VER_SHIFT); 303 bootblock.bb_secstart = (bootcode_offset * 512); 304 bootblock.bb_secsize = ((uint64_t) bootbufsize) | 305 (((uint64_t) datacsum) << BOOT_DATA_CHECKSUM_SHIFT); 306 bootblock.bb_archinfo = 0; 307 308 do_checksum(&(bootblock.bb_magic),BOOT_BLOCK_SIZE,&hdrcsum,0); 309 bootblock.bb_hdrinfo |= (uint64_t) hdrcsum; 310 311 if (verbose) dumpbootblock(&bootblock); 312 313 bswap_bootblock(&bootblock); 314 315 /* 316 * Now write the output file 317 */ 318 319 fh = open(argv[2],O_RDWR|O_CREAT,S_IREAD|S_IWRITE); 320 if (fh < 0) { 321 perror(argv[2]); 322 exit(1); 323 } 324 325 fprintf(stderr,"Installing boot block\n"); 326 if (lseek(fh, bootsect_offset * 512, SEEK_SET) != (bootsect_offset * 512)) { 327 perror(argv[2]); 328 exit(1); 329 } 330 if (write(fh,&bootblock,sizeof(bootblock)) != sizeof(bootblock)) { 331 perror(argv[2]); 332 exit(1); 333 } 334 fprintf(stderr,"Installing bootstrap program\n"); 335 if (lseek(fh, bootcode_offset * 512, SEEK_SET) != (bootcode_offset * 512)) { 336 perror(argv[2]); 337 exit(1); 338 } 339 if (write(fh,bootcode,bootbufsize) != bootbufsize) { 340 perror(argv[2]); 341 exit(1); 342 } 343 344 close(fh); 345 346 fprintf(stderr,"Done. %s installed on %s\n",argv[1],argv[2]); 347 348 exit(0); 349 350 351} 352 353