]>
Commit | Line | Data |
---|---|---|
5b1d7137 WD |
1 | /* |
2 | * (C) Copyright 2000-2002 | |
3 | * DENX Software Engineering | |
4 | * Wolfgang Denk, wd@denx.de | |
5 | * All rights reserved. | |
6 | */ | |
7 | ||
8 | #include <errno.h> | |
9 | #include <fcntl.h> | |
10 | #include <stdio.h> | |
11 | #include <stdlib.h> | |
12 | #include <string.h> | |
13 | #ifndef __WIN32__ | |
14 | #include <netinet/in.h> /* for host / network byte order conversions */ | |
15 | #endif | |
16 | #include <sys/mman.h> | |
17 | #include <sys/stat.h> | |
18 | #include <time.h> | |
19 | #include <unistd.h> | |
20 | ||
21 | #if defined(__BEOS__) || defined(__NetBSD__) || defined(__APPLE__) | |
22 | #include <inttypes.h> | |
23 | #endif | |
24 | ||
25 | #ifdef __WIN32__ | |
26 | typedef unsigned int __u32; | |
27 | ||
28 | #define SWAP_LONG(x) \ | |
29 | ((__u32)( \ | |
30 | (((__u32)(x) & (__u32)0x000000ffUL) << 24) | \ | |
31 | (((__u32)(x) & (__u32)0x0000ff00UL) << 8) | \ | |
32 | (((__u32)(x) & (__u32)0x00ff0000UL) >> 8) | \ | |
33 | (((__u32)(x) & (__u32)0xff000000UL) >> 24) )) | |
34 | typedef unsigned char uint8_t; | |
35 | typedef unsigned short uint16_t; | |
36 | typedef unsigned int uint32_t; | |
37 | ||
38 | #define ntohl(a) SWAP_LONG(a) | |
39 | #define htonl(a) SWAP_LONG(a) | |
40 | #endif /* __WIN32__ */ | |
41 | ||
42 | #include <image.h> | |
43 | ||
44 | extern int errno; | |
45 | ||
46 | #ifndef MAP_FAILED | |
47 | #define MAP_FAILED (-1) | |
48 | #endif | |
49 | ||
50 | char *cmdname; | |
51 | ||
52 | extern unsigned long crc32 (unsigned long crc, const char *buf, unsigned int len); | |
53 | ||
54 | typedef struct table_entry { | |
55 | int val; /* as defined in image.h */ | |
56 | char *sname; /* short (input) name */ | |
57 | char *lname; /* long (output) name */ | |
58 | } table_entry_t; | |
59 | ||
60 | table_entry_t arch_name[] = { | |
61 | { IH_CPU_INVALID, NULL, "Invalid CPU", }, | |
62 | { IH_CPU_ALPHA, "alpha", "Alpha", }, | |
63 | { IH_CPU_ARM, "arm", "ARM", }, | |
64 | { IH_CPU_I386, "x86", "Intel x86", }, | |
65 | { IH_CPU_IA64, "ia64", "IA64", }, | |
66 | { IH_CPU_MIPS, "mips", "MIPS", }, | |
67 | { IH_CPU_MIPS64, "mips64", "MIPS 64 Bit", }, | |
68 | { IH_CPU_PPC, "ppc", "PowerPC", }, | |
69 | { IH_CPU_S390, "s390", "IBM S390", }, | |
70 | { IH_CPU_SH, "sh", "SuperH", }, | |
71 | { IH_CPU_SPARC, "sparc", "SPARC", }, | |
72 | { IH_CPU_SPARC64, "sparc64", "SPARC 64 Bit", }, | |
73 | { -1, "", "", }, | |
74 | }; | |
75 | ||
76 | table_entry_t os_name[] = { | |
77 | { IH_OS_INVALID, NULL, "Invalid OS", }, | |
78 | { IH_OS_OPENBSD, "openbsd", "OpenBSD", }, | |
79 | { IH_OS_NETBSD, "netbsd", "NetBSD", }, | |
80 | { IH_OS_FREEBSD, "freebsd", "FreeBSD", }, | |
81 | { IH_OS_4_4BSD, "4_4bsd", "4_4BSD", }, | |
82 | { IH_OS_LINUX, "linux", "Linux", }, | |
83 | { IH_OS_SVR4, "svr4", "SVR4", }, | |
84 | { IH_OS_ESIX, "esix", "Esix", }, | |
85 | { IH_OS_SOLARIS, "solaris", "Solaris", }, | |
86 | { IH_OS_IRIX, "irix", "Irix", }, | |
87 | { IH_OS_SCO, "sco", "SCO", }, | |
88 | { IH_OS_DELL, "dell", "Dell", }, | |
89 | { IH_OS_NCR, "ncr", "NCR", }, | |
90 | { IH_OS_LYNXOS, "lynxos", "LynxOS", }, | |
91 | { IH_OS_VXWORKS, "vxworks", "VxWorks", }, | |
92 | { IH_OS_PSOS, "psos", "pSOS", }, | |
93 | { IH_OS_QNX, "qnx", "QNX", }, | |
94 | { IH_OS_U_BOOT, "u-boot", "U-Boot", }, | |
d791b1dc | 95 | { IH_OS_RTEMS, "rtems", "RTEMS", }, |
7f70e853 | 96 | { IH_OS_ARTOS, "artos", "ARTOS", }, |
5b1d7137 WD |
97 | { -1, "", "", }, |
98 | }; | |
99 | ||
100 | table_entry_t type_name[] = { | |
101 | { IH_TYPE_INVALID, NULL, "Invalid Image", }, | |
102 | { IH_TYPE_STANDALONE, "standalone", "Standalone Program", }, | |
103 | { IH_TYPE_KERNEL, "kernel", "Kernel Image", }, | |
104 | { IH_TYPE_RAMDISK, "ramdisk", "RAMDisk Image", }, | |
105 | { IH_TYPE_MULTI, "multi", "Multi-File Image", }, | |
106 | { IH_TYPE_FIRMWARE, "firmware", "Firmware", }, | |
107 | { IH_TYPE_SCRIPT, "script", "Script", }, | |
108 | { -1, "", "", }, | |
109 | }; | |
110 | ||
111 | table_entry_t comp_name[] = { | |
112 | { IH_COMP_NONE, "none", "uncompressed", }, | |
113 | { IH_COMP_GZIP, "gzip", "gzip compressed", }, | |
114 | { IH_COMP_BZIP2, "bzip2", "bzip2 compressed", }, | |
115 | { -1, "", "", }, | |
116 | }; | |
117 | ||
118 | static void copy_file (int, const char *, int); | |
119 | static void usage (void); | |
120 | static void print_header (image_header_t *); | |
121 | static void print_type (image_header_t *); | |
122 | static char *put_table_entry (table_entry_t *, char *, int); | |
123 | static char *put_arch (int); | |
124 | static char *put_type (int); | |
125 | static char *put_os (int); | |
126 | static char *put_comp (int); | |
127 | static int get_table_entry (table_entry_t *, char *, char *); | |
128 | static int get_arch(char *); | |
129 | static int get_comp(char *); | |
130 | static int get_os (char *); | |
131 | static int get_type(char *); | |
132 | ||
133 | ||
134 | char *datafile; | |
135 | char *imagefile; | |
136 | ||
137 | int dflag = 0; | |
138 | int eflag = 0; | |
139 | int lflag = 0; | |
140 | int vflag = 0; | |
141 | int xflag = 0; | |
142 | int opt_os = IH_OS_LINUX; | |
143 | int opt_arch = IH_CPU_PPC; | |
144 | int opt_type = IH_TYPE_KERNEL; | |
145 | int opt_comp = IH_COMP_GZIP; | |
146 | ||
147 | image_header_t header; | |
148 | image_header_t *hdr = &header; | |
149 | ||
150 | int | |
151 | main (int argc, char **argv) | |
152 | { | |
153 | int ifd; | |
154 | uint32_t checksum; | |
155 | uint32_t addr; | |
156 | uint32_t ep; | |
157 | struct stat sbuf; | |
158 | unsigned char *ptr; | |
159 | char *name = ""; | |
160 | ||
161 | cmdname = *argv; | |
162 | ||
163 | addr = ep = 0; | |
164 | ||
165 | while (--argc > 0 && **++argv == '-') { | |
166 | while (*++*argv) { | |
167 | switch (**argv) { | |
168 | case 'l': | |
169 | lflag = 1; | |
170 | break; | |
171 | case 'A': | |
172 | if ((--argc <= 0) || | |
173 | (opt_arch = get_arch(*++argv)) < 0) | |
174 | usage (); | |
175 | goto NXTARG; | |
176 | case 'C': | |
177 | if ((--argc <= 0) || | |
178 | (opt_comp = get_comp(*++argv)) < 0) | |
179 | usage (); | |
180 | goto NXTARG; | |
181 | case 'O': | |
182 | if ((--argc <= 0) || | |
183 | (opt_os = get_os(*++argv)) < 0) | |
184 | usage (); | |
185 | goto NXTARG; | |
186 | case 'T': | |
187 | if ((--argc <= 0) || | |
188 | (opt_type = get_type(*++argv)) < 0) | |
189 | usage (); | |
190 | goto NXTARG; | |
191 | ||
192 | case 'a': | |
193 | if (--argc <= 0) | |
194 | usage (); | |
195 | addr = strtoul (*++argv, (char **)&ptr, 16); | |
196 | if (*ptr) { | |
197 | fprintf (stderr, | |
198 | "%s: invalid load address %s\n", | |
199 | cmdname, *argv); | |
200 | exit (EXIT_FAILURE); | |
201 | } | |
202 | goto NXTARG; | |
203 | case 'd': | |
204 | if (--argc <= 0) | |
205 | usage (); | |
206 | datafile = *++argv; | |
207 | dflag = 1; | |
208 | goto NXTARG; | |
209 | case 'e': | |
210 | if (--argc <= 0) | |
211 | usage (); | |
212 | ep = strtoul (*++argv, (char **)&ptr, 16); | |
213 | if (*ptr) { | |
214 | fprintf (stderr, | |
215 | "%s: invalid entry point %s\n", | |
216 | cmdname, *argv); | |
217 | exit (EXIT_FAILURE); | |
218 | } | |
219 | eflag = 1; | |
220 | goto NXTARG; | |
221 | case 'n': | |
222 | if (--argc <= 0) | |
223 | usage (); | |
224 | name = *++argv; | |
225 | goto NXTARG; | |
226 | case 'v': | |
227 | vflag++; | |
228 | break; | |
229 | case 'x': | |
230 | xflag++; | |
231 | break; | |
232 | default: | |
233 | usage (); | |
234 | } | |
235 | } | |
236 | NXTARG: ; | |
237 | } | |
238 | ||
239 | if ((argc != 1) || ((lflag ^ dflag) == 0)) | |
240 | usage(); | |
241 | ||
242 | if (!eflag) { | |
243 | ep = addr; | |
244 | /* If XIP, entry point must be after the U-Boot header */ | |
245 | if (xflag) | |
246 | ep += sizeof(image_header_t); | |
247 | } | |
248 | ||
249 | /* | |
250 | * If XIP, ensure the entry point is equal to the load address plus | |
251 | * the size of the U-Boot header. | |
252 | */ | |
253 | if (xflag) { | |
254 | if (ep != addr + sizeof(image_header_t)) { | |
a6c7ad2f WD |
255 | fprintf (stderr, "%s: For XIP, the entry point must be the load addr + %lu\n", |
256 | cmdname, | |
257 | (unsigned long)sizeof(image_header_t)); | |
5b1d7137 WD |
258 | exit (EXIT_FAILURE); |
259 | } | |
260 | } | |
261 | ||
262 | imagefile = *argv; | |
263 | ||
264 | if (lflag) { | |
265 | ifd = open(imagefile, O_RDONLY); | |
266 | } else { | |
267 | #ifdef __WIN32__ | |
268 | ifd = open(imagefile, O_RDWR|O_CREAT|O_TRUNC|O_BINARY, 0666); | |
269 | #else | |
270 | ifd = open(imagefile, O_RDWR|O_CREAT|O_TRUNC, 0666); | |
271 | #endif | |
272 | } | |
273 | ||
274 | if (ifd < 0) { | |
275 | fprintf (stderr, "%s: Can't open %s: %s\n", | |
276 | cmdname, imagefile, strerror(errno)); | |
277 | exit (EXIT_FAILURE); | |
278 | } | |
279 | ||
280 | if (lflag) { | |
281 | int len; | |
282 | char *data; | |
283 | /* | |
284 | * list header information of existing image | |
285 | */ | |
286 | if (fstat(ifd, &sbuf) < 0) { | |
287 | fprintf (stderr, "%s: Can't stat %s: %s\n", | |
288 | cmdname, imagefile, strerror(errno)); | |
289 | exit (EXIT_FAILURE); | |
290 | } | |
291 | ||
292 | if (sbuf.st_size < sizeof(image_header_t)) { | |
293 | fprintf (stderr, | |
294 | "%s: Bad size: \"%s\" is no valid image\n", | |
295 | cmdname, imagefile); | |
296 | exit (EXIT_FAILURE); | |
297 | } | |
298 | ||
299 | ptr = (unsigned char *)mmap(0, sbuf.st_size, | |
300 | PROT_READ, MAP_SHARED, ifd, 0); | |
301 | if ((caddr_t)ptr == (caddr_t)-1) { | |
302 | fprintf (stderr, "%s: Can't read %s: %s\n", | |
303 | cmdname, imagefile, strerror(errno)); | |
304 | exit (EXIT_FAILURE); | |
305 | } | |
306 | ||
307 | /* | |
308 | * create copy of header so that we can blank out the | |
309 | * checksum field for checking - this can't be done | |
310 | * on the PROT_READ mapped data. | |
311 | */ | |
312 | memcpy (hdr, ptr, sizeof(image_header_t)); | |
313 | ||
314 | if (ntohl(hdr->ih_magic) != IH_MAGIC) { | |
315 | fprintf (stderr, | |
316 | "%s: Bad Magic Number: \"%s\" is no valid image\n", | |
317 | cmdname, imagefile); | |
318 | exit (EXIT_FAILURE); | |
319 | } | |
320 | ||
321 | data = (char *)hdr; | |
322 | len = sizeof(image_header_t); | |
323 | ||
324 | checksum = ntohl(hdr->ih_hcrc); | |
325 | hdr->ih_hcrc = htonl(0); /* clear for re-calculation */ | |
326 | ||
327 | if (crc32 (0, data, len) != checksum) { | |
328 | fprintf (stderr, | |
329 | "*** Warning: \"%s\" has bad header checksum!\n", | |
330 | imagefile); | |
331 | } | |
332 | ||
333 | data = (char *)(ptr + sizeof(image_header_t)); | |
334 | len = sbuf.st_size - sizeof(image_header_t) ; | |
335 | ||
336 | if (crc32 (0, data, len) != ntohl(hdr->ih_dcrc)) { | |
337 | fprintf (stderr, | |
338 | "*** Warning: \"%s\" has corrupted data!\n", | |
339 | imagefile); | |
340 | } | |
341 | ||
342 | /* for multi-file images we need the data part, too */ | |
343 | print_header ((image_header_t *)ptr); | |
344 | ||
345 | (void) munmap((void *)ptr, sbuf.st_size); | |
346 | (void) close (ifd); | |
347 | ||
348 | exit (EXIT_SUCCESS); | |
349 | } | |
350 | ||
351 | /* | |
352 | * Must be -w then: | |
353 | * | |
354 | * write dummy header, to be fixed later | |
355 | */ | |
356 | memset (hdr, 0, sizeof(image_header_t)); | |
357 | ||
358 | if (write(ifd, hdr, sizeof(image_header_t)) != sizeof(image_header_t)) { | |
359 | fprintf (stderr, "%s: Write error on %s: %s\n", | |
360 | cmdname, imagefile, strerror(errno)); | |
361 | exit (EXIT_FAILURE); | |
362 | } | |
363 | ||
364 | if (opt_type == IH_TYPE_MULTI || opt_type == IH_TYPE_SCRIPT) { | |
365 | char *file = datafile; | |
366 | unsigned long size; | |
367 | ||
368 | for (;;) { | |
369 | char *sep = NULL; | |
370 | ||
371 | if (file) { | |
372 | if ((sep = strchr(file, ':')) != NULL) { | |
373 | *sep = '\0'; | |
374 | } | |
375 | ||
376 | if (stat (file, &sbuf) < 0) { | |
377 | fprintf (stderr, "%s: Can't stat %s: %s\n", | |
378 | cmdname, file, strerror(errno)); | |
379 | exit (EXIT_FAILURE); | |
380 | } | |
381 | size = htonl(sbuf.st_size); | |
382 | } else { | |
383 | size = 0; | |
384 | } | |
385 | ||
386 | if (write(ifd, (char *)&size, sizeof(size)) != sizeof(size)) { | |
387 | fprintf (stderr, "%s: Write error on %s: %s\n", | |
388 | cmdname, imagefile, strerror(errno)); | |
389 | exit (EXIT_FAILURE); | |
390 | } | |
391 | ||
392 | if (!file) { | |
393 | break; | |
394 | } | |
395 | ||
396 | if (sep) { | |
397 | *sep = ':'; | |
398 | file = sep + 1; | |
399 | } else { | |
400 | file = NULL; | |
401 | } | |
402 | } | |
403 | ||
404 | file = datafile; | |
405 | ||
406 | for (;;) { | |
407 | char *sep = strchr(file, ':'); | |
408 | if (sep) { | |
409 | *sep = '\0'; | |
410 | copy_file (ifd, file, 1); | |
411 | *sep++ = ':'; | |
412 | file = sep; | |
413 | } else { | |
414 | copy_file (ifd, file, 0); | |
415 | break; | |
416 | } | |
417 | } | |
418 | } else { | |
419 | copy_file (ifd, datafile, 0); | |
420 | } | |
421 | ||
422 | /* We're a bit of paranoid */ | |
423 | #if defined(_POSIX_SYNCHRONIZED_IO) && !defined(__sun__) | |
424 | (void) fdatasync (ifd); | |
425 | #else | |
426 | (void) fsync (ifd); | |
427 | #endif | |
428 | ||
429 | if (fstat(ifd, &sbuf) < 0) { | |
430 | fprintf (stderr, "%s: Can't stat %s: %s\n", | |
431 | cmdname, imagefile, strerror(errno)); | |
432 | exit (EXIT_FAILURE); | |
433 | } | |
434 | ||
435 | ptr = (unsigned char *)mmap(0, sbuf.st_size, | |
436 | PROT_READ|PROT_WRITE, MAP_SHARED, ifd, 0); | |
437 | if (ptr == (unsigned char *)MAP_FAILED) { | |
438 | fprintf (stderr, "%s: Can't map %s: %s\n", | |
439 | cmdname, imagefile, strerror(errno)); | |
440 | exit (EXIT_FAILURE); | |
441 | } | |
442 | ||
443 | hdr = (image_header_t *)ptr; | |
444 | ||
445 | checksum = crc32 (0, | |
446 | (const char *)(ptr + sizeof(image_header_t)), | |
447 | sbuf.st_size - sizeof(image_header_t) | |
448 | ); | |
449 | ||
450 | /* Build new header */ | |
451 | hdr->ih_magic = htonl(IH_MAGIC); | |
452 | hdr->ih_time = htonl(sbuf.st_mtime); | |
453 | hdr->ih_size = htonl(sbuf.st_size - sizeof(image_header_t)); | |
454 | hdr->ih_load = htonl(addr); | |
455 | hdr->ih_ep = htonl(ep); | |
456 | hdr->ih_dcrc = htonl(checksum); | |
457 | hdr->ih_os = opt_os; | |
458 | hdr->ih_arch = opt_arch; | |
459 | hdr->ih_type = opt_type; | |
460 | hdr->ih_comp = opt_comp; | |
461 | ||
462 | strncpy((char *)hdr->ih_name, name, IH_NMLEN); | |
463 | ||
464 | checksum = crc32(0,(const char *)hdr,sizeof(image_header_t)); | |
465 | ||
466 | hdr->ih_hcrc = htonl(checksum); | |
467 | ||
468 | print_header (hdr); | |
469 | ||
470 | (void) munmap((void *)ptr, sbuf.st_size); | |
471 | ||
472 | /* We're a bit of paranoid */ | |
473 | #if defined(_POSIX_SYNCHRONIZED_IO) && !defined(__sun__) | |
474 | (void) fdatasync (ifd); | |
475 | #else | |
476 | (void) fsync (ifd); | |
477 | #endif | |
478 | ||
479 | if (close(ifd)) { | |
480 | fprintf (stderr, "%s: Write error on %s: %s\n", | |
481 | cmdname, imagefile, strerror(errno)); | |
482 | exit (EXIT_FAILURE); | |
483 | } | |
484 | ||
485 | exit (EXIT_SUCCESS); | |
486 | } | |
487 | ||
488 | static void | |
489 | copy_file (int ifd, const char *datafile, int pad) | |
490 | { | |
491 | int dfd; | |
492 | struct stat sbuf; | |
493 | unsigned char *ptr; | |
494 | int tail; | |
495 | int zero = 0; | |
496 | int offset = 0; | |
497 | int size; | |
498 | ||
499 | if (vflag) { | |
500 | fprintf (stderr, "Adding Image %s\n", datafile); | |
501 | } | |
502 | ||
503 | if ((dfd = open(datafile, O_RDONLY)) < 0) { | |
504 | fprintf (stderr, "%s: Can't open %s: %s\n", | |
505 | cmdname, datafile, strerror(errno)); | |
506 | exit (EXIT_FAILURE); | |
507 | } | |
508 | ||
509 | if (fstat(dfd, &sbuf) < 0) { | |
510 | fprintf (stderr, "%s: Can't stat %s: %s\n", | |
511 | cmdname, datafile, strerror(errno)); | |
512 | exit (EXIT_FAILURE); | |
513 | } | |
514 | ||
515 | ptr = (unsigned char *)mmap(0, sbuf.st_size, | |
516 | PROT_READ, MAP_SHARED, dfd, 0); | |
517 | if (ptr == (unsigned char *)MAP_FAILED) { | |
518 | fprintf (stderr, "%s: Can't read %s: %s\n", | |
519 | cmdname, datafile, strerror(errno)); | |
520 | exit (EXIT_FAILURE); | |
521 | } | |
522 | ||
523 | if (xflag) { | |
524 | unsigned char *p = NULL; | |
525 | /* | |
526 | * XIP: do not append the image_header_t at the | |
527 | * beginning of the file, but consume the space | |
528 | * reserved for it. | |
529 | */ | |
530 | ||
531 | if (sbuf.st_size < sizeof(image_header_t)) { | |
532 | fprintf (stderr, | |
533 | "%s: Bad size: \"%s\" is too small for XIP\n", | |
534 | cmdname, datafile); | |
535 | exit (EXIT_FAILURE); | |
536 | } | |
537 | ||
538 | for (p=ptr; p < ptr+sizeof(image_header_t); p++) { | |
539 | if ( *p != 0xff ) { | |
540 | fprintf (stderr, | |
541 | "%s: Bad file: \"%s\" has invalid buffer for XIP\n", | |
542 | cmdname, datafile); | |
543 | exit (EXIT_FAILURE); | |
544 | } | |
545 | } | |
546 | ||
547 | offset = sizeof(image_header_t); | |
548 | } | |
549 | ||
550 | size = sbuf.st_size - offset; | |
551 | if (write(ifd, ptr + offset, size) != size) { | |
552 | fprintf (stderr, "%s: Write error on %s: %s\n", | |
553 | cmdname, imagefile, strerror(errno)); | |
554 | exit (EXIT_FAILURE); | |
555 | } | |
556 | ||
557 | if (pad && ((tail = size % 4) != 0)) { | |
558 | ||
559 | if (write(ifd, (char *)&zero, 4-tail) != 4-tail) { | |
560 | fprintf (stderr, "%s: Write error on %s: %s\n", | |
561 | cmdname, imagefile, strerror(errno)); | |
562 | exit (EXIT_FAILURE); | |
563 | } | |
564 | } | |
565 | ||
566 | (void) munmap((void *)ptr, sbuf.st_size); | |
567 | (void) close (dfd); | |
568 | } | |
569 | ||
570 | void | |
571 | usage () | |
572 | { | |
573 | fprintf (stderr, "Usage: %s -l image\n" | |
574 | " -l ==> list image header information\n" | |
575 | " %s -A arch -O os -T type -C comp " | |
576 | "-a addr -e ep -n name -d data_file[:data_file...] image\n", | |
577 | cmdname, cmdname); | |
578 | fprintf (stderr, " -A ==> set architecture to 'arch'\n" | |
579 | " -O ==> set operating system to 'os'\n" | |
580 | " -T ==> set image type to 'type'\n" | |
581 | " -C ==> set compression type 'comp'\n" | |
582 | " -a ==> set load address to 'addr' (hex)\n" | |
583 | " -e ==> set entry point to 'ep' (hex)\n" | |
584 | " -n ==> set image name to 'name'\n" | |
585 | " -d ==> use image data from 'datafile'\n" | |
586 | " -x ==> set XIP (execute in place)\n" | |
587 | ); | |
588 | exit (EXIT_FAILURE); | |
589 | } | |
590 | ||
591 | static void | |
592 | print_header (image_header_t *hdr) | |
593 | { | |
594 | time_t timestamp; | |
595 | uint32_t size; | |
596 | ||
597 | timestamp = (time_t)ntohl(hdr->ih_time); | |
598 | size = ntohl(hdr->ih_size); | |
599 | ||
600 | printf ("Image Name: %.*s\n", IH_NMLEN, hdr->ih_name); | |
601 | printf ("Created: %s", ctime(×tamp)); | |
602 | printf ("Image Type: "); print_type(hdr); | |
603 | printf ("Data Size: %d Bytes = %.2f kB = %.2f MB\n", | |
604 | size, (double)size / 1.024e3, (double)size / 1.048576e6 ); | |
605 | printf ("Load Address: 0x%08x\n", ntohl(hdr->ih_load)); | |
606 | printf ("Entry Point: 0x%08x\n", ntohl(hdr->ih_ep)); | |
607 | ||
608 | if (hdr->ih_type == IH_TYPE_MULTI || hdr->ih_type == IH_TYPE_SCRIPT) { | |
609 | int i, ptrs; | |
610 | uint32_t pos; | |
611 | unsigned long *len_ptr = (unsigned long *) ( | |
612 | (unsigned long)hdr + sizeof(image_header_t) | |
613 | ); | |
614 | ||
615 | /* determine number of images first (to calculate image offsets) */ | |
616 | for (i=0; len_ptr[i]; ++i) /* null pointer terminates list */ | |
617 | ; | |
618 | ptrs = i; /* null pointer terminates list */ | |
619 | ||
620 | pos = sizeof(image_header_t) + ptrs * sizeof(long); | |
621 | printf ("Contents:\n"); | |
622 | for (i=0; len_ptr[i]; ++i) { | |
623 | size = ntohl(len_ptr[i]); | |
624 | ||
625 | printf (" Image %d: %8d Bytes = %4d kB = %d MB\n", | |
626 | i, size, size>>10, size>>20); | |
627 | if (hdr->ih_type == IH_TYPE_SCRIPT && i > 0) { | |
628 | /* | |
629 | * the user may need to know offsets | |
630 | * if planning to do something with | |
631 | * multiple files | |
632 | */ | |
633 | printf (" Offset = %08x\n", pos); | |
634 | } | |
635 | /* copy_file() will pad the first files to even word align */ | |
636 | size += 3; | |
637 | size &= ~3; | |
638 | pos += size; | |
639 | } | |
640 | } | |
641 | } | |
642 | ||
643 | ||
644 | static void | |
645 | print_type (image_header_t *hdr) | |
646 | { | |
647 | printf ("%s %s %s (%s)\n", | |
648 | put_arch (hdr->ih_arch), | |
649 | put_os (hdr->ih_os ), | |
650 | put_type (hdr->ih_type), | |
651 | put_comp (hdr->ih_comp) | |
652 | ); | |
653 | } | |
654 | ||
655 | static char *put_arch (int arch) | |
656 | { | |
657 | return (put_table_entry(arch_name, "Unknown Architecture", arch)); | |
658 | } | |
659 | ||
660 | static char *put_os (int os) | |
661 | { | |
662 | return (put_table_entry(os_name, "Unknown OS", os)); | |
663 | } | |
664 | ||
665 | static char *put_type (int type) | |
666 | { | |
667 | return (put_table_entry(type_name, "Unknown Image", type)); | |
668 | } | |
669 | ||
670 | static char *put_comp (int comp) | |
671 | { | |
672 | return (put_table_entry(comp_name, "Unknown Compression", comp)); | |
673 | } | |
674 | ||
675 | static char *put_table_entry (table_entry_t *table, char *msg, int type) | |
676 | { | |
677 | for (; table->val>=0; ++table) { | |
678 | if (table->val == type) | |
679 | return (table->lname); | |
680 | } | |
681 | return (msg); | |
682 | } | |
683 | ||
684 | static int get_arch(char *name) | |
685 | { | |
686 | return (get_table_entry(arch_name, "CPU", name)); | |
687 | } | |
688 | ||
689 | ||
690 | static int get_comp(char *name) | |
691 | { | |
692 | return (get_table_entry(comp_name, "Compression", name)); | |
693 | } | |
694 | ||
695 | ||
696 | static int get_os (char *name) | |
697 | { | |
698 | return (get_table_entry(os_name, "OS", name)); | |
699 | } | |
700 | ||
701 | ||
702 | static int get_type(char *name) | |
703 | { | |
704 | return (get_table_entry(type_name, "Image", name)); | |
705 | } | |
706 | ||
707 | static int get_table_entry (table_entry_t *table, char *msg, char *name) | |
708 | { | |
709 | table_entry_t *t; | |
710 | int first = 1; | |
711 | ||
712 | for (t=table; t->val>=0; ++t) { | |
713 | if (t->sname && strcasecmp(t->sname, name)==0) | |
714 | return (t->val); | |
715 | } | |
716 | fprintf (stderr, "\nInvalid %s Type - valid names are", msg); | |
717 | for (t=table; t->val>=0; ++t) { | |
718 | if (t->sname == NULL) | |
719 | continue; | |
720 | fprintf (stderr, "%c %s", (first) ? ':' : ',', t->sname); | |
721 | first = 0; | |
722 | } | |
723 | fprintf (stderr, "\n"); | |
724 | return (-1); | |
725 | } |