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