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