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