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