blob: 9253f81fff5430e84eb4c5ec48eb9b2f4ff8c8de [file] [log] [blame]
Tom Rini10e47792018-05-06 17:58:06 -04001// SPDX-License-Identifier: GPL-2.0+
Simon Glassda0af362013-05-07 06:11:53 +00002/*
3 * Copyright (c) 2013, Google Inc.
4 *
5 * (C) Copyright 2008 Semihalf
6 *
7 * (C) Copyright 2000-2006
8 * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
Simon Glassda0af362013-05-07 06:11:53 +00009 */
10
Simon Glassd563c252021-02-15 17:08:09 -070011#define LOG_CATEGORY LOGC_BOOT
12
Simon Glassda0af362013-05-07 06:11:53 +000013#ifdef USE_HOSTCC
14#include "mkimage.h"
Simon Glassda0af362013-05-07 06:11:53 +000015#include <time.h>
Simon Glass2dc9c342020-05-10 11:40:01 -060016#include <linux/libfdt.h>
Simon Glass48b6c6b2019-11-14 12:57:16 -070017#include <u-boot/crc.h>
Tom Rini8fac3d42023-12-14 07:16:54 -050018#include <linux/kconfig.h>
Simon Glassda0af362013-05-07 06:11:53 +000019#else
Andreas Dannenberg67aaa6d2016-07-27 12:12:39 -050020#include <linux/compiler.h>
Marek Vasutf7d24612021-06-11 04:09:56 +020021#include <linux/sizes.h>
Simon Glass384d86d2013-05-16 13:53:21 +000022#include <errno.h>
Simon Glass0f2af882020-05-10 11:40:05 -060023#include <log.h>
Joe Hershberger65b905b2015-03-22 17:08:59 -050024#include <mapmem.h>
Simon Glass384d86d2013-05-16 13:53:21 +000025#include <asm/io.h>
Pantelis Antoniou6e51fb22017-09-04 23:12:16 +030026#include <malloc.h>
Sean Anderson615e31c2022-03-24 11:26:11 -040027#include <memalign.h>
Simon Glass3ba929a2020-10-30 21:38:53 -060028#include <asm/global_data.h>
Chia-Wei Wang4a733b32021-07-30 09:08:05 +080029#ifdef CONFIG_DM_HASH
30#include <dm.h>
31#include <u-boot/hash.h>
32#endif
Simon Glass384d86d2013-05-16 13:53:21 +000033DECLARE_GLOBAL_DATA_PTR;
Simon Glassda0af362013-05-07 06:11:53 +000034#endif /* !USE_HOSTCC*/
35
Julius Werner97b09cd2019-07-24 19:37:55 -070036#include <bootm.h>
Andreas Dannenberg67aaa6d2016-07-27 12:12:39 -050037#include <image.h>
Simon Glassda0af362013-05-07 06:11:53 +000038#include <bootstage.h>
Simon Glassda0af362013-05-07 06:11:53 +000039#include <u-boot/crc.h>
Simon Glassda0af362013-05-07 06:11:53 +000040
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)
Simon Glass3ff49ec2021-07-24 09:03:29 -060056 *addr = hextoul(spec, NULL);
Simon Glassda0af362013-05-07 06:11:53 +000057
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 *
Masahiro Yamada4ac739a2013-09-18 09:36:38 +090074 * fit_parse_conf() expects configuration spec in the form of [<addr>]#<conf>,
Simon Glassda0af362013-05-07 06:11:53 +000075 * 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 *
Masahiro Yamada4ac739a2013-09-18 09:36:38 +0900100 * fit_parse_subimage() expects subimage spec in the form of
Simon Glassda0af362013-05-07 06:11:53 +0000101 * [<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
Joel Stanleyc3baacd2020-12-08 14:42:14 +1030119#ifdef USE_HOSTCC
120/* Host tools use these implementations for Cipher and Signature support */
121static void *host_blob;
122
123void image_set_host_blob(void *blob)
124{
125 host_blob = blob;
126}
127
128void *image_get_host_blob(void)
129{
130 return host_blob;
131}
132#endif /* USE_HOSTCC */
133
Simon Glassda0af362013-05-07 06:11:53 +0000134static void fit_get_debug(const void *fit, int noffset,
135 char *prop_name, int err)
136{
137 debug("Can't get '%s' property from FIT 0x%08lx, node: offset %d, name %s (%s)\n",
138 prop_name, (ulong)fit, noffset, fit_get_name(fit, noffset, NULL),
139 fdt_strerror(err));
140}
141
Guilherme Maciel Ferreira3c46bcd2015-01-15 02:54:42 -0200142/**
143 * fit_get_subimage_count - get component (sub-image) count
144 * @fit: pointer to the FIT format image header
145 * @images_noffset: offset of images node
146 *
147 * returns:
148 * number of image components
149 */
150int fit_get_subimage_count(const void *fit, int images_noffset)
151{
152 int noffset;
153 int ndepth;
154 int count = 0;
155
156 /* Process its subnodes, print out component images details */
157 for (ndepth = 0, count = 0,
158 noffset = fdt_next_node(fit, images_noffset, &ndepth);
159 (noffset >= 0) && (ndepth > 0);
160 noffset = fdt_next_node(fit, noffset, &ndepth)) {
161 if (ndepth == 1) {
162 count++;
163 }
164 }
165
166 return count;
167}
168
Simon Glassda0af362013-05-07 06:11:53 +0000169/**
Tom Rini7d77b662018-05-08 14:34:05 -0400170 * fit_image_print_data() - prints out the hash node details
171 * @fit: pointer to the FIT format image header
172 * @noffset: offset of the hash node
173 * @p: pointer to prefix string
174 * @type: Type of information to print ("hash" or "sign")
175 *
176 * fit_image_print_data() lists properties for the processed hash node
177 *
178 * This function avoid using puts() since it prints a newline on the host
179 * but does not in U-Boot.
180 *
181 * returns:
182 * no returned results
183 */
184static void fit_image_print_data(const void *fit, int noffset, const char *p,
185 const char *type)
186{
187 const char *keyname;
188 uint8_t *value;
189 int value_len;
Jan Kiszka27beec22022-01-14 10:21:17 +0100190 const char *algo;
Philippe Reynes12468352018-11-14 13:51:00 +0100191 const char *padding;
Simon Glassd7aabcc2020-03-18 11:44:06 -0600192 bool required;
Tom Rini7d77b662018-05-08 14:34:05 -0400193 int ret, i;
194
195 debug("%s %s node: '%s'\n", p, type,
196 fit_get_name(fit, noffset, NULL));
197 printf("%s %s algo: ", p, type);
198 if (fit_image_hash_get_algo(fit, noffset, &algo)) {
199 printf("invalid/unsupported\n");
200 return;
201 }
202 printf("%s", algo);
Simon Glassd7aabcc2020-03-18 11:44:06 -0600203 keyname = fdt_getprop(fit, noffset, FIT_KEY_HINT, NULL);
204 required = fdt_getprop(fit, noffset, FIT_KEY_REQUIRED, NULL) != NULL;
Tom Rini7d77b662018-05-08 14:34:05 -0400205 if (keyname)
206 printf(":%s", keyname);
207 if (required)
208 printf(" (required)");
209 printf("\n");
210
Philippe Reynes12468352018-11-14 13:51:00 +0100211 padding = fdt_getprop(fit, noffset, "padding", NULL);
212 if (padding)
213 printf("%s %s padding: %s\n", p, type, padding);
214
Tom Rini7d77b662018-05-08 14:34:05 -0400215 ret = fit_image_hash_get_value(fit, noffset, &value,
216 &value_len);
217 printf("%s %s value: ", p, type);
218 if (ret) {
219 printf("unavailable\n");
220 } else {
221 for (i = 0; i < value_len; i++)
222 printf("%02x", value[i]);
223 printf("\n");
224 }
225
226 debug("%s %s len: %d\n", p, type, value_len);
227
228 /* Signatures have a time stamp */
229 if (IMAGE_ENABLE_TIMESTAMP && keyname) {
230 time_t timestamp;
231
232 printf("%s Timestamp: ", p);
233 if (fit_get_timestamp(fit, noffset, &timestamp))
234 printf("unavailable\n");
235 else
236 genimg_print_time(timestamp);
237 }
238}
239
240/**
241 * fit_image_print_verification_data() - prints out the hash/signature details
242 * @fit: pointer to the FIT format image header
243 * @noffset: offset of the hash or signature node
244 * @p: pointer to prefix string
245 *
246 * This lists properties for the processed hash node
247 *
248 * returns:
249 * no returned results
250 */
251static void fit_image_print_verification_data(const void *fit, int noffset,
252 const char *p)
253{
254 const char *name;
255
256 /*
257 * Check subnode name, must be equal to "hash" or "signature".
258 * Multiple hash/signature nodes require unique unit node
259 * names, e.g. hash-1, hash-2, signature-1, signature-2, etc.
260 */
261 name = fit_get_name(fit, noffset, NULL);
262 if (!strncmp(name, FIT_HASH_NODENAME, strlen(FIT_HASH_NODENAME))) {
263 fit_image_print_data(fit, noffset, p, "Hash");
264 } else if (!strncmp(name, FIT_SIG_NODENAME,
265 strlen(FIT_SIG_NODENAME))) {
266 fit_image_print_data(fit, noffset, p, "Sign");
267 }
268}
269
270/**
271 * fit_conf_print - prints out the FIT configuration details
272 * @fit: pointer to the FIT format image header
273 * @noffset: offset of the configuration node
274 * @p: pointer to prefix string
275 *
276 * fit_conf_print() lists all mandatory properties for the processed
277 * configuration node.
278 *
279 * returns:
280 * no returned results
281 */
282static void fit_conf_print(const void *fit, int noffset, const char *p)
283{
284 char *desc;
285 const char *uname;
286 int ret;
287 int fdt_index, loadables_index;
288 int ndepth;
289
290 /* Mandatory properties */
291 ret = fit_get_desc(fit, noffset, &desc);
292 printf("%s Description: ", p);
293 if (ret)
294 printf("unavailable\n");
295 else
296 printf("%s\n", desc);
297
298 uname = fdt_getprop(fit, noffset, FIT_KERNEL_PROP, NULL);
299 printf("%s Kernel: ", p);
300 if (!uname)
301 printf("unavailable\n");
302 else
303 printf("%s\n", uname);
304
305 /* Optional properties */
306 uname = fdt_getprop(fit, noffset, FIT_RAMDISK_PROP, NULL);
307 if (uname)
308 printf("%s Init Ramdisk: %s\n", p, uname);
309
310 uname = fdt_getprop(fit, noffset, FIT_FIRMWARE_PROP, NULL);
311 if (uname)
312 printf("%s Firmware: %s\n", p, uname);
313
314 for (fdt_index = 0;
315 uname = fdt_stringlist_get(fit, noffset, FIT_FDT_PROP,
316 fdt_index, NULL), uname;
317 fdt_index++) {
318 if (fdt_index == 0)
319 printf("%s FDT: ", p);
320 else
321 printf("%s ", p);
322 printf("%s\n", uname);
323 }
324
325 uname = fdt_getprop(fit, noffset, FIT_FPGA_PROP, NULL);
326 if (uname)
327 printf("%s FPGA: %s\n", p, uname);
328
329 /* Print out all of the specified loadables */
330 for (loadables_index = 0;
331 uname = fdt_stringlist_get(fit, noffset, FIT_LOADABLE_PROP,
332 loadables_index, NULL), uname;
333 loadables_index++) {
334 if (loadables_index == 0) {
335 printf("%s Loadables: ", p);
336 } else {
337 printf("%s ", p);
338 }
339 printf("%s\n", uname);
340 }
341
342 /* Process all hash subnodes of the component configuration node */
343 for (ndepth = 0, noffset = fdt_next_node(fit, noffset, &ndepth);
344 (noffset >= 0) && (ndepth > 0);
345 noffset = fdt_next_node(fit, noffset, &ndepth)) {
346 if (ndepth == 1) {
347 /* Direct child node of the component configuration node */
348 fit_image_print_verification_data(fit, noffset, p);
349 }
350 }
351}
352
353/**
Simon Glassda0af362013-05-07 06:11:53 +0000354 * fit_print_contents - prints out the contents of the FIT format image
355 * @fit: pointer to the FIT format image header
356 * @p: pointer to prefix string
357 *
358 * fit_print_contents() formats a multi line FIT image contents description.
Andreas Dannenberg8ca5a902016-06-15 17:00:19 -0500359 * The routine prints out FIT image properties (root node level) followed by
Simon Glassda0af362013-05-07 06:11:53 +0000360 * the details of each component image.
361 *
362 * returns:
363 * no returned results
364 */
365void fit_print_contents(const void *fit)
366{
367 char *desc;
368 char *uname;
369 int images_noffset;
370 int confs_noffset;
371 int noffset;
372 int ndepth;
373 int count = 0;
374 int ret;
375 const char *p;
376 time_t timestamp;
377
Simon Glass800b6fb2021-09-25 19:43:34 -0600378 if (!CONFIG_IS_ENABLED(FIT_PRINT))
379 return;
380
Simon Glass1030f162013-05-08 08:05:58 +0000381 /* Indent string is defined in header image.h */
382 p = IMAGE_INDENT_STRING;
Simon Glassda0af362013-05-07 06:11:53 +0000383
384 /* Root node properties */
385 ret = fit_get_desc(fit, 0, &desc);
386 printf("%sFIT description: ", p);
387 if (ret)
388 printf("unavailable\n");
389 else
390 printf("%s\n", desc);
391
392 if (IMAGE_ENABLE_TIMESTAMP) {
393 ret = fit_get_timestamp(fit, 0, &timestamp);
394 printf("%sCreated: ", p);
395 if (ret)
396 printf("unavailable\n");
397 else
398 genimg_print_time(timestamp);
399 }
400
401 /* Find images parent node offset */
402 images_noffset = fdt_path_offset(fit, FIT_IMAGES_PATH);
403 if (images_noffset < 0) {
404 printf("Can't find images parent node '%s' (%s)\n",
405 FIT_IMAGES_PATH, fdt_strerror(images_noffset));
406 return;
407 }
408
409 /* Process its subnodes, print out component images details */
410 for (ndepth = 0, count = 0,
411 noffset = fdt_next_node(fit, images_noffset, &ndepth);
412 (noffset >= 0) && (ndepth > 0);
413 noffset = fdt_next_node(fit, noffset, &ndepth)) {
414 if (ndepth == 1) {
415 /*
416 * Direct child node of the images parent node,
417 * i.e. component image node.
418 */
419 printf("%s Image %u (%s)\n", p, count++,
420 fit_get_name(fit, noffset, NULL));
421
422 fit_image_print(fit, noffset, p);
423 }
424 }
425
426 /* Find configurations parent node offset */
427 confs_noffset = fdt_path_offset(fit, FIT_CONFS_PATH);
428 if (confs_noffset < 0) {
429 debug("Can't get configurations parent node '%s' (%s)\n",
430 FIT_CONFS_PATH, fdt_strerror(confs_noffset));
431 return;
432 }
433
434 /* get default configuration unit name from default property */
435 uname = (char *)fdt_getprop(fit, noffset, FIT_DEFAULT_PROP, NULL);
436 if (uname)
437 printf("%s Default Configuration: '%s'\n", p, uname);
438
439 /* Process its subnodes, print out configurations details */
440 for (ndepth = 0, count = 0,
441 noffset = fdt_next_node(fit, confs_noffset, &ndepth);
442 (noffset >= 0) && (ndepth > 0);
443 noffset = fdt_next_node(fit, noffset, &ndepth)) {
444 if (ndepth == 1) {
445 /*
446 * Direct child node of the configurations parent node,
447 * i.e. configuration node.
448 */
449 printf("%s Configuration %u (%s)\n", p, count++,
450 fit_get_name(fit, noffset, NULL));
451
452 fit_conf_print(fit, noffset, p);
453 }
454 }
455}
456
457/**
458 * fit_image_print - prints out the FIT component image details
459 * @fit: pointer to the FIT format image header
460 * @image_noffset: offset of the component image node
461 * @p: pointer to prefix string
462 *
Andreas Dannenberg8ca5a902016-06-15 17:00:19 -0500463 * fit_image_print() lists all mandatory properties for the processed component
Simon Glassda0af362013-05-07 06:11:53 +0000464 * image. If present, hash nodes are printed out as well. Load
465 * address for images of type firmware is also printed out. Since the load
466 * address is not mandatory for firmware images, it will be output as
467 * "unavailable" when not present.
468 *
469 * returns:
470 * no returned results
471 */
472void fit_image_print(const void *fit, int image_noffset, const char *p)
473{
474 char *desc;
Daniel Golle2ebfd222022-08-27 04:17:28 +0100475 uint8_t type, arch, os, comp = IH_COMP_NONE;
Simon Glassda0af362013-05-07 06:11:53 +0000476 size_t size;
477 ulong load, entry;
478 const void *data;
479 int noffset;
480 int ndepth;
481 int ret;
482
Simon Glass800b6fb2021-09-25 19:43:34 -0600483 if (!CONFIG_IS_ENABLED(FIT_PRINT))
484 return;
485
Simon Glassda0af362013-05-07 06:11:53 +0000486 /* Mandatory properties */
487 ret = fit_get_desc(fit, image_noffset, &desc);
488 printf("%s Description: ", p);
489 if (ret)
490 printf("unavailable\n");
491 else
492 printf("%s\n", desc);
493
Simon Glass749a6e72013-07-16 20:10:01 -0700494 if (IMAGE_ENABLE_TIMESTAMP) {
495 time_t timestamp;
496
497 ret = fit_get_timestamp(fit, 0, &timestamp);
498 printf("%s Created: ", p);
499 if (ret)
500 printf("unavailable\n");
501 else
502 genimg_print_time(timestamp);
503 }
504
Simon Glassda0af362013-05-07 06:11:53 +0000505 fit_image_get_type(fit, image_noffset, &type);
506 printf("%s Type: %s\n", p, genimg_get_type_name(type));
507
508 fit_image_get_comp(fit, image_noffset, &comp);
509 printf("%s Compression: %s\n", p, genimg_get_comp_name(comp));
510
Kelvin Cheung186cc992018-05-19 18:21:37 +0800511 ret = fit_image_get_data_and_size(fit, image_noffset, &data, &size);
Simon Glassda0af362013-05-07 06:11:53 +0000512
Simon Glassdb503fb2021-09-25 19:43:14 -0600513 if (!tools_build()) {
Sebastian Reichelbfe8ddf2021-01-04 20:48:03 +0100514 printf("%s Data Start: ", p);
515 if (ret) {
516 printf("unavailable\n");
517 } else {
518 void *vdata = (void *)data;
Simon Glasse8d6a5b2013-05-16 13:53:26 +0000519
Sebastian Reichelbfe8ddf2021-01-04 20:48:03 +0100520 printf("0x%08lx\n", (ulong)map_to_sysmem(vdata));
521 }
Simon Glasse8d6a5b2013-05-16 13:53:26 +0000522 }
Simon Glassda0af362013-05-07 06:11:53 +0000523
524 printf("%s Data Size: ", p);
525 if (ret)
526 printf("unavailable\n");
527 else
528 genimg_print_size(size);
529
530 /* Remaining, type dependent properties */
531 if ((type == IH_TYPE_KERNEL) || (type == IH_TYPE_STANDALONE) ||
532 (type == IH_TYPE_RAMDISK) || (type == IH_TYPE_FIRMWARE) ||
533 (type == IH_TYPE_FLATDT)) {
534 fit_image_get_arch(fit, image_noffset, &arch);
535 printf("%s Architecture: %s\n", p, genimg_get_arch_name(arch));
536 }
537
Michal Simek55f698f2018-03-26 16:31:27 +0200538 if ((type == IH_TYPE_KERNEL) || (type == IH_TYPE_RAMDISK) ||
539 (type == IH_TYPE_FIRMWARE)) {
Simon Glassda0af362013-05-07 06:11:53 +0000540 fit_image_get_os(fit, image_noffset, &os);
541 printf("%s OS: %s\n", p, genimg_get_os_name(os));
542 }
543
544 if ((type == IH_TYPE_KERNEL) || (type == IH_TYPE_STANDALONE) ||
Michal Simekebae78b2016-05-17 14:03:50 +0200545 (type == IH_TYPE_FIRMWARE) || (type == IH_TYPE_RAMDISK) ||
546 (type == IH_TYPE_FPGA)) {
Simon Glassda0af362013-05-07 06:11:53 +0000547 ret = fit_image_get_load(fit, image_noffset, &load);
548 printf("%s Load Address: ", p);
549 if (ret)
550 printf("unavailable\n");
551 else
552 printf("0x%08lx\n", load);
553 }
554
Pantelis Antoniou6e51fb22017-09-04 23:12:16 +0300555 /* optional load address for FDT */
556 if (type == IH_TYPE_FLATDT && !fit_image_get_load(fit, image_noffset, &load))
557 printf("%s Load Address: 0x%08lx\n", p, load);
558
Simon Glassda0af362013-05-07 06:11:53 +0000559 if ((type == IH_TYPE_KERNEL) || (type == IH_TYPE_STANDALONE) ||
560 (type == IH_TYPE_RAMDISK)) {
York Sun2b0464e2016-02-29 15:48:40 -0800561 ret = fit_image_get_entry(fit, image_noffset, &entry);
Simon Glassda0af362013-05-07 06:11:53 +0000562 printf("%s Entry Point: ", p);
563 if (ret)
564 printf("unavailable\n");
565 else
566 printf("0x%08lx\n", entry);
567 }
568
569 /* Process all hash subnodes of the component image node */
570 for (ndepth = 0, noffset = fdt_next_node(fit, image_noffset, &ndepth);
571 (noffset >= 0) && (ndepth > 0);
572 noffset = fdt_next_node(fit, noffset, &ndepth)) {
573 if (ndepth == 1) {
574 /* Direct child node of the component image node */
Simon Glasse61aa442013-05-07 06:12:02 +0000575 fit_image_print_verification_data(fit, noffset, p);
Simon Glassda0af362013-05-07 06:11:53 +0000576 }
577 }
Simon Glassda0af362013-05-07 06:11:53 +0000578}
579
580/**
581 * fit_get_desc - get node description property
582 * @fit: pointer to the FIT format image header
583 * @noffset: node offset
Andreas Dannenberg8ca5a902016-06-15 17:00:19 -0500584 * @desc: double pointer to the char, will hold pointer to the description
Simon Glassda0af362013-05-07 06:11:53 +0000585 *
586 * fit_get_desc() reads description property from a given node, if
Andreas Dannenberg8ca5a902016-06-15 17:00:19 -0500587 * description is found pointer to it is returned in third call argument.
Simon Glassda0af362013-05-07 06:11:53 +0000588 *
589 * returns:
590 * 0, on success
591 * -1, on failure
592 */
593int fit_get_desc(const void *fit, int noffset, char **desc)
594{
595 int len;
596
597 *desc = (char *)fdt_getprop(fit, noffset, FIT_DESC_PROP, &len);
598 if (*desc == NULL) {
599 fit_get_debug(fit, noffset, FIT_DESC_PROP, len);
600 return -1;
601 }
602
603 return 0;
604}
605
606/**
607 * fit_get_timestamp - get node timestamp property
608 * @fit: pointer to the FIT format image header
609 * @noffset: node offset
610 * @timestamp: pointer to the time_t, will hold read timestamp
611 *
Andreas Dannenberg8ca5a902016-06-15 17:00:19 -0500612 * fit_get_timestamp() reads timestamp property from given node, if timestamp
613 * is found and has a correct size its value is returned in third call
Simon Glassda0af362013-05-07 06:11:53 +0000614 * argument.
615 *
616 * returns:
617 * 0, on success
618 * -1, on property read failure
619 * -2, on wrong timestamp size
620 */
621int fit_get_timestamp(const void *fit, int noffset, time_t *timestamp)
622{
623 int len;
624 const void *data;
625
626 data = fdt_getprop(fit, noffset, FIT_TIMESTAMP_PROP, &len);
627 if (data == NULL) {
628 fit_get_debug(fit, noffset, FIT_TIMESTAMP_PROP, len);
629 return -1;
630 }
631 if (len != sizeof(uint32_t)) {
632 debug("FIT timestamp with incorrect size of (%u)\n", len);
633 return -2;
634 }
635
636 *timestamp = uimage_to_cpu(*((uint32_t *)data));
637 return 0;
638}
639
640/**
641 * fit_image_get_node - get node offset for component image of a given unit name
642 * @fit: pointer to the FIT format image header
643 * @image_uname: component image node unit name
644 *
Andreas Dannenberg8ca5a902016-06-15 17:00:19 -0500645 * fit_image_get_node() finds a component image (within the '/images'
Simon Glassda0af362013-05-07 06:11:53 +0000646 * node) of a provided unit name. If image is found its node offset is
647 * returned to the caller.
648 *
649 * returns:
650 * image node offset when found (>=0)
651 * negative number on failure (FDT_ERR_* code)
652 */
653int fit_image_get_node(const void *fit, const char *image_uname)
654{
655 int noffset, images_noffset;
656
657 images_noffset = fdt_path_offset(fit, FIT_IMAGES_PATH);
658 if (images_noffset < 0) {
659 debug("Can't find images parent node '%s' (%s)\n",
660 FIT_IMAGES_PATH, fdt_strerror(images_noffset));
661 return images_noffset;
662 }
663
664 noffset = fdt_subnode_offset(fit, images_noffset, image_uname);
665 if (noffset < 0) {
666 debug("Can't get node offset for image unit name: '%s' (%s)\n",
667 image_uname, fdt_strerror(noffset));
668 }
669
670 return noffset;
671}
672
673/**
674 * fit_image_get_os - get os id for a given component image node
675 * @fit: pointer to the FIT format image header
676 * @noffset: component image node offset
677 * @os: pointer to the uint8_t, will hold os numeric id
678 *
679 * fit_image_get_os() finds os property in a given component image node.
680 * If the property is found, its (string) value is translated to the numeric
681 * id which is returned to the caller.
682 *
683 * returns:
684 * 0, on success
685 * -1, on failure
686 */
687int fit_image_get_os(const void *fit, int noffset, uint8_t *os)
688{
689 int len;
690 const void *data;
691
692 /* Get OS name from property data */
693 data = fdt_getprop(fit, noffset, FIT_OS_PROP, &len);
694 if (data == NULL) {
695 fit_get_debug(fit, noffset, FIT_OS_PROP, len);
696 *os = -1;
697 return -1;
698 }
699
700 /* Translate OS name to id */
701 *os = genimg_get_os_id(data);
702 return 0;
703}
704
705/**
706 * fit_image_get_arch - get arch id for a given component image node
707 * @fit: pointer to the FIT format image header
708 * @noffset: component image node offset
709 * @arch: pointer to the uint8_t, will hold arch numeric id
710 *
711 * fit_image_get_arch() finds arch property in a given component image node.
712 * If the property is found, its (string) value is translated to the numeric
713 * id which is returned to the caller.
714 *
715 * returns:
716 * 0, on success
717 * -1, on failure
718 */
719int fit_image_get_arch(const void *fit, int noffset, uint8_t *arch)
720{
721 int len;
722 const void *data;
723
724 /* Get architecture name from property data */
725 data = fdt_getprop(fit, noffset, FIT_ARCH_PROP, &len);
726 if (data == NULL) {
727 fit_get_debug(fit, noffset, FIT_ARCH_PROP, len);
728 *arch = -1;
729 return -1;
730 }
731
732 /* Translate architecture name to id */
733 *arch = genimg_get_arch_id(data);
734 return 0;
735}
736
737/**
738 * fit_image_get_type - get type id for a given component image node
739 * @fit: pointer to the FIT format image header
740 * @noffset: component image node offset
741 * @type: pointer to the uint8_t, will hold type numeric id
742 *
743 * fit_image_get_type() finds type property in a given component image node.
744 * If the property is found, its (string) value is translated to the numeric
745 * id which is returned to the caller.
746 *
747 * returns:
748 * 0, on success
749 * -1, on failure
750 */
751int fit_image_get_type(const void *fit, int noffset, uint8_t *type)
752{
753 int len;
754 const void *data;
755
756 /* Get image type name from property data */
757 data = fdt_getprop(fit, noffset, FIT_TYPE_PROP, &len);
758 if (data == NULL) {
759 fit_get_debug(fit, noffset, FIT_TYPE_PROP, len);
760 *type = -1;
761 return -1;
762 }
763
764 /* Translate image type name to id */
765 *type = genimg_get_type_id(data);
766 return 0;
767}
768
769/**
770 * fit_image_get_comp - get comp id for a given component image node
771 * @fit: pointer to the FIT format image header
772 * @noffset: component image node offset
773 * @comp: pointer to the uint8_t, will hold comp numeric id
774 *
775 * fit_image_get_comp() finds comp property in a given component image node.
776 * If the property is found, its (string) value is translated to the numeric
777 * id which is returned to the caller.
778 *
779 * returns:
780 * 0, on success
781 * -1, on failure
782 */
783int fit_image_get_comp(const void *fit, int noffset, uint8_t *comp)
784{
785 int len;
786 const void *data;
787
788 /* Get compression name from property data */
789 data = fdt_getprop(fit, noffset, FIT_COMP_PROP, &len);
790 if (data == NULL) {
791 fit_get_debug(fit, noffset, FIT_COMP_PROP, len);
Simon Glassda0af362013-05-07 06:11:53 +0000792 return -1;
793 }
794
795 /* Translate compression name to id */
796 *comp = genimg_get_comp_id(data);
797 return 0;
798}
799
Simon Glassa42f11f2022-10-20 18:23:04 -0600800/**
801 * fit_image_get_phase() - get the phase for a configuration node
802 * @fit: pointer to the FIT format image header
803 * @offset: configuration-node offset
804 * @phasep: returns the phase
805 *
806 * Finds the phase property in a given configuration node. If the property is
807 * found, its (string) value is translated to the numeric id which is returned
808 * to the caller.
809 *
810 * Returns: 0 on success, -ENOENT if missing, -EINVAL for invalid value
811 */
812int fit_image_get_phase(const void *fit, int offset, enum image_phase_t *phasep)
813{
814 const void *data;
815 int len, ret;
816
817 /* Get phase name from property data */
818 data = fdt_getprop(fit, offset, FIT_PHASE_PROP, &len);
819 if (!data) {
820 fit_get_debug(fit, offset, FIT_PHASE_PROP, len);
821 *phasep = 0;
822 return -ENOENT;
823 }
824
825 /* Translate phase name to id */
826 ret = genimg_get_phase_id(data);
827 if (ret < 0)
828 return ret;
829 *phasep = ret;
830
831 return 0;
832}
833
York Sun2b0464e2016-02-29 15:48:40 -0800834static int fit_image_get_address(const void *fit, int noffset, char *name,
835 ulong *load)
836{
York Sun31e5add2016-02-29 15:48:41 -0800837 int len, cell_len;
838 const fdt32_t *cell;
839 uint64_t load64 = 0;
York Sun2b0464e2016-02-29 15:48:40 -0800840
York Sun31e5add2016-02-29 15:48:41 -0800841 cell = fdt_getprop(fit, noffset, name, &len);
842 if (cell == NULL) {
York Sun2b0464e2016-02-29 15:48:40 -0800843 fit_get_debug(fit, noffset, name, len);
844 return -1;
845 }
846
York Sun31e5add2016-02-29 15:48:41 -0800847 cell_len = len >> 2;
848 /* Use load64 to avoid compiling warning for 32-bit target */
849 while (cell_len--) {
850 load64 = (load64 << 32) | uimage_to_cpu(*cell);
851 cell++;
852 }
Michal Simekd31b40f2020-09-03 12:44:51 +0200853
854 if (len > sizeof(ulong) && (uint32_t)(load64 >> 32)) {
855 printf("Unsupported %s address size\n", name);
856 return -1;
857 }
858
York Sun31e5add2016-02-29 15:48:41 -0800859 *load = (ulong)load64;
York Sun2b0464e2016-02-29 15:48:40 -0800860
861 return 0;
862}
Simon Glassda0af362013-05-07 06:11:53 +0000863/**
864 * fit_image_get_load() - get load addr property for given component image node
865 * @fit: pointer to the FIT format image header
866 * @noffset: component image node offset
867 * @load: pointer to the uint32_t, will hold load address
868 *
869 * fit_image_get_load() finds load address property in a given component
870 * image node. If the property is found, its value is returned to the caller.
871 *
872 * returns:
873 * 0, on success
874 * -1, on failure
875 */
876int fit_image_get_load(const void *fit, int noffset, ulong *load)
877{
York Sun2b0464e2016-02-29 15:48:40 -0800878 return fit_image_get_address(fit, noffset, FIT_LOAD_PROP, load);
Simon Glassda0af362013-05-07 06:11:53 +0000879}
880
881/**
882 * fit_image_get_entry() - get entry point address property
883 * @fit: pointer to the FIT format image header
884 * @noffset: component image node offset
885 * @entry: pointer to the uint32_t, will hold entry point address
886 *
887 * This gets the entry point address property for a given component image
888 * node.
889 *
890 * fit_image_get_entry() finds entry point address property in a given
891 * component image node. If the property is found, its value is returned
892 * to the caller.
893 *
894 * returns:
895 * 0, on success
896 * -1, on failure
897 */
898int fit_image_get_entry(const void *fit, int noffset, ulong *entry)
899{
York Sun2b0464e2016-02-29 15:48:40 -0800900 return fit_image_get_address(fit, noffset, FIT_ENTRY_PROP, entry);
Simon Glassda0af362013-05-07 06:11:53 +0000901}
902
903/**
904 * fit_image_get_data - get data property and its size for a given component image node
905 * @fit: pointer to the FIT format image header
906 * @noffset: component image node offset
907 * @data: double pointer to void, will hold data property's data address
908 * @size: pointer to size_t, will hold data property's data size
909 *
910 * fit_image_get_data() finds data property in a given component image node.
911 * If the property is found its data start address and size are returned to
912 * the caller.
913 *
914 * returns:
915 * 0, on success
916 * -1, on failure
917 */
918int fit_image_get_data(const void *fit, int noffset,
919 const void **data, size_t *size)
920{
921 int len;
922
923 *data = fdt_getprop(fit, noffset, FIT_DATA_PROP, &len);
924 if (*data == NULL) {
925 fit_get_debug(fit, noffset, FIT_DATA_PROP, len);
926 *size = 0;
927 return -1;
928 }
929
930 *size = len;
931 return 0;
932}
933
934/**
tomas.melin@vaisala.com45ee7902017-01-13 13:20:14 +0200935 * Get 'data-offset' property from a given image node.
936 *
937 * @fit: pointer to the FIT image header
938 * @noffset: component image node offset
939 * @data_offset: holds the data-offset property
940 *
941 * returns:
942 * 0, on success
943 * -ENOENT if the property could not be found
944 */
945int fit_image_get_data_offset(const void *fit, int noffset, int *data_offset)
946{
947 const fdt32_t *val;
948
949 val = fdt_getprop(fit, noffset, FIT_DATA_OFFSET_PROP, NULL);
950 if (!val)
951 return -ENOENT;
952
953 *data_offset = fdt32_to_cpu(*val);
954
955 return 0;
956}
957
958/**
Peng Fan8876c7e2017-12-05 13:20:59 +0800959 * Get 'data-position' property from a given image node.
960 *
961 * @fit: pointer to the FIT image header
962 * @noffset: component image node offset
963 * @data_position: holds the data-position property
964 *
965 * returns:
966 * 0, on success
967 * -ENOENT if the property could not be found
968 */
969int fit_image_get_data_position(const void *fit, int noffset,
970 int *data_position)
971{
972 const fdt32_t *val;
973
974 val = fdt_getprop(fit, noffset, FIT_DATA_POSITION_PROP, NULL);
975 if (!val)
976 return -ENOENT;
977
978 *data_position = fdt32_to_cpu(*val);
979
980 return 0;
981}
982
983/**
tomas.melin@vaisala.com45ee7902017-01-13 13:20:14 +0200984 * Get 'data-size' property from a given image node.
985 *
986 * @fit: pointer to the FIT image header
987 * @noffset: component image node offset
988 * @data_size: holds the data-size property
989 *
990 * returns:
991 * 0, on success
992 * -ENOENT if the property could not be found
993 */
994int fit_image_get_data_size(const void *fit, int noffset, int *data_size)
995{
996 const fdt32_t *val;
997
998 val = fdt_getprop(fit, noffset, FIT_DATA_SIZE_PROP, NULL);
999 if (!val)
1000 return -ENOENT;
1001
1002 *data_size = fdt32_to_cpu(*val);
1003
1004 return 0;
1005}
1006
1007/**
Philippe Reynes3d964702019-12-18 18:25:42 +01001008 * Get 'data-size-unciphered' property from a given image node.
1009 *
1010 * @fit: pointer to the FIT image header
1011 * @noffset: component image node offset
1012 * @data_size: holds the data-size property
1013 *
1014 * returns:
1015 * 0, on success
1016 * -ENOENT if the property could not be found
1017 */
1018int fit_image_get_data_size_unciphered(const void *fit, int noffset,
1019 size_t *data_size)
1020{
1021 const fdt32_t *val;
1022
1023 val = fdt_getprop(fit, noffset, "data-size-unciphered", NULL);
1024 if (!val)
1025 return -ENOENT;
1026
1027 *data_size = (size_t)fdt32_to_cpu(*val);
1028
1029 return 0;
1030}
1031
1032/**
Kelvin Cheung186cc992018-05-19 18:21:37 +08001033 * fit_image_get_data_and_size - get data and its size including
1034 * both embedded and external data
1035 * @fit: pointer to the FIT format image header
1036 * @noffset: component image node offset
1037 * @data: double pointer to void, will hold data property's data address
1038 * @size: pointer to size_t, will hold data property's data size
1039 *
1040 * fit_image_get_data_and_size() finds data and its size including
1041 * both embedded and external data. If the property is found
1042 * its data start address and size are returned to the caller.
1043 *
1044 * returns:
1045 * 0, on success
1046 * otherwise, on failure
1047 */
1048int fit_image_get_data_and_size(const void *fit, int noffset,
1049 const void **data, size_t *size)
1050{
1051 bool external_data = false;
1052 int offset;
1053 int len;
1054 int ret;
1055
1056 if (!fit_image_get_data_position(fit, noffset, &offset)) {
1057 external_data = true;
1058 } else if (!fit_image_get_data_offset(fit, noffset, &offset)) {
1059 external_data = true;
1060 /*
1061 * For FIT with external data, figure out where
1062 * the external images start. This is the base
1063 * for the data-offset properties in each image.
1064 */
1065 offset += ((fdt_totalsize(fit) + 3) & ~3);
1066 }
1067
1068 if (external_data) {
1069 debug("External Data\n");
1070 ret = fit_image_get_data_size(fit, noffset, &len);
Heinrich Schuchardt0be986f2020-03-11 21:51:08 +01001071 if (!ret) {
1072 *data = fit + offset;
1073 *size = len;
1074 }
Kelvin Cheung186cc992018-05-19 18:21:37 +08001075 } else {
1076 ret = fit_image_get_data(fit, noffset, data, size);
1077 }
1078
1079 return ret;
1080}
1081
1082/**
Simon Glassda0af362013-05-07 06:11:53 +00001083 * fit_image_hash_get_algo - get hash algorithm name
1084 * @fit: pointer to the FIT format image header
1085 * @noffset: hash node offset
1086 * @algo: double pointer to char, will hold pointer to the algorithm name
1087 *
1088 * fit_image_hash_get_algo() finds hash algorithm property in a given hash node.
1089 * If the property is found its data start address is returned to the caller.
1090 *
1091 * returns:
1092 * 0, on success
1093 * -1, on failure
1094 */
Jan Kiszka27beec22022-01-14 10:21:17 +01001095int fit_image_hash_get_algo(const void *fit, int noffset, const char **algo)
Simon Glassda0af362013-05-07 06:11:53 +00001096{
1097 int len;
1098
Jan Kiszka27beec22022-01-14 10:21:17 +01001099 *algo = (const char *)fdt_getprop(fit, noffset, FIT_ALGO_PROP, &len);
Simon Glassda0af362013-05-07 06:11:53 +00001100 if (*algo == NULL) {
1101 fit_get_debug(fit, noffset, FIT_ALGO_PROP, len);
1102 return -1;
1103 }
1104
1105 return 0;
1106}
1107
1108/**
1109 * fit_image_hash_get_value - get hash value and length
1110 * @fit: pointer to the FIT format image header
1111 * @noffset: hash node offset
1112 * @value: double pointer to uint8_t, will hold address of a hash value data
1113 * @value_len: pointer to an int, will hold hash data length
1114 *
1115 * fit_image_hash_get_value() finds hash value property in a given hash node.
1116 * If the property is found its data start address and size are returned to
1117 * the caller.
1118 *
1119 * returns:
1120 * 0, on success
1121 * -1, on failure
1122 */
1123int fit_image_hash_get_value(const void *fit, int noffset, uint8_t **value,
1124 int *value_len)
1125{
1126 int len;
1127
1128 *value = (uint8_t *)fdt_getprop(fit, noffset, FIT_VALUE_PROP, &len);
1129 if (*value == NULL) {
1130 fit_get_debug(fit, noffset, FIT_VALUE_PROP, len);
1131 *value_len = 0;
1132 return -1;
1133 }
1134
1135 *value_len = len;
1136 return 0;
1137}
1138
Simon Glassda0af362013-05-07 06:11:53 +00001139/**
1140 * fit_image_hash_get_ignore - get hash ignore flag
1141 * @fit: pointer to the FIT format image header
1142 * @noffset: hash node offset
1143 * @ignore: pointer to an int, will hold hash ignore flag
1144 *
1145 * fit_image_hash_get_ignore() finds hash ignore property in a given hash node.
1146 * If the property is found and non-zero, the hash algorithm is not verified by
1147 * u-boot automatically.
1148 *
1149 * returns:
1150 * 0, on ignore not found
1151 * value, on ignore found
1152 */
Simon Glassf0fd5112013-05-07 06:11:58 +00001153static int fit_image_hash_get_ignore(const void *fit, int noffset, int *ignore)
Simon Glassda0af362013-05-07 06:11:53 +00001154{
1155 int len;
1156 int *value;
1157
1158 value = (int *)fdt_getprop(fit, noffset, FIT_IGNORE_PROP, &len);
1159 if (value == NULL || len != sizeof(int))
1160 *ignore = 0;
1161 else
1162 *ignore = *value;
1163
1164 return 0;
1165}
Simon Glassda0af362013-05-07 06:11:53 +00001166
Philippe Reynes3148e422019-12-18 18:25:41 +01001167/**
1168 * fit_image_cipher_get_algo - get cipher algorithm name
1169 * @fit: pointer to the FIT format image header
1170 * @noffset: cipher node offset
1171 * @algo: double pointer to char, will hold pointer to the algorithm name
1172 *
1173 * fit_image_cipher_get_algo() finds cipher algorithm property in a given
1174 * cipher node. If the property is found its data start address is returned
1175 * to the caller.
1176 *
1177 * returns:
1178 * 0, on success
1179 * -1, on failure
1180 */
1181int fit_image_cipher_get_algo(const void *fit, int noffset, char **algo)
1182{
1183 int len;
1184
1185 *algo = (char *)fdt_getprop(fit, noffset, FIT_ALGO_PROP, &len);
1186 if (!*algo) {
1187 fit_get_debug(fit, noffset, FIT_ALGO_PROP, len);
1188 return -1;
1189 }
1190
1191 return 0;
1192}
1193
Simon Glass5b539a02016-02-24 09:14:42 -07001194ulong fit_get_end(const void *fit)
1195{
1196 return map_to_sysmem((void *)(fit + fdt_totalsize(fit)));
1197}
1198
Simon Glassda0af362013-05-07 06:11:53 +00001199/**
1200 * fit_set_timestamp - set node timestamp property
1201 * @fit: pointer to the FIT format image header
1202 * @noffset: node offset
1203 * @timestamp: timestamp value to be set
1204 *
1205 * fit_set_timestamp() attempts to set timestamp property in the requested
1206 * node and returns operation status to the caller.
1207 *
1208 * returns:
1209 * 0, on success
Simon Glassaf2f9d52014-06-02 22:04:51 -06001210 * -ENOSPC if no space in device tree, -1 for other error
Simon Glassda0af362013-05-07 06:11:53 +00001211 */
1212int fit_set_timestamp(void *fit, int noffset, time_t timestamp)
1213{
1214 uint32_t t;
1215 int ret;
1216
1217 t = cpu_to_uimage(timestamp);
1218 ret = fdt_setprop(fit, noffset, FIT_TIMESTAMP_PROP, &t,
1219 sizeof(uint32_t));
1220 if (ret) {
Simon Glasse4016fa2016-05-01 13:55:37 -06001221 debug("Can't set '%s' property for '%s' node (%s)\n",
1222 FIT_TIMESTAMP_PROP, fit_get_name(fit, noffset, NULL),
1223 fdt_strerror(ret));
Simon Glassaf2f9d52014-06-02 22:04:51 -06001224 return ret == -FDT_ERR_NOSPACE ? -ENOSPC : -1;
Simon Glassda0af362013-05-07 06:11:53 +00001225 }
1226
1227 return 0;
1228}
1229
1230/**
1231 * calculate_hash - calculate and return hash for provided input data
1232 * @data: pointer to the input data
1233 * @data_len: data length
Chia-Wei Wang311c1f22021-10-27 14:17:24 +08001234 * @name: requested hash algorithm name
Simon Glassda0af362013-05-07 06:11:53 +00001235 * @value: pointer to the char, will hold hash value data (caller must
1236 * allocate enough free space)
1237 * value_len: length of the calculated hash
1238 *
1239 * calculate_hash() computes input data hash according to the requested
1240 * algorithm.
1241 * Resulting hash value is placed in caller provided 'value' buffer, length
1242 * of the calculated hash is returned via value_len pointer argument.
1243 *
1244 * returns:
1245 * 0, on success
1246 * -1, when algo is unsupported
1247 */
Alexandru Gagniuc650b7862021-09-02 19:54:21 -05001248int calculate_hash(const void *data, int data_len, const char *name,
Simon Glassda0af362013-05-07 06:11:53 +00001249 uint8_t *value, int *value_len)
1250{
Chia-Wei Wang4a733b32021-07-30 09:08:05 +08001251#if !defined(USE_HOSTCC) && defined(CONFIG_DM_HASH)
1252 int rc;
1253 enum HASH_ALGO hash_algo;
1254 struct udevice *dev;
1255
1256 rc = uclass_get_device(UCLASS_HASH, 0, &dev);
1257 if (rc) {
1258 debug("failed to get hash device, rc=%d\n", rc);
1259 return -1;
1260 }
1261
Chia-Wei Wang311c1f22021-10-27 14:17:24 +08001262 hash_algo = hash_algo_lookup_by_name(name);
Chia-Wei Wang4a733b32021-07-30 09:08:05 +08001263 if (hash_algo == HASH_ALGO_INVALID) {
1264 debug("Unsupported hash algorithm\n");
1265 return -1;
1266 };
1267
1268 rc = hash_digest_wd(dev, hash_algo, data, data_len, value, CHUNKSZ);
1269 if (rc) {
1270 debug("failed to get hash value, rc=%d\n", rc);
1271 return -1;
1272 }
1273
1274 *value_len = hash_algo_digest_size(hash_algo);
1275#else
Alexandru Gagniuc650b7862021-09-02 19:54:21 -05001276 struct hash_algo *algo;
1277 int ret;
1278
1279 ret = hash_lookup_algo(name, &algo);
1280 if (ret < 0) {
Simon Glassda0af362013-05-07 06:11:53 +00001281 debug("Unsupported hash alogrithm\n");
1282 return -1;
1283 }
Alexandru Gagniuc650b7862021-09-02 19:54:21 -05001284
1285 algo->hash_func_ws(data, data_len, value, algo->chunk_size);
1286 *value_len = algo->digest_size;
Chia-Wei Wang4a733b32021-07-30 09:08:05 +08001287#endif
Alexandru Gagniuc650b7862021-09-02 19:54:21 -05001288
Simon Glassda0af362013-05-07 06:11:53 +00001289 return 0;
1290}
1291
Simon Glassf0fd5112013-05-07 06:11:58 +00001292static int fit_image_check_hash(const void *fit, int noffset, const void *data,
1293 size_t size, char **err_msgp)
1294{
Joel Stanley447cc7a2022-06-20 16:31:17 +09301295 ALLOC_CACHE_ALIGN_BUFFER(uint8_t, value, FIT_MAX_HASH_LEN);
Simon Glassf0fd5112013-05-07 06:11:58 +00001296 int value_len;
Jan Kiszka27beec22022-01-14 10:21:17 +01001297 const char *algo;
Simon Glassf0fd5112013-05-07 06:11:58 +00001298 uint8_t *fit_value;
1299 int fit_value_len;
1300 int ignore;
1301
1302 *err_msgp = NULL;
1303
1304 if (fit_image_hash_get_algo(fit, noffset, &algo)) {
Simon Glass8f3aa462013-05-07 06:11:59 +00001305 *err_msgp = "Can't get hash algo property";
Simon Glassf0fd5112013-05-07 06:11:58 +00001306 return -1;
1307 }
1308 printf("%s", algo);
1309
Simon Glassa0cfb842021-09-25 19:43:28 -06001310 if (!tools_build()) {
Simon Glassf0fd5112013-05-07 06:11:58 +00001311 fit_image_hash_get_ignore(fit, noffset, &ignore);
1312 if (ignore) {
1313 printf("-skipped ");
1314 return 0;
1315 }
1316 }
1317
1318 if (fit_image_hash_get_value(fit, noffset, &fit_value,
1319 &fit_value_len)) {
Simon Glass8f3aa462013-05-07 06:11:59 +00001320 *err_msgp = "Can't get hash value property";
Simon Glassf0fd5112013-05-07 06:11:58 +00001321 return -1;
1322 }
1323
1324 if (calculate_hash(data, size, algo, value, &value_len)) {
Simon Glass8f3aa462013-05-07 06:11:59 +00001325 *err_msgp = "Unsupported hash algorithm";
Simon Glassf0fd5112013-05-07 06:11:58 +00001326 return -1;
1327 }
1328
1329 if (value_len != fit_value_len) {
Simon Glass8f3aa462013-05-07 06:11:59 +00001330 *err_msgp = "Bad hash value len";
Simon Glassf0fd5112013-05-07 06:11:58 +00001331 return -1;
1332 } else if (memcmp(value, fit_value, value_len) != 0) {
Simon Glass8f3aa462013-05-07 06:11:59 +00001333 *err_msgp = "Bad hash value";
Simon Glassf0fd5112013-05-07 06:11:58 +00001334 return -1;
1335 }
1336
1337 return 0;
1338}
1339
Jun Nieadf5d1c2018-02-27 16:55:58 +08001340int fit_image_verify_with_data(const void *fit, int image_noffset,
Simon Glasse10e2ee2021-11-12 12:28:10 -07001341 const void *key_blob, const void *data,
1342 size_t size)
Simon Glassda0af362013-05-07 06:11:53 +00001343{
Simon Glassfbabc0f2013-06-13 15:10:01 -07001344 int noffset = 0;
Simon Glassda0af362013-05-07 06:11:53 +00001345 char *err_msg = "";
Simon Glassfbabc0f2013-06-13 15:10:01 -07001346 int verify_all = 1;
1347 int ret;
Simon Glassda0af362013-05-07 06:11:53 +00001348
Simon Glassfbabc0f2013-06-13 15:10:01 -07001349 /* Verify all required signatures */
AKASHI Takahiro2223c7d2020-02-21 15:12:55 +09001350 if (FIT_IMAGE_ENABLE_VERIFY &&
Simon Glassfbabc0f2013-06-13 15:10:01 -07001351 fit_image_verify_required_sigs(fit, image_noffset, data, size,
Simon Glasse10e2ee2021-11-12 12:28:10 -07001352 key_blob, &verify_all)) {
Simon Glassfbabc0f2013-06-13 15:10:01 -07001353 err_msg = "Unable to verify required signature";
1354 goto error;
1355 }
1356
Simon Glassda0af362013-05-07 06:11:53 +00001357 /* Process all hash subnodes of the component image node */
Simon Glass499c29e2016-10-02 17:59:29 -06001358 fdt_for_each_subnode(noffset, fit, image_noffset) {
Simon Glassf0fd5112013-05-07 06:11:58 +00001359 const char *name = fit_get_name(fit, noffset, NULL);
Simon Glassda0af362013-05-07 06:11:53 +00001360
Simon Glassf0fd5112013-05-07 06:11:58 +00001361 /*
1362 * Check subnode name, must be equal to "hash".
1363 * Multiple hash nodes require unique unit node
Andre Przywara3234ecd2017-12-04 02:05:10 +00001364 * names, e.g. hash-1, hash-2, etc.
Simon Glassf0fd5112013-05-07 06:11:58 +00001365 */
1366 if (!strncmp(name, FIT_HASH_NODENAME,
1367 strlen(FIT_HASH_NODENAME))) {
1368 if (fit_image_check_hash(fit, noffset, data, size,
1369 &err_msg))
Simon Glassda0af362013-05-07 06:11:53 +00001370 goto error;
Simon Glassf0fd5112013-05-07 06:11:58 +00001371 puts("+ ");
AKASHI Takahiro2223c7d2020-02-21 15:12:55 +09001372 } else if (FIT_IMAGE_ENABLE_VERIFY && verify_all &&
Simon Glassfbabc0f2013-06-13 15:10:01 -07001373 !strncmp(name, FIT_SIG_NODENAME,
1374 strlen(FIT_SIG_NODENAME))) {
Simon Glasse10e2ee2021-11-12 12:28:10 -07001375 ret = fit_image_check_sig(fit, noffset, data, size,
1376 gd_fdt_blob(), -1, &err_msg);
Simon Glass51026aa2016-02-24 09:14:43 -07001377
1378 /*
1379 * Show an indication on failure, but do not return
1380 * an error. Only keys marked 'required' can cause
1381 * an image validation failure. See the call to
1382 * fit_image_verify_required_sigs() above.
1383 */
1384 if (ret)
Simon Glassfbabc0f2013-06-13 15:10:01 -07001385 puts("- ");
1386 else
1387 puts("+ ");
Simon Glassda0af362013-05-07 06:11:53 +00001388 }
1389 }
1390
1391 if (noffset == -FDT_ERR_TRUNCATED || noffset == -FDT_ERR_BADSTRUCTURE) {
Simon Glass8f3aa462013-05-07 06:11:59 +00001392 err_msg = "Corrupted or truncated tree";
Simon Glassda0af362013-05-07 06:11:53 +00001393 goto error;
1394 }
1395
1396 return 1;
1397
1398error:
Simon Glass8f3aa462013-05-07 06:11:59 +00001399 printf(" error!\n%s for '%s' hash node in '%s' image node\n",
Simon Glassda0af362013-05-07 06:11:53 +00001400 err_msg, fit_get_name(fit, noffset, NULL),
1401 fit_get_name(fit, image_noffset, NULL));
1402 return 0;
1403}
1404
1405/**
Jun Nieadf5d1c2018-02-27 16:55:58 +08001406 * fit_image_verify - verify data integrity
1407 * @fit: pointer to the FIT format image header
1408 * @image_noffset: component image node offset
1409 *
1410 * fit_image_verify() goes over component image hash nodes,
1411 * re-calculates each data hash and compares with the value stored in hash
1412 * node.
1413 *
1414 * returns:
1415 * 1, if all hashes are valid
1416 * 0, otherwise (or on error)
1417 */
1418int fit_image_verify(const void *fit, int image_noffset)
1419{
Simon Glass44338902021-02-15 17:08:06 -07001420 const char *name = fit_get_name(fit, image_noffset, NULL);
Jun Nieadf5d1c2018-02-27 16:55:58 +08001421 const void *data;
1422 size_t size;
Jun Nieadf5d1c2018-02-27 16:55:58 +08001423 char *err_msg = "";
1424
Simon Glass3d702182021-07-05 16:32:56 -06001425 if (IS_ENABLED(CONFIG_FIT_SIGNATURE) && strchr(name, '@')) {
Simon Glass44338902021-02-15 17:08:06 -07001426 /*
1427 * We don't support this since libfdt considers names with the
1428 * name root but different @ suffix to be equal
1429 */
1430 err_msg = "Node name contains @";
1431 goto err;
1432 }
Jun Nieadf5d1c2018-02-27 16:55:58 +08001433 /* Get image data and data length */
Kelvin Cheung186cc992018-05-19 18:21:37 +08001434 if (fit_image_get_data_and_size(fit, image_noffset, &data, &size)) {
Jun Nieadf5d1c2018-02-27 16:55:58 +08001435 err_msg = "Can't get image data/size";
Simon Glass44338902021-02-15 17:08:06 -07001436 goto err;
Jun Nieadf5d1c2018-02-27 16:55:58 +08001437 }
1438
Simon Glasse10e2ee2021-11-12 12:28:10 -07001439 return fit_image_verify_with_data(fit, image_noffset, gd_fdt_blob(),
1440 data, size);
Simon Glass44338902021-02-15 17:08:06 -07001441
1442err:
1443 printf("error!\n%s in '%s' image node\n", err_msg,
1444 fit_get_name(fit, image_noffset, NULL));
1445 return 0;
Jun Nieadf5d1c2018-02-27 16:55:58 +08001446}
1447
1448/**
Andreas Dannenberg8ca5a902016-06-15 17:00:19 -05001449 * fit_all_image_verify - verify data integrity for all images
Simon Glassda0af362013-05-07 06:11:53 +00001450 * @fit: pointer to the FIT format image header
1451 *
Simon Glass7428ad12013-05-07 06:11:57 +00001452 * fit_all_image_verify() goes over all images in the FIT and
Simon Glassda0af362013-05-07 06:11:53 +00001453 * for every images checks if all it's hashes are valid.
1454 *
1455 * returns:
1456 * 1, if all hashes of all images are valid
1457 * 0, otherwise (or on error)
1458 */
Simon Glass7428ad12013-05-07 06:11:57 +00001459int fit_all_image_verify(const void *fit)
Simon Glassda0af362013-05-07 06:11:53 +00001460{
1461 int images_noffset;
1462 int noffset;
1463 int ndepth;
1464 int count;
1465
1466 /* Find images parent node offset */
1467 images_noffset = fdt_path_offset(fit, FIT_IMAGES_PATH);
1468 if (images_noffset < 0) {
1469 printf("Can't find images parent node '%s' (%s)\n",
1470 FIT_IMAGES_PATH, fdt_strerror(images_noffset));
1471 return 0;
1472 }
1473
1474 /* Process all image subnodes, check hashes for each */
1475 printf("## Checking hash(es) for FIT Image at %08lx ...\n",
1476 (ulong)fit);
1477 for (ndepth = 0, count = 0,
1478 noffset = fdt_next_node(fit, images_noffset, &ndepth);
1479 (noffset >= 0) && (ndepth > 0);
1480 noffset = fdt_next_node(fit, noffset, &ndepth)) {
1481 if (ndepth == 1) {
1482 /*
1483 * Direct child node of the images parent node,
1484 * i.e. component image node.
1485 */
Simon Glasse3ee2fb2016-02-22 22:55:43 -07001486 printf(" Hash(es) for Image %u (%s): ", count,
Simon Glassda0af362013-05-07 06:11:53 +00001487 fit_get_name(fit, noffset, NULL));
Simon Glasse3ee2fb2016-02-22 22:55:43 -07001488 count++;
Simon Glassda0af362013-05-07 06:11:53 +00001489
Simon Glass7428ad12013-05-07 06:11:57 +00001490 if (!fit_image_verify(fit, noffset))
Simon Glassda0af362013-05-07 06:11:53 +00001491 return 0;
1492 printf("\n");
1493 }
1494 }
1495 return 1;
1496}
1497
Philippe Reynes3d964702019-12-18 18:25:42 +01001498static int fit_image_uncipher(const void *fit, int image_noffset,
1499 void **data, size_t *size)
1500{
1501 int cipher_noffset, ret;
1502 void *dst;
1503 size_t size_dst;
1504
1505 cipher_noffset = fdt_subnode_offset(fit, image_noffset,
1506 FIT_CIPHER_NODENAME);
1507 if (cipher_noffset < 0)
1508 return 0;
1509
1510 ret = fit_image_decrypt_data(fit, image_noffset, cipher_noffset,
1511 *data, *size, &dst, &size_dst);
1512 if (ret)
1513 goto out;
1514
1515 *data = dst;
1516 *size = size_dst;
1517
1518 out:
1519 return ret;
1520}
Philippe Reynes3d964702019-12-18 18:25:42 +01001521
Simon Glassda0af362013-05-07 06:11:53 +00001522/**
1523 * fit_image_check_os - check whether image node is of a given os type
1524 * @fit: pointer to the FIT format image header
1525 * @noffset: component image node offset
1526 * @os: requested image os
1527 *
1528 * fit_image_check_os() reads image os property and compares its numeric
1529 * id with the requested os. Comparison result is returned to the caller.
1530 *
1531 * returns:
1532 * 1 if image is of given os type
1533 * 0 otherwise (or on error)
1534 */
1535int fit_image_check_os(const void *fit, int noffset, uint8_t os)
1536{
1537 uint8_t image_os;
1538
1539 if (fit_image_get_os(fit, noffset, &image_os))
1540 return 0;
1541 return (os == image_os);
1542}
1543
1544/**
1545 * fit_image_check_arch - check whether image node is of a given arch
1546 * @fit: pointer to the FIT format image header
1547 * @noffset: component image node offset
1548 * @arch: requested imagearch
1549 *
1550 * fit_image_check_arch() reads image arch property and compares its numeric
1551 * id with the requested arch. Comparison result is returned to the caller.
1552 *
1553 * returns:
1554 * 1 if image is of given arch
1555 * 0 otherwise (or on error)
1556 */
1557int fit_image_check_arch(const void *fit, int noffset, uint8_t arch)
1558{
1559 uint8_t image_arch;
Alison Wang73818d52016-11-10 10:49:03 +08001560 int aarch32_support = 0;
1561
Simon Glass062e79f2021-03-15 18:11:12 +13001562 /* Let's assume that sandbox can load any architecture */
1563 if (IS_ENABLED(CONFIG_SANDBOX))
1564 return true;
1565
Sebastian Reichelbfe8ddf2021-01-04 20:48:03 +01001566 if (IS_ENABLED(CONFIG_ARM64_SUPPORT_AARCH32))
1567 aarch32_support = 1;
Simon Glassda0af362013-05-07 06:11:53 +00001568
1569 if (fit_image_get_arch(fit, noffset, &image_arch))
1570 return 0;
Simon Glass9d428302014-10-10 08:21:57 -06001571 return (arch == image_arch) ||
Alison Wang73818d52016-11-10 10:49:03 +08001572 (arch == IH_ARCH_I386 && image_arch == IH_ARCH_X86_64) ||
1573 (arch == IH_ARCH_ARM64 && image_arch == IH_ARCH_ARM &&
1574 aarch32_support);
Simon Glassda0af362013-05-07 06:11:53 +00001575}
1576
1577/**
1578 * fit_image_check_type - check whether image node is of a given type
1579 * @fit: pointer to the FIT format image header
1580 * @noffset: component image node offset
1581 * @type: requested image type
1582 *
1583 * fit_image_check_type() reads image type property and compares its numeric
1584 * id with the requested type. Comparison result is returned to the caller.
1585 *
1586 * returns:
1587 * 1 if image is of given type
1588 * 0 otherwise (or on error)
1589 */
1590int fit_image_check_type(const void *fit, int noffset, uint8_t type)
1591{
1592 uint8_t image_type;
1593
1594 if (fit_image_get_type(fit, noffset, &image_type))
1595 return 0;
1596 return (type == image_type);
1597}
1598
1599/**
1600 * fit_image_check_comp - check whether image node uses given compression
1601 * @fit: pointer to the FIT format image header
1602 * @noffset: component image node offset
1603 * @comp: requested image compression type
1604 *
1605 * fit_image_check_comp() reads image compression property and compares its
1606 * numeric id with the requested compression type. Comparison result is
1607 * returned to the caller.
1608 *
1609 * returns:
1610 * 1 if image uses requested compression
1611 * 0 otherwise (or on error)
1612 */
1613int fit_image_check_comp(const void *fit, int noffset, uint8_t comp)
1614{
1615 uint8_t image_comp;
1616
1617 if (fit_image_get_comp(fit, noffset, &image_comp))
1618 return 0;
1619 return (comp == image_comp);
1620}
1621
Simon Glassb823daa2021-02-15 17:08:12 -07001622/**
1623 * fdt_check_no_at() - Check for nodes whose names contain '@'
1624 *
1625 * This checks the parent node and all subnodes recursively
1626 *
1627 * @fit: FIT to check
1628 * @parent: Parent node to check
Heinrich Schuchardt47b4c022022-01-19 18:05:50 +01001629 * Return: 0 if OK, -EADDRNOTAVAIL is a node has a name containing '@'
Simon Glassb823daa2021-02-15 17:08:12 -07001630 */
1631static int fdt_check_no_at(const void *fit, int parent)
1632{
1633 const char *name;
1634 int node;
1635 int ret;
1636
1637 name = fdt_get_name(fit, parent, NULL);
1638 if (!name || strchr(name, '@'))
1639 return -EADDRNOTAVAIL;
1640
1641 fdt_for_each_subnode(node, fit, parent) {
1642 ret = fdt_check_no_at(fit, node);
1643 if (ret)
1644 return ret;
1645 }
1646
1647 return 0;
1648}
1649
Simon Glassd563c252021-02-15 17:08:09 -07001650int fit_check_format(const void *fit, ulong size)
Simon Glassda0af362013-05-07 06:11:53 +00001651{
Simon Glassd563c252021-02-15 17:08:09 -07001652 int ret;
1653
Heinrich Schuchardtef98b212021-01-13 02:09:12 +01001654 /* A FIT image must be a valid FDT */
Simon Glassd563c252021-02-15 17:08:09 -07001655 ret = fdt_check_header(fit);
1656 if (ret) {
1657 log_debug("Wrong FIT format: not a flattened device tree (err=%d)\n",
1658 ret);
1659 return -ENOEXEC;
Heinrich Schuchardtef98b212021-01-13 02:09:12 +01001660 }
1661
Simon Glass244705b2021-02-15 17:08:10 -07001662 if (CONFIG_IS_ENABLED(FIT_FULL_CHECK)) {
1663 /*
1664 * If we are not given the size, make do wtih calculating it.
1665 * This is not as secure, so we should consider a flag to
1666 * control this.
1667 */
1668 if (size == IMAGE_SIZE_INVAL)
1669 size = fdt_totalsize(fit);
1670 ret = fdt_check_full(fit, size);
Simon Glassb823daa2021-02-15 17:08:12 -07001671 if (ret)
1672 ret = -EINVAL;
1673
1674 /*
1675 * U-Boot stopped using unit addressed in 2017. Since libfdt
1676 * can match nodes ignoring any unit address, signature
1677 * verification can see the wrong node if one is inserted with
1678 * the same name as a valid node but with a unit address
1679 * attached. Protect against this by disallowing unit addresses.
1680 */
1681 if (!ret && CONFIG_IS_ENABLED(FIT_SIGNATURE)) {
1682 ret = fdt_check_no_at(fit, 0);
Simon Glass244705b2021-02-15 17:08:10 -07001683
Simon Glassb823daa2021-02-15 17:08:12 -07001684 if (ret) {
1685 log_debug("FIT check error %d\n", ret);
1686 return ret;
1687 }
1688 }
Simon Glass244705b2021-02-15 17:08:10 -07001689 if (ret) {
1690 log_debug("FIT check error %d\n", ret);
Simon Glassb823daa2021-02-15 17:08:12 -07001691 return ret;
Simon Glass244705b2021-02-15 17:08:10 -07001692 }
1693 }
1694
Simon Glassda0af362013-05-07 06:11:53 +00001695 /* mandatory / node 'description' property */
Simon Glassd563c252021-02-15 17:08:09 -07001696 if (!fdt_getprop(fit, 0, FIT_DESC_PROP, NULL)) {
1697 log_debug("Wrong FIT format: no description\n");
1698 return -ENOMSG;
Simon Glassda0af362013-05-07 06:11:53 +00001699 }
1700
1701 if (IMAGE_ENABLE_TIMESTAMP) {
1702 /* mandatory / node 'timestamp' property */
Simon Glassd563c252021-02-15 17:08:09 -07001703 if (!fdt_getprop(fit, 0, FIT_TIMESTAMP_PROP, NULL)) {
1704 log_debug("Wrong FIT format: no timestamp\n");
Simon Glassb641de82021-02-24 08:50:32 -05001705 return -EBADMSG;
Simon Glassda0af362013-05-07 06:11:53 +00001706 }
1707 }
1708
1709 /* mandatory subimages parent '/images' node */
1710 if (fdt_path_offset(fit, FIT_IMAGES_PATH) < 0) {
Simon Glassd563c252021-02-15 17:08:09 -07001711 log_debug("Wrong FIT format: no images parent node\n");
1712 return -ENOENT;
Simon Glassda0af362013-05-07 06:11:53 +00001713 }
1714
Simon Glassd563c252021-02-15 17:08:09 -07001715 return 0;
Simon Glassda0af362013-05-07 06:11:53 +00001716}
1717
Simon Glassda0af362013-05-07 06:11:53 +00001718int fit_conf_find_compat(const void *fit, const void *fdt)
1719{
1720 int ndepth = 0;
1721 int noffset, confs_noffset, images_noffset;
1722 const void *fdt_compat;
1723 int fdt_compat_len;
1724 int best_match_offset = 0;
1725 int best_match_pos = 0;
1726
1727 confs_noffset = fdt_path_offset(fit, FIT_CONFS_PATH);
1728 images_noffset = fdt_path_offset(fit, FIT_IMAGES_PATH);
1729 if (confs_noffset < 0 || images_noffset < 0) {
1730 debug("Can't find configurations or images nodes.\n");
1731 return -1;
1732 }
1733
1734 fdt_compat = fdt_getprop(fdt, 0, "compatible", &fdt_compat_len);
1735 if (!fdt_compat) {
1736 debug("Fdt for comparison has no \"compatible\" property.\n");
1737 return -1;
1738 }
1739
1740 /*
1741 * Loop over the configurations in the FIT image.
1742 */
1743 for (noffset = fdt_next_node(fit, confs_noffset, &ndepth);
1744 (noffset >= 0) && (ndepth > 0);
1745 noffset = fdt_next_node(fit, noffset, &ndepth)) {
Julius Werner4e823522019-07-24 19:37:56 -07001746 const void *fdt;
Simon Glassda0af362013-05-07 06:11:53 +00001747 const char *kfdt_name;
Julius Werner4e823522019-07-24 19:37:56 -07001748 int kfdt_noffset, compat_noffset;
Simon Glassda0af362013-05-07 06:11:53 +00001749 const char *cur_fdt_compat;
1750 int len;
Julius Werner4e823522019-07-24 19:37:56 -07001751 size_t sz;
Simon Glassda0af362013-05-07 06:11:53 +00001752 int i;
1753
1754 if (ndepth > 1)
1755 continue;
1756
Julius Werner4e823522019-07-24 19:37:56 -07001757 /* If there's a compat property in the config node, use that. */
1758 if (fdt_getprop(fit, noffset, "compatible", NULL)) {
1759 fdt = fit; /* search in FIT image */
1760 compat_noffset = noffset; /* search under config node */
1761 } else { /* Otherwise extract it from the kernel FDT. */
1762 kfdt_name = fdt_getprop(fit, noffset, "fdt", &len);
1763 if (!kfdt_name) {
1764 debug("No fdt property found.\n");
1765 continue;
1766 }
1767 kfdt_noffset = fdt_subnode_offset(fit, images_noffset,
1768 kfdt_name);
1769 if (kfdt_noffset < 0) {
1770 debug("No image node named \"%s\" found.\n",
1771 kfdt_name);
1772 continue;
1773 }
Julius Werner97b09cd2019-07-24 19:37:55 -07001774
Julius Werner4e823522019-07-24 19:37:56 -07001775 if (!fit_image_check_comp(fit, kfdt_noffset,
1776 IH_COMP_NONE)) {
1777 debug("Can't extract compat from \"%s\" "
1778 "(compressed)\n", kfdt_name);
1779 continue;
1780 }
Julius Werner97b09cd2019-07-24 19:37:55 -07001781
Julius Werner4e823522019-07-24 19:37:56 -07001782 /* search in this config's kernel FDT */
John Keeping645a3122021-06-25 17:58:04 +01001783 if (fit_image_get_data_and_size(fit, kfdt_noffset,
1784 &fdt, &sz)) {
Julius Werner4e823522019-07-24 19:37:56 -07001785 debug("Failed to get fdt \"%s\".\n", kfdt_name);
1786 continue;
1787 }
1788
1789 compat_noffset = 0; /* search kFDT under root node */
Simon Glassda0af362013-05-07 06:11:53 +00001790 }
1791
1792 len = fdt_compat_len;
1793 cur_fdt_compat = fdt_compat;
1794 /*
1795 * Look for a match for each U-Boot compatibility string in
Julius Werner4e823522019-07-24 19:37:56 -07001796 * turn in the compat string property.
Simon Glassda0af362013-05-07 06:11:53 +00001797 */
1798 for (i = 0; len > 0 &&
1799 (!best_match_offset || best_match_pos > i); i++) {
1800 int cur_len = strlen(cur_fdt_compat) + 1;
1801
Julius Werner4e823522019-07-24 19:37:56 -07001802 if (!fdt_node_check_compatible(fdt, compat_noffset,
Simon Glassda0af362013-05-07 06:11:53 +00001803 cur_fdt_compat)) {
1804 best_match_offset = noffset;
1805 best_match_pos = i;
1806 break;
1807 }
1808 len -= cur_len;
1809 cur_fdt_compat += cur_len;
1810 }
1811 }
1812 if (!best_match_offset) {
1813 debug("No match found.\n");
1814 return -1;
1815 }
1816
1817 return best_match_offset;
1818}
1819
Simon Glassda0af362013-05-07 06:11:53 +00001820int fit_conf_get_node(const void *fit, const char *conf_uname)
1821{
1822 int noffset, confs_noffset;
1823 int len;
Pantelis Antoniou6e51fb22017-09-04 23:12:16 +03001824 const char *s;
1825 char *conf_uname_copy = NULL;
Simon Glassda0af362013-05-07 06:11:53 +00001826
1827 confs_noffset = fdt_path_offset(fit, FIT_CONFS_PATH);
1828 if (confs_noffset < 0) {
1829 debug("Can't find configurations parent node '%s' (%s)\n",
1830 FIT_CONFS_PATH, fdt_strerror(confs_noffset));
1831 return confs_noffset;
1832 }
1833
1834 if (conf_uname == NULL) {
1835 /* get configuration unit name from the default property */
1836 debug("No configuration specified, trying default...\n");
Simon Glassdb503fb2021-09-25 19:43:14 -06001837 if (!tools_build() && IS_ENABLED(CONFIG_MULTI_DTB_FIT)) {
Sebastian Reichel0890f942021-01-04 20:48:04 +01001838 noffset = fit_find_config_node(fit);
1839 if (noffset < 0)
1840 return noffset;
1841 conf_uname = fdt_get_name(fit, noffset, NULL);
1842 } else {
1843 conf_uname = (char *)fdt_getprop(fit, confs_noffset,
1844 FIT_DEFAULT_PROP, &len);
1845 if (conf_uname == NULL) {
1846 fit_get_debug(fit, confs_noffset, FIT_DEFAULT_PROP,
1847 len);
1848 return len;
1849 }
Simon Glassda0af362013-05-07 06:11:53 +00001850 }
1851 debug("Found default configuration: '%s'\n", conf_uname);
1852 }
1853
Pantelis Antoniou6e51fb22017-09-04 23:12:16 +03001854 s = strchr(conf_uname, '#');
1855 if (s) {
1856 len = s - conf_uname;
1857 conf_uname_copy = malloc(len + 1);
1858 if (!conf_uname_copy) {
1859 debug("Can't allocate uname copy: '%s'\n",
1860 conf_uname);
1861 return -ENOMEM;
1862 }
1863 memcpy(conf_uname_copy, conf_uname, len);
1864 conf_uname_copy[len] = '\0';
1865 conf_uname = conf_uname_copy;
1866 }
1867
Simon Glassda0af362013-05-07 06:11:53 +00001868 noffset = fdt_subnode_offset(fit, confs_noffset, conf_uname);
1869 if (noffset < 0) {
1870 debug("Can't get node offset for configuration unit name: '%s' (%s)\n",
1871 conf_uname, fdt_strerror(noffset));
1872 }
1873
Heinrich Schuchardtf5686462022-04-11 20:08:03 +02001874 free(conf_uname_copy);
Pantelis Antoniou6e51fb22017-09-04 23:12:16 +03001875
Simon Glassda0af362013-05-07 06:11:53 +00001876 return noffset;
1877}
1878
Pantelis Antonioua4880742017-09-04 23:12:14 +03001879int fit_conf_get_prop_node_count(const void *fit, int noffset,
Simon Glassda0af362013-05-07 06:11:53 +00001880 const char *prop_name)
1881{
Pantelis Antonioua4880742017-09-04 23:12:14 +03001882 return fdt_stringlist_count(fit, noffset, prop_name);
1883}
1884
1885int fit_conf_get_prop_node_index(const void *fit, int noffset,
1886 const char *prop_name, int index)
1887{
1888 const char *uname;
Simon Glassda0af362013-05-07 06:11:53 +00001889 int len;
1890
1891 /* get kernel image unit name from configuration kernel property */
Pantelis Antonioua4880742017-09-04 23:12:14 +03001892 uname = fdt_stringlist_get(fit, noffset, prop_name, index, &len);
Simon Glassda0af362013-05-07 06:11:53 +00001893 if (uname == NULL)
1894 return len;
1895
1896 return fit_image_get_node(fit, uname);
1897}
1898
Simon Glassa42f11f2022-10-20 18:23:04 -06001899int fit_conf_get_prop_node(const void *fit, int noffset, const char *prop_name,
1900 enum image_phase_t sel_phase)
Pantelis Antonioua4880742017-09-04 23:12:14 +03001901{
Simon Glassa42f11f2022-10-20 18:23:04 -06001902 int i, count;
1903
1904 if (sel_phase == IH_PHASE_NONE)
1905 return fit_conf_get_prop_node_index(fit, noffset, prop_name, 0);
1906
1907 count = fit_conf_get_prop_node_count(fit, noffset, prop_name);
1908 if (count < 0)
1909 return count;
1910
1911 /* check each image in the list */
1912 for (i = 0; i < count; i++) {
1913 enum image_phase_t phase;
1914 int ret, node;
1915
1916 node = fit_conf_get_prop_node_index(fit, noffset, prop_name, i);
1917 ret = fit_image_get_phase(fit, node, &phase);
1918
1919 /* if the image is for any phase, let's use it */
1920 if (ret == -ENOENT)
1921 return node;
1922 else if (ret < 0)
1923 return ret;
1924
1925 if (phase == sel_phase)
1926 return node;
1927 }
1928
1929 return -ENOENT;
Pantelis Antonioua4880742017-09-04 23:12:14 +03001930}
Simon Glassda0af362013-05-07 06:11:53 +00001931
Sean Anderson080d3a02022-08-16 11:16:03 -04001932static int fit_get_data_tail(const void *fit, int noffset,
1933 const void **data, size_t *size)
1934{
1935 char *desc;
1936
1937 if (noffset < 0)
1938 return noffset;
1939
1940 if (!fit_image_verify(fit, noffset))
1941 return -EINVAL;
1942
1943 if (fit_image_get_data_and_size(fit, noffset, data, size))
1944 return -ENOENT;
1945
1946 if (!fit_get_desc(fit, noffset, &desc))
1947 printf("%s\n", desc);
1948
1949 return 0;
1950}
1951
1952int fit_get_data_node(const void *fit, const char *image_uname,
1953 const void **data, size_t *size)
1954{
1955 int noffset = fit_image_get_node(fit, image_uname);
1956
1957 return fit_get_data_tail(fit, noffset, data, size);
1958}
1959
1960int fit_get_data_conf_prop(const void *fit, const char *prop_name,
1961 const void **data, size_t *size)
1962{
1963 int noffset = fit_conf_get_node(fit, NULL);
1964
Simon Glassa42f11f2022-10-20 18:23:04 -06001965 noffset = fit_conf_get_prop_node(fit, noffset, prop_name,
1966 IH_PHASE_NONE);
Sean Anderson080d3a02022-08-16 11:16:03 -04001967 return fit_get_data_tail(fit, noffset, data, size);
1968}
1969
Jeroen Hofsteeffa60da2014-10-08 22:57:38 +02001970static int fit_image_select(const void *fit, int rd_noffset, int verify)
Simon Glass384d86d2013-05-16 13:53:21 +00001971{
1972 fit_image_print(fit, rd_noffset, " ");
1973
1974 if (verify) {
1975 puts(" Verifying Hash Integrity ... ");
1976 if (!fit_image_verify(fit, rd_noffset)) {
1977 puts("Bad Data Hash\n");
1978 return -EACCES;
1979 }
1980 puts("OK\n");
1981 }
1982
1983 return 0;
1984}
1985
Simon Glassdf00afa2022-09-06 20:26:50 -06001986int fit_get_node_from_config(struct bootm_headers *images,
1987 const char *prop_name, ulong addr)
Simon Glass384d86d2013-05-16 13:53:21 +00001988{
1989 int cfg_noffset;
1990 void *fit_hdr;
1991 int noffset;
1992
1993 debug("* %s: using config '%s' from image at 0x%08lx\n",
1994 prop_name, images->fit_uname_cfg, addr);
1995
1996 /* Check whether configuration has this property defined */
1997 fit_hdr = map_sysmem(addr, 0);
1998 cfg_noffset = fit_conf_get_node(fit_hdr, images->fit_uname_cfg);
1999 if (cfg_noffset < 0) {
2000 debug("* %s: no such config\n", prop_name);
Paul Burton14171b12016-09-20 18:17:12 +01002001 return -EINVAL;
Simon Glass384d86d2013-05-16 13:53:21 +00002002 }
2003
Simon Glassa42f11f2022-10-20 18:23:04 -06002004 noffset = fit_conf_get_prop_node(fit_hdr, cfg_noffset, prop_name,
2005 IH_PHASE_NONE);
Simon Glass384d86d2013-05-16 13:53:21 +00002006 if (noffset < 0) {
2007 debug("* %s: no '%s' in config\n", prop_name, prop_name);
Jonathan Grayae6a02f2016-09-03 08:30:14 +10002008 return -ENOENT;
Simon Glass384d86d2013-05-16 13:53:21 +00002009 }
2010
2011 return noffset;
2012}
2013
Simon Glassa0c0b632014-06-12 07:24:47 -06002014/**
2015 * fit_get_image_type_property() - get property name for IH_TYPE_...
2016 *
Heinrich Schuchardt47b4c022022-01-19 18:05:50 +01002017 * Return: the properly name where we expect to find the image in the
Simon Glassa0c0b632014-06-12 07:24:47 -06002018 * config node
2019 */
2020static const char *fit_get_image_type_property(int type)
2021{
2022 /*
2023 * This is sort-of available in the uimage_type[] table in image.c
Andreas Dannenberg8ca5a902016-06-15 17:00:19 -05002024 * but we don't have access to the short name, and "fdt" is different
Simon Glassa0c0b632014-06-12 07:24:47 -06002025 * anyway. So let's just keep it here.
2026 */
2027 switch (type) {
2028 case IH_TYPE_FLATDT:
2029 return FIT_FDT_PROP;
2030 case IH_TYPE_KERNEL:
2031 return FIT_KERNEL_PROP;
Alexandru Gagniucd1f78262021-04-01 13:25:30 -05002032 case IH_TYPE_FIRMWARE:
2033 return FIT_FIRMWARE_PROP;
Simon Glassa0c0b632014-06-12 07:24:47 -06002034 case IH_TYPE_RAMDISK:
2035 return FIT_RAMDISK_PROP;
Simon Glass0129b522014-10-19 21:11:24 -06002036 case IH_TYPE_X86_SETUP:
2037 return FIT_SETUP_PROP;
Karl Apsite1b21c282015-05-21 09:52:48 -04002038 case IH_TYPE_LOADABLE:
2039 return FIT_LOADABLE_PROP;
Michal Simekebae78b2016-05-17 14:03:50 +02002040 case IH_TYPE_FPGA:
2041 return FIT_FPGA_PROP;
Marek Vasut93e95752018-05-13 00:22:54 +02002042 case IH_TYPE_STANDALONE:
2043 return FIT_STANDALONE_PROP;
Simon Glassa0c0b632014-06-12 07:24:47 -06002044 }
2045
2046 return "unknown";
2047}
2048
Simon Glassdf00afa2022-09-06 20:26:50 -06002049int fit_image_load(struct bootm_headers *images, ulong addr,
Simon Glassad68fc32013-07-10 23:08:10 -07002050 const char **fit_unamep, const char **fit_uname_configp,
Simon Glassa42f11f2022-10-20 18:23:04 -06002051 int arch, int ph_type, int bootstage_id,
Simon Glass384d86d2013-05-16 13:53:21 +00002052 enum fit_load_op load_op, ulong *datap, ulong *lenp)
2053{
Simon Glassa42f11f2022-10-20 18:23:04 -06002054 int image_type = image_ph_type(ph_type);
Simon Glass384d86d2013-05-16 13:53:21 +00002055 int cfg_noffset, noffset;
2056 const char *fit_uname;
Simon Glassad68fc32013-07-10 23:08:10 -07002057 const char *fit_uname_config;
Pantelis Antoniou5e671d62017-09-04 23:12:15 +03002058 const char *fit_base_uname_config;
Simon Glass384d86d2013-05-16 13:53:21 +00002059 const void *fit;
Julius Werner97b09cd2019-07-24 19:37:55 -07002060 void *buf;
2061 void *loadbuf;
Simon Glass384d86d2013-05-16 13:53:21 +00002062 size_t size;
2063 int type_ok, os_ok;
Julius Werner97b09cd2019-07-24 19:37:55 -07002064 ulong load, load_end, data, len;
2065 uint8_t os, comp;
Simon Glassa0c0b632014-06-12 07:24:47 -06002066 const char *prop_name;
Simon Glass384d86d2013-05-16 13:53:21 +00002067 int ret;
2068
2069 fit = map_sysmem(addr, 0);
2070 fit_uname = fit_unamep ? *fit_unamep : NULL;
Simon Glassad68fc32013-07-10 23:08:10 -07002071 fit_uname_config = fit_uname_configp ? *fit_uname_configp : NULL;
Pantelis Antoniou5e671d62017-09-04 23:12:15 +03002072 fit_base_uname_config = NULL;
Simon Glassa0c0b632014-06-12 07:24:47 -06002073 prop_name = fit_get_image_type_property(image_type);
Simon Glass384d86d2013-05-16 13:53:21 +00002074 printf("## Loading %s from FIT Image at %08lx ...\n", prop_name, addr);
2075
2076 bootstage_mark(bootstage_id + BOOTSTAGE_SUB_FORMAT);
Simon Glassb823daa2021-02-15 17:08:12 -07002077 ret = fit_check_format(fit, IMAGE_SIZE_INVAL);
2078 if (ret) {
2079 printf("Bad FIT %s image format! (err=%d)\n", prop_name, ret);
2080 if (CONFIG_IS_ENABLED(FIT_SIGNATURE) && ret == -EADDRNOTAVAIL)
2081 printf("Signature checking prevents use of unit addresses (@) in nodes\n");
Simon Glass384d86d2013-05-16 13:53:21 +00002082 bootstage_error(bootstage_id + BOOTSTAGE_SUB_FORMAT);
Simon Glassb823daa2021-02-15 17:08:12 -07002083 return ret;
Simon Glass384d86d2013-05-16 13:53:21 +00002084 }
2085 bootstage_mark(bootstage_id + BOOTSTAGE_SUB_FORMAT_OK);
2086 if (fit_uname) {
Masahiro Yamadaaa58eec2014-02-18 15:39:21 +09002087 /* get FIT component image node offset */
Simon Glass384d86d2013-05-16 13:53:21 +00002088 bootstage_mark(bootstage_id + BOOTSTAGE_SUB_UNIT_NAME);
2089 noffset = fit_image_get_node(fit, fit_uname);
2090 } else {
2091 /*
2092 * no image node unit name, try to get config
2093 * node first. If config unit node name is NULL
2094 * fit_conf_get_node() will try to find default config node
2095 */
2096 bootstage_mark(bootstage_id + BOOTSTAGE_SUB_NO_UNIT_NAME);
Simon Glass0434ea12021-07-14 17:05:36 -05002097 if (IS_ENABLED(CONFIG_FIT_BEST_MATCH) && !fit_uname_config) {
Simon Glass384d86d2013-05-16 13:53:21 +00002098 cfg_noffset = fit_conf_find_compat(fit, gd_fdt_blob());
2099 } else {
Simon Glassa42f11f2022-10-20 18:23:04 -06002100 cfg_noffset = fit_conf_get_node(fit, fit_uname_config);
Simon Glass384d86d2013-05-16 13:53:21 +00002101 }
2102 if (cfg_noffset < 0) {
2103 puts("Could not find configuration node\n");
2104 bootstage_error(bootstage_id +
2105 BOOTSTAGE_SUB_NO_UNIT_NAME);
2106 return -ENOENT;
2107 }
Marek Vasut5dee1342018-05-31 17:59:07 +02002108
Pantelis Antoniou5e671d62017-09-04 23:12:15 +03002109 fit_base_uname_config = fdt_get_name(fit, cfg_noffset, NULL);
2110 printf(" Using '%s' configuration\n", fit_base_uname_config);
Marek Vasut5dee1342018-05-31 17:59:07 +02002111 /* Remember this config */
2112 if (image_type == IH_TYPE_KERNEL)
Pantelis Antoniou5e671d62017-09-04 23:12:15 +03002113 images->fit_uname_cfg = fit_base_uname_config;
Marek Vasut5dee1342018-05-31 17:59:07 +02002114
AKASHI Takahiro2223c7d2020-02-21 15:12:55 +09002115 if (FIT_IMAGE_ENABLE_VERIFY && images->verify) {
Marek Vasut5dee1342018-05-31 17:59:07 +02002116 puts(" Verifying Hash Integrity ... ");
2117 if (fit_config_verify(fit, cfg_noffset)) {
2118 puts("Bad Data Hash\n");
2119 bootstage_error(bootstage_id +
2120 BOOTSTAGE_SUB_HASH);
2121 return -EACCES;
Simon Glass384d86d2013-05-16 13:53:21 +00002122 }
Marek Vasut5dee1342018-05-31 17:59:07 +02002123 puts("OK\n");
Simon Glass384d86d2013-05-16 13:53:21 +00002124 }
2125
Marek Vasut5dee1342018-05-31 17:59:07 +02002126 bootstage_mark(BOOTSTAGE_ID_FIT_CONFIG);
2127
Simon Glassa42f11f2022-10-20 18:23:04 -06002128 noffset = fit_conf_get_prop_node(fit, cfg_noffset, prop_name,
2129 image_ph_phase(ph_type));
Simon Glass384d86d2013-05-16 13:53:21 +00002130 fit_uname = fit_get_name(fit, noffset, NULL);
2131 }
2132 if (noffset < 0) {
Simon Glassa559bb22020-03-18 11:43:56 -06002133 printf("Could not find subimage node type '%s'\n", prop_name);
Simon Glass384d86d2013-05-16 13:53:21 +00002134 bootstage_error(bootstage_id + BOOTSTAGE_SUB_SUBNODE);
2135 return -ENOENT;
2136 }
2137
2138 printf(" Trying '%s' %s subimage\n", fit_uname, prop_name);
2139
2140 ret = fit_image_select(fit, noffset, images->verify);
2141 if (ret) {
2142 bootstage_error(bootstage_id + BOOTSTAGE_SUB_HASH);
2143 return ret;
2144 }
2145
2146 bootstage_mark(bootstage_id + BOOTSTAGE_SUB_CHECK_ARCH);
Simon Glassdb503fb2021-09-25 19:43:14 -06002147 if (!tools_build() && IS_ENABLED(CONFIG_SANDBOX)) {
Sebastian Reichelbfe8ddf2021-01-04 20:48:03 +01002148 if (!fit_image_check_target_arch(fit, noffset)) {
2149 puts("Unsupported Architecture\n");
2150 bootstage_error(bootstage_id + BOOTSTAGE_SUB_CHECK_ARCH);
2151 return -ENOEXEC;
2152 }
Simon Glass384d86d2013-05-16 13:53:21 +00002153 }
Alison Wang73818d52016-11-10 10:49:03 +08002154
2155#ifndef USE_HOSTCC
Simon Glassc0cabbc2021-09-25 19:43:39 -06002156 {
2157 uint8_t os_arch;
2158
Alison Wang73818d52016-11-10 10:49:03 +08002159 fit_image_get_arch(fit, noffset, &os_arch);
2160 images->os.arch = os_arch;
Simon Glassc0cabbc2021-09-25 19:43:39 -06002161 }
Alison Wang73818d52016-11-10 10:49:03 +08002162#endif
2163
Simon Glass384d86d2013-05-16 13:53:21 +00002164 bootstage_mark(bootstage_id + BOOTSTAGE_SUB_CHECK_ALL);
2165 type_ok = fit_image_check_type(fit, noffset, image_type) ||
mario.six@gdsys.cca82eeaf2016-07-20 08:32:50 +02002166 fit_image_check_type(fit, noffset, IH_TYPE_FIRMWARE) ||
Alexandru Gagniuce14c9b42021-04-01 13:25:31 -05002167 fit_image_check_type(fit, noffset, IH_TYPE_TEE) ||
mario.six@gdsys.cca82eeaf2016-07-20 08:32:50 +02002168 (image_type == IH_TYPE_KERNEL &&
2169 fit_image_check_type(fit, noffset, IH_TYPE_KERNEL_NOLOAD));
Marek Vasutcaee41f2014-12-16 14:07:22 +01002170
Andreas Bießmannb4cc60d2016-08-14 20:31:24 +02002171 os_ok = image_type == IH_TYPE_FLATDT ||
2172 image_type == IH_TYPE_FPGA ||
Marek Vasutcaee41f2014-12-16 14:07:22 +01002173 fit_image_check_os(fit, noffset, IH_OS_LINUX) ||
mario.six@gdsys.cca82eeaf2016-07-20 08:32:50 +02002174 fit_image_check_os(fit, noffset, IH_OS_U_BOOT) ||
Alexandru Gagniuce14c9b42021-04-01 13:25:31 -05002175 fit_image_check_os(fit, noffset, IH_OS_TEE) ||
Cristian Ciocaltea217f9642019-12-24 18:05:38 +02002176 fit_image_check_os(fit, noffset, IH_OS_OPENRTOS) ||
Lihua Zhao03b0d1e2020-03-18 07:32:07 -07002177 fit_image_check_os(fit, noffset, IH_OS_EFI) ||
Maxim Moskaletse2b258c2024-06-21 14:42:10 +03002178 fit_image_check_os(fit, noffset, IH_OS_VXWORKS) ||
2179 fit_image_check_os(fit, noffset, IH_OS_ELF);
Karl Apsite1b21c282015-05-21 09:52:48 -04002180
2181 /*
2182 * If either of the checks fail, we should report an error, but
2183 * if the image type is coming from the "loadables" field, we
2184 * don't care what it is
2185 */
2186 if ((!type_ok || !os_ok) && image_type != IH_TYPE_LOADABLE) {
Marek Vasutcaee41f2014-12-16 14:07:22 +01002187 fit_image_get_os(fit, noffset, &os);
2188 printf("No %s %s %s Image\n",
2189 genimg_get_os_name(os),
2190 genimg_get_arch_name(arch),
Simon Glass384d86d2013-05-16 13:53:21 +00002191 genimg_get_type_name(image_type));
2192 bootstage_error(bootstage_id + BOOTSTAGE_SUB_CHECK_ALL);
2193 return -EIO;
2194 }
2195
2196 bootstage_mark(bootstage_id + BOOTSTAGE_SUB_CHECK_ALL_OK);
2197
2198 /* get image data address and length */
Julius Werner97b09cd2019-07-24 19:37:55 -07002199 if (fit_image_get_data_and_size(fit, noffset,
2200 (const void **)&buf, &size)) {
Simon Glass384d86d2013-05-16 13:53:21 +00002201 printf("Could not find %s subimage data!\n", prop_name);
2202 bootstage_error(bootstage_id + BOOTSTAGE_SUB_GET_DATA);
Simon Glass9d0da5b2013-06-16 07:46:49 -07002203 return -ENOENT;
Simon Glass384d86d2013-05-16 13:53:21 +00002204 }
Andrew F. Davisc6d8cc02016-11-21 14:37:09 -06002205
Philippe Reynes3d964702019-12-18 18:25:42 +01002206 /* Decrypt data before uncompress/move */
Sebastian Reichelbfe8ddf2021-01-04 20:48:03 +01002207 if (IS_ENABLED(CONFIG_FIT_CIPHER) && IMAGE_ENABLE_DECRYPT) {
Philippe Reynes3d964702019-12-18 18:25:42 +01002208 puts(" Decrypting Data ... ");
2209 if (fit_image_uncipher(fit, noffset, &buf, &size)) {
2210 puts("Error\n");
2211 return -EACCES;
2212 }
2213 puts("OK\n");
2214 }
Philippe Reynes3d964702019-12-18 18:25:42 +01002215
Andrew F. Davisc6d8cc02016-11-21 14:37:09 -06002216 /* perform any post-processing on the image data */
Simon Glassdb503fb2021-09-25 19:43:14 -06002217 if (!tools_build() && IS_ENABLED(CONFIG_FIT_IMAGE_POST_PROCESS))
Lokesh Vutlab36dd3e2021-06-11 11:45:05 +03002218 board_fit_image_post_process(fit, noffset, &buf, &size);
Andrew F. Davisc6d8cc02016-11-21 14:37:09 -06002219
Simon Glass384d86d2013-05-16 13:53:21 +00002220 len = (ulong)size;
2221
Simon Glass384d86d2013-05-16 13:53:21 +00002222 bootstage_mark(bootstage_id + BOOTSTAGE_SUB_GET_DATA_OK);
2223
Julius Werner97b09cd2019-07-24 19:37:55 -07002224 data = map_to_sysmem(buf);
2225 load = data;
Simon Glass384d86d2013-05-16 13:53:21 +00002226 if (load_op == FIT_LOAD_IGNORED) {
2227 /* Don't load */
2228 } else if (fit_image_get_load(fit, noffset, &load)) {
2229 if (load_op == FIT_LOAD_REQUIRED) {
2230 printf("Can't get %s subimage load address!\n",
2231 prop_name);
2232 bootstage_error(bootstage_id + BOOTSTAGE_SUB_LOAD);
2233 return -EBADF;
2234 }
Simon Glass05a9ad72014-08-22 14:26:43 -06002235 } else if (load_op != FIT_LOAD_OPTIONAL_NON_ZERO || load) {
Simon Glass384d86d2013-05-16 13:53:21 +00002236 ulong image_start, image_end;
Simon Glass384d86d2013-05-16 13:53:21 +00002237
2238 /*
2239 * move image data to the load address,
2240 * make sure we don't overwrite initial image
2241 */
2242 image_start = addr;
2243 image_end = addr + fit_get_size(fit);
2244
2245 load_end = load + len;
2246 if (image_type != IH_TYPE_KERNEL &&
2247 load < image_end && load_end > image_start) {
2248 printf("Error: %s overwritten\n", prop_name);
2249 return -EXDEV;
2250 }
2251
2252 printf(" Loading %s from 0x%08lx to 0x%08lx\n",
2253 prop_name, data, load);
Julius Werner97b09cd2019-07-24 19:37:55 -07002254 } else {
2255 load = data; /* No load address specified */
2256 }
2257
2258 comp = IH_COMP_NONE;
2259 loadbuf = buf;
2260 /* Kernel images get decompressed later in bootm_load_os(). */
Julius Werner88040022019-08-02 15:52:28 -07002261 if (!fit_image_get_comp(fit, noffset, &comp) &&
2262 comp != IH_COMP_NONE &&
2263 !(image_type == IH_TYPE_KERNEL ||
2264 image_type == IH_TYPE_KERNEL_NOLOAD ||
2265 image_type == IH_TYPE_RAMDISK)) {
Julius Werner97b09cd2019-07-24 19:37:55 -07002266 ulong max_decomp_len = len * 20;
2267 if (load == data) {
2268 loadbuf = malloc(max_decomp_len);
2269 load = map_to_sysmem(loadbuf);
2270 } else {
2271 loadbuf = map_sysmem(load, max_decomp_len);
2272 }
2273 if (image_decomp(comp, load, data, image_type,
2274 loadbuf, buf, len, max_decomp_len, &load_end)) {
2275 printf("Error decompressing %s\n", prop_name);
Simon Glass384d86d2013-05-16 13:53:21 +00002276
Julius Werner97b09cd2019-07-24 19:37:55 -07002277 return -ENOEXEC;
2278 }
2279 len = load_end - load;
2280 } else if (load != data) {
2281 loadbuf = map_sysmem(load, len);
2282 memcpy(loadbuf, buf, len);
Simon Glass384d86d2013-05-16 13:53:21 +00002283 }
Julius Werner97b09cd2019-07-24 19:37:55 -07002284
Julius Werner88040022019-08-02 15:52:28 -07002285 if (image_type == IH_TYPE_RAMDISK && comp != IH_COMP_NONE)
2286 puts("WARNING: 'compression' nodes for ramdisks are deprecated,"
2287 " please fix your .its file!\n");
2288
Julius Werner97b09cd2019-07-24 19:37:55 -07002289 /* verify that image data is a proper FDT blob */
2290 if (image_type == IH_TYPE_FLATDT && fdt_check_header(loadbuf)) {
2291 puts("Subimage data is not a FDT");
2292 return -ENOEXEC;
2293 }
2294
Simon Glass384d86d2013-05-16 13:53:21 +00002295 bootstage_mark(bootstage_id + BOOTSTAGE_SUB_LOAD);
2296
Julius Werner97b09cd2019-07-24 19:37:55 -07002297 *datap = load;
Simon Glass384d86d2013-05-16 13:53:21 +00002298 *lenp = len;
2299 if (fit_unamep)
2300 *fit_unamep = (char *)fit_uname;
Simon Glassad68fc32013-07-10 23:08:10 -07002301 if (fit_uname_configp)
Pantelis Antoniou5e671d62017-09-04 23:12:15 +03002302 *fit_uname_configp = (char *)(fit_uname_config ? :
2303 fit_base_uname_config);
Simon Glass384d86d2013-05-16 13:53:21 +00002304
2305 return noffset;
2306}
Simon Glass0129b522014-10-19 21:11:24 -06002307
Simon Glassdf00afa2022-09-06 20:26:50 -06002308int boot_get_setup_fit(struct bootm_headers *images, uint8_t arch,
2309 ulong *setup_start, ulong *setup_len)
Simon Glass0129b522014-10-19 21:11:24 -06002310{
2311 int noffset;
2312 ulong addr;
2313 ulong len;
2314 int ret;
2315
2316 addr = map_to_sysmem(images->fit_hdr_os);
2317 noffset = fit_get_node_from_config(images, FIT_SETUP_PROP, addr);
2318 if (noffset < 0)
2319 return noffset;
2320
2321 ret = fit_image_load(images, addr, NULL, NULL, arch,
2322 IH_TYPE_X86_SETUP, BOOTSTAGE_ID_FIT_SETUP_START,
2323 FIT_LOAD_REQUIRED, setup_start, &len);
2324
2325 return ret;
2326}
Pantelis Antoniou6e51fb22017-09-04 23:12:16 +03002327
2328#ifndef USE_HOSTCC
Simon Glassdf00afa2022-09-06 20:26:50 -06002329int boot_get_fdt_fit(struct bootm_headers *images, ulong addr,
2330 const char **fit_unamep, const char **fit_uname_configp,
2331 int arch, ulong *datap, ulong *lenp)
Pantelis Antoniou6e51fb22017-09-04 23:12:16 +03002332{
2333 int fdt_noffset, cfg_noffset, count;
2334 const void *fit;
2335 const char *fit_uname = NULL;
2336 const char *fit_uname_config = NULL;
2337 char *fit_uname_config_copy = NULL;
2338 char *next_config = NULL;
2339 ulong load, len;
2340#ifdef CONFIG_OF_LIBFDT_OVERLAY
2341 ulong image_start, image_end;
Marek Vasutf7d24612021-06-11 04:09:56 +02002342 ulong ovload, ovlen, ovcopylen;
Pantelis Antoniou6e51fb22017-09-04 23:12:16 +03002343 const char *uconfig;
2344 const char *uname;
Marek Vasutf7d24612021-06-11 04:09:56 +02002345 void *base, *ov, *ovcopy = NULL;
Pantelis Antoniou6e51fb22017-09-04 23:12:16 +03002346 int i, err, noffset, ov_noffset;
2347#endif
2348
2349 fit_uname = fit_unamep ? *fit_unamep : NULL;
2350
2351 if (fit_uname_configp && *fit_uname_configp) {
2352 fit_uname_config_copy = strdup(*fit_uname_configp);
2353 if (!fit_uname_config_copy)
2354 return -ENOMEM;
2355
2356 next_config = strchr(fit_uname_config_copy, '#');
2357 if (next_config)
2358 *next_config++ = '\0';
2359 if (next_config - 1 > fit_uname_config_copy)
2360 fit_uname_config = fit_uname_config_copy;
2361 }
2362
2363 fdt_noffset = fit_image_load(images,
2364 addr, &fit_uname, &fit_uname_config,
2365 arch, IH_TYPE_FLATDT,
2366 BOOTSTAGE_ID_FIT_FDT_START,
2367 FIT_LOAD_OPTIONAL, &load, &len);
2368
2369 if (fdt_noffset < 0)
2370 goto out;
2371
2372 debug("fit_uname=%s, fit_uname_config=%s\n",
2373 fit_uname ? fit_uname : "<NULL>",
2374 fit_uname_config ? fit_uname_config : "<NULL>");
2375
2376 fit = map_sysmem(addr, 0);
2377
2378 cfg_noffset = fit_conf_get_node(fit, fit_uname_config);
2379
2380 /* single blob, or error just return as well */
2381 count = fit_conf_get_prop_node_count(fit, cfg_noffset, FIT_FDT_PROP);
2382 if (count <= 1 && !next_config)
2383 goto out;
2384
2385 /* we need to apply overlays */
2386
2387#ifdef CONFIG_OF_LIBFDT_OVERLAY
2388 image_start = addr;
2389 image_end = addr + fit_get_size(fit);
2390 /* verify that relocation took place by load address not being in fit */
2391 if (load >= image_start && load < image_end) {
2392 /* check is simplified; fit load checks for overlaps */
2393 printf("Overlayed FDT requires relocation\n");
2394 fdt_noffset = -EBADF;
2395 goto out;
2396 }
2397
2398 base = map_sysmem(load, len);
2399
2400 /* apply extra configs in FIT first, followed by args */
2401 for (i = 1; ; i++) {
2402 if (i < count) {
2403 noffset = fit_conf_get_prop_node_index(fit, cfg_noffset,
2404 FIT_FDT_PROP, i);
2405 uname = fit_get_name(fit, noffset, NULL);
2406 uconfig = NULL;
2407 } else {
2408 if (!next_config)
2409 break;
2410 uconfig = next_config;
2411 next_config = strchr(next_config, '#');
2412 if (next_config)
2413 *next_config++ = '\0';
2414 uname = NULL;
Peter Ujfalusiaf15dc42019-03-06 15:52:27 +02002415
2416 /*
2417 * fit_image_load() would load the first FDT from the
2418 * extra config only when uconfig is specified.
2419 * Check if the extra config contains multiple FDTs and
2420 * if so, load them.
2421 */
2422 cfg_noffset = fit_conf_get_node(fit, uconfig);
2423
2424 i = 0;
2425 count = fit_conf_get_prop_node_count(fit, cfg_noffset,
2426 FIT_FDT_PROP);
Pantelis Antoniou6e51fb22017-09-04 23:12:16 +03002427 }
2428
2429 debug("%d: using uname=%s uconfig=%s\n", i, uname, uconfig);
2430
2431 ov_noffset = fit_image_load(images,
2432 addr, &uname, &uconfig,
2433 arch, IH_TYPE_FLATDT,
2434 BOOTSTAGE_ID_FIT_FDT_START,
Marek Vasutf7d24612021-06-11 04:09:56 +02002435 FIT_LOAD_IGNORED, &ovload, &ovlen);
Pantelis Antoniou6e51fb22017-09-04 23:12:16 +03002436 if (ov_noffset < 0) {
2437 printf("load of %s failed\n", uname);
2438 continue;
2439 }
2440 debug("%s loaded at 0x%08lx len=0x%08lx\n",
2441 uname, ovload, ovlen);
2442 ov = map_sysmem(ovload, ovlen);
2443
Marek Vasutf7d24612021-06-11 04:09:56 +02002444 ovcopylen = ALIGN(fdt_totalsize(ov), SZ_4K);
2445 ovcopy = malloc(ovcopylen);
2446 if (!ovcopy) {
2447 printf("failed to duplicate DTO before application\n");
2448 fdt_noffset = -ENOMEM;
2449 goto out;
2450 }
2451
2452 err = fdt_open_into(ov, ovcopy, ovcopylen);
2453 if (err < 0) {
2454 printf("failed on fdt_open_into for DTO\n");
2455 fdt_noffset = err;
2456 goto out;
2457 }
2458
Pantelis Antoniou6e51fb22017-09-04 23:12:16 +03002459 base = map_sysmem(load, len + ovlen);
2460 err = fdt_open_into(base, base, len + ovlen);
2461 if (err < 0) {
2462 printf("failed on fdt_open_into\n");
2463 fdt_noffset = err;
2464 goto out;
2465 }
Marek Vasutf7d24612021-06-11 04:09:56 +02002466
Pantelis Antoniou6e51fb22017-09-04 23:12:16 +03002467 /* the verbose method prints out messages on error */
Marek Vasutf7d24612021-06-11 04:09:56 +02002468 err = fdt_overlay_apply_verbose(base, ovcopy);
Pantelis Antoniou6e51fb22017-09-04 23:12:16 +03002469 if (err < 0) {
2470 fdt_noffset = err;
2471 goto out;
2472 }
2473 fdt_pack(base);
2474 len = fdt_totalsize(base);
2475 }
2476#else
2477 printf("config with overlays but CONFIG_OF_LIBFDT_OVERLAY not set\n");
2478 fdt_noffset = -EBADF;
2479#endif
2480
2481out:
2482 if (datap)
2483 *datap = load;
2484 if (lenp)
2485 *lenp = len;
2486 if (fit_unamep)
2487 *fit_unamep = fit_uname;
2488 if (fit_uname_configp)
2489 *fit_uname_configp = fit_uname_config;
2490
Marek Vasutf7d24612021-06-11 04:09:56 +02002491#ifdef CONFIG_OF_LIBFDT_OVERLAY
Heinrich Schuchardtf5686462022-04-11 20:08:03 +02002492 free(ovcopy);
Marek Vasutf7d24612021-06-11 04:09:56 +02002493#endif
Heinrich Schuchardtf5686462022-04-11 20:08:03 +02002494 free(fit_uname_config_copy);
Pantelis Antoniou6e51fb22017-09-04 23:12:16 +03002495 return fdt_noffset;
2496}
2497#endif