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