summaryrefslogtreecommitdiff
path: root/include/image.h
blob: e4c6a50b885ffc603b45ae37ecd5f3541395d6cd (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331
1332
1333
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356
1357
1358
1359
1360
1361
1362
1363
1364
1365
1366
1367
1368
1369
1370
1371
1372
1373
1374
1375
1376
1377
1378
1379
1380
1381
1382
1383
1384
1385
1386
1387
1388
1389
1390
1391
1392
1393
1394
1395
1396
1397
1398
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416
1417
1418
1419
1420
1421
1422
1423
1424
1425
1426
1427
1428
1429
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444
1445
1446
1447
1448
1449
1450
1451
1452
1453
1454
1455
1456
1457
1458
1459
1460
1461
1462
1463
1464
1465
1466
1467
1468
1469
1470
1471
1472
1473
1474
1475
1476
1477
1478
1479
1480
1481
1482
1483
1484
1485
1486
1487
1488
1489
1490
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500
1501
1502
1503
1504
1505
1506
1507
1508
1509
1510
1511
1512
1513
1514
1515
1516
1517
1518
1519
1520
1521
1522
1523
1524
1525
1526
1527
1528
1529
1530
1531
1532
1533
1534
1535
1536
1537
1538
1539
1540
1541
1542
1543
1544
1545
1546
1547
1548
1549
1550
1551
1552
1553
1554
1555
1556
1557
1558
1559
1560
1561
1562
1563
1564
1565
1566
1567
1568
1569
1570
1571
1572
1573
1574
1575
1576
1577
1578
1579
1580
1581
1582
1583
1584
1585
1586
1587
1588
1589
1590
1591
1592
/* SPDX-License-Identifier: GPL-2.0+ */
/*
 * (C) Copyright 2008 Semihalf
 *
 * (C) Copyright 2000-2005
 * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
 ********************************************************************
 * NOTE: This header file defines an interface to U-Boot. Including
 * this (unmodified) header file in another file is considered normal
 * use of U-Boot, and does *not* fall under the heading of "derived
 * work".
 ********************************************************************
 */

#ifndef __IMAGE_H__
#define __IMAGE_H__

#include "compiler.h"
#include <asm/byteorder.h>
#include <stdbool.h>

/* Define this to avoid #ifdefs later on */
struct lmb;
struct fdt_region;

#ifdef USE_HOSTCC
#include <sys/types.h>
#include <linux/kconfig.h>

#define IMAGE_INDENT_STRING	""

#else

#include <lmb.h>
#include <asm/u-boot.h>
#include <command.h>
#include <linker_lists.h>

#define IMAGE_INDENT_STRING	"   "

#endif /* USE_HOSTCC */

#include <hash.h>
#include <linux/libfdt.h>
#include <fdt_support.h>
#include <u-boot/hash-checksum.h>

extern ulong image_load_addr;		/* Default Load Address */
extern ulong image_save_addr;		/* Default Save Address */
extern ulong image_save_size;		/* Default Save Size */
extern ulong image_load_offset;	/* Default Load Address Offset */

/* An invalid size, meaning that the image size is not known */
#define IMAGE_SIZE_INVAL	(-1UL)

enum ih_category {
	IH_ARCH,
	IH_COMP,
	IH_OS,
	IH_TYPE,

	IH_COUNT,
};

/*
 * Operating System Codes
 *
 * The following are exposed to uImage header.
 * New IDs *MUST* be appended at the end of the list and *NEVER*
 * inserted for backward compatibility.
 */
enum {
	IH_OS_INVALID		= 0,	/* Invalid OS	*/
	IH_OS_OPENBSD,			/* OpenBSD	*/
	IH_OS_NETBSD,			/* NetBSD	*/
	IH_OS_FREEBSD,			/* FreeBSD	*/
	IH_OS_4_4BSD,			/* 4.4BSD	*/
	IH_OS_LINUX,			/* Linux	*/
	IH_OS_SVR4,			/* SVR4		*/
	IH_OS_ESIX,			/* Esix		*/
	IH_OS_SOLARIS,			/* Solaris	*/
	IH_OS_IRIX,			/* Irix		*/
	IH_OS_SCO,			/* SCO		*/
	IH_OS_DELL,			/* Dell		*/
	IH_OS_NCR,			/* NCR		*/
	IH_OS_LYNXOS,			/* LynxOS	*/
	IH_OS_VXWORKS,			/* VxWorks	*/
	IH_OS_PSOS,			/* pSOS		*/
	IH_OS_QNX,			/* QNX		*/
	IH_OS_U_BOOT,			/* Firmware	*/
	IH_OS_RTEMS,			/* RTEMS	*/
	IH_OS_ARTOS,			/* ARTOS	*/
	IH_OS_UNITY,			/* Unity OS	*/
	IH_OS_INTEGRITY,		/* INTEGRITY	*/
	IH_OS_OSE,			/* OSE		*/
	IH_OS_PLAN9,			/* Plan 9	*/
	IH_OS_OPENRTOS,		/* OpenRTOS	*/
	IH_OS_ARM_TRUSTED_FIRMWARE,     /* ARM Trusted Firmware */
	IH_OS_TEE,			/* Trusted Execution Environment */
	IH_OS_OPENSBI,			/* RISC-V OpenSBI */
	IH_OS_EFI,			/* EFI Firmware (e.g. GRUB2) */

	IH_OS_COUNT,
};

/*
 * CPU Architecture Codes (supported by Linux)
 *
 * The following are exposed to uImage header.
 * New IDs *MUST* be appended at the end of the list and *NEVER*
 * inserted for backward compatibility.
 */
enum {
	IH_ARCH_INVALID		= 0,	/* Invalid CPU	*/
	IH_ARCH_ALPHA,			/* Alpha	*/
	IH_ARCH_ARM,			/* ARM		*/
	IH_ARCH_I386,			/* Intel x86	*/
	IH_ARCH_IA64,			/* IA64		*/
	IH_ARCH_MIPS,			/* MIPS		*/
	IH_ARCH_MIPS64,			/* MIPS	 64 Bit */
	IH_ARCH_PPC,			/* PowerPC	*/
	IH_ARCH_S390,			/* IBM S390	*/
	IH_ARCH_SH,			/* SuperH	*/
	IH_ARCH_SPARC,			/* Sparc	*/
	IH_ARCH_SPARC64,		/* Sparc 64 Bit */
	IH_ARCH_M68K,			/* M68K		*/
	IH_ARCH_NIOS,			/* Nios-32	*/
	IH_ARCH_MICROBLAZE,		/* MicroBlaze   */
	IH_ARCH_NIOS2,			/* Nios-II	*/
	IH_ARCH_BLACKFIN,		/* Blackfin	*/
	IH_ARCH_AVR32,			/* AVR32	*/
	IH_ARCH_ST200,			/* STMicroelectronics ST200  */
	IH_ARCH_SANDBOX,		/* Sandbox architecture (test only) */
	IH_ARCH_NDS32,			/* ANDES Technology - NDS32  */
	IH_ARCH_OPENRISC,		/* OpenRISC 1000  */
	IH_ARCH_ARM64,			/* ARM64	*/
	IH_ARCH_ARC,			/* Synopsys DesignWare ARC */
	IH_ARCH_X86_64,			/* AMD x86_64, Intel and Via */
	IH_ARCH_XTENSA,			/* Xtensa	*/
	IH_ARCH_RISCV,			/* RISC-V */

	IH_ARCH_COUNT,
};

/*
 * Image Types
 *
 * "Standalone Programs" are directly runnable in the environment
 *	provided by U-Boot; it is expected that (if they behave
 *	well) you can continue to work in U-Boot after return from
 *	the Standalone Program.
 * "OS Kernel Images" are usually images of some Embedded OS which
 *	will take over control completely. Usually these programs
 *	will install their own set of exception handlers, device
 *	drivers, set up the MMU, etc. - this means, that you cannot
 *	expect to re-enter U-Boot except by resetting the CPU.
 * "RAMDisk Images" are more or less just data blocks, and their
 *	parameters (address, size) are passed to an OS kernel that is
 *	being started.
 * "Multi-File Images" contain several images, typically an OS
 *	(Linux) kernel image and one or more data images like
 *	RAMDisks. This construct is useful for instance when you want
 *	to boot over the network using BOOTP etc., where the boot
 *	server provides just a single image file, but you want to get
 *	for instance an OS kernel and a RAMDisk image.
 *
 *	"Multi-File Images" start with a list of image sizes, each
 *	image size (in bytes) specified by an "uint32_t" in network
 *	byte order. This list is terminated by an "(uint32_t)0".
 *	Immediately after the terminating 0 follow the images, one by
 *	one, all aligned on "uint32_t" boundaries (size rounded up to
 *	a multiple of 4 bytes - except for the last file).
 *
 * "Firmware Images" are binary images containing firmware (like
 *	U-Boot or FPGA images) which usually will be programmed to
 *	flash memory.
 *
 * "Script files" are command sequences that will be executed by
 *	U-Boot's command interpreter; this feature is especially
 *	useful when you configure U-Boot to use a real shell (hush)
 *	as command interpreter (=> Shell Scripts).
 *
 * The following are exposed to uImage header.
 * New IDs *MUST* be appended at the end of the list and *NEVER*
 * inserted for backward compatibility.
 */

enum {
	IH_TYPE_INVALID		= 0,	/* Invalid Image		*/
	IH_TYPE_STANDALONE,		/* Standalone Program		*/
	IH_TYPE_KERNEL,			/* OS Kernel Image		*/
	IH_TYPE_RAMDISK,		/* RAMDisk Image		*/
	IH_TYPE_MULTI,			/* Multi-File Image		*/
	IH_TYPE_FIRMWARE,		/* Firmware Image		*/
	IH_TYPE_SCRIPT,			/* Script file			*/
	IH_TYPE_FILESYSTEM,		/* Filesystem Image (any type)	*/
	IH_TYPE_FLATDT,			/* Binary Flat Device Tree Blob	*/
	IH_TYPE_KWBIMAGE,		/* Kirkwood Boot Image		*/
	IH_TYPE_IMXIMAGE,		/* Freescale IMXBoot Image	*/
	IH_TYPE_UBLIMAGE,		/* Davinci UBL Image		*/
	IH_TYPE_OMAPIMAGE,		/* TI OMAP Config Header Image	*/
	IH_TYPE_AISIMAGE,		/* TI Davinci AIS Image		*/
	/* OS Kernel Image, can run from any load address */
	IH_TYPE_KERNEL_NOLOAD,
	IH_TYPE_PBLIMAGE,		/* Freescale PBL Boot Image	*/
	IH_TYPE_MXSIMAGE,		/* Freescale MXSBoot Image	*/
	IH_TYPE_GPIMAGE,		/* TI Keystone GPHeader Image	*/
	IH_TYPE_ATMELIMAGE,		/* ATMEL ROM bootable Image	*/
	IH_TYPE_SOCFPGAIMAGE,		/* Altera SOCFPGA CV/AV Preloader */
	IH_TYPE_X86_SETUP,		/* x86 setup.bin Image		*/
	IH_TYPE_LPC32XXIMAGE,		/* x86 setup.bin Image		*/
	IH_TYPE_LOADABLE,		/* A list of typeless images	*/
	IH_TYPE_RKIMAGE,		/* Rockchip Boot Image		*/
	IH_TYPE_RKSD,			/* Rockchip SD card		*/
	IH_TYPE_RKSPI,			/* Rockchip SPI image		*/
	IH_TYPE_ZYNQIMAGE,		/* Xilinx Zynq Boot Image */
	IH_TYPE_ZYNQMPIMAGE,		/* Xilinx ZynqMP Boot Image */
	IH_TYPE_ZYNQMPBIF,		/* Xilinx ZynqMP Boot Image (bif) */
	IH_TYPE_FPGA,			/* FPGA Image */
	IH_TYPE_VYBRIDIMAGE,	/* VYBRID .vyb Image */
	IH_TYPE_TEE,            /* Trusted Execution Environment OS Image */
	IH_TYPE_FIRMWARE_IVT,		/* Firmware Image with HABv4 IVT */
	IH_TYPE_PMMC,            /* TI Power Management Micro-Controller Firmware */
	IH_TYPE_STM32IMAGE,		/* STMicroelectronics STM32 Image */
	IH_TYPE_SOCFPGAIMAGE_V1,	/* Altera SOCFPGA A10 Preloader	*/
	IH_TYPE_MTKIMAGE,		/* MediaTek BootROM loadable Image */
	IH_TYPE_IMX8MIMAGE,		/* Freescale IMX8MBoot Image	*/
	IH_TYPE_IMX8IMAGE,		/* Freescale IMX8Boot Image	*/
	IH_TYPE_COPRO,			/* Coprocessor Image for remoteproc*/
	IH_TYPE_SUNXI_EGON,		/* Allwinner eGON Boot Image */
	IH_TYPE_SUNXI_TOC0,		/* Allwinner TOC0 Boot Image */

	IH_TYPE_COUNT,			/* Number of image types */
};

/*
 * Compression Types
 *
 * The following are exposed to uImage header.
 * New IDs *MUST* be appended at the end of the list and *NEVER*
 * inserted for backward compatibility.
 */
enum {
	IH_COMP_NONE		= 0,	/*  No	 Compression Used	*/
	IH_COMP_GZIP,			/* gzip	 Compression Used	*/
	IH_COMP_BZIP2,			/* bzip2 Compression Used	*/
	IH_COMP_LZMA,			/* lzma  Compression Used	*/
	IH_COMP_LZO,			/* lzo   Compression Used	*/
	IH_COMP_LZ4,			/* lz4   Compression Used	*/
	IH_COMP_ZSTD,			/* zstd   Compression Used	*/

	IH_COMP_COUNT,
};

#define LZ4F_MAGIC	0x184D2204	/* LZ4 Magic Number		*/
#define IH_MAGIC	0x27051956	/* Image Magic Number		*/
#define IH_NMLEN		32	/* Image Name Length		*/

/* Reused from common.h */
#define ROUND(a, b)		(((a) + (b) - 1) & ~((b) - 1))

/*
 * Legacy format image header,
 * all data in network byte order (aka natural aka bigendian).
 */
typedef struct image_header {
	uint32_t	ih_magic;	/* Image Header Magic Number	*/
	uint32_t	ih_hcrc;	/* Image Header CRC Checksum	*/
	uint32_t	ih_time;	/* Image Creation Timestamp	*/
	uint32_t	ih_size;	/* Image Data Size		*/
	uint32_t	ih_load;	/* Data	 Load  Address		*/
	uint32_t	ih_ep;		/* Entry Point Address		*/
	uint32_t	ih_dcrc;	/* Image Data CRC Checksum	*/
	uint8_t		ih_os;		/* Operating System		*/
	uint8_t		ih_arch;	/* CPU architecture		*/
	uint8_t		ih_type;	/* Image Type			*/
	uint8_t		ih_comp;	/* Compression Type		*/
	uint8_t		ih_name[IH_NMLEN];	/* Image Name		*/
} image_header_t;

typedef struct image_info {
	ulong		start, end;		/* start/end of blob */
	ulong		image_start, image_len; /* start of image within blob, len of image */
	ulong		load;			/* load addr for the image */
	uint8_t		comp, type, os;		/* compression, type of image, os type */
	uint8_t		arch;			/* CPU architecture */
} image_info_t;

/*
 * Legacy and FIT format headers used by do_bootm() and do_bootm_<os>()
 * routines.
 */
typedef struct bootm_headers {
	/*
	 * Legacy os image header, if it is a multi component image
	 * then boot_get_ramdisk() and get_fdt() will attempt to get
	 * data from second and third component accordingly.
	 */
	image_header_t	*legacy_hdr_os;		/* image header pointer */
	image_header_t	legacy_hdr_os_copy;	/* header copy */
	ulong		legacy_hdr_valid;

	/*
	 * The fit_ members are only used with FIT, but it involves a lot of
	 * #ifdefs to avoid compiling that code. Since FIT is the standard
	 * format, even for SPL, this extra data size seems worth it.
	 */
	const char	*fit_uname_cfg;	/* configuration node unit name */

	void		*fit_hdr_os;	/* os FIT image header */
	const char	*fit_uname_os;	/* os subimage node unit name */
	int		fit_noffset_os;	/* os subimage node offset */

	void		*fit_hdr_rd;	/* init ramdisk FIT image header */
	const char	*fit_uname_rd;	/* init ramdisk subimage node unit name */
	int		fit_noffset_rd;	/* init ramdisk subimage node offset */

	void		*fit_hdr_fdt;	/* FDT blob FIT image header */
	const char	*fit_uname_fdt;	/* FDT blob subimage node unit name */
	int		fit_noffset_fdt;/* FDT blob subimage node offset */

	void		*fit_hdr_setup;	/* x86 setup FIT image header */
	const char	*fit_uname_setup; /* x86 setup subimage node name */
	int		fit_noffset_setup;/* x86 setup subimage node offset */

#ifndef USE_HOSTCC
	image_info_t	os;		/* os image info */
	ulong		ep;		/* entry point of OS */

	ulong		rd_start, rd_end;/* ramdisk start/end */

	char		*ft_addr;	/* flat dev tree address */
	ulong		ft_len;		/* length of flat device tree */

	ulong		initrd_start;
	ulong		initrd_end;
	ulong		cmdline_start;
	ulong		cmdline_end;
	struct bd_info		*kbd;
#endif

	int		verify;		/* env_get("verify")[0] != 'n' */

#define	BOOTM_STATE_START	(0x00000001)
#define	BOOTM_STATE_FINDOS	(0x00000002)
#define	BOOTM_STATE_FINDOTHER	(0x00000004)
#define	BOOTM_STATE_LOADOS	(0x00000008)
#define	BOOTM_STATE_RAMDISK	(0x00000010)
#define	BOOTM_STATE_FDT		(0x00000020)
#define	BOOTM_STATE_OS_CMDLINE	(0x00000040)
#define	BOOTM_STATE_OS_BD_T	(0x00000080)
#define	BOOTM_STATE_OS_PREP	(0x00000100)
#define	BOOTM_STATE_OS_FAKE_GO	(0x00000200)	/* 'Almost' run the OS */
#define	BOOTM_STATE_OS_GO	(0x00000400)
#define	BOOTM_STATE_PRE_LOAD	0x00000800
	int		state;

#if defined(CONFIG_LMB) && !defined(USE_HOSTCC)
	struct lmb	lmb;		/* for memory mgmt */
#endif
} bootm_headers_t;

extern bootm_headers_t images;

/*
 * Some systems (for example LWMON) have very short watchdog periods;
 * we must make sure to split long operations like memmove() or
 * checksum calculations into reasonable chunks.
 */
#ifndef CHUNKSZ
#define CHUNKSZ (64 * 1024)
#endif

#ifndef CHUNKSZ_CRC32
#define CHUNKSZ_CRC32 (64 * 1024)
#endif

#ifndef CHUNKSZ_MD5
#define CHUNKSZ_MD5 (64 * 1024)
#endif

#ifndef CHUNKSZ_SHA1
#define CHUNKSZ_SHA1 (64 * 1024)
#endif

#define uimage_to_cpu(x)		be32_to_cpu(x)
#define cpu_to_uimage(x)		cpu_to_be32(x)

/*
 * Translation table for entries of a specific type; used by
 * get_table_entry_id() and get_table_entry_name().
 */
typedef struct table_entry {
	int	id;
	char	*sname;		/* short (input) name to find table entry */
	char	*lname;		/* long (output) name to print for messages */
} table_entry_t;

/*
 * Compression type and magic number mapping table.
 */
struct comp_magic_map {
	int		comp_id;
	const char	*name;
	unsigned char	magic[2];
};

/*
 * get_table_entry_id() scans the translation table trying to find an
 * entry that matches the given short name. If a matching entry is
 * found, it's id is returned to the caller.
 */
int get_table_entry_id(const table_entry_t *table,
		const char *table_name, const char *name);
/*
 * get_table_entry_name() scans the translation table trying to find
 * an entry that matches the given id. If a matching entry is found,
 * its long name is returned to the caller.
 */
char *get_table_entry_name(const table_entry_t *table, char *msg, int id);

const char *genimg_get_os_name(uint8_t os);

/**
 * genimg_get_os_short_name() - get the short name for an OS
 *
 * @param os	OS (IH_OS_...)
 * Return: OS short name, or "unknown" if unknown
 */
const char *genimg_get_os_short_name(uint8_t comp);

const char *genimg_get_arch_name(uint8_t arch);

/**
 * genimg_get_arch_short_name() - get the short name for an architecture
 *
 * @param arch	Architecture type (IH_ARCH_...)
 * Return: architecture short name, or "unknown" if unknown
 */
const char *genimg_get_arch_short_name(uint8_t arch);

const char *genimg_get_type_name(uint8_t type);

/**
 * genimg_get_type_short_name() - get the short name for an image type
 *
 * @param type	Image type (IH_TYPE_...)
 * Return: image short name, or "unknown" if unknown
 */
const char *genimg_get_type_short_name(uint8_t type);

const char *genimg_get_comp_name(uint8_t comp);

/**
 * genimg_get_comp_short_name() - get the short name for a compression method
 *
 * @param comp	compression method (IH_COMP_...)
 * Return: compression method short name, or "unknown" if unknown
 */
const char *genimg_get_comp_short_name(uint8_t comp);

/**
 * genimg_get_cat_name() - Get the name of an item in a category
 *
 * @category:	Category of item
 * @id:		Item ID
 * Return: name of item, or "Unknown ..." if unknown
 */
const char *genimg_get_cat_name(enum ih_category category, uint id);

/**
 * genimg_get_cat_short_name() - Get the short name of an item in a category
 *
 * @category:	Category of item
 * @id:		Item ID
 * Return: short name of item, or "Unknown ..." if unknown
 */
const char *genimg_get_cat_short_name(enum ih_category category, uint id);

/**
 * genimg_get_cat_count() - Get the number of items in a category
 *
 * @category:	Category to check
 * Return: the number of items in the category (IH_xxx_COUNT)
 */
int genimg_get_cat_count(enum ih_category category);

/**
 * genimg_get_cat_desc() - Get the description of a category
 *
 * @category:	Category to check
 * Return: the description of a category, e.g. "architecture". This
 * effectively converts the enum to a string.
 */
const char *genimg_get_cat_desc(enum ih_category category);

/**
 * genimg_cat_has_id() - Check whether a category has an item
 *
 * @category:	Category to check
 * @id:		Item ID
 * Return: true or false as to whether a category has an item
 */
bool genimg_cat_has_id(enum ih_category category, uint id);

int genimg_get_os_id(const char *name);
int genimg_get_arch_id(const char *name);
int genimg_get_type_id(const char *name);
int genimg_get_comp_id(const char *name);
void genimg_print_size(uint32_t size);

#if defined(CONFIG_TIMESTAMP) || defined(CONFIG_CMD_DATE) || defined(USE_HOSTCC)
#define IMAGE_ENABLE_TIMESTAMP 1
#else
#define IMAGE_ENABLE_TIMESTAMP 0
#endif
void genimg_print_time(time_t timestamp);

/* What to do with a image load address ('load = <> 'in the FIT) */
enum fit_load_op {
	FIT_LOAD_IGNORED,	/* Ignore load address */
	FIT_LOAD_OPTIONAL,	/* Can be provided, but optional */
	FIT_LOAD_OPTIONAL_NON_ZERO,	/* Optional, a value of 0 is ignored */
	FIT_LOAD_REQUIRED,	/* Must be provided */
};

int boot_get_setup(bootm_headers_t *images, uint8_t arch, ulong *setup_start,
		   ulong *setup_len);

/* Image format types, returned by _get_format() routine */
#define IMAGE_FORMAT_INVALID	0x00
#define IMAGE_FORMAT_LEGACY	0x01	/* legacy image_header based format */
#define IMAGE_FORMAT_FIT	0x02	/* new, libfdt based format */
#define IMAGE_FORMAT_ANDROID	0x03	/* Android boot image */

ulong genimg_get_kernel_addr_fit(char * const img_addr,
			         const char **fit_uname_config,
			         const char **fit_uname_kernel);
ulong genimg_get_kernel_addr(char * const img_addr);
int genimg_get_format(const void *img_addr);
int genimg_has_config(bootm_headers_t *images);

int boot_get_fpga(int argc, char *const argv[], bootm_headers_t *images,
		  uint8_t arch, const ulong *ld_start, ulong * const ld_len);
int boot_get_ramdisk(int argc, char *const argv[], bootm_headers_t *images,
		     uint8_t arch, ulong *rd_start, ulong *rd_end);

/**
 * boot_get_loadable - routine to load a list of binaries to memory
 * @argc: Ignored Argument
 * @argv: Ignored Argument
 * @images: pointer to the bootm images structure
 * @arch: expected architecture for the image
 * @ld_start: Ignored Argument
 * @ld_len: Ignored Argument
 *
 * boot_get_loadable() will take the given FIT configuration, and look
 * for a field named "loadables".  Loadables, is a list of elements in
 * the FIT given as strings.  exe:
 *   loadables = "linux_kernel", "fdt-2";
 * this function will attempt to parse each string, and load the
 * corresponding element from the FIT into memory.  Once placed,
 * no aditional actions are taken.
 *
 * @return:
 *     0, if only valid images or no images are found
 *     error code, if an error occurs during fit_image_load
 */
int boot_get_loadable(int argc, char *const argv[], bootm_headers_t *images,
		      uint8_t arch, const ulong *ld_start, ulong *const ld_len);

int boot_get_setup_fit(bootm_headers_t *images, uint8_t arch,
		       ulong *setup_start, ulong *setup_len);

/**
 * boot_get_fdt_fit() - load a DTB from a FIT file (applying overlays)
 *
 * This deals with all aspects of loading an DTB from a FIT.
 * The correct base image based on configuration will be selected, and
 * then any overlays specified will be applied (as present in fit_uname_configp).
 *
 * @param images	Boot images structure
 * @param addr		Address of FIT in memory
 * @param fit_unamep	On entry this is the requested image name
 *			(e.g. "kernel") or NULL to use the default. On exit
 *			points to the selected image name
 * @param fit_uname_configp	On entry this is the requested configuration
 *			name (e.g. "conf-1") or NULL to use the default. On
 *			exit points to the selected configuration name.
 * @param arch		Expected architecture (IH_ARCH_...)
 * @param datap		Returns address of loaded image
 * @param lenp		Returns length of loaded image
 *
 * Return: node offset of base image, or -ve error code on error
 */
int boot_get_fdt_fit(bootm_headers_t *images, ulong addr,
		   const char **fit_unamep, const char **fit_uname_configp,
		   int arch, ulong *datap, ulong *lenp);

/**
 * fit_image_load() - load an image from a FIT
 *
 * This deals with all aspects of loading an image from a FIT, including
 * selecting the right image based on configuration, verifying it, printing
 * out progress messages, checking the type/arch/os and optionally copying it
 * to the right load address.
 *
 * The property to look up is defined by image_type.
 *
 * @param images	Boot images structure
 * @param addr		Address of FIT in memory
 * @param fit_unamep	On entry this is the requested image name
 *			(e.g. "kernel") or NULL to use the default. On exit
 *			points to the selected image name
 * @param fit_uname_configp	On entry this is the requested configuration
 *			name (e.g. "conf-1") or NULL to use the default. On
 *			exit points to the selected configuration name.
 * @param arch		Expected architecture (IH_ARCH_...)
 * @param image_type	Required image type (IH_TYPE_...). If this is
 *			IH_TYPE_KERNEL then we allow IH_TYPE_KERNEL_NOLOAD
 *			also.
 * @param bootstage_id	ID of starting bootstage to use for progress updates.
 *			This will be added to the BOOTSTAGE_SUB values when
 *			calling bootstage_mark()
 * @param load_op	Decribes what to do with the load address
 * @param datap		Returns address of loaded image
 * @param lenp		Returns length of loaded image
 * Return: node offset of image, or -ve error code on error
 */
int fit_image_load(bootm_headers_t *images, ulong addr,
		   const char **fit_unamep, const char **fit_uname_configp,
		   int arch, int image_type, int bootstage_id,
		   enum fit_load_op load_op, ulong *datap, ulong *lenp);

/**
 * image_source_script() - Execute a script
 *
 * Executes a U-Boot script at a particular address in memory. The script should
 * have a header (FIT or legacy) with the script type (IH_TYPE_SCRIPT).
 *
 * @addr: Address of script
 * @fit_uname: FIT subimage name
 * Return: result code (enum command_ret_t)
 */
int image_source_script(ulong addr, const char *fit_uname);

/**
 * fit_get_node_from_config() - Look up an image a FIT by type
 *
 * This looks in the selected conf- node (images->fit_uname_cfg) for a
 * particular image type (e.g. "kernel") and then finds the image that is
 * referred to.
 *
 * For example, for something like:
 *
 * images {
 *	kernel {
 *		...
 *	};
 * };
 * configurations {
 *	conf-1 {
 *		kernel = "kernel";
 *	};
 * };
 *
 * the function will return the node offset of the kernel@1 node, assuming
 * that conf-1 is the chosen configuration.
 *
 * @param images	Boot images structure
 * @param prop_name	Property name to look up (FIT_..._PROP)
 * @param addr		Address of FIT in memory
 */
int fit_get_node_from_config(bootm_headers_t *images, const char *prop_name,
			ulong addr);

int boot_get_fdt(int flag, int argc, char *const argv[], uint8_t arch,
		 bootm_headers_t *images,
		 char **of_flat_tree, ulong *of_size);
void boot_fdt_add_mem_rsv_regions(struct lmb *lmb, void *fdt_blob);
int boot_relocate_fdt(struct lmb *lmb, char **of_flat_tree, ulong *of_size);

int boot_ramdisk_high(struct lmb *lmb, ulong rd_data, ulong rd_len,
		  ulong *initrd_start, ulong *initrd_end);
int boot_get_cmdline(struct lmb *lmb, ulong *cmd_start, ulong *cmd_end);
int boot_get_kbd(struct lmb *lmb, struct bd_info **kbd);

/*******************************************************************/
/* Legacy format specific code (prefixed with image_) */
/*******************************************************************/
static inline uint32_t image_get_header_size(void)
{
	return (sizeof(image_header_t));
}

#define image_get_hdr_l(f) \
	static inline uint32_t image_get_##f(const image_header_t *hdr) \
	{ \
		return uimage_to_cpu(hdr->ih_##f); \
	}
image_get_hdr_l(magic)		/* image_get_magic */
image_get_hdr_l(hcrc)		/* image_get_hcrc */
image_get_hdr_l(time)		/* image_get_time */
image_get_hdr_l(size)		/* image_get_size */
image_get_hdr_l(load)		/* image_get_load */
image_get_hdr_l(ep)		/* image_get_ep */
image_get_hdr_l(dcrc)		/* image_get_dcrc */

#define image_get_hdr_b(f) \
	static inline uint8_t image_get_##f(const image_header_t *hdr) \
	{ \
		return hdr->ih_##f; \
	}
image_get_hdr_b(os)		/* image_get_os */
image_get_hdr_b(arch)		/* image_get_arch */
image_get_hdr_b(type)		/* image_get_type */
image_get_hdr_b(comp)		/* image_get_comp */

static inline char *image_get_name(const image_header_t *hdr)
{
	return (char *)hdr->ih_name;
}

static inline uint32_t image_get_data_size(const image_header_t *hdr)
{
	return image_get_size(hdr);
}

/**
 * image_get_data - get image payload start address
 * @hdr: image header
 *
 * image_get_data() returns address of the image payload. For single
 * component images it is image data start. For multi component
 * images it points to the null terminated table of sub-images sizes.
 *
 * returns:
 *     image payload data start address
 */
static inline ulong image_get_data(const image_header_t *hdr)
{
	return ((ulong)hdr + image_get_header_size());
}

static inline uint32_t image_get_image_size(const image_header_t *hdr)
{
	return (image_get_size(hdr) + image_get_header_size());
}
static inline ulong image_get_image_end(const image_header_t *hdr)
{
	return ((ulong)hdr + image_get_image_size(hdr));
}

#define image_set_hdr_l(f) \
	static inline void image_set_##f(image_header_t *hdr, uint32_t val) \
	{ \
		hdr->ih_##f = cpu_to_uimage(val); \
	}
image_set_hdr_l(magic)		/* image_set_magic */
image_set_hdr_l(hcrc)		/* image_set_hcrc */
image_set_hdr_l(time)		/* image_set_time */
image_set_hdr_l(size)		/* image_set_size */
image_set_hdr_l(load)		/* image_set_load */
image_set_hdr_l(ep)		/* image_set_ep */
image_set_hdr_l(dcrc)		/* image_set_dcrc */

#define image_set_hdr_b(f) \
	static inline void image_set_##f(image_header_t *hdr, uint8_t val) \
	{ \
		hdr->ih_##f = val; \
	}
image_set_hdr_b(os)		/* image_set_os */
image_set_hdr_b(arch)		/* image_set_arch */
image_set_hdr_b(type)		/* image_set_type */
image_set_hdr_b(comp)		/* image_set_comp */

static inline void image_set_name(image_header_t *hdr, const char *name)
{
	strncpy(image_get_name(hdr), name, IH_NMLEN);
}

int image_check_hcrc(const image_header_t *hdr);
int image_check_dcrc(const image_header_t *hdr);
#ifndef USE_HOSTCC
ulong env_get_bootm_low(void);
phys_size_t env_get_bootm_size(void);
phys_size_t env_get_bootm_mapsize(void);
#endif
void memmove_wd(void *to, void *from, size_t len, ulong chunksz);

static inline int image_check_magic(const image_header_t *hdr)
{
	return (image_get_magic(hdr) == IH_MAGIC);
}
static inline int image_check_type(const image_header_t *hdr, uint8_t type)
{
	return (image_get_type(hdr) == type);
}
static inline int image_check_arch(const image_header_t *hdr, uint8_t arch)
{
	/* Let's assume that sandbox can load any architecture */
	if (!tools_build() && IS_ENABLED(CONFIG_SANDBOX))
		return true;
	return (image_get_arch(hdr) == arch) ||
		(image_get_arch(hdr) == IH_ARCH_ARM && arch == IH_ARCH_ARM64);
}
static inline int image_check_os(const image_header_t *hdr, uint8_t os)
{
	return (image_get_os(hdr) == os);
}

ulong image_multi_count(const image_header_t *hdr);
void image_multi_getimg(const image_header_t *hdr, ulong idx,
			ulong *data, ulong *len);

void image_print_contents(const void *hdr);

#ifndef USE_HOSTCC
static inline int image_check_target_arch(const image_header_t *hdr)
{
#ifndef IH_ARCH_DEFAULT
# error "please define IH_ARCH_DEFAULT in your arch asm/u-boot.h"
#endif
	return image_check_arch(hdr, IH_ARCH_DEFAULT);
}
#endif /* USE_HOSTCC */

/**
 * image_decomp_type() - Find out compression type of an image
 *
 * @buf:	Address in U-Boot memory where image is loaded.
 * @len:	Length of the compressed image.
 * Return:	compression type or IH_COMP_NONE if not compressed.
 *
 * Note: Only following compression types are supported now.
 * lzo, lzma, gzip, bzip2
 */
int image_decomp_type(const unsigned char *buf, ulong len);

/**
 * image_decomp() - decompress an image
 *
 * @comp:	Compression algorithm that is used (IH_COMP_...)
 * @load:	Destination load address in U-Boot memory
 * @image_start Image start address (where we are decompressing from)
 * @type:	OS type (IH_OS_...)
 * @load_bug:	Place to decompress to
 * @image_buf:	Address to decompress from
 * @image_len:	Number of bytes in @image_buf to decompress
 * @unc_len:	Available space for decompression
 * Return: 0 if OK, -ve on error (BOOTM_ERR_...)
 */
int image_decomp(int comp, ulong load, ulong image_start, int type,
		 void *load_buf, void *image_buf, ulong image_len,
		 uint unc_len, ulong *load_end);

/**
 * Set up properties in the FDT
 *
 * This sets up properties in the FDT that is to be passed to linux.
 *
 * @images:	Images information
 * @blob:	FDT to update
 * @of_size:	Size of the FDT
 * @lmb:	Points to logical memory block structure
 * Return: 0 if ok, <0 on failure
 */
int image_setup_libfdt(bootm_headers_t *images, void *blob,
		       int of_size, struct lmb *lmb);

/**
 * Set up the FDT to use for booting a kernel
 *
 * This performs ramdisk setup, sets up the FDT if required, and adds
 * paramters to the FDT if libfdt is available.
 *
 * @param images	Images information
 * Return: 0 if ok, <0 on failure
 */
int image_setup_linux(bootm_headers_t *images);

/**
 * bootz_setup() - Extract stat and size of a Linux xImage
 *
 * @image: Address of image
 * @start: Returns start address of image
 * @end : Returns end address of image
 * Return: 0 if OK, 1 if the image was not recognised
 */
int bootz_setup(ulong image, ulong *start, ulong *end);

/**
 * Return the correct start address and size of a Linux aarch64 Image.
 *
 * @image: Address of image
 * @start: Returns start address of image
 * @size : Returns size image
 * @force_reloc: Ignore image->ep field, always place image to RAM start
 * Return: 0 if OK, 1 if the image was not recognised
 */
int booti_setup(ulong image, ulong *relocated_addr, ulong *size,
		bool force_reloc);

/*******************************************************************/
/* New uImage format specific code (prefixed with fit_) */
/*******************************************************************/

#define FIT_IMAGES_PATH		"/images"
#define FIT_CONFS_PATH		"/configurations"

/* hash/signature/key node */
#define FIT_HASH_NODENAME	"hash"
#define FIT_ALGO_PROP		"algo"
#define FIT_VALUE_PROP		"value"
#define FIT_IGNORE_PROP		"uboot-ignore"
#define FIT_SIG_NODENAME	"signature"
#define FIT_KEY_REQUIRED	"required"
#define FIT_KEY_HINT		"key-name-hint"

/* cipher node */
#define FIT_CIPHER_NODENAME	"cipher"
#define FIT_ALGO_PROP		"algo"

/* image node */
#define FIT_DATA_PROP		"data"
#define FIT_DATA_POSITION_PROP	"data-position"
#define FIT_DATA_OFFSET_PROP	"data-offset"
#define FIT_DATA_SIZE_PROP	"data-size"
#define FIT_TIMESTAMP_PROP	"timestamp"
#define FIT_DESC_PROP		"description"
#define FIT_ARCH_PROP		"arch"
#define FIT_TYPE_PROP		"type"
#define FIT_OS_PROP		"os"
#define FIT_COMP_PROP		"compression"
#define FIT_ENTRY_PROP		"entry"
#define FIT_LOAD_PROP		"load"

/* configuration node */
#define FIT_KERNEL_PROP		"kernel"
#define FIT_RAMDISK_PROP	"ramdisk"
#define FIT_FDT_PROP		"fdt"
#define FIT_LOADABLE_PROP	"loadables"
#define FIT_DEFAULT_PROP	"default"
#define FIT_SETUP_PROP		"setup"
#define FIT_FPGA_PROP		"fpga"
#define FIT_FIRMWARE_PROP	"firmware"
#define FIT_STANDALONE_PROP	"standalone"

#define FIT_MAX_HASH_LEN	HASH_MAX_DIGEST_SIZE

/* cmdline argument format parsing */
int fit_parse_conf(const char *spec, ulong addr_curr,
		ulong *addr, const char **conf_name);
int fit_parse_subimage(const char *spec, ulong addr_curr,
		ulong *addr, const char **image_name);

int fit_get_subimage_count(const void *fit, int images_noffset);
void fit_print_contents(const void *fit);
void fit_image_print(const void *fit, int noffset, const char *p);

/**
 * fit_get_end - get FIT image size
 * @fit: pointer to the FIT format image header
 *
 * returns:
 *     size of the FIT image (blob) in memory
 */
static inline ulong fit_get_size(const void *fit)
{
	return fdt_totalsize(fit);
}

/**
 * fit_get_end - get FIT image end
 * @fit: pointer to the FIT format image header
 *
 * returns:
 *     end address of the FIT image (blob) in memory
 */
ulong fit_get_end(const void *fit);

/**
 * fit_get_name - get FIT node name
 * @fit: pointer to the FIT format image header
 *
 * returns:
 *     NULL, on error
 *     pointer to node name, on success
 */
static inline const char *fit_get_name(const void *fit_hdr,
		int noffset, int *len)
{
	return fdt_get_name(fit_hdr, noffset, len);
}

int fit_get_desc(const void *fit, int noffset, char **desc);
int fit_get_timestamp(const void *fit, int noffset, time_t *timestamp);

int fit_image_get_node(const void *fit, const char *image_uname);
int fit_image_get_os(const void *fit, int noffset, uint8_t *os);
int fit_image_get_arch(const void *fit, int noffset, uint8_t *arch);
int fit_image_get_type(const void *fit, int noffset, uint8_t *type);
int fit_image_get_comp(const void *fit, int noffset, uint8_t *comp);
int fit_image_get_load(const void *fit, int noffset, ulong *load);
int fit_image_get_entry(const void *fit, int noffset, ulong *entry);
int fit_image_get_data(const void *fit, int noffset,
				const void **data, size_t *size);
int fit_image_get_data_offset(const void *fit, int noffset, int *data_offset);
int fit_image_get_data_position(const void *fit, int noffset,
				int *data_position);
int fit_image_get_data_size(const void *fit, int noffset, int *data_size);
int fit_image_get_data_size_unciphered(const void *fit, int noffset,
				       size_t *data_size);
int fit_image_get_data_and_size(const void *fit, int noffset,
				const void **data, size_t *size);

int fit_image_hash_get_algo(const void *fit, int noffset, const char **algo);
int fit_image_hash_get_value(const void *fit, int noffset, uint8_t **value,
				int *value_len);

int fit_set_timestamp(void *fit, int noffset, time_t timestamp);

/**
 * fit_pre_load_data() - add public key to fdt blob
 *
 * Adds public key to the node pre load.
 *
 * @keydir:	Directory containing keys
 * @keydest:	FDT blob to write public key
 * @fit:	Pointer to the FIT format image header
 *
 * returns:
 *	0, on success
 *	< 0, on failure
 */
int fit_pre_load_data(const char *keydir, void *keydest, void *fit);

int fit_cipher_data(const char *keydir, void *keydest, void *fit,
		    const char *comment, int require_keys,
		    const char *engine_id, const char *cmdname);

#define NODE_MAX_NAME_LEN	80

/**
 * struct image_summary  - Provides information about signing info added
 *
 * @sig_offset: Offset of the node in the blob devicetree where the signature
 *	was wriiten
 * @sig_path: Path to @sig_offset
 * @keydest_offset: Offset of the node in the keydest devicetree where the
 *	public key was written (-1 if none)
 * @keydest_path: Path to @keydest_offset
 */
struct image_summary {
	int sig_offset;
	char sig_path[NODE_MAX_NAME_LEN];
	int keydest_offset;
	char keydest_path[NODE_MAX_NAME_LEN];
};

/**
 * fit_add_verification_data() - add verification data to FIT image nodes
 *
 * @keydir:	Directory containing keys
 * @kwydest:	FDT blob to write public key information to (NULL if none)
 * @fit:	Pointer to the FIT format image header
 * @comment:	Comment to add to signature nodes
 * @require_keys: Mark all keys as 'required'
 * @engine_id:	Engine to use for signing
 * @cmdname:	Command name used when reporting errors
 * @algo_name:	Algorithm name, or NULL if to be read from FIT
 * @summary:	Returns information about what data was written
 *
 * Adds hash values for all component images in the FIT blob.
 * Hashes are calculated for all component images which have hash subnodes
 * with algorithm property set to one of the supported hash algorithms.
 *
 * Also add signatures if signature nodes are present.
 *
 * returns
 *     0, on success
 *     libfdt error code, on failure
 */
int fit_add_verification_data(const char *keydir, const char *keyfile,
			      void *keydest, void *fit, const char *comment,
			      int require_keys, const char *engine_id,
			      const char *cmdname, const char *algo_name,
			      struct image_summary *summary);

/**
 * fit_image_verify_with_data() - Verify an image with given data
 *
 * @fit:	Pointer to the FIT format image header
 * @image_offset: Offset in @fit of image to verify
 * @key_blob:	FDT containing public keys
 * @data:	Image data to verify
 * @size:	Size of image data
 */
int fit_image_verify_with_data(const void *fit, int image_noffset,
			       const void *key_blob, const void *data,
			       size_t size);

int fit_image_verify(const void *fit, int noffset);
int fit_config_verify(const void *fit, int conf_noffset);
int fit_all_image_verify(const void *fit);
int fit_config_decrypt(const void *fit, int conf_noffset);
int fit_image_check_os(const void *fit, int noffset, uint8_t os);
int fit_image_check_arch(const void *fit, int noffset, uint8_t arch);
int fit_image_check_type(const void *fit, int noffset, uint8_t type);
int fit_image_check_comp(const void *fit, int noffset, uint8_t comp);

/**
 * fit_check_format() - Check that the FIT is valid
 *
 * This performs various checks on the FIT to make sure it is suitable for
 * use, looking for mandatory properties, nodes, etc.
 *
 * If FIT_FULL_CHECK is enabled, it also runs it through libfdt to make
 * sure that there are no strange tags or broken nodes in the FIT.
 *
 * @fit: pointer to the FIT format image header
 * Return: 0 if OK, -ENOEXEC if not an FDT file, -EINVAL if the full FDT check
 *	failed (e.g. due to bad structure), -ENOMSG if the description is
 *	missing, -EBADMSG if the timestamp is missing, -ENOENT if the /images
 *	path is missing
 */
int fit_check_format(const void *fit, ulong size);

int fit_conf_find_compat(const void *fit, const void *fdt);

/**
 * fit_conf_get_node - get node offset for configuration of a given unit name
 * @fit: pointer to the FIT format image header
 * @conf_uname: configuration node unit name (NULL to use default)
 *
 * fit_conf_get_node() finds a configuration (within the '/configurations'
 * parent node) of a provided unit name. If configuration is found its node
 * offset is returned to the caller.
 *
 * When NULL is provided in second argument fit_conf_get_node() will search
 * for a default configuration node instead. Default configuration node unit
 * name is retrieved from FIT_DEFAULT_PROP property of the '/configurations'
 * node.
 *
 * returns:
 *     configuration node offset when found (>=0)
 *     negative number on failure (FDT_ERR_* code)
 */
int fit_conf_get_node(const void *fit, const char *conf_uname);

int fit_conf_get_prop_node_count(const void *fit, int noffset,
		const char *prop_name);
int fit_conf_get_prop_node_index(const void *fit, int noffset,
		const char *prop_name, int index);

/**
 * fit_conf_get_prop_node() - Get node refered to by a configuration
 * @fit:	FIT to check
 * @noffset:	Offset of conf@xxx node to check
 * @prop_name:	Property to read from the conf node
 *
 * The conf- nodes contain references to other nodes, using properties
 * like 'kernel = "kernel"'. Given such a property name (e.g. "kernel"),
 * return the offset of the node referred to (e.g. offset of node
 * "/images/kernel".
 */
int fit_conf_get_prop_node(const void *fit, int noffset,
		const char *prop_name);

int fit_check_ramdisk(const void *fit, int os_noffset,
		uint8_t arch, int verify);

int calculate_hash(const void *data, int data_len, const char *algo,
			uint8_t *value, int *value_len);

/*
 * At present we only support signing on the host, and verification on the
 * device
 */
#if defined(USE_HOSTCC)
# if defined(CONFIG_FIT_SIGNATURE)
#  define IMAGE_ENABLE_SIGN	1
#  define FIT_IMAGE_ENABLE_VERIFY	1
#  include <openssl/evp.h>
# else
#  define IMAGE_ENABLE_SIGN	0
#  define FIT_IMAGE_ENABLE_VERIFY	0
# endif
#else
# define IMAGE_ENABLE_SIGN	0
# define FIT_IMAGE_ENABLE_VERIFY	CONFIG_IS_ENABLED(FIT_SIGNATURE)
#endif

#ifdef USE_HOSTCC
void *image_get_host_blob(void);
void image_set_host_blob(void *host_blob);
# define gd_fdt_blob()		image_get_host_blob()
#else
# define gd_fdt_blob()		(gd->fdt_blob)
#endif

/*
 * Information passed to the signing routines
 *
 * Either 'keydir',  'keyname', or 'keyfile' can be NULL. However, either
 * 'keyfile', or both 'keydir' and 'keyname' should have valid values. If
 * neither are valid, some operations might fail with EINVAL.
 */
struct image_sign_info {
	const char *keydir;		/* Directory conaining keys */
	const char *keyname;		/* Name of key to use */
	const char *keyfile;		/* Filename of private or public key */
	const void *fit;		/* Pointer to FIT blob */
	int node_offset;		/* Offset of signature node */
	const char *name;		/* Algorithm name */
	struct checksum_algo *checksum;	/* Checksum algorithm information */
	struct padding_algo *padding;	/* Padding algorithm information */
	struct crypto_algo *crypto;	/* Crypto algorithm information */
	const void *fdt_blob;		/* FDT containing public keys */
	int required_keynode;		/* Node offset of key to use: -1=any */
	const char *require_keys;	/* Value for 'required' property */
	const char *engine_id;		/* Engine to use for signing */
	/*
	 * Note: the following two fields are always valid even w/o
	 * RSA_VERIFY_WITH_PKEY in order to make sure this structure is
	 * the same on target and host. Otherwise, vboot test may fail.
	 */
	const void *key;		/* Pointer to public key in DER */
	int keylen;			/* Length of public key */
};

/* A part of an image, used for hashing */
struct image_region {
	const void *data;
	int size;
};

struct checksum_algo {
	const char *name;
	const int checksum_len;
	const int der_len;
	const uint8_t *der_prefix;
#if IMAGE_ENABLE_SIGN
	const EVP_MD *(*calculate_sign)(void);
#endif
	int (*calculate)(const char *name,
			 const struct image_region *region,
			 int region_count, uint8_t *checksum);
};

struct crypto_algo {
	const char *name;		/* Name of algorithm */
	const int key_len;

	/**
	 * sign() - calculate and return signature for given input data
	 *
	 * @info:	Specifies key and FIT information
	 * @data:	Pointer to the input data
	 * @data_len:	Data length
	 * @sigp:	Set to an allocated buffer holding the signature
	 * @sig_len:	Set to length of the calculated hash
	 *
	 * This computes input data signature according to selected algorithm.
	 * Resulting signature value is placed in an allocated buffer, the
	 * pointer is returned as *sigp. The length of the calculated
	 * signature is returned via the sig_len pointer argument. The caller
	 * should free *sigp.
	 *
	 * @return: 0, on success, -ve on error
	 */
	int (*sign)(struct image_sign_info *info,
		    const struct image_region region[],
		    int region_count, uint8_t **sigp, uint *sig_len);

	/**
	 * add_verify_data() - Add verification information to FDT
	 *
	 * Add public key information to the FDT node, suitable for
	 * verification at run-time. The information added depends on the
	 * algorithm being used.
	 *
	 * @info:	Specifies key and FIT information
	 * @keydest:	Destination FDT blob for public key data
	 * @return: node offset within the FDT blob where the data was written,
	 *	or -ve on error
	 */
	int (*add_verify_data)(struct image_sign_info *info, void *keydest);

	/**
	 * verify() - Verify a signature against some data
	 *
	 * @info:	Specifies key and FIT information
	 * @data:	Pointer to the input data
	 * @data_len:	Data length
	 * @sig:	Signature
	 * @sig_len:	Number of bytes in signature
	 * @return 0 if verified, -ve on error
	 */
	int (*verify)(struct image_sign_info *info,
		      const struct image_region region[], int region_count,
		      uint8_t *sig, uint sig_len);
};

/* Declare a new U-Boot crypto algorithm handler */
#define U_BOOT_CRYPTO_ALGO(__name)						\
ll_entry_declare(struct crypto_algo, __name, cryptos)

struct padding_algo {
	const char *name;
	int (*verify)(struct image_sign_info *info,
		      const uint8_t *pad, int pad_len,
		      const uint8_t *hash, int hash_len);
};

/* Declare a new U-Boot padding algorithm handler */
#define U_BOOT_PADDING_ALGO(__name)						\
ll_entry_declare(struct padding_algo, __name, paddings)

/**
 * image_get_checksum_algo() - Look up a checksum algorithm
 *
 * @param full_name	Name of algorithm in the form "checksum,crypto"
 * Return: pointer to algorithm information, or NULL if not found
 */
struct checksum_algo *image_get_checksum_algo(const char *full_name);

/**
 * image_get_crypto_algo() - Look up a cryptosystem algorithm
 *
 * @param full_name	Name of algorithm in the form "checksum,crypto"
 * Return: pointer to algorithm information, or NULL if not found
 */
struct crypto_algo *image_get_crypto_algo(const char *full_name);

/**
 * image_get_padding_algo() - Look up a padding algorithm
 *
 * @param name		Name of padding algorithm
 * Return: pointer to algorithm information, or NULL if not found
 */
struct padding_algo *image_get_padding_algo(const char *name);

/**
 * image_pre_load() - Manage pre load header
 *
 * Manage the pre-load header before launching the image.
 * It checks the signature of the image. It also set the
 * variable image_load_offset to skip this header before
 * launching the image.
 *
 * @param addr		Address of the image
 * @return: 0 on success, -ve on error
 */
int image_pre_load(ulong addr);

/**
 * fit_image_verify_required_sigs() - Verify signatures marked as 'required'
 *
 * @fit:		FIT to check
 * @image_noffset:	Offset of image node to check
 * @data:		Image data to check
 * @size:		Size of image data
 * @key_blob:		FDT containing public keys
 * @no_sigsp:		Returns 1 if no signatures were required, and
 *			therefore nothing was checked. The caller may wish
 *			to fall back to other mechanisms, or refuse to
 *			boot.
 * Return: 0 if all verified ok, <0 on error
 */
int fit_image_verify_required_sigs(const void *fit, int image_noffset,
		const char *data, size_t size, const void *key_blob,
		int *no_sigsp);

/**
 * fit_image_check_sig() - Check a single image signature node
 *
 * @fit:		FIT to check
 * @noffset:		Offset of signature node to check
 * @data:		Image data to check
 * @size:		Size of image data
 * @keyblob:		Key blob to check (typically the control FDT)
 * @required_keynode:	Offset in the keyblob of the required key node,
 *			if any. If this is given, then the image wil not
 *			pass verification unless that key is used. If this is
 *			-1 then any signature will do.
 * @err_msgp:		In the event of an error, this will be pointed to a
 *			help error string to display to the user.
 * Return: 0 if all verified ok, <0 on error
 */
int fit_image_check_sig(const void *fit, int noffset, const void *data,
			size_t size, const void *key_blob, int required_keynode,
			char **err_msgp);

int fit_image_decrypt_data(const void *fit,
			   int image_noffset, int cipher_noffset,
			   const void *data, size_t size,
			   void **data_unciphered, size_t *size_unciphered);

/**
 * fit_region_make_list() - Make a list of regions to hash
 *
 * Given a list of FIT regions (offset, size) provided by libfdt, create
 * a list of regions (void *, size) for use by the signature creationg
 * and verification code.
 *
 * @fit:		FIT image to process
 * @fdt_regions:	Regions as returned by libfdt
 * @count:		Number of regions returned by libfdt
 * @region:		Place to put list of regions (NULL to allocate it)
 * Return: pointer to list of regions, or NULL if out of memory
 */
struct image_region *fit_region_make_list(const void *fit,
		struct fdt_region *fdt_regions, int count,
		struct image_region *region);

static inline int fit_image_check_target_arch(const void *fdt, int node)
{
#ifndef USE_HOSTCC
	return fit_image_check_arch(fdt, node, IH_ARCH_DEFAULT);
#else
	return 0;
#endif
}

/*
 * At present we only support ciphering on the host, and unciphering on the
 * device
 */
#if defined(USE_HOSTCC)
# if defined(CONFIG_FIT_CIPHER)
#  define IMAGE_ENABLE_ENCRYPT	1
#  define IMAGE_ENABLE_DECRYPT	1
#  include <openssl/evp.h>
# else
#  define IMAGE_ENABLE_ENCRYPT	0
#  define IMAGE_ENABLE_DECRYPT	0
# endif
#else
# define IMAGE_ENABLE_ENCRYPT	0
# define IMAGE_ENABLE_DECRYPT	CONFIG_IS_ENABLED(FIT_CIPHER)
#endif

/* Information passed to the ciphering routines */
struct image_cipher_info {
	const char *keydir;		/* Directory containing keys */
	const char *keyname;		/* Name of key to use */
	const char *ivname;		/* Name of IV to use */
	const void *fit;		/* Pointer to FIT blob */
	int node_noffset;		/* Offset of the cipher node */
	const char *name;		/* Algorithm name */
	struct cipher_algo *cipher;	/* Cipher algorithm information */
	const void *fdt_blob;		/* FDT containing key and IV */
	const void *key;		/* Value of the key */
	const void *iv;			/* Value of the IV */
	size_t size_unciphered;		/* Size of the unciphered data */
};

struct cipher_algo {
	const char *name;		/* Name of algorithm */
	int key_len;			/* Length of the key */
	int iv_len;			/* Length of the IV */

#if IMAGE_ENABLE_ENCRYPT
	const EVP_CIPHER * (*calculate_type)(void);
#endif

	int (*encrypt)(struct image_cipher_info *info,
		       const unsigned char *data, int data_len,
		       unsigned char **cipher, int *cipher_len);

	int (*add_cipher_data)(struct image_cipher_info *info,
			       void *keydest, void *fit, int node_noffset);

	int (*decrypt)(struct image_cipher_info *info,
		       const void *cipher, size_t cipher_len,
		       void **data, size_t *data_len);
};

int fit_image_cipher_get_algo(const void *fit, int noffset, char **algo);

struct cipher_algo *image_get_cipher_algo(const char *full_name);

struct andr_img_hdr;
int android_image_check_header(const struct andr_img_hdr *hdr);
int android_image_get_kernel(const struct andr_img_hdr *hdr, int verify,
			     ulong *os_data, ulong *os_len);
int android_image_get_ramdisk(const struct andr_img_hdr *hdr,
			      ulong *rd_data, ulong *rd_len);
int android_image_get_second(const struct andr_img_hdr *hdr,
			      ulong *second_data, ulong *second_len);
bool android_image_get_dtbo(ulong hdr_addr, ulong *addr, u32 *size);
bool android_image_get_dtb_by_index(ulong hdr_addr, u32 index, ulong *addr,
				    u32 *size);
ulong android_image_get_end(const struct andr_img_hdr *hdr);
ulong android_image_get_kload(const struct andr_img_hdr *hdr);
ulong android_image_get_kcomp(const struct andr_img_hdr *hdr);
void android_print_contents(const struct andr_img_hdr *hdr);
bool android_image_print_dtb_contents(ulong hdr_addr);

/**
 * board_fit_config_name_match() - Check for a matching board name
 *
 * This is used when SPL loads a FIT containing multiple device tree files
 * and wants to work out which one to use. The description of each one is
 * passed to this function. The description comes from the 'description' field
 * in each (FDT) image node.
 *
 * @name: Device tree description
 * Return: 0 if this device tree should be used, non-zero to try the next
 */
int board_fit_config_name_match(const char *name);

/**
 * board_fit_image_post_process() - Do any post-process on FIT binary data
 *
 * This is used to do any sort of image manipulation, verification, decryption
 * etc. in a platform or board specific way. Obviously, anything done here would
 * need to be comprehended in how the images were prepared before being injected
 * into the FIT creation (i.e. the binary blobs would have been pre-processed
 * before being added to the FIT image).
 *
 * @fit: pointer to fit image
 * @node: offset of image node
 * @image: pointer to the image start pointer
 * @size: pointer to the image size
 * Return: no return value (failure should be handled internally)
 */
void board_fit_image_post_process(const void *fit, int node, void **p_image,
				  size_t *p_size);

#define FDT_ERROR	((ulong)(-1))

ulong fdt_getprop_u32(const void *fdt, int node, const char *prop);

/**
 * fit_find_config_node() - Find the node for the best DTB in a FIT image
 *
 * A FIT image contains one or more DTBs. This function parses the
 * configurations described in the FIT images and returns the node of
 * the first matching DTB. To check if a DTB matches a board, this function
 * calls board_fit_config_name_match(). If no matching DTB is found, it returns
 * the node described by the default configuration if it exists.
 *
 * @fdt: pointer to flat device tree
 * Return: the node if found, -ve otherwise
 */
int fit_find_config_node(const void *fdt);

/**
 * Mapping of image types to function handlers to be invoked on the associated
 * loaded images
 *
 * @type: Type of image, I.E. IH_TYPE_*
 * @handler: Function to call on loaded image
 */
struct fit_loadable_tbl {
	int type;
	/**
	 * handler() - Process a loaded image
	 *
	 * @data: Pointer to start of loaded image data
	 * @size: Size of loaded image data
	 */
	void (*handler)(ulong data, size_t size);
};

/*
 * Define a FIT loadable image type handler
 *
 * _type is a valid uimage_type ID as defined in the "Image Type" enum above
 * _handler is the handler function to call after this image type is loaded
 */
#define U_BOOT_FIT_LOADABLE_HANDLER(_type, _handler) \
	ll_entry_declare(struct fit_loadable_tbl, _function, fit_loadable) = { \
		.type = _type, \
		.handler = _handler, \
	}

/**
 * fit_update - update storage with FIT image
 * @fit:        Pointer to FIT image
 *
 * Update firmware on storage using FIT image as input.
 * The storage area to be update will be identified by the name
 * in FIT and matching it to "dfu_alt_info" variable.
 *
 * Return:      0 on success, non-zero otherwise
 */
int fit_update(const void *fit);

#endif	/* __IMAGE_H__ */