1/* 2 * BK Id: %F% %I% %G% %U% %#% 3 * 4 * Makes a tree bootable image for IBM Evaluation boards. 5 * Basically, just take a zImage, skip the ELF header, and stuff 6 * a 32 byte header on the front. 7 * 8 * We use htonl, which is a network macro, to make sure we're doing 9 * The Right Thing on an LE machine. It's non-obvious, but it should 10 * work on anything BSD'ish. 11 */ 12 13#include <fcntl.h> 14#include <stdio.h> 15#include <stdlib.h> 16#include <string.h> 17#include <sys/stat.h> 18#include <unistd.h> 19#include <netinet/in.h> 20 21/* This gets tacked on the front of the image. There are also a few 22 * bytes allocated after the _start label used by the boot rom (see 23 * head.S for details). 24 */ 25typedef struct boot_block { 26 unsigned long bb_magic; /* 0x0052504F */ 27 unsigned long bb_dest; /* Target address of the image */ 28 unsigned long bb_num_512blocks; /* Size, rounded-up, in 512 byte blks */ 29 unsigned long bb_debug_flag; /* Run debugger or image after load */ 30 unsigned long bb_entry_point; /* The image address to start */ 31 unsigned long bb_checksum; /* 32 bit checksum including header */ 32 unsigned long reserved[2]; 33} boot_block_t; 34 35#define IMGBLK 512 36char tmpbuf[IMGBLK]; 37 38int main(int argc, char *argv[]) 39{ 40 int in_fd, out_fd; 41 int nblks, i; 42 uint cksum, *cp; 43 struct stat st; 44 boot_block_t bt; 45 46 if (argc < 3) { 47 fprintf(stderr, "usage: %s <zImage-file> <boot-image> [entry-point]\n",argv[0]); 48 exit(1); 49 } 50 51 if (stat(argv[1], &st) < 0) { 52 perror("stat"); 53 exit(2); 54 } 55 56 nblks = (st.st_size + IMGBLK) / IMGBLK; 57 58 bt.bb_magic = htonl(0x0052504F); 59 60 /* If we have the optional entry point parameter, use it */ 61 if (argc == 4) 62 bt.bb_dest = bt.bb_entry_point = htonl(strtoul(argv[3], NULL, 0)); 63 else 64 bt.bb_dest = bt.bb_entry_point = htonl(0x500000); 65 66 /* We know these from the linker command. 67 * ...and then move it up into memory a little more so the 68 * relocation can happen. 69 */ 70 bt.bb_num_512blocks = htonl(nblks); 71 bt.bb_debug_flag = 0; 72 73 bt.bb_checksum = 0; 74 75 /* To be neat and tidy :-). 76 */ 77 bt.reserved[0] = 0; 78 bt.reserved[1] = 0; 79 80 if ((in_fd = open(argv[1], O_RDONLY)) < 0) { 81 perror("zImage open"); 82 exit(3); 83 } 84 85 if ((out_fd = open(argv[2], (O_RDWR | O_CREAT | O_TRUNC), 0666)) < 0) { 86 perror("bootfile open"); 87 exit(3); 88 } 89 90 cksum = 0; 91 cp = (uint *)&bt; 92 for (i=0; i<sizeof(bt)/sizeof(uint); i++) 93 cksum += *cp++; 94 95 /* Assume zImage is an ELF file, and skip the 64K header. 96 */ 97 if (read(in_fd, tmpbuf, IMGBLK) != IMGBLK) { 98 fprintf(stderr, "%s is too small to be an ELF image\n", 99 argv[1]); 100 exit(4); 101 } 102 103 if ((*(uint *)tmpbuf) != htonl(0x7f454c46)) { 104 fprintf(stderr, "%s is not an ELF image\n", argv[1]); 105 exit(4); 106 } 107 108 if (lseek(in_fd, (64 * 1024), SEEK_SET) < 0) { 109 fprintf(stderr, "%s failed to seek in ELF image\n", argv[1]); 110 exit(4); 111 } 112 113 nblks -= (64 * 1024) / IMGBLK; 114 115 /* And away we go...... 116 */ 117 if (write(out_fd, &bt, sizeof(bt)) != sizeof(bt)) { 118 perror("boot-image write"); 119 exit(5); 120 } 121 122 while (nblks-- > 0) { 123 if (read(in_fd, tmpbuf, IMGBLK) < 0) { 124 perror("zImage read"); 125 exit(5); 126 } 127 cp = (uint *)tmpbuf; 128 for (i=0; i<sizeof(tmpbuf)/sizeof(uint); i++) 129 cksum += *cp++; 130 if (write(out_fd, tmpbuf, sizeof(tmpbuf)) != sizeof(tmpbuf)) { 131 perror("boot-image write"); 132 exit(5); 133 } 134 } 135 136 /* rewrite the header with the computed checksum. 137 */ 138 bt.bb_checksum = htonl(cksum); 139 if (lseek(out_fd, 0, SEEK_SET) < 0) { 140 perror("rewrite seek"); 141 exit(1); 142 } 143 if (write(out_fd, &bt, sizeof(bt)) != sizeof(bt)) { 144 perror("boot-image rewrite"); 145 exit(1); 146 } 147 148 exit(0); 149} 150