10cfcccb4SJosh Boyer /* 20cfcccb4SJosh Boyer * Makes a tree bootable image for IBM Evaluation boards. 30cfcccb4SJosh Boyer * Basically, just take a zImage, skip the ELF header, and stuff 40cfcccb4SJosh Boyer * a 32 byte header on the front. 50cfcccb4SJosh Boyer * 60cfcccb4SJosh Boyer * We use htonl, which is a network macro, to make sure we're doing 70cfcccb4SJosh Boyer * The Right Thing on an LE machine. It's non-obvious, but it should 80cfcccb4SJosh Boyer * work on anything BSD'ish. 90cfcccb4SJosh Boyer */ 100cfcccb4SJosh Boyer 110cfcccb4SJosh Boyer #include <fcntl.h> 120cfcccb4SJosh Boyer #include <stdio.h> 130cfcccb4SJosh Boyer #include <stdlib.h> 140cfcccb4SJosh Boyer #include <string.h> 150cfcccb4SJosh Boyer #include <sys/stat.h> 160cfcccb4SJosh Boyer #include <unistd.h> 170cfcccb4SJosh Boyer #include <netinet/in.h> 180cfcccb4SJosh Boyer #ifdef __sun__ 190cfcccb4SJosh Boyer #include <inttypes.h> 200cfcccb4SJosh Boyer #else 210cfcccb4SJosh Boyer #include <stdint.h> 220cfcccb4SJosh Boyer #endif 230cfcccb4SJosh Boyer 240cfcccb4SJosh Boyer /* This gets tacked on the front of the image. There are also a few 250cfcccb4SJosh Boyer * bytes allocated after the _start label used by the boot rom (see 260cfcccb4SJosh Boyer * head.S for details). 270cfcccb4SJosh Boyer */ 280cfcccb4SJosh Boyer typedef struct boot_block { 290cfcccb4SJosh Boyer uint32_t bb_magic; /* 0x0052504F */ 300cfcccb4SJosh Boyer uint32_t bb_dest; /* Target address of the image */ 310cfcccb4SJosh Boyer uint32_t bb_num_512blocks; /* Size, rounded-up, in 512 byte blks */ 320cfcccb4SJosh Boyer uint32_t bb_debug_flag; /* Run debugger or image after load */ 330cfcccb4SJosh Boyer uint32_t bb_entry_point; /* The image address to start */ 340cfcccb4SJosh Boyer uint32_t bb_checksum; /* 32 bit checksum including header */ 350cfcccb4SJosh Boyer uint32_t reserved[2]; 360cfcccb4SJosh Boyer } boot_block_t; 370cfcccb4SJosh Boyer 380cfcccb4SJosh Boyer #define IMGBLK 512 390cfcccb4SJosh Boyer char tmpbuf[IMGBLK]; 400cfcccb4SJosh Boyer 410cfcccb4SJosh Boyer int main(int argc, char *argv[]) 420cfcccb4SJosh Boyer { 430cfcccb4SJosh Boyer int in_fd, out_fd; 440cfcccb4SJosh Boyer int nblks, i; 45*93f1cc60STimur Tabi unsigned int cksum, *cp; 460cfcccb4SJosh Boyer struct stat st; 470cfcccb4SJosh Boyer boot_block_t bt; 480cfcccb4SJosh Boyer 49f6dfc805SDavid Gibson if (argc < 5) { 50f6dfc805SDavid Gibson fprintf(stderr, "usage: %s <zImage-file> <boot-image> <load address> <entry point>\n",argv[0]); 510cfcccb4SJosh Boyer exit(1); 520cfcccb4SJosh Boyer } 530cfcccb4SJosh Boyer 540cfcccb4SJosh Boyer if (stat(argv[1], &st) < 0) { 550cfcccb4SJosh Boyer perror("stat"); 560cfcccb4SJosh Boyer exit(2); 570cfcccb4SJosh Boyer } 580cfcccb4SJosh Boyer 590cfcccb4SJosh Boyer nblks = (st.st_size + IMGBLK) / IMGBLK; 600cfcccb4SJosh Boyer 610cfcccb4SJosh Boyer bt.bb_magic = htonl(0x0052504F); 620cfcccb4SJosh Boyer 630cfcccb4SJosh Boyer /* If we have the optional entry point parameter, use it */ 64f6dfc805SDavid Gibson bt.bb_dest = htonl(strtoul(argv[3], NULL, 0)); 65f6dfc805SDavid Gibson bt.bb_entry_point = htonl(strtoul(argv[4], NULL, 0)); 660cfcccb4SJosh Boyer 670cfcccb4SJosh Boyer /* We know these from the linker command. 680cfcccb4SJosh Boyer * ...and then move it up into memory a little more so the 690cfcccb4SJosh Boyer * relocation can happen. 700cfcccb4SJosh Boyer */ 710cfcccb4SJosh Boyer bt.bb_num_512blocks = htonl(nblks); 720cfcccb4SJosh Boyer bt.bb_debug_flag = 0; 730cfcccb4SJosh Boyer 740cfcccb4SJosh Boyer bt.bb_checksum = 0; 750cfcccb4SJosh Boyer 760cfcccb4SJosh Boyer /* To be neat and tidy :-). 770cfcccb4SJosh Boyer */ 780cfcccb4SJosh Boyer bt.reserved[0] = 0; 790cfcccb4SJosh Boyer bt.reserved[1] = 0; 800cfcccb4SJosh Boyer 810cfcccb4SJosh Boyer if ((in_fd = open(argv[1], O_RDONLY)) < 0) { 820cfcccb4SJosh Boyer perror("zImage open"); 830cfcccb4SJosh Boyer exit(3); 840cfcccb4SJosh Boyer } 850cfcccb4SJosh Boyer 860cfcccb4SJosh Boyer if ((out_fd = open(argv[2], (O_RDWR | O_CREAT | O_TRUNC), 0666)) < 0) { 870cfcccb4SJosh Boyer perror("bootfile open"); 880cfcccb4SJosh Boyer exit(3); 890cfcccb4SJosh Boyer } 900cfcccb4SJosh Boyer 910cfcccb4SJosh Boyer cksum = 0; 920cfcccb4SJosh Boyer cp = (void *)&bt; 93*93f1cc60STimur Tabi for (i = 0; i < sizeof(bt) / sizeof(unsigned int); i++) 940cfcccb4SJosh Boyer cksum += *cp++; 950cfcccb4SJosh Boyer 960cfcccb4SJosh Boyer /* Assume zImage is an ELF file, and skip the 64K header. 970cfcccb4SJosh Boyer */ 980cfcccb4SJosh Boyer if (read(in_fd, tmpbuf, IMGBLK) != IMGBLK) { 990cfcccb4SJosh Boyer fprintf(stderr, "%s is too small to be an ELF image\n", 1000cfcccb4SJosh Boyer argv[1]); 1010cfcccb4SJosh Boyer exit(4); 1020cfcccb4SJosh Boyer } 1030cfcccb4SJosh Boyer 104*93f1cc60STimur Tabi if ((*(unsigned int *)tmpbuf) != htonl(0x7f454c46)) { 1050cfcccb4SJosh Boyer fprintf(stderr, "%s is not an ELF image\n", argv[1]); 1060cfcccb4SJosh Boyer exit(4); 1070cfcccb4SJosh Boyer } 1080cfcccb4SJosh Boyer 1090cfcccb4SJosh Boyer if (lseek(in_fd, (64 * 1024), SEEK_SET) < 0) { 1100cfcccb4SJosh Boyer fprintf(stderr, "%s failed to seek in ELF image\n", argv[1]); 1110cfcccb4SJosh Boyer exit(4); 1120cfcccb4SJosh Boyer } 1130cfcccb4SJosh Boyer 1140cfcccb4SJosh Boyer nblks -= (64 * 1024) / IMGBLK; 1150cfcccb4SJosh Boyer 1160cfcccb4SJosh Boyer /* And away we go...... 1170cfcccb4SJosh Boyer */ 1180cfcccb4SJosh Boyer if (write(out_fd, &bt, sizeof(bt)) != sizeof(bt)) { 1190cfcccb4SJosh Boyer perror("boot-image write"); 1200cfcccb4SJosh Boyer exit(5); 1210cfcccb4SJosh Boyer } 1220cfcccb4SJosh Boyer 1230cfcccb4SJosh Boyer while (nblks-- > 0) { 1240cfcccb4SJosh Boyer if (read(in_fd, tmpbuf, IMGBLK) < 0) { 1250cfcccb4SJosh Boyer perror("zImage read"); 1260cfcccb4SJosh Boyer exit(5); 1270cfcccb4SJosh Boyer } 128*93f1cc60STimur Tabi cp = (unsigned int *)tmpbuf; 129*93f1cc60STimur Tabi for (i = 0; i < sizeof(tmpbuf) / sizeof(unsigned int); i++) 1300cfcccb4SJosh Boyer cksum += *cp++; 1310cfcccb4SJosh Boyer if (write(out_fd, tmpbuf, sizeof(tmpbuf)) != sizeof(tmpbuf)) { 1320cfcccb4SJosh Boyer perror("boot-image write"); 1330cfcccb4SJosh Boyer exit(5); 1340cfcccb4SJosh Boyer } 1350cfcccb4SJosh Boyer } 1360cfcccb4SJosh Boyer 1370cfcccb4SJosh Boyer /* rewrite the header with the computed checksum. 1380cfcccb4SJosh Boyer */ 1390cfcccb4SJosh Boyer bt.bb_checksum = htonl(cksum); 1400cfcccb4SJosh Boyer if (lseek(out_fd, 0, SEEK_SET) < 0) { 1410cfcccb4SJosh Boyer perror("rewrite seek"); 1420cfcccb4SJosh Boyer exit(1); 1430cfcccb4SJosh Boyer } 1440cfcccb4SJosh Boyer if (write(out_fd, &bt, sizeof(bt)) != sizeof(bt)) { 1450cfcccb4SJosh Boyer perror("boot-image rewrite"); 1460cfcccb4SJosh Boyer exit(1); 1470cfcccb4SJosh Boyer } 1480cfcccb4SJosh Boyer 1490cfcccb4SJosh Boyer exit(0); 1500cfcccb4SJosh Boyer } 151