[SPARC64]: Update defconfig.
[pandora-kernel.git] / arch / ppc / boot / utils / mkbugboot.c
1 /*
2  * Makes a Motorola PPCBUG ROM bootable image which can be flashed
3  * into one of the FLASH banks on a Motorola PowerPlus board.
4  *
5  * Author: Matt Porter <mporter@mvista.com>
6  *
7  * 2001 (c) MontaVista, Software, Inc.  This file is licensed under
8  * the terms of the GNU General Public License version 2.  This program
9  * is licensed "as is" without any warranty of any kind, whether express
10  * or implied.
11  */
12
13 #define ELF_HEADER_SIZE 65536
14
15 #include <unistd.h>
16 #include <sys/stat.h>
17 #include <string.h>
18 #include <stdio.h>
19 #include <stdlib.h>
20 #include <errno.h>
21 #include <fcntl.h>
22 #ifdef __sun__
23 #include <inttypes.h>
24 #else
25 #include <stdint.h>
26 #endif
27
28 #ifdef __i386__
29 #define cpu_to_be32(x) le32_to_cpu(x)
30 #define cpu_to_be16(x) le16_to_cpu(x)
31 #else
32 #define cpu_to_be32(x) (x)
33 #define cpu_to_be16(x) (x)
34 #endif
35
36 #define cpu_to_le32(x) le32_to_cpu((x))
37 unsigned long le32_to_cpu(unsigned long x)
38 {
39         return (((x & 0x000000ffU) << 24) |
40                 ((x & 0x0000ff00U) <<  8) |
41                 ((x & 0x00ff0000U) >>  8) |
42                 ((x & 0xff000000U) >> 24));
43 }
44
45 #define cpu_to_le16(x) le16_to_cpu((x))
46 unsigned short le16_to_cpu(unsigned short x)
47 {
48         return (((x & 0x00ff) << 8) |
49                 ((x & 0xff00) >> 8));
50 }
51
52 /* size of read buffer */
53 #define SIZE 0x1000
54
55 /* PPCBUG ROM boot header */
56 typedef struct bug_boot_header {
57   uint8_t       magic_word[4];          /* "BOOT" */
58   uint32_t      entry_offset;           /* Offset from top of header to code */
59   uint32_t      routine_length;         /* Length of code */
60   uint8_t       routine_name[8];        /* Name of the boot code */
61 } bug_boot_header_t;
62
63 #define HEADER_SIZE     sizeof(bug_boot_header_t)
64
65 uint32_t copy_image(int32_t in_fd, int32_t out_fd)
66 {
67   uint8_t buf[SIZE];
68   int n;
69   uint32_t image_size = 0;
70   uint8_t zero = 0;
71
72   lseek(in_fd, ELF_HEADER_SIZE, SEEK_SET);
73
74   /* Copy an image while recording its size */
75   while ( (n = read(in_fd, buf, SIZE)) > 0 )
76     {
77     image_size = image_size + n;
78     write(out_fd, buf, n);
79     }
80
81   /* BUG romboot requires that our size is divisible by 2 */
82   /* align image to 2 byte boundary */
83   if (image_size % 2)
84     {
85     image_size++;
86     write(out_fd, &zero, 1);
87     }
88
89   return image_size;
90 }
91
92 void write_bugboot_header(int32_t out_fd, uint32_t boot_size)
93 {
94   uint8_t header_block[HEADER_SIZE];
95   bug_boot_header_t *bbh = (bug_boot_header_t *)&header_block[0];
96
97   memset(header_block, 0, HEADER_SIZE);
98
99   /* Fill in the PPCBUG ROM boot header */
100   strncpy(bbh->magic_word, "BOOT", 4);          /* PPCBUG magic word */
101   bbh->entry_offset = cpu_to_be32(HEADER_SIZE); /* Entry address */
102   bbh->routine_length= cpu_to_be32(HEADER_SIZE+boot_size+2);    /* Routine length */
103   strncpy(bbh->routine_name, "LINUXROM", 8);            /* Routine name   */
104
105   /* Output the header and bootloader to the file */
106   write(out_fd, header_block, HEADER_SIZE);
107 }
108
109 uint16_t calc_checksum(int32_t bug_fd)
110 {
111   uint32_t checksum_var = 0;
112   uint8_t buf[2];
113   int n;
114
115   /* Checksum loop */
116   while ( (n = read(bug_fd, buf, 2) ) )
117   {
118     checksum_var = checksum_var + *(uint16_t *)buf;
119
120     /* If we carry out, mask it and add one to the checksum */
121     if (checksum_var >> 16)
122       checksum_var = (checksum_var & 0x0000ffff) + 1;
123   }
124
125   return checksum_var;
126 }
127
128 int main(int argc, char *argv[])
129 {
130   int32_t image_fd, bugboot_fd;
131   int argptr = 1;
132   uint32_t kernel_size = 0;
133   uint16_t checksum = 0;
134   uint8_t bugbootname[256];
135
136   if ( (argc != 3) )
137   {
138     fprintf(stderr, "usage: %s <kernel_image> <bugboot>\n",argv[0]);
139     exit(-1);
140   }
141
142   /* Get file args */
143
144   /* kernel image file */
145     if ((image_fd = open( argv[argptr] , 0)) < 0)
146       exit(-1);
147   argptr++;
148
149   /* bugboot file */
150   if ( !strcmp( argv[argptr], "-" ) )
151     bugboot_fd = 1;                     /* stdout */
152   else
153     if ((bugboot_fd = creat( argv[argptr] , 0755)) < 0)
154       exit(-1);
155     else
156       strcpy(bugbootname, argv[argptr]);
157   argptr++;
158
159   /* Set file position after ROM header block where zImage will be written */
160   lseek(bugboot_fd, HEADER_SIZE, SEEK_SET);
161
162   /* Copy kernel image into bugboot image */
163   kernel_size = copy_image(image_fd, bugboot_fd);
164   close(image_fd);
165
166   /* Set file position to beginning where header/romboot will be written */
167   lseek(bugboot_fd, 0, SEEK_SET);
168
169   /* Write out BUG header/romboot */
170   write_bugboot_header(bugboot_fd, kernel_size);
171
172   /* Close bugboot file */
173   close(bugboot_fd);
174
175   /* Reopen it as read/write */
176   bugboot_fd = open(bugbootname, O_RDWR);
177
178   /* Calculate checksum */
179   checksum = calc_checksum(bugboot_fd);
180
181   /* Write out the calculated checksum */
182   write(bugboot_fd, &checksum, 2);
183
184   return 0;
185 }