xref: /linux/arch/powerpc/boot/mktree.c (revision 498495dba268b20e8eadd7fe93c140c68b6cc9d2)
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 
main(int argc,char * argv[])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