]> git.kernelconcepts.de Git - karo-tx-uboot.git/blob - tools/pblimage.c
Merge branch 'master' of git://git.denx.de/u-boot-nand-flash
[karo-tx-uboot.git] / tools / pblimage.c
1 /*
2  * Copyright 2012 Freescale Semiconductor, Inc.
3  *
4  * See file CREDITS for list of people who contributed to this
5  * project.
6  *
7  * This program is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU General Public License as
9  * published by the Free Software Foundation; either version 2 of
10  * the License, or (at your option) any later version.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program; if not, write to the Free Software
19  * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
20  * MA 02111-1307 USA
21  */
22 #define _GNU_SOURCE
23
24 #include "mkimage.h"
25 #include <image.h>
26 #include "pblimage.h"
27
28 /*
29  * Initialize to an invalid value.
30  */
31 static uint32_t next_pbl_cmd = 0x82000000;
32 /*
33  * need to store all bytes in memory for calculating crc32, then write the
34  * bytes to image file for PBL boot.
35  */
36 static unsigned char mem_buf[1000000];
37 static unsigned char *pmem_buf = mem_buf;
38 static int pbl_size;
39 static char *fname = "Unknown";
40 static int lineno = -1;
41 static struct pbl_header pblimage_header;
42
43 static union
44 {
45         char c[4];
46         unsigned char l;
47 } endian_test = { {'l', '?', '?', 'b'} };
48
49 #define ENDIANNESS ((char)endian_test.l)
50
51 /*
52  * The PBL can load up to 64 bytes at a time, so we split the U-Boot
53  * image into 64 byte chunks. PBL needs a command for each piece, of
54  * the form "81xxxxxx", where "xxxxxx" is the offset. Calculate the
55  * start offset by subtracting the size of the u-boot image from the
56  * top of the allowable 24-bit range.
57  */
58 static void init_next_pbl_cmd(FILE *fp_uboot)
59 {
60         struct stat st;
61         int fd = fileno(fp_uboot);
62
63         if (fstat(fd, &st) == -1) {
64                 printf("Error: Could not determine u-boot image size. %s\n",
65                         strerror(errno));
66                 exit(EXIT_FAILURE);
67         }
68
69         next_pbl_cmd = 0x82000000 - st.st_size;
70 }
71
72 static void generate_pbl_cmd(void)
73 {
74         uint32_t val = next_pbl_cmd;
75         next_pbl_cmd += 0x40;
76         int i;
77
78         for (i = 3; i >= 0; i--) {
79                 *pmem_buf++ = (val >> (i * 8)) & 0xff;
80                 pbl_size++;
81         }
82 }
83
84 static void pbl_fget(size_t size, FILE *stream)
85 {
86         unsigned char c;
87         int c_temp;
88
89         while (size && (c_temp = fgetc(stream)) != EOF) {
90                 c = (unsigned char)c_temp;
91                 *pmem_buf++ = c;
92                 pbl_size++;
93                 size--;
94         }
95 }
96
97 /* load split u-boot with PBI command 81xxxxxx. */
98 static void load_uboot(FILE *fp_uboot)
99 {
100         init_next_pbl_cmd(fp_uboot);
101         while (next_pbl_cmd < 0x82000000) {
102                 generate_pbl_cmd();
103                 pbl_fget(64, fp_uboot);
104         }
105 }
106
107 static void check_get_hexval(char *token)
108 {
109         uint32_t hexval;
110         int i;
111
112         if (!sscanf(token, "%x", &hexval)) {
113                 printf("Error:%s[%d] - Invalid hex data(%s)\n", fname,
114                         lineno, token);
115                 exit(EXIT_FAILURE);
116         }
117         for (i = 3; i >= 0; i--) {
118                 *pmem_buf++ = (hexval >> (i * 8)) & 0xff;
119                 pbl_size++;
120         }
121 }
122
123 static void pbl_parser(char *name)
124 {
125         FILE *fd = NULL;
126         char *line = NULL;
127         char *token, *saveptr1, *saveptr2;
128         size_t len = 0;
129
130         fname = name;
131         fd = fopen(name, "r");
132         if (fd == NULL) {
133                 printf("Error:%s - Can't open\n", fname);
134                 exit(EXIT_FAILURE);
135         }
136
137         while ((getline(&line, &len, fd)) > 0) {
138                 lineno++;
139                 token = strtok_r(line, "\r\n", &saveptr1);
140                 /* drop all lines with zero tokens (= empty lines) */
141                 if (token == NULL)
142                         continue;
143                 for (line = token;; line = NULL) {
144                         token = strtok_r(line, " \t", &saveptr2);
145                         if (token == NULL)
146                                 break;
147                         /* Drop all text starting with '#' as comments */
148                         if (token[0] == '#')
149                                 break;
150                         check_get_hexval(token);
151                 }
152         }
153         if (line)
154                 free(line);
155         fclose(fd);
156 }
157
158 static uint32_t crc_table[256];
159
160 static void make_crc_table(void)
161 {
162         uint32_t mask;
163         int i, j;
164         uint32_t poly; /* polynomial exclusive-or pattern */
165
166         /*
167          * the polynomial used by PBL is 1 + x1 + x2 + x4 + x5 + x7 + x8 + x10
168          * + x11 + x12 + x16 + x22 + x23 + x26 + x32.
169          */
170         poly = 0x04c11db7;
171
172         for (i = 0; i < 256; i++) {
173                 mask = i << 24;
174                 for (j = 0; j < 8; j++) {
175                         if (mask & 0x80000000)
176                                 mask = (mask << 1) ^ poly;
177                         else
178                                 mask <<= 1;
179                 }
180                 crc_table[i] = mask;
181         }
182 }
183
184 unsigned long pbl_crc32(unsigned long crc, const char *buf, uint32_t len)
185 {
186         uint32_t crc32_val = 0xffffffff;
187         uint32_t xor = 0x0;
188         int i;
189
190         make_crc_table();
191
192         for (i = 0; i < len; i++)
193                 crc32_val = (crc32_val << 8) ^
194                         crc_table[(crc32_val >> 24) ^ (*buf++ & 0xff)];
195
196         crc32_val = crc32_val ^ xor;
197         if (crc32_val < 0) {
198                 crc32_val += 0xffffffff;
199                 crc32_val += 1;
200         }
201         return crc32_val;
202 }
203
204 static uint32_t reverse_byte(uint32_t val)
205 {
206         uint32_t temp;
207         unsigned char *p1;
208         int j;
209
210         temp = val;
211         p1 = (unsigned char *)&temp;
212         for (j = 3; j >= 0; j--)
213                 *p1++ = (val >> (j * 8)) & 0xff;
214         return temp;
215 }
216
217 /* write end command and crc command to memory. */
218 static void add_end_cmd(void)
219 {
220         uint32_t pbl_end_cmd[4] = {0x09138000, 0x00000000,
221                 0x091380c0, 0x00000000};
222         uint32_t crc32_pbl;
223         int i;
224         unsigned char *p = (unsigned char *)&pbl_end_cmd;
225
226         if (ENDIANNESS == 'l') {
227                 for (i = 0; i < 4; i++)
228                         pbl_end_cmd[i] = reverse_byte(pbl_end_cmd[i]);
229         }
230
231         for (i = 0; i < 16; i++) {
232                 *pmem_buf++ = *p++;
233                 pbl_size++;
234         }
235
236         /* Add PBI CRC command. */
237         *pmem_buf++ = 0x08;
238         *pmem_buf++ = 0x13;
239         *pmem_buf++ = 0x80;
240         *pmem_buf++ = 0x40;
241         pbl_size += 4;
242
243         /* calculated CRC32 and write it to memory. */
244         crc32_pbl = pbl_crc32(0, (const char *)mem_buf, pbl_size);
245         *pmem_buf++ = (crc32_pbl >> 24) & 0xff;
246         *pmem_buf++ = (crc32_pbl >> 16) & 0xff;
247         *pmem_buf++ = (crc32_pbl >> 8) & 0xff;
248         *pmem_buf++ = (crc32_pbl) & 0xff;
249         pbl_size += 4;
250
251         if ((pbl_size % 16) != 0) {
252                 for (i = 0; i < 8; i++) {
253                         *pmem_buf++ = 0x0;
254                         pbl_size++;
255                 }
256         }
257         if ((pbl_size % 16 != 0)) {
258                 printf("Error: Bad size of image file\n");
259                 exit(EXIT_FAILURE);
260         }
261 }
262
263 void pbl_load_uboot(int ifd, struct mkimage_params *params)
264 {
265         FILE *fp_uboot;
266         int size;
267
268         /* parse the rcw.cfg file. */
269         pbl_parser(params->imagename);
270
271         /* parse the pbi.cfg file. */
272         pbl_parser(params->imagename2);
273
274         fp_uboot = fopen(params->datafile, "r");
275         if (fp_uboot == NULL) {
276                 printf("Error: %s open failed\n", params->datafile);
277                 exit(EXIT_FAILURE);
278         }
279
280         load_uboot(fp_uboot);
281         add_end_cmd();
282         fclose(fp_uboot);
283         lseek(ifd, 0, SEEK_SET);
284
285         size = pbl_size;
286         if (write(ifd, (const void *)&mem_buf, size) != size) {
287                 fprintf(stderr, "Write error on %s: %s\n",
288                         params->imagefile, strerror(errno));
289                 exit(EXIT_FAILURE);
290         }
291 }
292
293 static int pblimage_check_image_types(uint8_t type)
294 {
295         if (type == IH_TYPE_PBLIMAGE)
296                 return EXIT_SUCCESS;
297         else
298                 return EXIT_FAILURE;
299 }
300
301 static int pblimage_verify_header(unsigned char *ptr, int image_size,
302                         struct mkimage_params *params)
303 {
304         struct pbl_header *pbl_hdr = (struct pbl_header *) ptr;
305
306         /* Only a few checks can be done: search for magic numbers */
307         if (ENDIANNESS == 'l') {
308                 if (pbl_hdr->preamble != reverse_byte(RCW_PREAMBLE))
309                         return -FDT_ERR_BADSTRUCTURE;
310
311                 if (pbl_hdr->rcwheader != reverse_byte(RCW_HEADER))
312                         return -FDT_ERR_BADSTRUCTURE;
313         } else {
314                 if (pbl_hdr->preamble != RCW_PREAMBLE)
315                         return -FDT_ERR_BADSTRUCTURE;
316
317                 if (pbl_hdr->rcwheader != RCW_HEADER)
318                         return -FDT_ERR_BADSTRUCTURE;
319         }
320         return 0;
321 }
322
323 static void pblimage_print_header(const void *ptr)
324 {
325         printf("Image Type:   Freescale PBL Boot Image\n");
326 }
327
328 static void pblimage_set_header(void *ptr, struct stat *sbuf, int ifd,
329                                 struct mkimage_params *params)
330 {
331         /*nothing need to do, pbl_load_uboot takes care of whole file. */
332 }
333
334 /* pblimage parameters */
335 static struct image_type_params pblimage_params = {
336         .name           = "Freescale PBL Boot Image support",
337         .header_size    = sizeof(struct pbl_header),
338         .hdr            = (void *)&pblimage_header,
339         .check_image_type = pblimage_check_image_types,
340         .verify_header  = pblimage_verify_header,
341         .print_header   = pblimage_print_header,
342         .set_header     = pblimage_set_header,
343 };
344
345 void init_pbl_image_type(void)
346 {
347         pbl_size = 0;
348         mkimage_register(&pblimage_params);
349 }