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