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 unsigned int tmpbuf[IMGBLK / sizeof(unsigned int)]; 40 41 int main(int argc, char *argv[]) 42 { 43 int in_fd, out_fd; 44 int nblks, i; 45 unsigned int cksum, *cp; 46 struct stat st; 47 boot_block_t bt; 48 49 if (argc < 5) { 50 fprintf(stderr, "usage: %s <zImage-file> <boot-image> <load address> <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 bt.bb_dest = htonl(strtoul(argv[3], NULL, 0)); 65 bt.bb_entry_point = htonl(strtoul(argv[4], NULL, 0)); 66 67 /* We know these from the linker command. 68 * ...and then move it up into memory a little more so the 69 * relocation can happen. 70 */ 71 bt.bb_num_512blocks = htonl(nblks); 72 bt.bb_debug_flag = 0; 73 74 bt.bb_checksum = 0; 75 76 /* To be neat and tidy :-). 77 */ 78 bt.reserved[0] = 0; 79 bt.reserved[1] = 0; 80 81 if ((in_fd = open(argv[1], O_RDONLY)) < 0) { 82 perror("zImage open"); 83 exit(3); 84 } 85 86 if ((out_fd = open(argv[2], (O_RDWR | O_CREAT | O_TRUNC), 0666)) < 0) { 87 perror("bootfile open"); 88 exit(3); 89 } 90 91 cksum = 0; 92 cp = (void *)&bt; 93 for (i = 0; i < sizeof(bt) / sizeof(unsigned int); i++) 94 cksum += *cp++; 95 96 /* Assume zImage is an ELF file, and skip the 64K header. 97 */ 98 if (read(in_fd, tmpbuf, sizeof(tmpbuf)) != sizeof(tmpbuf)) { 99 fprintf(stderr, "%s is too small to be an ELF image\n", 100 argv[1]); 101 exit(4); 102 } 103 104 if (tmpbuf[0] != htonl(0x7f454c46)) { 105 fprintf(stderr, "%s is not an ELF image\n", argv[1]); 106 exit(4); 107 } 108 109 if (lseek(in_fd, (64 * 1024), SEEK_SET) < 0) { 110 fprintf(stderr, "%s failed to seek in ELF image\n", argv[1]); 111 exit(4); 112 } 113 114 nblks -= (64 * 1024) / IMGBLK; 115 116 /* And away we go...... 117 */ 118 if (write(out_fd, &bt, sizeof(bt)) != sizeof(bt)) { 119 perror("boot-image write"); 120 exit(5); 121 } 122 123 while (nblks-- > 0) { 124 if (read(in_fd, tmpbuf, sizeof(tmpbuf)) < 0) { 125 perror("zImage read"); 126 exit(5); 127 } 128 cp = tmpbuf; 129 for (i = 0; i < sizeof(tmpbuf) / sizeof(unsigned int); i++) 130 cksum += *cp++; 131 if (write(out_fd, tmpbuf, sizeof(tmpbuf)) != sizeof(tmpbuf)) { 132 perror("boot-image write"); 133 exit(5); 134 } 135 } 136 137 /* rewrite the header with the computed checksum. 138 */ 139 bt.bb_checksum = htonl(cksum); 140 if (lseek(out_fd, 0, SEEK_SET) < 0) { 141 perror("rewrite seek"); 142 exit(1); 143 } 144 if (write(out_fd, &bt, sizeof(bt)) != sizeof(bt)) { 145 perror("boot-image rewrite"); 146 exit(1); 147 } 148 149 exit(0); 150 } 151