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