toolchain: bump Codescape IMG MIPS version to 2016.05-06
[buildroot-gz.git] / package / mkpimage / mkpimage.c
blob1a7a66d98841e9f52c3ea49c651286aa1412c9a5
1 #include <stdio.h>
2 #include <unistd.h>
3 #include <getopt.h>
4 #include <stdlib.h>
5 #include <stdint.h>
6 #include <string.h>
7 #include <errno.h>
8 #include <sys/types.h>
9 #include <sys/stat.h>
10 #include <fcntl.h>
11 #include <endian.h>
13 #define VALIDATION_WORD 0x31305341
15 #define MAX_IMAGE_SIZE (60 * 1024 - 4)
17 static int add_barebox_header;
19 struct socfpga_header {
20 uint8_t validation_word[4];
21 uint8_t version;
22 uint8_t flags;
23 uint8_t program_length[2];
24 uint8_t spare[2];
25 uint8_t checksum[2];
28 static uint32_t bb_header[] = {
29 0xea00007e, /* b 0x200 */
30 0xeafffffe, /* 1: b 1b */
31 0xeafffffe, /* 1: b 1b */
32 0xeafffffe, /* 1: b 1b */
33 0xeafffffe, /* 1: b 1b */
34 0xeafffffe, /* 1: b 1b */
35 0xeafffffe, /* 1: b 1b */
36 0xeafffffe, /* 1: b 1b */
37 0x65726162, /* 'bare' */
38 0x00786f62, /* 'box\0' */
39 0x00000000, /* padding */
40 0x00000000, /* padding */
41 0x00000000, /* padding */
42 0x00000000, /* padding */
43 0x00000000, /* padding */
44 0x00000000, /* padding */
45 0x00000000, /* socfpga header */
46 0x00000000, /* socfpga header */
47 0x00000000, /* socfpga header */
48 0xea00006b, /* entry. b 0x200 */
51 static int read_full(int fd, void *buf, size_t size)
53 size_t insize = size;
54 int now;
55 int total = 0;
57 while (size) {
58 now = read(fd, buf, size);
59 if (now == 0)
60 return total;
61 if (now < 0)
62 return now;
63 total += now;
64 size -= now;
65 buf += now;
68 return insize;
71 static int write_full(int fd, void *buf, size_t size)
73 size_t insize = size;
74 int now;
76 while (size) {
77 now = write(fd, buf, size);
78 if (now <= 0)
79 return now;
80 size -= now;
81 buf += now;
84 return insize;
87 static uint32_t crc_table[256] = {
88 0x00000000, 0x04c11db7, 0x09823b6e, 0x0d4326d9, 0x130476dc, 0x17c56b6b,
89 0x1a864db2, 0x1e475005, 0x2608edb8, 0x22c9f00f, 0x2f8ad6d6, 0x2b4bcb61,
90 0x350c9b64, 0x31cd86d3, 0x3c8ea00a, 0x384fbdbd, 0x4c11db70, 0x48d0c6c7,
91 0x4593e01e, 0x4152fda9, 0x5f15adac, 0x5bd4b01b, 0x569796c2, 0x52568b75,
92 0x6a1936c8, 0x6ed82b7f, 0x639b0da6, 0x675a1011, 0x791d4014, 0x7ddc5da3,
93 0x709f7b7a, 0x745e66cd, 0x9823b6e0, 0x9ce2ab57, 0x91a18d8e, 0x95609039,
94 0x8b27c03c, 0x8fe6dd8b, 0x82a5fb52, 0x8664e6e5, 0xbe2b5b58, 0xbaea46ef,
95 0xb7a96036, 0xb3687d81, 0xad2f2d84, 0xa9ee3033, 0xa4ad16ea, 0xa06c0b5d,
96 0xd4326d90, 0xd0f37027, 0xddb056fe, 0xd9714b49, 0xc7361b4c, 0xc3f706fb,
97 0xceb42022, 0xca753d95, 0xf23a8028, 0xf6fb9d9f, 0xfbb8bb46, 0xff79a6f1,
98 0xe13ef6f4, 0xe5ffeb43, 0xe8bccd9a, 0xec7dd02d, 0x34867077, 0x30476dc0,
99 0x3d044b19, 0x39c556ae, 0x278206ab, 0x23431b1c, 0x2e003dc5, 0x2ac12072,
100 0x128e9dcf, 0x164f8078, 0x1b0ca6a1, 0x1fcdbb16, 0x018aeb13, 0x054bf6a4,
101 0x0808d07d, 0x0cc9cdca, 0x7897ab07, 0x7c56b6b0, 0x71159069, 0x75d48dde,
102 0x6b93dddb, 0x6f52c06c, 0x6211e6b5, 0x66d0fb02, 0x5e9f46bf, 0x5a5e5b08,
103 0x571d7dd1, 0x53dc6066, 0x4d9b3063, 0x495a2dd4, 0x44190b0d, 0x40d816ba,
104 0xaca5c697, 0xa864db20, 0xa527fdf9, 0xa1e6e04e, 0xbfa1b04b, 0xbb60adfc,
105 0xb6238b25, 0xb2e29692, 0x8aad2b2f, 0x8e6c3698, 0x832f1041, 0x87ee0df6,
106 0x99a95df3, 0x9d684044, 0x902b669d, 0x94ea7b2a, 0xe0b41de7, 0xe4750050,
107 0xe9362689, 0xedf73b3e, 0xf3b06b3b, 0xf771768c, 0xfa325055, 0xfef34de2,
108 0xc6bcf05f, 0xc27dede8, 0xcf3ecb31, 0xcbffd686, 0xd5b88683, 0xd1799b34,
109 0xdc3abded, 0xd8fba05a, 0x690ce0ee, 0x6dcdfd59, 0x608edb80, 0x644fc637,
110 0x7a089632, 0x7ec98b85, 0x738aad5c, 0x774bb0eb, 0x4f040d56, 0x4bc510e1,
111 0x46863638, 0x42472b8f, 0x5c007b8a, 0x58c1663d, 0x558240e4, 0x51435d53,
112 0x251d3b9e, 0x21dc2629, 0x2c9f00f0, 0x285e1d47, 0x36194d42, 0x32d850f5,
113 0x3f9b762c, 0x3b5a6b9b, 0x0315d626, 0x07d4cb91, 0x0a97ed48, 0x0e56f0ff,
114 0x1011a0fa, 0x14d0bd4d, 0x19939b94, 0x1d528623, 0xf12f560e, 0xf5ee4bb9,
115 0xf8ad6d60, 0xfc6c70d7, 0xe22b20d2, 0xe6ea3d65, 0xeba91bbc, 0xef68060b,
116 0xd727bbb6, 0xd3e6a601, 0xdea580d8, 0xda649d6f, 0xc423cd6a, 0xc0e2d0dd,
117 0xcda1f604, 0xc960ebb3, 0xbd3e8d7e, 0xb9ff90c9, 0xb4bcb610, 0xb07daba7,
118 0xae3afba2, 0xaafbe615, 0xa7b8c0cc, 0xa379dd7b, 0x9b3660c6, 0x9ff77d71,
119 0x92b45ba8, 0x9675461f, 0x8832161a, 0x8cf30bad, 0x81b02d74, 0x857130c3,
120 0x5d8a9099, 0x594b8d2e, 0x5408abf7, 0x50c9b640, 0x4e8ee645, 0x4a4ffbf2,
121 0x470cdd2b, 0x43cdc09c, 0x7b827d21, 0x7f436096, 0x7200464f, 0x76c15bf8,
122 0x68860bfd, 0x6c47164a, 0x61043093, 0x65c52d24, 0x119b4be9, 0x155a565e,
123 0x18197087, 0x1cd86d30, 0x029f3d35, 0x065e2082, 0x0b1d065b, 0x0fdc1bec,
124 0x3793a651, 0x3352bbe6, 0x3e119d3f, 0x3ad08088, 0x2497d08d, 0x2056cd3a,
125 0x2d15ebe3, 0x29d4f654, 0xc5a92679, 0xc1683bce, 0xcc2b1d17, 0xc8ea00a0,
126 0xd6ad50a5, 0xd26c4d12, 0xdf2f6bcb, 0xdbee767c, 0xe3a1cbc1, 0xe760d676,
127 0xea23f0af, 0xeee2ed18, 0xf0a5bd1d, 0xf464a0aa, 0xf9278673, 0xfde69bc4,
128 0x89b8fd09, 0x8d79e0be, 0x803ac667, 0x84fbdbd0, 0x9abc8bd5, 0x9e7d9662,
129 0x933eb0bb, 0x97ffad0c, 0xafb010b1, 0xab710d06, 0xa6322bdf, 0xa2f33668,
130 0xbcb4666d, 0xb8757bda, 0xb5365d03, 0xb1f740b4
133 uint32_t crc32(uint32_t crc, void *_buf, int length)
135 uint8_t *buf = _buf;
137 while (length--)
138 crc = crc << 8 ^ crc_table[(crc >> 24 ^ *(buf++)) & 0xff];
140 return crc;
143 static int add_socfpga_header(void *buf, int size)
145 struct socfpga_header *header = buf + 0x40;
146 uint8_t *buf_header = buf + 0x40;
147 uint32_t *crc;
148 unsigned checksum;
149 int length = size >> 2;
150 int i;
152 if (size & 0x3) {
153 fprintf(stderr, "%s: size must be multiple of 4\n", __func__);
154 return -EINVAL;
157 header->validation_word[0] = VALIDATION_WORD & 0xff;
158 header->validation_word[1] = (VALIDATION_WORD >> 8) & 0xff;
159 header->validation_word[2] = (VALIDATION_WORD >> 16) & 0xff;
160 header->validation_word[3] = (VALIDATION_WORD >> 24) & 0xff;
161 header->version = 0;
162 header->flags = 0;
163 header->program_length[0] = length & 0xff;
164 header->program_length[1] = (length >> 8) & 0xff;
165 header->spare[0] = 0;
166 header->spare[1] = 0;
168 checksum = 0;
169 for (i = 0; i < sizeof(*header) - 2; i++)
170 checksum += buf_header[i];
172 header->checksum[0] = checksum & 0xff;;
173 header->checksum[1] = (checksum >> 8) & 0xff;;
175 crc = buf + size - sizeof(uint32_t);
177 *crc = crc32(0xffffffff, buf, size - sizeof(uint32_t));
178 *crc ^= 0xffffffff;
180 return 0;
183 static void usage(const char *prgname)
185 fprintf(stderr, "usage: %s [OPTIONS] <infile>\n", prgname);
188 int main(int argc, char *argv[])
190 int opt, ret;
191 const char *outfile = NULL, *infile;
192 struct stat s;
193 void *buf;
194 int fd;
195 int min_image_size = 80;
196 int max_image_size = MAX_IMAGE_SIZE;
197 int addsize = 0, pad;
199 while ((opt = getopt(argc, argv, "o:hb")) != -1) {
200 switch (opt) {
201 case 'b':
202 add_barebox_header = 1;
203 min_image_size = 0;
204 max_image_size = MAX_IMAGE_SIZE - 512;
205 addsize = 512;
206 break;
207 case 'h':
208 usage(argv[0]);
209 exit(0);
210 case 'o':
211 outfile = optarg;
212 break;
213 default:
214 exit(1);
218 if (optind == argc) {
219 usage(argv[0]);
220 exit(1);
223 infile = argv[optind];
225 ret = stat(infile, &s);
226 if (ret) {
227 perror("stat");
228 exit(1);
231 if (s.st_size < min_image_size) {
232 fprintf(stderr, "input image too small. Minimum is 80 bytes\n");
233 exit(1);
236 if (s.st_size > max_image_size) {
237 fprintf(stderr, "input image too big. Maximum is %d bytes, got %ld bytes\n",
238 max_image_size, s.st_size);
239 exit(1);
242 fd = open(infile, O_RDONLY);
243 if (fd < 0) {
244 perror("open infile");
245 exit(1);
248 pad = s.st_size & 0x3;
249 if (pad)
250 pad = 4 - pad;
252 buf = calloc(s.st_size + 4 + addsize + pad, 1);
253 if (!buf) {
254 perror("malloc");
255 exit(1);
258 ret = read_full(fd, buf + addsize, s.st_size);
259 if (ret < 0) {
260 perror("read infile");
261 exit(1);
264 close(fd);
266 if (add_barebox_header) {
267 memcpy(buf, bb_header, sizeof(bb_header));
270 ret = add_socfpga_header(buf, s.st_size + 4 + addsize + pad);
271 if (ret)
272 exit(1);
274 fd = open(outfile, O_WRONLY | O_CREAT | O_TRUNC, 0644);
275 if (fd < 0) {
276 perror("open outfile");
277 exit(1);
280 ret = write_full(fd, buf, s.st_size + 4 + addsize + pad);
281 if (ret < 0) {
282 perror("write outfile");
283 exit(1);
286 exit(0);