xref: /linux/arch/powerpc/boot/mktree.c (revision 0cfcccb4687862a34eb609d16e75b39b6cb54c80)
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