blob: 254feecaad7cf807bf905aabfc49f806bc92f70c [file] [log] [blame]
Simon Glassda0af362013-05-07 06:11:53 +00001/*
2 * Copyright (c) 2013, Google Inc.
3 *
4 * (C) Copyright 2008 Semihalf
5 *
6 * (C) Copyright 2000-2006
7 * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
8 *
9 * See file CREDITS for list of people who contributed to this
10 * project.
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License as
14 * published by the Free Software Foundation; either version 2 of
15 * the License, or (at your option) any later version.
16 *
17 * This program is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, write to the Free Software
24 * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
25 * MA 02111-1307 USA
26 */
27
28#ifdef USE_HOSTCC
29#include "mkimage.h"
30#include <image.h>
31#include <time.h>
32#else
33#include <common.h>
34#endif /* !USE_HOSTCC*/
35
36#include <bootstage.h>
37#include <sha1.h>
38#include <u-boot/crc.h>
39#include <u-boot/md5.h>
40
41/*****************************************************************************/
42/* New uImage format routines */
43/*****************************************************************************/
44#ifndef USE_HOSTCC
45static int fit_parse_spec(const char *spec, char sepc, ulong addr_curr,
46 ulong *addr, const char **name)
47{
48 const char *sep;
49
50 *addr = addr_curr;
51 *name = NULL;
52
53 sep = strchr(spec, sepc);
54 if (sep) {
55 if (sep - spec > 0)
56 *addr = simple_strtoul(spec, NULL, 16);
57
58 *name = sep + 1;
59 return 1;
60 }
61
62 return 0;
63}
64
65/**
66 * fit_parse_conf - parse FIT configuration spec
67 * @spec: input string, containing configuration spec
68 * @add_curr: current image address (to be used as a possible default)
69 * @addr: pointer to a ulong variable, will hold FIT image address of a given
70 * configuration
71 * @conf_name double pointer to a char, will hold pointer to a configuration
72 * unit name
73 *
74 * fit_parse_conf() expects configuration spec in the for of [<addr>]#<conf>,
75 * where <addr> is a FIT image address that contains configuration
76 * with a <conf> unit name.
77 *
78 * Address part is optional, and if omitted default add_curr will
79 * be used instead.
80 *
81 * returns:
82 * 1 if spec is a valid configuration string,
83 * addr and conf_name are set accordingly
84 * 0 otherwise
85 */
86int fit_parse_conf(const char *spec, ulong addr_curr,
87 ulong *addr, const char **conf_name)
88{
89 return fit_parse_spec(spec, '#', addr_curr, addr, conf_name);
90}
91
92/**
93 * fit_parse_subimage - parse FIT subimage spec
94 * @spec: input string, containing subimage spec
95 * @add_curr: current image address (to be used as a possible default)
96 * @addr: pointer to a ulong variable, will hold FIT image address of a given
97 * subimage
98 * @image_name: double pointer to a char, will hold pointer to a subimage name
99 *
100 * fit_parse_subimage() expects subimage spec in the for of
101 * [<addr>]:<subimage>, where <addr> is a FIT image address that contains
102 * subimage with a <subimg> unit name.
103 *
104 * Address part is optional, and if omitted default add_curr will
105 * be used instead.
106 *
107 * returns:
108 * 1 if spec is a valid subimage string,
109 * addr and image_name are set accordingly
110 * 0 otherwise
111 */
112int fit_parse_subimage(const char *spec, ulong addr_curr,
113 ulong *addr, const char **image_name)
114{
115 return fit_parse_spec(spec, ':', addr_curr, addr, image_name);
116}
117#endif /* !USE_HOSTCC */
118
119static void fit_get_debug(const void *fit, int noffset,
120 char *prop_name, int err)
121{
122 debug("Can't get '%s' property from FIT 0x%08lx, node: offset %d, name %s (%s)\n",
123 prop_name, (ulong)fit, noffset, fit_get_name(fit, noffset, NULL),
124 fdt_strerror(err));
125}
126
Simon Glass82d94532013-05-08 08:05:59 +0000127#if !defined(CONFIG_SPL_BUILD) || defined(CONFIG_FIT_SPL_PRINT)
Simon Glassda0af362013-05-07 06:11:53 +0000128/**
129 * fit_print_contents - prints out the contents of the FIT format image
130 * @fit: pointer to the FIT format image header
131 * @p: pointer to prefix string
132 *
133 * fit_print_contents() formats a multi line FIT image contents description.
134 * The routine prints out FIT image properties (root node level) follwed by
135 * the details of each component image.
136 *
137 * returns:
138 * no returned results
139 */
140void fit_print_contents(const void *fit)
141{
142 char *desc;
143 char *uname;
144 int images_noffset;
145 int confs_noffset;
146 int noffset;
147 int ndepth;
148 int count = 0;
149 int ret;
150 const char *p;
151 time_t timestamp;
152
Simon Glass1030f162013-05-08 08:05:58 +0000153 /* Indent string is defined in header image.h */
154 p = IMAGE_INDENT_STRING;
Simon Glassda0af362013-05-07 06:11:53 +0000155
156 /* Root node properties */
157 ret = fit_get_desc(fit, 0, &desc);
158 printf("%sFIT description: ", p);
159 if (ret)
160 printf("unavailable\n");
161 else
162 printf("%s\n", desc);
163
164 if (IMAGE_ENABLE_TIMESTAMP) {
165 ret = fit_get_timestamp(fit, 0, &timestamp);
166 printf("%sCreated: ", p);
167 if (ret)
168 printf("unavailable\n");
169 else
170 genimg_print_time(timestamp);
171 }
172
173 /* Find images parent node offset */
174 images_noffset = fdt_path_offset(fit, FIT_IMAGES_PATH);
175 if (images_noffset < 0) {
176 printf("Can't find images parent node '%s' (%s)\n",
177 FIT_IMAGES_PATH, fdt_strerror(images_noffset));
178 return;
179 }
180
181 /* Process its subnodes, print out component images details */
182 for (ndepth = 0, count = 0,
183 noffset = fdt_next_node(fit, images_noffset, &ndepth);
184 (noffset >= 0) && (ndepth > 0);
185 noffset = fdt_next_node(fit, noffset, &ndepth)) {
186 if (ndepth == 1) {
187 /*
188 * Direct child node of the images parent node,
189 * i.e. component image node.
190 */
191 printf("%s Image %u (%s)\n", p, count++,
192 fit_get_name(fit, noffset, NULL));
193
194 fit_image_print(fit, noffset, p);
195 }
196 }
197
198 /* Find configurations parent node offset */
199 confs_noffset = fdt_path_offset(fit, FIT_CONFS_PATH);
200 if (confs_noffset < 0) {
201 debug("Can't get configurations parent node '%s' (%s)\n",
202 FIT_CONFS_PATH, fdt_strerror(confs_noffset));
203 return;
204 }
205
206 /* get default configuration unit name from default property */
207 uname = (char *)fdt_getprop(fit, noffset, FIT_DEFAULT_PROP, NULL);
208 if (uname)
209 printf("%s Default Configuration: '%s'\n", p, uname);
210
211 /* Process its subnodes, print out configurations details */
212 for (ndepth = 0, count = 0,
213 noffset = fdt_next_node(fit, confs_noffset, &ndepth);
214 (noffset >= 0) && (ndepth > 0);
215 noffset = fdt_next_node(fit, noffset, &ndepth)) {
216 if (ndepth == 1) {
217 /*
218 * Direct child node of the configurations parent node,
219 * i.e. configuration node.
220 */
221 printf("%s Configuration %u (%s)\n", p, count++,
222 fit_get_name(fit, noffset, NULL));
223
224 fit_conf_print(fit, noffset, p);
225 }
226 }
227}
228
229/**
Simon Glasse61aa442013-05-07 06:12:02 +0000230 * fit_image_print_data() - prints out the hash node details
231 * @fit: pointer to the FIT format image header
232 * @noffset: offset of the hash node
233 * @p: pointer to prefix string
234 *
235 * fit_image_print_data() lists properies for the processed hash node
236 *
237 * returns:
238 * no returned results
239 */
240static void fit_image_print_data(const void *fit, int noffset, const char *p)
241{
242 char *algo;
243 uint8_t *value;
244 int value_len;
245 int i, ret;
246
247 /*
248 * Check subnode name, must be equal to "hash".
249 * Multiple hash nodes require unique unit node
250 * names, e.g. hash@1, hash@2, etc.
251 */
252 if (strncmp(fit_get_name(fit, noffset, NULL),
253 FIT_HASH_NODENAME,
254 strlen(FIT_HASH_NODENAME)) != 0)
255 return;
256
257 debug("%s Hash node: '%s'\n", p,
258 fit_get_name(fit, noffset, NULL));
259
260 printf("%s Hash algo: ", p);
261 if (fit_image_hash_get_algo(fit, noffset, &algo)) {
262 printf("invalid/unsupported\n");
263 return;
264 }
265 printf("%s\n", algo);
266
267 ret = fit_image_hash_get_value(fit, noffset, &value,
268 &value_len);
269 printf("%s Hash value: ", p);
270 if (ret) {
271 printf("unavailable\n");
272 } else {
273 for (i = 0; i < value_len; i++)
274 printf("%02x", value[i]);
275 printf("\n");
276 }
277
278 debug("%s Hash len: %d\n", p, value_len);
279}
280
281/**
282 * fit_image_print_verification_data() - prints out the hash/signature details
283 * @fit: pointer to the FIT format image header
284 * @noffset: offset of the hash or signature node
285 * @p: pointer to prefix string
286 *
287 * This lists properies for the processed hash node
288 *
289 * returns:
290 * no returned results
291 */
292static void fit_image_print_verification_data(const void *fit, int noffset,
293 const char *p)
294{
295 const char *name;
296
297 /*
298 * Check subnode name, must be equal to "hash" or "signature".
299 * Multiple hash/signature nodes require unique unit node
300 * names, e.g. hash@1, hash@2, signature@1, signature@2, etc.
301 */
302 name = fit_get_name(fit, noffset, NULL);
303 if (!strncmp(name, FIT_HASH_NODENAME, strlen(FIT_HASH_NODENAME)))
304 fit_image_print_data(fit, noffset, p);
305}
306
307/**
Simon Glassda0af362013-05-07 06:11:53 +0000308 * fit_image_print - prints out the FIT component image details
309 * @fit: pointer to the FIT format image header
310 * @image_noffset: offset of the component image node
311 * @p: pointer to prefix string
312 *
313 * fit_image_print() lists all mandatory properies for the processed component
314 * image. If present, hash nodes are printed out as well. Load
315 * address for images of type firmware is also printed out. Since the load
316 * address is not mandatory for firmware images, it will be output as
317 * "unavailable" when not present.
318 *
319 * returns:
320 * no returned results
321 */
322void fit_image_print(const void *fit, int image_noffset, const char *p)
323{
324 char *desc;
325 uint8_t type, arch, os, comp;
326 size_t size;
327 ulong load, entry;
328 const void *data;
329 int noffset;
330 int ndepth;
331 int ret;
332
333 /* Mandatory properties */
334 ret = fit_get_desc(fit, image_noffset, &desc);
335 printf("%s Description: ", p);
336 if (ret)
337 printf("unavailable\n");
338 else
339 printf("%s\n", desc);
340
341 fit_image_get_type(fit, image_noffset, &type);
342 printf("%s Type: %s\n", p, genimg_get_type_name(type));
343
344 fit_image_get_comp(fit, image_noffset, &comp);
345 printf("%s Compression: %s\n", p, genimg_get_comp_name(comp));
346
347 ret = fit_image_get_data(fit, image_noffset, &data, &size);
348
349#ifndef USE_HOSTCC
350 printf("%s Data Start: ", p);
351 if (ret)
352 printf("unavailable\n");
353 else
354 printf("0x%08lx\n", (ulong)data);
355#endif
356
357 printf("%s Data Size: ", p);
358 if (ret)
359 printf("unavailable\n");
360 else
361 genimg_print_size(size);
362
363 /* Remaining, type dependent properties */
364 if ((type == IH_TYPE_KERNEL) || (type == IH_TYPE_STANDALONE) ||
365 (type == IH_TYPE_RAMDISK) || (type == IH_TYPE_FIRMWARE) ||
366 (type == IH_TYPE_FLATDT)) {
367 fit_image_get_arch(fit, image_noffset, &arch);
368 printf("%s Architecture: %s\n", p, genimg_get_arch_name(arch));
369 }
370
371 if ((type == IH_TYPE_KERNEL) || (type == IH_TYPE_RAMDISK)) {
372 fit_image_get_os(fit, image_noffset, &os);
373 printf("%s OS: %s\n", p, genimg_get_os_name(os));
374 }
375
376 if ((type == IH_TYPE_KERNEL) || (type == IH_TYPE_STANDALONE) ||
377 (type == IH_TYPE_FIRMWARE) || (type == IH_TYPE_RAMDISK)) {
378 ret = fit_image_get_load(fit, image_noffset, &load);
379 printf("%s Load Address: ", p);
380 if (ret)
381 printf("unavailable\n");
382 else
383 printf("0x%08lx\n", load);
384 }
385
386 if ((type == IH_TYPE_KERNEL) || (type == IH_TYPE_STANDALONE) ||
387 (type == IH_TYPE_RAMDISK)) {
388 fit_image_get_entry(fit, image_noffset, &entry);
389 printf("%s Entry Point: ", p);
390 if (ret)
391 printf("unavailable\n");
392 else
393 printf("0x%08lx\n", entry);
394 }
395
396 /* Process all hash subnodes of the component image node */
397 for (ndepth = 0, noffset = fdt_next_node(fit, image_noffset, &ndepth);
398 (noffset >= 0) && (ndepth > 0);
399 noffset = fdt_next_node(fit, noffset, &ndepth)) {
400 if (ndepth == 1) {
401 /* Direct child node of the component image node */
Simon Glasse61aa442013-05-07 06:12:02 +0000402 fit_image_print_verification_data(fit, noffset, p);
Simon Glassda0af362013-05-07 06:11:53 +0000403 }
404 }
Simon Glassda0af362013-05-07 06:11:53 +0000405}
Simon Glass82d94532013-05-08 08:05:59 +0000406#endif
Simon Glassda0af362013-05-07 06:11:53 +0000407
408/**
409 * fit_get_desc - get node description property
410 * @fit: pointer to the FIT format image header
411 * @noffset: node offset
412 * @desc: double pointer to the char, will hold pointer to the descrption
413 *
414 * fit_get_desc() reads description property from a given node, if
415 * description is found pointer to it is returened in third call argument.
416 *
417 * returns:
418 * 0, on success
419 * -1, on failure
420 */
421int fit_get_desc(const void *fit, int noffset, char **desc)
422{
423 int len;
424
425 *desc = (char *)fdt_getprop(fit, noffset, FIT_DESC_PROP, &len);
426 if (*desc == NULL) {
427 fit_get_debug(fit, noffset, FIT_DESC_PROP, len);
428 return -1;
429 }
430
431 return 0;
432}
433
434/**
435 * fit_get_timestamp - get node timestamp property
436 * @fit: pointer to the FIT format image header
437 * @noffset: node offset
438 * @timestamp: pointer to the time_t, will hold read timestamp
439 *
440 * fit_get_timestamp() reads timestamp poperty from given node, if timestamp
441 * is found and has a correct size its value is retured in third call
442 * argument.
443 *
444 * returns:
445 * 0, on success
446 * -1, on property read failure
447 * -2, on wrong timestamp size
448 */
449int fit_get_timestamp(const void *fit, int noffset, time_t *timestamp)
450{
451 int len;
452 const void *data;
453
454 data = fdt_getprop(fit, noffset, FIT_TIMESTAMP_PROP, &len);
455 if (data == NULL) {
456 fit_get_debug(fit, noffset, FIT_TIMESTAMP_PROP, len);
457 return -1;
458 }
459 if (len != sizeof(uint32_t)) {
460 debug("FIT timestamp with incorrect size of (%u)\n", len);
461 return -2;
462 }
463
464 *timestamp = uimage_to_cpu(*((uint32_t *)data));
465 return 0;
466}
467
468/**
469 * fit_image_get_node - get node offset for component image of a given unit name
470 * @fit: pointer to the FIT format image header
471 * @image_uname: component image node unit name
472 *
473 * fit_image_get_node() finds a component image (withing the '/images'
474 * node) of a provided unit name. If image is found its node offset is
475 * returned to the caller.
476 *
477 * returns:
478 * image node offset when found (>=0)
479 * negative number on failure (FDT_ERR_* code)
480 */
481int fit_image_get_node(const void *fit, const char *image_uname)
482{
483 int noffset, images_noffset;
484
485 images_noffset = fdt_path_offset(fit, FIT_IMAGES_PATH);
486 if (images_noffset < 0) {
487 debug("Can't find images parent node '%s' (%s)\n",
488 FIT_IMAGES_PATH, fdt_strerror(images_noffset));
489 return images_noffset;
490 }
491
492 noffset = fdt_subnode_offset(fit, images_noffset, image_uname);
493 if (noffset < 0) {
494 debug("Can't get node offset for image unit name: '%s' (%s)\n",
495 image_uname, fdt_strerror(noffset));
496 }
497
498 return noffset;
499}
500
501/**
502 * fit_image_get_os - get os id for a given component image node
503 * @fit: pointer to the FIT format image header
504 * @noffset: component image node offset
505 * @os: pointer to the uint8_t, will hold os numeric id
506 *
507 * fit_image_get_os() finds os property in a given component image node.
508 * If the property is found, its (string) value is translated to the numeric
509 * id which is returned to the caller.
510 *
511 * returns:
512 * 0, on success
513 * -1, on failure
514 */
515int fit_image_get_os(const void *fit, int noffset, uint8_t *os)
516{
517 int len;
518 const void *data;
519
520 /* Get OS name from property data */
521 data = fdt_getprop(fit, noffset, FIT_OS_PROP, &len);
522 if (data == NULL) {
523 fit_get_debug(fit, noffset, FIT_OS_PROP, len);
524 *os = -1;
525 return -1;
526 }
527
528 /* Translate OS name to id */
529 *os = genimg_get_os_id(data);
530 return 0;
531}
532
533/**
534 * fit_image_get_arch - get arch id for a given component image node
535 * @fit: pointer to the FIT format image header
536 * @noffset: component image node offset
537 * @arch: pointer to the uint8_t, will hold arch numeric id
538 *
539 * fit_image_get_arch() finds arch property in a given component image node.
540 * If the property is found, its (string) value is translated to the numeric
541 * id which is returned to the caller.
542 *
543 * returns:
544 * 0, on success
545 * -1, on failure
546 */
547int fit_image_get_arch(const void *fit, int noffset, uint8_t *arch)
548{
549 int len;
550 const void *data;
551
552 /* Get architecture name from property data */
553 data = fdt_getprop(fit, noffset, FIT_ARCH_PROP, &len);
554 if (data == NULL) {
555 fit_get_debug(fit, noffset, FIT_ARCH_PROP, len);
556 *arch = -1;
557 return -1;
558 }
559
560 /* Translate architecture name to id */
561 *arch = genimg_get_arch_id(data);
562 return 0;
563}
564
565/**
566 * fit_image_get_type - get type id for a given component image node
567 * @fit: pointer to the FIT format image header
568 * @noffset: component image node offset
569 * @type: pointer to the uint8_t, will hold type numeric id
570 *
571 * fit_image_get_type() finds type property in a given component image node.
572 * If the property is found, its (string) value is translated to the numeric
573 * id which is returned to the caller.
574 *
575 * returns:
576 * 0, on success
577 * -1, on failure
578 */
579int fit_image_get_type(const void *fit, int noffset, uint8_t *type)
580{
581 int len;
582 const void *data;
583
584 /* Get image type name from property data */
585 data = fdt_getprop(fit, noffset, FIT_TYPE_PROP, &len);
586 if (data == NULL) {
587 fit_get_debug(fit, noffset, FIT_TYPE_PROP, len);
588 *type = -1;
589 return -1;
590 }
591
592 /* Translate image type name to id */
593 *type = genimg_get_type_id(data);
594 return 0;
595}
596
597/**
598 * fit_image_get_comp - get comp id for a given component image node
599 * @fit: pointer to the FIT format image header
600 * @noffset: component image node offset
601 * @comp: pointer to the uint8_t, will hold comp numeric id
602 *
603 * fit_image_get_comp() finds comp property in a given component image node.
604 * If the property is found, its (string) value is translated to the numeric
605 * id which is returned to the caller.
606 *
607 * returns:
608 * 0, on success
609 * -1, on failure
610 */
611int fit_image_get_comp(const void *fit, int noffset, uint8_t *comp)
612{
613 int len;
614 const void *data;
615
616 /* Get compression name from property data */
617 data = fdt_getprop(fit, noffset, FIT_COMP_PROP, &len);
618 if (data == NULL) {
619 fit_get_debug(fit, noffset, FIT_COMP_PROP, len);
620 *comp = -1;
621 return -1;
622 }
623
624 /* Translate compression name to id */
625 *comp = genimg_get_comp_id(data);
626 return 0;
627}
628
629/**
630 * fit_image_get_load() - get load addr property for given component image node
631 * @fit: pointer to the FIT format image header
632 * @noffset: component image node offset
633 * @load: pointer to the uint32_t, will hold load address
634 *
635 * fit_image_get_load() finds load address property in a given component
636 * image node. If the property is found, its value is returned to the caller.
637 *
638 * returns:
639 * 0, on success
640 * -1, on failure
641 */
642int fit_image_get_load(const void *fit, int noffset, ulong *load)
643{
644 int len;
645 const uint32_t *data;
646
647 data = fdt_getprop(fit, noffset, FIT_LOAD_PROP, &len);
648 if (data == NULL) {
649 fit_get_debug(fit, noffset, FIT_LOAD_PROP, len);
650 return -1;
651 }
652
653 *load = uimage_to_cpu(*data);
654 return 0;
655}
656
657/**
658 * fit_image_get_entry() - get entry point address property
659 * @fit: pointer to the FIT format image header
660 * @noffset: component image node offset
661 * @entry: pointer to the uint32_t, will hold entry point address
662 *
663 * This gets the entry point address property for a given component image
664 * node.
665 *
666 * fit_image_get_entry() finds entry point address property in a given
667 * component image node. If the property is found, its value is returned
668 * to the caller.
669 *
670 * returns:
671 * 0, on success
672 * -1, on failure
673 */
674int fit_image_get_entry(const void *fit, int noffset, ulong *entry)
675{
676 int len;
677 const uint32_t *data;
678
679 data = fdt_getprop(fit, noffset, FIT_ENTRY_PROP, &len);
680 if (data == NULL) {
681 fit_get_debug(fit, noffset, FIT_ENTRY_PROP, len);
682 return -1;
683 }
684
685 *entry = uimage_to_cpu(*data);
686 return 0;
687}
688
689/**
690 * fit_image_get_data - get data property and its size for a given component image node
691 * @fit: pointer to the FIT format image header
692 * @noffset: component image node offset
693 * @data: double pointer to void, will hold data property's data address
694 * @size: pointer to size_t, will hold data property's data size
695 *
696 * fit_image_get_data() finds data property in a given component image node.
697 * If the property is found its data start address and size are returned to
698 * the caller.
699 *
700 * returns:
701 * 0, on success
702 * -1, on failure
703 */
704int fit_image_get_data(const void *fit, int noffset,
705 const void **data, size_t *size)
706{
707 int len;
708
709 *data = fdt_getprop(fit, noffset, FIT_DATA_PROP, &len);
710 if (*data == NULL) {
711 fit_get_debug(fit, noffset, FIT_DATA_PROP, len);
712 *size = 0;
713 return -1;
714 }
715
716 *size = len;
717 return 0;
718}
719
720/**
721 * fit_image_hash_get_algo - get hash algorithm name
722 * @fit: pointer to the FIT format image header
723 * @noffset: hash node offset
724 * @algo: double pointer to char, will hold pointer to the algorithm name
725 *
726 * fit_image_hash_get_algo() finds hash algorithm property in a given hash node.
727 * If the property is found its data start address is returned to the caller.
728 *
729 * returns:
730 * 0, on success
731 * -1, on failure
732 */
733int fit_image_hash_get_algo(const void *fit, int noffset, char **algo)
734{
735 int len;
736
737 *algo = (char *)fdt_getprop(fit, noffset, FIT_ALGO_PROP, &len);
738 if (*algo == NULL) {
739 fit_get_debug(fit, noffset, FIT_ALGO_PROP, len);
740 return -1;
741 }
742
743 return 0;
744}
745
746/**
747 * fit_image_hash_get_value - get hash value and length
748 * @fit: pointer to the FIT format image header
749 * @noffset: hash node offset
750 * @value: double pointer to uint8_t, will hold address of a hash value data
751 * @value_len: pointer to an int, will hold hash data length
752 *
753 * fit_image_hash_get_value() finds hash value property in a given hash node.
754 * If the property is found its data start address and size are returned to
755 * the caller.
756 *
757 * returns:
758 * 0, on success
759 * -1, on failure
760 */
761int fit_image_hash_get_value(const void *fit, int noffset, uint8_t **value,
762 int *value_len)
763{
764 int len;
765
766 *value = (uint8_t *)fdt_getprop(fit, noffset, FIT_VALUE_PROP, &len);
767 if (*value == NULL) {
768 fit_get_debug(fit, noffset, FIT_VALUE_PROP, len);
769 *value_len = 0;
770 return -1;
771 }
772
773 *value_len = len;
774 return 0;
775}
776
Simon Glassda0af362013-05-07 06:11:53 +0000777/**
778 * fit_image_hash_get_ignore - get hash ignore flag
779 * @fit: pointer to the FIT format image header
780 * @noffset: hash node offset
781 * @ignore: pointer to an int, will hold hash ignore flag
782 *
783 * fit_image_hash_get_ignore() finds hash ignore property in a given hash node.
784 * If the property is found and non-zero, the hash algorithm is not verified by
785 * u-boot automatically.
786 *
787 * returns:
788 * 0, on ignore not found
789 * value, on ignore found
790 */
Simon Glassf0fd5112013-05-07 06:11:58 +0000791static int fit_image_hash_get_ignore(const void *fit, int noffset, int *ignore)
Simon Glassda0af362013-05-07 06:11:53 +0000792{
793 int len;
794 int *value;
795
796 value = (int *)fdt_getprop(fit, noffset, FIT_IGNORE_PROP, &len);
797 if (value == NULL || len != sizeof(int))
798 *ignore = 0;
799 else
800 *ignore = *value;
801
802 return 0;
803}
Simon Glassda0af362013-05-07 06:11:53 +0000804
805/**
806 * fit_set_timestamp - set node timestamp property
807 * @fit: pointer to the FIT format image header
808 * @noffset: node offset
809 * @timestamp: timestamp value to be set
810 *
811 * fit_set_timestamp() attempts to set timestamp property in the requested
812 * node and returns operation status to the caller.
813 *
814 * returns:
815 * 0, on success
816 * -1, on property read failure
817 */
818int fit_set_timestamp(void *fit, int noffset, time_t timestamp)
819{
820 uint32_t t;
821 int ret;
822
823 t = cpu_to_uimage(timestamp);
824 ret = fdt_setprop(fit, noffset, FIT_TIMESTAMP_PROP, &t,
825 sizeof(uint32_t));
826 if (ret) {
827 printf("Can't set '%s' property for '%s' node (%s)\n",
828 FIT_TIMESTAMP_PROP, fit_get_name(fit, noffset, NULL),
829 fdt_strerror(ret));
830 return -1;
831 }
832
833 return 0;
834}
835
836/**
837 * calculate_hash - calculate and return hash for provided input data
838 * @data: pointer to the input data
839 * @data_len: data length
840 * @algo: requested hash algorithm
841 * @value: pointer to the char, will hold hash value data (caller must
842 * allocate enough free space)
843 * value_len: length of the calculated hash
844 *
845 * calculate_hash() computes input data hash according to the requested
846 * algorithm.
847 * Resulting hash value is placed in caller provided 'value' buffer, length
848 * of the calculated hash is returned via value_len pointer argument.
849 *
850 * returns:
851 * 0, on success
852 * -1, when algo is unsupported
853 */
Simon Glass10a1eca2013-05-07 06:11:54 +0000854int calculate_hash(const void *data, int data_len, const char *algo,
Simon Glassda0af362013-05-07 06:11:53 +0000855 uint8_t *value, int *value_len)
856{
Simon Glass82d94532013-05-08 08:05:59 +0000857 if (IMAGE_ENABLE_CRC32 && strcmp(algo, "crc32") == 0) {
Simon Glassda0af362013-05-07 06:11:53 +0000858 *((uint32_t *)value) = crc32_wd(0, data, data_len,
859 CHUNKSZ_CRC32);
860 *((uint32_t *)value) = cpu_to_uimage(*((uint32_t *)value));
861 *value_len = 4;
Simon Glass82d94532013-05-08 08:05:59 +0000862 } else if (IMAGE_ENABLE_SHA1 && strcmp(algo, "sha1") == 0) {
Simon Glassda0af362013-05-07 06:11:53 +0000863 sha1_csum_wd((unsigned char *)data, data_len,
864 (unsigned char *)value, CHUNKSZ_SHA1);
865 *value_len = 20;
Simon Glass82d94532013-05-08 08:05:59 +0000866 } else if (IMAGE_ENABLE_MD5 && strcmp(algo, "md5") == 0) {
Simon Glassda0af362013-05-07 06:11:53 +0000867 md5_wd((unsigned char *)data, data_len, value, CHUNKSZ_MD5);
868 *value_len = 16;
869 } else {
870 debug("Unsupported hash alogrithm\n");
871 return -1;
872 }
873 return 0;
874}
875
Simon Glassf0fd5112013-05-07 06:11:58 +0000876static int fit_image_check_hash(const void *fit, int noffset, const void *data,
877 size_t size, char **err_msgp)
878{
879 uint8_t value[FIT_MAX_HASH_LEN];
880 int value_len;
881 char *algo;
882 uint8_t *fit_value;
883 int fit_value_len;
884 int ignore;
885
886 *err_msgp = NULL;
887
888 if (fit_image_hash_get_algo(fit, noffset, &algo)) {
Simon Glass8f3aa462013-05-07 06:11:59 +0000889 *err_msgp = "Can't get hash algo property";
Simon Glassf0fd5112013-05-07 06:11:58 +0000890 return -1;
891 }
892 printf("%s", algo);
893
894 if (IMAGE_ENABLE_IGNORE) {
895 fit_image_hash_get_ignore(fit, noffset, &ignore);
896 if (ignore) {
897 printf("-skipped ");
898 return 0;
899 }
900 }
901
902 if (fit_image_hash_get_value(fit, noffset, &fit_value,
903 &fit_value_len)) {
Simon Glass8f3aa462013-05-07 06:11:59 +0000904 *err_msgp = "Can't get hash value property";
Simon Glassf0fd5112013-05-07 06:11:58 +0000905 return -1;
906 }
907
908 if (calculate_hash(data, size, algo, value, &value_len)) {
Simon Glass8f3aa462013-05-07 06:11:59 +0000909 *err_msgp = "Unsupported hash algorithm";
Simon Glassf0fd5112013-05-07 06:11:58 +0000910 return -1;
911 }
912
913 if (value_len != fit_value_len) {
Simon Glass8f3aa462013-05-07 06:11:59 +0000914 *err_msgp = "Bad hash value len";
Simon Glassf0fd5112013-05-07 06:11:58 +0000915 return -1;
916 } else if (memcmp(value, fit_value, value_len) != 0) {
Simon Glass8f3aa462013-05-07 06:11:59 +0000917 *err_msgp = "Bad hash value";
Simon Glassf0fd5112013-05-07 06:11:58 +0000918 return -1;
919 }
920
921 return 0;
922}
923
Simon Glassda0af362013-05-07 06:11:53 +0000924/**
Simon Glass7428ad12013-05-07 06:11:57 +0000925 * fit_image_verify - verify data intergity
Simon Glassda0af362013-05-07 06:11:53 +0000926 * @fit: pointer to the FIT format image header
927 * @image_noffset: component image node offset
928 *
Simon Glass7428ad12013-05-07 06:11:57 +0000929 * fit_image_verify() goes over component image hash nodes,
Simon Glassda0af362013-05-07 06:11:53 +0000930 * re-calculates each data hash and compares with the value stored in hash
931 * node.
932 *
933 * returns:
934 * 1, if all hashes are valid
935 * 0, otherwise (or on error)
936 */
Simon Glass7428ad12013-05-07 06:11:57 +0000937int fit_image_verify(const void *fit, int image_noffset)
Simon Glassda0af362013-05-07 06:11:53 +0000938{
939 const void *data;
940 size_t size;
Simon Glassda0af362013-05-07 06:11:53 +0000941 int noffset;
Simon Glassda0af362013-05-07 06:11:53 +0000942 char *err_msg = "";
943
944 /* Get image data and data length */
945 if (fit_image_get_data(fit, image_noffset, &data, &size)) {
Simon Glass8f3aa462013-05-07 06:11:59 +0000946 err_msg = "Can't get image data/size";
Simon Glassda0af362013-05-07 06:11:53 +0000947 return 0;
948 }
949
950 /* Process all hash subnodes of the component image node */
Simon Glassf0fd5112013-05-07 06:11:58 +0000951 for (noffset = fdt_first_subnode(fit, image_noffset);
952 noffset >= 0;
953 noffset = fdt_next_subnode(fit, noffset)) {
954 const char *name = fit_get_name(fit, noffset, NULL);
Simon Glassda0af362013-05-07 06:11:53 +0000955
Simon Glassf0fd5112013-05-07 06:11:58 +0000956 /*
957 * Check subnode name, must be equal to "hash".
958 * Multiple hash nodes require unique unit node
959 * names, e.g. hash@1, hash@2, etc.
960 */
961 if (!strncmp(name, FIT_HASH_NODENAME,
962 strlen(FIT_HASH_NODENAME))) {
963 if (fit_image_check_hash(fit, noffset, data, size,
964 &err_msg))
Simon Glassda0af362013-05-07 06:11:53 +0000965 goto error;
Simon Glassf0fd5112013-05-07 06:11:58 +0000966 puts("+ ");
Simon Glassda0af362013-05-07 06:11:53 +0000967 }
968 }
969
970 if (noffset == -FDT_ERR_TRUNCATED || noffset == -FDT_ERR_BADSTRUCTURE) {
Simon Glass8f3aa462013-05-07 06:11:59 +0000971 err_msg = "Corrupted or truncated tree";
Simon Glassda0af362013-05-07 06:11:53 +0000972 goto error;
973 }
974
975 return 1;
976
977error:
Simon Glass8f3aa462013-05-07 06:11:59 +0000978 printf(" error!\n%s for '%s' hash node in '%s' image node\n",
Simon Glassda0af362013-05-07 06:11:53 +0000979 err_msg, fit_get_name(fit, noffset, NULL),
980 fit_get_name(fit, image_noffset, NULL));
981 return 0;
982}
983
984/**
Simon Glass7428ad12013-05-07 06:11:57 +0000985 * fit_all_image_verify - verify data intergity for all images
Simon Glassda0af362013-05-07 06:11:53 +0000986 * @fit: pointer to the FIT format image header
987 *
Simon Glass7428ad12013-05-07 06:11:57 +0000988 * fit_all_image_verify() goes over all images in the FIT and
Simon Glassda0af362013-05-07 06:11:53 +0000989 * for every images checks if all it's hashes are valid.
990 *
991 * returns:
992 * 1, if all hashes of all images are valid
993 * 0, otherwise (or on error)
994 */
Simon Glass7428ad12013-05-07 06:11:57 +0000995int fit_all_image_verify(const void *fit)
Simon Glassda0af362013-05-07 06:11:53 +0000996{
997 int images_noffset;
998 int noffset;
999 int ndepth;
1000 int count;
1001
1002 /* Find images parent node offset */
1003 images_noffset = fdt_path_offset(fit, FIT_IMAGES_PATH);
1004 if (images_noffset < 0) {
1005 printf("Can't find images parent node '%s' (%s)\n",
1006 FIT_IMAGES_PATH, fdt_strerror(images_noffset));
1007 return 0;
1008 }
1009
1010 /* Process all image subnodes, check hashes for each */
1011 printf("## Checking hash(es) for FIT Image at %08lx ...\n",
1012 (ulong)fit);
1013 for (ndepth = 0, count = 0,
1014 noffset = fdt_next_node(fit, images_noffset, &ndepth);
1015 (noffset >= 0) && (ndepth > 0);
1016 noffset = fdt_next_node(fit, noffset, &ndepth)) {
1017 if (ndepth == 1) {
1018 /*
1019 * Direct child node of the images parent node,
1020 * i.e. component image node.
1021 */
1022 printf(" Hash(es) for Image %u (%s): ", count++,
1023 fit_get_name(fit, noffset, NULL));
1024
Simon Glass7428ad12013-05-07 06:11:57 +00001025 if (!fit_image_verify(fit, noffset))
Simon Glassda0af362013-05-07 06:11:53 +00001026 return 0;
1027 printf("\n");
1028 }
1029 }
1030 return 1;
1031}
1032
1033/**
1034 * fit_image_check_os - check whether image node is of a given os type
1035 * @fit: pointer to the FIT format image header
1036 * @noffset: component image node offset
1037 * @os: requested image os
1038 *
1039 * fit_image_check_os() reads image os property and compares its numeric
1040 * id with the requested os. Comparison result is returned to the caller.
1041 *
1042 * returns:
1043 * 1 if image is of given os type
1044 * 0 otherwise (or on error)
1045 */
1046int fit_image_check_os(const void *fit, int noffset, uint8_t os)
1047{
1048 uint8_t image_os;
1049
1050 if (fit_image_get_os(fit, noffset, &image_os))
1051 return 0;
1052 return (os == image_os);
1053}
1054
1055/**
1056 * fit_image_check_arch - check whether image node is of a given arch
1057 * @fit: pointer to the FIT format image header
1058 * @noffset: component image node offset
1059 * @arch: requested imagearch
1060 *
1061 * fit_image_check_arch() reads image arch property and compares its numeric
1062 * id with the requested arch. Comparison result is returned to the caller.
1063 *
1064 * returns:
1065 * 1 if image is of given arch
1066 * 0 otherwise (or on error)
1067 */
1068int fit_image_check_arch(const void *fit, int noffset, uint8_t arch)
1069{
1070 uint8_t image_arch;
1071
1072 if (fit_image_get_arch(fit, noffset, &image_arch))
1073 return 0;
1074 return (arch == image_arch);
1075}
1076
1077/**
1078 * fit_image_check_type - check whether image node is of a given type
1079 * @fit: pointer to the FIT format image header
1080 * @noffset: component image node offset
1081 * @type: requested image type
1082 *
1083 * fit_image_check_type() reads image type property and compares its numeric
1084 * id with the requested type. Comparison result is returned to the caller.
1085 *
1086 * returns:
1087 * 1 if image is of given type
1088 * 0 otherwise (or on error)
1089 */
1090int fit_image_check_type(const void *fit, int noffset, uint8_t type)
1091{
1092 uint8_t image_type;
1093
1094 if (fit_image_get_type(fit, noffset, &image_type))
1095 return 0;
1096 return (type == image_type);
1097}
1098
1099/**
1100 * fit_image_check_comp - check whether image node uses given compression
1101 * @fit: pointer to the FIT format image header
1102 * @noffset: component image node offset
1103 * @comp: requested image compression type
1104 *
1105 * fit_image_check_comp() reads image compression property and compares its
1106 * numeric id with the requested compression type. Comparison result is
1107 * returned to the caller.
1108 *
1109 * returns:
1110 * 1 if image uses requested compression
1111 * 0 otherwise (or on error)
1112 */
1113int fit_image_check_comp(const void *fit, int noffset, uint8_t comp)
1114{
1115 uint8_t image_comp;
1116
1117 if (fit_image_get_comp(fit, noffset, &image_comp))
1118 return 0;
1119 return (comp == image_comp);
1120}
1121
1122/**
1123 * fit_check_format - sanity check FIT image format
1124 * @fit: pointer to the FIT format image header
1125 *
1126 * fit_check_format() runs a basic sanity FIT image verification.
1127 * Routine checks for mandatory properties, nodes, etc.
1128 *
1129 * returns:
1130 * 1, on success
1131 * 0, on failure
1132 */
1133int fit_check_format(const void *fit)
1134{
1135 /* mandatory / node 'description' property */
1136 if (fdt_getprop(fit, 0, FIT_DESC_PROP, NULL) == NULL) {
1137 debug("Wrong FIT format: no description\n");
1138 return 0;
1139 }
1140
1141 if (IMAGE_ENABLE_TIMESTAMP) {
1142 /* mandatory / node 'timestamp' property */
1143 if (fdt_getprop(fit, 0, FIT_TIMESTAMP_PROP, NULL) == NULL) {
1144 debug("Wrong FIT format: no timestamp\n");
1145 return 0;
1146 }
1147 }
1148
1149 /* mandatory subimages parent '/images' node */
1150 if (fdt_path_offset(fit, FIT_IMAGES_PATH) < 0) {
1151 debug("Wrong FIT format: no images parent node\n");
1152 return 0;
1153 }
1154
1155 return 1;
1156}
1157
1158
1159/**
1160 * fit_conf_find_compat
1161 * @fit: pointer to the FIT format image header
1162 * @fdt: pointer to the device tree to compare against
1163 *
1164 * fit_conf_find_compat() attempts to find the configuration whose fdt is the
1165 * most compatible with the passed in device tree.
1166 *
1167 * Example:
1168 *
1169 * / o image-tree
1170 * |-o images
1171 * | |-o fdt@1
1172 * | |-o fdt@2
1173 * |
1174 * |-o configurations
1175 * |-o config@1
1176 * | |-fdt = fdt@1
1177 * |
1178 * |-o config@2
1179 * |-fdt = fdt@2
1180 *
1181 * / o U-Boot fdt
1182 * |-compatible = "foo,bar", "bim,bam"
1183 *
1184 * / o kernel fdt1
1185 * |-compatible = "foo,bar",
1186 *
1187 * / o kernel fdt2
1188 * |-compatible = "bim,bam", "baz,biz"
1189 *
1190 * Configuration 1 would be picked because the first string in U-Boot's
1191 * compatible list, "foo,bar", matches a compatible string in the root of fdt1.
1192 * "bim,bam" in fdt2 matches the second string which isn't as good as fdt1.
1193 *
1194 * returns:
1195 * offset to the configuration to use if one was found
1196 * -1 otherwise
1197 */
1198int fit_conf_find_compat(const void *fit, const void *fdt)
1199{
1200 int ndepth = 0;
1201 int noffset, confs_noffset, images_noffset;
1202 const void *fdt_compat;
1203 int fdt_compat_len;
1204 int best_match_offset = 0;
1205 int best_match_pos = 0;
1206
1207 confs_noffset = fdt_path_offset(fit, FIT_CONFS_PATH);
1208 images_noffset = fdt_path_offset(fit, FIT_IMAGES_PATH);
1209 if (confs_noffset < 0 || images_noffset < 0) {
1210 debug("Can't find configurations or images nodes.\n");
1211 return -1;
1212 }
1213
1214 fdt_compat = fdt_getprop(fdt, 0, "compatible", &fdt_compat_len);
1215 if (!fdt_compat) {
1216 debug("Fdt for comparison has no \"compatible\" property.\n");
1217 return -1;
1218 }
1219
1220 /*
1221 * Loop over the configurations in the FIT image.
1222 */
1223 for (noffset = fdt_next_node(fit, confs_noffset, &ndepth);
1224 (noffset >= 0) && (ndepth > 0);
1225 noffset = fdt_next_node(fit, noffset, &ndepth)) {
1226 const void *kfdt;
1227 const char *kfdt_name;
1228 int kfdt_noffset;
1229 const char *cur_fdt_compat;
1230 int len;
1231 size_t size;
1232 int i;
1233
1234 if (ndepth > 1)
1235 continue;
1236
1237 kfdt_name = fdt_getprop(fit, noffset, "fdt", &len);
1238 if (!kfdt_name) {
1239 debug("No fdt property found.\n");
1240 continue;
1241 }
1242 kfdt_noffset = fdt_subnode_offset(fit, images_noffset,
1243 kfdt_name);
1244 if (kfdt_noffset < 0) {
1245 debug("No image node named \"%s\" found.\n",
1246 kfdt_name);
1247 continue;
1248 }
1249 /*
1250 * Get a pointer to this configuration's fdt.
1251 */
1252 if (fit_image_get_data(fit, kfdt_noffset, &kfdt, &size)) {
1253 debug("Failed to get fdt \"%s\".\n", kfdt_name);
1254 continue;
1255 }
1256
1257 len = fdt_compat_len;
1258 cur_fdt_compat = fdt_compat;
1259 /*
1260 * Look for a match for each U-Boot compatibility string in
1261 * turn in this configuration's fdt.
1262 */
1263 for (i = 0; len > 0 &&
1264 (!best_match_offset || best_match_pos > i); i++) {
1265 int cur_len = strlen(cur_fdt_compat) + 1;
1266
1267 if (!fdt_node_check_compatible(kfdt, 0,
1268 cur_fdt_compat)) {
1269 best_match_offset = noffset;
1270 best_match_pos = i;
1271 break;
1272 }
1273 len -= cur_len;
1274 cur_fdt_compat += cur_len;
1275 }
1276 }
1277 if (!best_match_offset) {
1278 debug("No match found.\n");
1279 return -1;
1280 }
1281
1282 return best_match_offset;
1283}
1284
1285/**
1286 * fit_conf_get_node - get node offset for configuration of a given unit name
1287 * @fit: pointer to the FIT format image header
1288 * @conf_uname: configuration node unit name
1289 *
1290 * fit_conf_get_node() finds a configuration (withing the '/configurations'
1291 * parant node) of a provided unit name. If configuration is found its node
1292 * offset is returned to the caller.
1293 *
1294 * When NULL is provided in second argument fit_conf_get_node() will search
1295 * for a default configuration node instead. Default configuration node unit
1296 * name is retrived from FIT_DEFAULT_PROP property of the '/configurations'
1297 * node.
1298 *
1299 * returns:
1300 * configuration node offset when found (>=0)
1301 * negative number on failure (FDT_ERR_* code)
1302 */
1303int fit_conf_get_node(const void *fit, const char *conf_uname)
1304{
1305 int noffset, confs_noffset;
1306 int len;
1307
1308 confs_noffset = fdt_path_offset(fit, FIT_CONFS_PATH);
1309 if (confs_noffset < 0) {
1310 debug("Can't find configurations parent node '%s' (%s)\n",
1311 FIT_CONFS_PATH, fdt_strerror(confs_noffset));
1312 return confs_noffset;
1313 }
1314
1315 if (conf_uname == NULL) {
1316 /* get configuration unit name from the default property */
1317 debug("No configuration specified, trying default...\n");
1318 conf_uname = (char *)fdt_getprop(fit, confs_noffset,
1319 FIT_DEFAULT_PROP, &len);
1320 if (conf_uname == NULL) {
1321 fit_get_debug(fit, confs_noffset, FIT_DEFAULT_PROP,
1322 len);
1323 return len;
1324 }
1325 debug("Found default configuration: '%s'\n", conf_uname);
1326 }
1327
1328 noffset = fdt_subnode_offset(fit, confs_noffset, conf_uname);
1329 if (noffset < 0) {
1330 debug("Can't get node offset for configuration unit name: '%s' (%s)\n",
1331 conf_uname, fdt_strerror(noffset));
1332 }
1333
1334 return noffset;
1335}
1336
Simon Glassdc0f52c2013-05-07 06:12:00 +00001337int fit_conf_get_prop_node(const void *fit, int noffset,
Simon Glassda0af362013-05-07 06:11:53 +00001338 const char *prop_name)
1339{
1340 char *uname;
1341 int len;
1342
1343 /* get kernel image unit name from configuration kernel property */
1344 uname = (char *)fdt_getprop(fit, noffset, prop_name, &len);
1345 if (uname == NULL)
1346 return len;
1347
1348 return fit_image_get_node(fit, uname);
1349}
1350
1351/**
1352 * fit_conf_get_kernel_node - get kernel image node offset that corresponds to
1353 * a given configuration
1354 * @fit: pointer to the FIT format image header
1355 * @noffset: configuration node offset
1356 *
1357 * fit_conf_get_kernel_node() retrives kernel image node unit name from
1358 * configuration FIT_KERNEL_PROP property and translates it to the node
1359 * offset.
1360 *
1361 * returns:
1362 * image node offset when found (>=0)
1363 * negative number on failure (FDT_ERR_* code)
1364 */
1365int fit_conf_get_kernel_node(const void *fit, int noffset)
1366{
Simon Glassdc0f52c2013-05-07 06:12:00 +00001367 return fit_conf_get_prop_node(fit, noffset, FIT_KERNEL_PROP);
Simon Glassda0af362013-05-07 06:11:53 +00001368}
1369
1370/**
1371 * fit_conf_get_ramdisk_node - get ramdisk image node offset that corresponds to
1372 * a given configuration
1373 * @fit: pointer to the FIT format image header
1374 * @noffset: configuration node offset
1375 *
1376 * fit_conf_get_ramdisk_node() retrives ramdisk image node unit name from
1377 * configuration FIT_KERNEL_PROP property and translates it to the node
1378 * offset.
1379 *
1380 * returns:
1381 * image node offset when found (>=0)
1382 * negative number on failure (FDT_ERR_* code)
1383 */
1384int fit_conf_get_ramdisk_node(const void *fit, int noffset)
1385{
Simon Glassdc0f52c2013-05-07 06:12:00 +00001386 return fit_conf_get_prop_node(fit, noffset, FIT_RAMDISK_PROP);
Simon Glassda0af362013-05-07 06:11:53 +00001387}
1388
1389/**
1390 * fit_conf_get_fdt_node - get fdt image node offset that corresponds to
1391 * a given configuration
1392 * @fit: pointer to the FIT format image header
1393 * @noffset: configuration node offset
1394 *
1395 * fit_conf_get_fdt_node() retrives fdt image node unit name from
1396 * configuration FIT_KERNEL_PROP property and translates it to the node
1397 * offset.
1398 *
1399 * returns:
1400 * image node offset when found (>=0)
1401 * negative number on failure (FDT_ERR_* code)
1402 */
1403int fit_conf_get_fdt_node(const void *fit, int noffset)
1404{
Simon Glassdc0f52c2013-05-07 06:12:00 +00001405 return fit_conf_get_prop_node(fit, noffset, FIT_FDT_PROP);
Simon Glassda0af362013-05-07 06:11:53 +00001406}
1407
1408/**
1409 * fit_conf_print - prints out the FIT configuration details
1410 * @fit: pointer to the FIT format image header
1411 * @noffset: offset of the configuration node
1412 * @p: pointer to prefix string
1413 *
1414 * fit_conf_print() lists all mandatory properies for the processed
1415 * configuration node.
1416 *
1417 * returns:
1418 * no returned results
1419 */
1420void fit_conf_print(const void *fit, int noffset, const char *p)
1421{
1422 char *desc;
1423 char *uname;
1424 int ret;
1425
1426 /* Mandatory properties */
1427 ret = fit_get_desc(fit, noffset, &desc);
1428 printf("%s Description: ", p);
1429 if (ret)
1430 printf("unavailable\n");
1431 else
1432 printf("%s\n", desc);
1433
1434 uname = (char *)fdt_getprop(fit, noffset, FIT_KERNEL_PROP, NULL);
1435 printf("%s Kernel: ", p);
1436 if (uname == NULL)
1437 printf("unavailable\n");
1438 else
1439 printf("%s\n", uname);
1440
1441 /* Optional properties */
1442 uname = (char *)fdt_getprop(fit, noffset, FIT_RAMDISK_PROP, NULL);
1443 if (uname)
1444 printf("%s Init Ramdisk: %s\n", p, uname);
1445
1446 uname = (char *)fdt_getprop(fit, noffset, FIT_FDT_PROP, NULL);
1447 if (uname)
1448 printf("%s FDT: %s\n", p, uname);
1449}
1450
1451/**
1452 * fit_check_ramdisk - verify FIT format ramdisk subimage
1453 * @fit_hdr: pointer to the FIT ramdisk header
1454 * @rd_noffset: ramdisk subimage node offset within FIT image
1455 * @arch: requested ramdisk image architecture type
1456 * @verify: data CRC verification flag
1457 *
1458 * fit_check_ramdisk() verifies integrity of the ramdisk subimage and from
1459 * specified FIT image.
1460 *
1461 * returns:
1462 * 1, on success
1463 * 0, on failure
1464 */
Simon Glassda0af362013-05-07 06:11:53 +00001465int fit_check_ramdisk(const void *fit, int rd_noffset, uint8_t arch,
1466 int verify)
1467{
1468 fit_image_print(fit, rd_noffset, " ");
1469
1470 if (verify) {
1471 puts(" Verifying Hash Integrity ... ");
Simon Glass7428ad12013-05-07 06:11:57 +00001472 if (!fit_image_verify(fit, rd_noffset)) {
Simon Glassda0af362013-05-07 06:11:53 +00001473 puts("Bad Data Hash\n");
1474 bootstage_error(BOOTSTAGE_ID_FIT_RD_HASH);
1475 return 0;
1476 }
1477 puts("OK\n");
1478 }
1479
1480 bootstage_mark(BOOTSTAGE_ID_FIT_RD_CHECK_ALL);
1481 if (!fit_image_check_os(fit, rd_noffset, IH_OS_LINUX) ||
1482 !fit_image_check_arch(fit, rd_noffset, arch) ||
1483 !fit_image_check_type(fit, rd_noffset, IH_TYPE_RAMDISK)) {
1484 printf("No Linux %s Ramdisk Image\n",
1485 genimg_get_arch_name(arch));
1486 bootstage_error(BOOTSTAGE_ID_FIT_RD_CHECK_ALL);
1487 return 0;
1488 }
1489
1490 bootstage_mark(BOOTSTAGE_ID_FIT_RD_CHECK_ALL_OK);
1491 return 1;
1492}