xref: /openbmc/u-boot/common/image.c (revision 7e40d0a3)
183d290c5STom Rini // SPDX-License-Identifier: GPL-2.0+
2b97a2a0aSMarian Balakowicz /*
3b97a2a0aSMarian Balakowicz  * (C) Copyright 2008 Semihalf
4b97a2a0aSMarian Balakowicz  *
5b97a2a0aSMarian Balakowicz  * (C) Copyright 2000-2006
6b97a2a0aSMarian Balakowicz  * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
7b97a2a0aSMarian Balakowicz  */
8ceaed2b1SMarian Balakowicz 
9b97a2a0aSMarian Balakowicz #ifndef USE_HOSTCC
10b97a2a0aSMarian Balakowicz #include <common.h>
11b97a2a0aSMarian Balakowicz #include <watchdog.h>
125ad03eb3SMarian Balakowicz 
135ad03eb3SMarian Balakowicz #ifdef CONFIG_SHOW_BOOT_PROGRESS
145ad03eb3SMarian Balakowicz #include <status_led.h>
155ad03eb3SMarian Balakowicz #endif
165ad03eb3SMarian Balakowicz 
172242f536SMarian Balakowicz #include <rtc.h>
182242f536SMarian Balakowicz 
191cf0a8b2SJoe Hershberger #include <environment.h>
205dfb5213SMarian Balakowicz #include <image.h>
210eb25b61SJoe Hershberger #include <mapmem.h>
225dfb5213SMarian Balakowicz 
23aa34fbc0SSimon Glass #if IMAGE_ENABLE_FIT || IMAGE_ENABLE_OF_LIBFDT
24b08c8c48SMasahiro Yamada #include <linux/libfdt.h>
25fff888a1SMarian Balakowicz #include <fdt_support.h>
2662afc601SMichal Simek #include <fpga.h>
2762afc601SMichal Simek #include <xilinx.h>
28c8779648SMarian Balakowicz #endif
29c8779648SMarian Balakowicz 
3020a14a42SAndy Fleming #include <u-boot/md5.h>
312b9912e6SJeroen Hofstee #include <u-boot/sha1.h>
321221ce45SMasahiro Yamada #include <linux/errno.h>
3335e7b0f1SSimon Glass #include <asm/io.h>
34c8779648SMarian Balakowicz 
35b6b0fe64SMarian Balakowicz #ifdef CONFIG_CMD_BDI
3654841ab5SWolfgang Denk extern int do_bdinfo(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]);
37b6b0fe64SMarian Balakowicz #endif
38b6b0fe64SMarian Balakowicz 
39b6b0fe64SMarian Balakowicz DECLARE_GLOBAL_DATA_PTR;
408a5ea3e6SMarian Balakowicz 
4121d29f7fSHeiko Schocher #if defined(CONFIG_IMAGE_FORMAT_LEGACY)
423a2003f6SWolfgang Denk static const image_header_t *image_get_ramdisk(ulong rd_addr, uint8_t arch,
43d985c849SMarian Balakowicz 						int verify);
4421d29f7fSHeiko Schocher #endif
45b97a2a0aSMarian Balakowicz #else
46b97a2a0aSMarian Balakowicz #include "mkimage.h"
4720a14a42SAndy Fleming #include <u-boot/md5.h>
485dfb5213SMarian Balakowicz #include <time.h>
49b97a2a0aSMarian Balakowicz #include <image.h>
5080402f34SHeiko Schocher 
5180402f34SHeiko Schocher #ifndef __maybe_unused
5280402f34SHeiko Schocher # define __maybe_unused		/* unimplemented */
5380402f34SHeiko Schocher #endif
545dfb5213SMarian Balakowicz #endif /* !USE_HOSTCC*/
55b97a2a0aSMarian Balakowicz 
560ccff500SSimon Glass #include <u-boot/crc.h>
570ccff500SSimon Glass 
5813d06981SSimon Glass #ifndef CONFIG_SYS_BARGSIZE
5913d06981SSimon Glass #define CONFIG_SYS_BARGSIZE 512
6013d06981SSimon Glass #endif
6113d06981SSimon Glass 
627edb186fSMike Frysinger static const table_entry_t uimage_arch[] = {
6330495bffSSimon Glass 	{	IH_ARCH_INVALID,	"invalid",	"Invalid ARCH",	},
64570abb0aSMarian Balakowicz 	{	IH_ARCH_ALPHA,		"alpha",	"Alpha",	},
65570abb0aSMarian Balakowicz 	{	IH_ARCH_ARM,		"arm",		"ARM",		},
66570abb0aSMarian Balakowicz 	{	IH_ARCH_I386,		"x86",		"Intel x86",	},
67570abb0aSMarian Balakowicz 	{	IH_ARCH_IA64,		"ia64",		"IA64",		},
68570abb0aSMarian Balakowicz 	{	IH_ARCH_M68K,		"m68k",		"M68K",		},
69570abb0aSMarian Balakowicz 	{	IH_ARCH_MICROBLAZE,	"microblaze",	"MicroBlaze",	},
70570abb0aSMarian Balakowicz 	{	IH_ARCH_MIPS,		"mips",		"MIPS",		},
71570abb0aSMarian Balakowicz 	{	IH_ARCH_MIPS64,		"mips64",	"MIPS 64 Bit",	},
72570abb0aSMarian Balakowicz 	{	IH_ARCH_NIOS2,		"nios2",	"NIOS II",	},
73e419e12dSGrant Erickson 	{	IH_ARCH_PPC,		"powerpc",	"PowerPC",	},
74570abb0aSMarian Balakowicz 	{	IH_ARCH_PPC,		"ppc",		"PowerPC",	},
75570abb0aSMarian Balakowicz 	{	IH_ARCH_S390,		"s390",		"IBM S390",	},
76570abb0aSMarian Balakowicz 	{	IH_ARCH_SH,		"sh",		"SuperH",	},
77570abb0aSMarian Balakowicz 	{	IH_ARCH_SPARC,		"sparc",	"SPARC",	},
78570abb0aSMarian Balakowicz 	{	IH_ARCH_SPARC64,	"sparc64",	"SPARC 64 Bit",	},
79570abb0aSMarian Balakowicz 	{	IH_ARCH_BLACKFIN,	"blackfin",	"Blackfin",	},
80570abb0aSMarian Balakowicz 	{	IH_ARCH_AVR32,		"avr32",	"AVR32",	},
8164d61461SMacpaul Lin 	{	IH_ARCH_NDS32,		"nds32",	"NDS32",	},
823ddcaccdSStefan Kristiansson 	{	IH_ARCH_OPENRISC,	"or1k",		"OpenRISC 1000",},
8335e7b0f1SSimon Glass 	{	IH_ARCH_SANDBOX,	"sandbox",	"Sandbox",	},
840ae76531SDavid Feng 	{	IH_ARCH_ARM64,		"arm64",	"AArch64",	},
85bc5d5428SAlexey Brodkin 	{	IH_ARCH_ARC,		"arc",		"ARC",		},
865bda35cfSSimon Glass 	{	IH_ARCH_X86_64,		"x86_64",	"AMD x86_64",	},
87de5e5ceaSChris Zankel 	{	IH_ARCH_XTENSA,		"xtensa",	"Xtensa",	},
8886aa65a0SRick Chen 	{	IH_ARCH_RISCV,		"riscv",	"RISC-V",	},
89570abb0aSMarian Balakowicz 	{	-1,			"",		"",		},
90570abb0aSMarian Balakowicz };
91570abb0aSMarian Balakowicz 
927edb186fSMike Frysinger static const table_entry_t uimage_os[] = {
9330495bffSSimon Glass 	{	IH_OS_INVALID,	"invalid",	"Invalid OS",		},
944914af12SPhilipp Tomsich 	{       IH_OS_ARM_TRUSTED_FIRMWARE, "arm-trusted-firmware", "ARM Trusted Firmware"  },
95570abb0aSMarian Balakowicz 	{	IH_OS_LINUX,	"linux",	"Linux",		},
96570abb0aSMarian Balakowicz #if defined(CONFIG_LYNXKDI) || defined(USE_HOSTCC)
97570abb0aSMarian Balakowicz 	{	IH_OS_LYNXOS,	"lynxos",	"LynxOS",		},
98570abb0aSMarian Balakowicz #endif
99570abb0aSMarian Balakowicz 	{	IH_OS_NETBSD,	"netbsd",	"NetBSD",		},
1003df61957STorkel Lundgren 	{	IH_OS_OSE,	"ose",		"Enea OSE",		},
10104d41409SSteven Stallion 	{	IH_OS_PLAN9,	"plan9",	"Plan 9",		},
102570abb0aSMarian Balakowicz 	{	IH_OS_RTEMS,	"rtems",	"RTEMS",		},
10345b55712SBryan O'Donoghue 	{	IH_OS_TEE,	"tee",		"Trusted Execution Environment" },
104570abb0aSMarian Balakowicz 	{	IH_OS_U_BOOT,	"u-boot",	"U-Boot",		},
10568b15e83Smiao.yan@windriver.com 	{	IH_OS_VXWORKS,	"vxworks",	"VxWorks",		},
106570abb0aSMarian Balakowicz #if defined(CONFIG_CMD_ELF) || defined(USE_HOSTCC)
107570abb0aSMarian Balakowicz 	{	IH_OS_QNX,	"qnx",		"QNX",			},
108570abb0aSMarian Balakowicz #endif
109f5ed9e39SPeter Tyser #if defined(CONFIG_INTEGRITY) || defined(USE_HOSTCC)
110f5ed9e39SPeter Tyser 	{	IH_OS_INTEGRITY,"integrity",	"INTEGRITY",		},
111f5ed9e39SPeter Tyser #endif
112570abb0aSMarian Balakowicz #ifdef USE_HOSTCC
113570abb0aSMarian Balakowicz 	{	IH_OS_4_4BSD,	"4_4bsd",	"4_4BSD",		},
114570abb0aSMarian Balakowicz 	{	IH_OS_DELL,	"dell",		"Dell",			},
115570abb0aSMarian Balakowicz 	{	IH_OS_ESIX,	"esix",		"Esix",			},
116570abb0aSMarian Balakowicz 	{	IH_OS_FREEBSD,	"freebsd",	"FreeBSD",		},
117570abb0aSMarian Balakowicz 	{	IH_OS_IRIX,	"irix",		"Irix",			},
118570abb0aSMarian Balakowicz 	{	IH_OS_NCR,	"ncr",		"NCR",			},
119570abb0aSMarian Balakowicz 	{	IH_OS_OPENBSD,	"openbsd",	"OpenBSD",		},
120570abb0aSMarian Balakowicz 	{	IH_OS_PSOS,	"psos",		"pSOS",			},
121570abb0aSMarian Balakowicz 	{	IH_OS_SCO,	"sco",		"SCO",			},
122570abb0aSMarian Balakowicz 	{	IH_OS_SOLARIS,	"solaris",	"Solaris",		},
123570abb0aSMarian Balakowicz 	{	IH_OS_SVR4,	"svr4",		"SVR4",			},
124570abb0aSMarian Balakowicz #endif
12567ddd955SMarek Vasut #if defined(CONFIG_BOOTM_OPENRTOS) || defined(USE_HOSTCC)
12667ddd955SMarek Vasut 	{	IH_OS_OPENRTOS,	"openrtos",	"OpenRTOS",		},
12767ddd955SMarek Vasut #endif
12867ddd955SMarek Vasut 
129570abb0aSMarian Balakowicz 	{	-1,		"",		"",			},
130570abb0aSMarian Balakowicz };
131570abb0aSMarian Balakowicz 
1327edb186fSMike Frysinger static const table_entry_t uimage_type[] = {
1334962e38eSStefano Babic 	{	IH_TYPE_AISIMAGE,   "aisimage",   "Davinci AIS image",},
134570abb0aSMarian Balakowicz 	{	IH_TYPE_FILESYSTEM, "filesystem", "Filesystem Image",	},
135570abb0aSMarian Balakowicz 	{	IH_TYPE_FIRMWARE,   "firmware",	  "Firmware",		},
1363decb14aSJohn Rigby 	{	IH_TYPE_FLATDT,     "flat_dt",    "Flat Device Tree",	},
137bf411ea9SKaricheri, Muralidharan 	{	IH_TYPE_GPIMAGE,    "gpimage",    "TI Keystone SPL Image",},
138570abb0aSMarian Balakowicz 	{	IH_TYPE_KERNEL,	    "kernel",	  "Kernel Image",	},
139b9b50e89SStephen Warren 	{	IH_TYPE_KERNEL_NOLOAD, "kernel_noload",  "Kernel Image (no loading done)", },
1404962e38eSStefano Babic 	{	IH_TYPE_KWBIMAGE,   "kwbimage",   "Kirkwood Boot Image",},
1414962e38eSStefano Babic 	{	IH_TYPE_IMXIMAGE,   "imximage",   "Freescale i.MX Boot Image",},
142a2b96eceSPeng Fan 	{	IH_TYPE_IMX8IMAGE,  "imx8image",  "NXP i.MX8 Boot Image",},
143*6609c266SPeng Fan 	{	IH_TYPE_IMX8MIMAGE, "imx8mimage", "NXP i.MX8M Boot Image",},
14430495bffSSimon Glass 	{	IH_TYPE_INVALID,    "invalid",	  "Invalid Image",	},
145570abb0aSMarian Balakowicz 	{	IH_TYPE_MULTI,	    "multi",	  "Multi-File Image",	},
1464962e38eSStefano Babic 	{	IH_TYPE_OMAPIMAGE,  "omapimage",  "TI OMAP SPL With GP CH",},
1475d898a00SShaohui Xie 	{	IH_TYPE_PBLIMAGE,   "pblimage",   "Freescale PBL Boot Image",},
148570abb0aSMarian Balakowicz 	{	IH_TYPE_RAMDISK,    "ramdisk",	  "RAMDisk Image",	},
149570abb0aSMarian Balakowicz 	{	IH_TYPE_SCRIPT,     "script",	  "Script",		},
150662abc4fSMarek Vasut 	{	IH_TYPE_SOCFPGAIMAGE, "socfpgaimage", "Altera SoCFPGA CV/AV preloader",},
151662abc4fSMarek Vasut 	{	IH_TYPE_SOCFPGAIMAGE_V1, "socfpgaimage_v1", "Altera SoCFPGA A10 preloader",},
152570abb0aSMarian Balakowicz 	{	IH_TYPE_STANDALONE, "standalone", "Standalone Program", },
1537816f2cfSHeiko Schocher 	{	IH_TYPE_UBLIMAGE,   "ublimage",   "Davinci UBL image",},
154bce88370SMarek Vasut 	{	IH_TYPE_MXSIMAGE,   "mxsimage",   "Freescale MXS Boot Image",},
1557b1a4117SAndreas Bießmann 	{	IH_TYPE_ATMELIMAGE, "atmelimage", "ATMEL ROM-Boot Image",},
15690268b87SSimon Glass 	{	IH_TYPE_X86_SETUP,  "x86_setup",  "x86 setup.bin",    },
15739f520bbSAlbert ARIBAUD \(3ADEV\) 	{	IH_TYPE_LPC32XXIMAGE, "lpc32xximage",  "LPC32XX Boot Image", },
158a131c1f4SSimon Glass 	{	IH_TYPE_RKIMAGE,    "rkimage",    "Rockchip Boot Image" },
159f9a3c278SSimon Glass 	{	IH_TYPE_RKSD,       "rksd",       "Rockchip SD Boot Image" },
16010b84fe1SSimon Glass 	{	IH_TYPE_RKSPI,      "rkspi",      "Rockchip SPI Boot Image" },
161ed0c2c0aSAlbert ARIBAUD \(3ADEV\) 	{	IH_TYPE_VYBRIDIMAGE, "vybridimage",  "Vybrid Boot Image", },
16266eef1e7SNathan Rossi 	{	IH_TYPE_ZYNQIMAGE,  "zynqimage",  "Xilinx Zynq Boot Image" },
163d9b58b30SMichal Simek 	{	IH_TYPE_ZYNQMPIMAGE, "zynqmpimage", "Xilinx ZynqMP Boot Image" },
1646915dcf3SAlexander Graf 	{	IH_TYPE_ZYNQMPBIF,  "zynqmpbif",  "Xilinx ZynqMP Boot Image (bif)" },
165ed0cea7cSMichal Simek 	{	IH_TYPE_FPGA,       "fpga",       "FPGA Image" },
1667e719ee7SAndrew F. Davis 	{       IH_TYPE_TEE,        "tee",        "Trusted Execution Environment Image",},
167d21bd69bSSven Ebenfeld 	{	IH_TYPE_FIRMWARE_IVT, "firmware_ivt", "Firmware with HABv4 IVT" },
1686442c964SAndrew F. Davis 	{       IH_TYPE_PMMC,        "pmmc",        "TI Power Management Micro-Controller Firmware",},
16981260e33SPatrick Delaunay 	{	IH_TYPE_STM32IMAGE, "stm32image", "STMicroelectronics STM32 Image" },
1703b975a14SRyder Lee 	{	IH_TYPE_MTKIMAGE,   "mtk_image",   "MediaTek BootROM loadable Image" },
171570abb0aSMarian Balakowicz 	{	-1,		    "",		  "",			},
172570abb0aSMarian Balakowicz };
173570abb0aSMarian Balakowicz 
1747edb186fSMike Frysinger static const table_entry_t uimage_comp[] = {
175570abb0aSMarian Balakowicz 	{	IH_COMP_NONE,	"none",		"uncompressed",		},
176570abb0aSMarian Balakowicz 	{	IH_COMP_BZIP2,	"bzip2",	"bzip2 compressed",	},
177570abb0aSMarian Balakowicz 	{	IH_COMP_GZIP,	"gzip",		"gzip compressed",	},
178fc9c1727SLuigi 'Comio' Mantellini 	{	IH_COMP_LZMA,	"lzma",		"lzma compressed",	},
17920dde48bSPeter Korsgaard 	{	IH_COMP_LZO,	"lzo",		"lzo compressed",	},
180027b728dSJulius Werner 	{	IH_COMP_LZ4,	"lz4",		"lz4 compressed",	},
181570abb0aSMarian Balakowicz 	{	-1,		"",		"",			},
182570abb0aSMarian Balakowicz };
183570abb0aSMarian Balakowicz 
18456d7ab74SSimon Glass struct table_info {
18556d7ab74SSimon Glass 	const char *desc;
18656d7ab74SSimon Glass 	int count;
18756d7ab74SSimon Glass 	const table_entry_t *table;
18856d7ab74SSimon Glass };
18956d7ab74SSimon Glass 
19056d7ab74SSimon Glass static const struct table_info table_info[IH_COUNT] = {
19156d7ab74SSimon Glass 	{ "architecture", IH_ARCH_COUNT, uimage_arch },
19256d7ab74SSimon Glass 	{ "compression", IH_COMP_COUNT, uimage_comp },
19356d7ab74SSimon Glass 	{ "operating system", IH_OS_COUNT, uimage_os },
19456d7ab74SSimon Glass 	{ "image type", IH_TYPE_COUNT, uimage_type },
19556d7ab74SSimon Glass };
19656d7ab74SSimon Glass 
1979a4daad0SMarian Balakowicz /*****************************************************************************/
1989a4daad0SMarian Balakowicz /* Legacy format routines */
1999a4daad0SMarian Balakowicz /*****************************************************************************/
image_check_hcrc(const image_header_t * hdr)2003a2003f6SWolfgang Denk int image_check_hcrc(const image_header_t *hdr)
201b97a2a0aSMarian Balakowicz {
202b97a2a0aSMarian Balakowicz 	ulong hcrc;
203b97a2a0aSMarian Balakowicz 	ulong len = image_get_header_size();
204b97a2a0aSMarian Balakowicz 	image_header_t header;
205b97a2a0aSMarian Balakowicz 
206b97a2a0aSMarian Balakowicz 	/* Copy header so we can blank CRC field for re-calculation */
207b97a2a0aSMarian Balakowicz 	memmove(&header, (char *)hdr, image_get_header_size());
208b97a2a0aSMarian Balakowicz 	image_set_hcrc(&header, 0);
209b97a2a0aSMarian Balakowicz 
210b97a2a0aSMarian Balakowicz 	hcrc = crc32(0, (unsigned char *)&header, len);
211b97a2a0aSMarian Balakowicz 
212b97a2a0aSMarian Balakowicz 	return (hcrc == image_get_hcrc(hdr));
213b97a2a0aSMarian Balakowicz }
214b97a2a0aSMarian Balakowicz 
image_check_dcrc(const image_header_t * hdr)2153a2003f6SWolfgang Denk int image_check_dcrc(const image_header_t *hdr)
216b97a2a0aSMarian Balakowicz {
217b97a2a0aSMarian Balakowicz 	ulong data = image_get_data(hdr);
218b97a2a0aSMarian Balakowicz 	ulong len = image_get_data_size(hdr);
2197590378fSBartlomiej Sieka 	ulong dcrc = crc32_wd(0, (unsigned char *)data, len, CHUNKSZ_CRC32);
220b97a2a0aSMarian Balakowicz 
221b97a2a0aSMarian Balakowicz 	return (dcrc == image_get_dcrc(hdr));
222b97a2a0aSMarian Balakowicz }
223b97a2a0aSMarian Balakowicz 
224f13e7b2eSMarian Balakowicz /**
225f13e7b2eSMarian Balakowicz  * image_multi_count - get component (sub-image) count
226f13e7b2eSMarian Balakowicz  * @hdr: pointer to the header of the multi component image
227f13e7b2eSMarian Balakowicz  *
228f13e7b2eSMarian Balakowicz  * image_multi_count() returns number of components in a multi
229f13e7b2eSMarian Balakowicz  * component image.
230f13e7b2eSMarian Balakowicz  *
231f13e7b2eSMarian Balakowicz  * Note: no checking of the image type is done, caller must pass
232f13e7b2eSMarian Balakowicz  * a valid multi component image.
233f13e7b2eSMarian Balakowicz  *
234f13e7b2eSMarian Balakowicz  * returns:
235f13e7b2eSMarian Balakowicz  *     number of components
236f13e7b2eSMarian Balakowicz  */
image_multi_count(const image_header_t * hdr)2373a2003f6SWolfgang Denk ulong image_multi_count(const image_header_t *hdr)
238f13e7b2eSMarian Balakowicz {
239f13e7b2eSMarian Balakowicz 	ulong i, count = 0;
240df6f1b89SMarian Balakowicz 	uint32_t *size;
241f13e7b2eSMarian Balakowicz 
242f13e7b2eSMarian Balakowicz 	/* get start of the image payload, which in case of multi
243f13e7b2eSMarian Balakowicz 	 * component images that points to a table of component sizes */
244df6f1b89SMarian Balakowicz 	size = (uint32_t *)image_get_data(hdr);
245f13e7b2eSMarian Balakowicz 
246f13e7b2eSMarian Balakowicz 	/* count non empty slots */
247f13e7b2eSMarian Balakowicz 	for (i = 0; size[i]; ++i)
248f13e7b2eSMarian Balakowicz 		count++;
249f13e7b2eSMarian Balakowicz 
250f13e7b2eSMarian Balakowicz 	return count;
251f13e7b2eSMarian Balakowicz }
252f13e7b2eSMarian Balakowicz 
253f13e7b2eSMarian Balakowicz /**
254f13e7b2eSMarian Balakowicz  * image_multi_getimg - get component data address and size
255f13e7b2eSMarian Balakowicz  * @hdr: pointer to the header of the multi component image
256f13e7b2eSMarian Balakowicz  * @idx: index of the requested component
257f13e7b2eSMarian Balakowicz  * @data: pointer to a ulong variable, will hold component data address
258f13e7b2eSMarian Balakowicz  * @len: pointer to a ulong variable, will hold component size
259f13e7b2eSMarian Balakowicz  *
260f13e7b2eSMarian Balakowicz  * image_multi_getimg() returns size and data address for the requested
261f13e7b2eSMarian Balakowicz  * component in a multi component image.
262f13e7b2eSMarian Balakowicz  *
263f13e7b2eSMarian Balakowicz  * Note: no checking of the image type is done, caller must pass
264f13e7b2eSMarian Balakowicz  * a valid multi component image.
265f13e7b2eSMarian Balakowicz  *
266f13e7b2eSMarian Balakowicz  * returns:
267f13e7b2eSMarian Balakowicz  *     data address and size of the component, if idx is valid
268f13e7b2eSMarian Balakowicz  *     0 in data and len, if idx is out of range
269f13e7b2eSMarian Balakowicz  */
image_multi_getimg(const image_header_t * hdr,ulong idx,ulong * data,ulong * len)2703a2003f6SWolfgang Denk void image_multi_getimg(const image_header_t *hdr, ulong idx,
271f13e7b2eSMarian Balakowicz 			ulong *data, ulong *len)
272f13e7b2eSMarian Balakowicz {
273f13e7b2eSMarian Balakowicz 	int i;
274df6f1b89SMarian Balakowicz 	uint32_t *size;
27502b9b224SNick Spence 	ulong offset, count, img_data;
276f13e7b2eSMarian Balakowicz 
277f13e7b2eSMarian Balakowicz 	/* get number of component */
278f13e7b2eSMarian Balakowicz 	count = image_multi_count(hdr);
279f13e7b2eSMarian Balakowicz 
280f13e7b2eSMarian Balakowicz 	/* get start of the image payload, which in case of multi
281f13e7b2eSMarian Balakowicz 	 * component images that points to a table of component sizes */
282df6f1b89SMarian Balakowicz 	size = (uint32_t *)image_get_data(hdr);
283f13e7b2eSMarian Balakowicz 
284f13e7b2eSMarian Balakowicz 	/* get address of the proper component data start, which means
285f13e7b2eSMarian Balakowicz 	 * skipping sizes table (add 1 for last, null entry) */
286df6f1b89SMarian Balakowicz 	img_data = image_get_data(hdr) + (count + 1) * sizeof(uint32_t);
287f13e7b2eSMarian Balakowicz 
288f13e7b2eSMarian Balakowicz 	if (idx < count) {
289df6f1b89SMarian Balakowicz 		*len = uimage_to_cpu(size[idx]);
290f13e7b2eSMarian Balakowicz 		offset = 0;
291f13e7b2eSMarian Balakowicz 
292f13e7b2eSMarian Balakowicz 		/* go over all indices preceding requested component idx */
293f13e7b2eSMarian Balakowicz 		for (i = 0; i < idx; i++) {
29402b9b224SNick Spence 			/* add up i-th component size, rounding up to 4 bytes */
29502b9b224SNick Spence 			offset += (uimage_to_cpu(size[i]) + 3) & ~3 ;
296f13e7b2eSMarian Balakowicz 		}
297f13e7b2eSMarian Balakowicz 
298f13e7b2eSMarian Balakowicz 		/* calculate idx-th component data address */
29902b9b224SNick Spence 		*data = img_data + offset;
300f13e7b2eSMarian Balakowicz 	} else {
301f13e7b2eSMarian Balakowicz 		*len = 0;
302f13e7b2eSMarian Balakowicz 		*data = 0;
303f13e7b2eSMarian Balakowicz 	}
304f13e7b2eSMarian Balakowicz }
30542b73e8eSMarian Balakowicz 
image_print_type(const image_header_t * hdr)3063a2003f6SWolfgang Denk static void image_print_type(const image_header_t *hdr)
3072242f536SMarian Balakowicz {
30880402f34SHeiko Schocher 	const char __maybe_unused *os, *arch, *type, *comp;
3092242f536SMarian Balakowicz 
3109a4daad0SMarian Balakowicz 	os = genimg_get_os_name(image_get_os(hdr));
3119a4daad0SMarian Balakowicz 	arch = genimg_get_arch_name(image_get_arch(hdr));
3129a4daad0SMarian Balakowicz 	type = genimg_get_type_name(image_get_type(hdr));
3139a4daad0SMarian Balakowicz 	comp = genimg_get_comp_name(image_get_comp(hdr));
3142242f536SMarian Balakowicz 
315570abb0aSMarian Balakowicz 	printf("%s %s %s (%s)\n", arch, os, type, comp);
3162242f536SMarian Balakowicz }
3172242f536SMarian Balakowicz 
3185dfb5213SMarian Balakowicz /**
319edbed247SBartlomiej Sieka  * image_print_contents - prints out the contents of the legacy format image
3203a2003f6SWolfgang Denk  * @ptr: pointer to the legacy format image header
3215dfb5213SMarian Balakowicz  * @p: pointer to prefix string
3225dfb5213SMarian Balakowicz  *
323edbed247SBartlomiej Sieka  * image_print_contents() formats a multi line legacy image contents description.
3245dfb5213SMarian Balakowicz  * The routine prints out all header fields followed by the size/offset data
3255dfb5213SMarian Balakowicz  * for MULTI/SCRIPT images.
3265dfb5213SMarian Balakowicz  *
3275dfb5213SMarian Balakowicz  * returns:
3285dfb5213SMarian Balakowicz  *     no returned results
3295dfb5213SMarian Balakowicz  */
image_print_contents(const void * ptr)3303a2003f6SWolfgang Denk void image_print_contents(const void *ptr)
3312242f536SMarian Balakowicz {
3323a2003f6SWolfgang Denk 	const image_header_t *hdr = (const image_header_t *)ptr;
33380402f34SHeiko Schocher 	const char __maybe_unused *p;
334edbed247SBartlomiej Sieka 
3351fe7d938SSimon Glass 	p = IMAGE_INDENT_STRING;
336570abb0aSMarian Balakowicz 	printf("%sImage Name:   %.*s\n", p, IH_NMLEN, image_get_name(hdr));
337859e92b7SSimon Glass 	if (IMAGE_ENABLE_TIMESTAMP) {
338570abb0aSMarian Balakowicz 		printf("%sCreated:      ", p);
339570abb0aSMarian Balakowicz 		genimg_print_time((time_t)image_get_time(hdr));
340859e92b7SSimon Glass 	}
341570abb0aSMarian Balakowicz 	printf("%sImage Type:   ", p);
3422242f536SMarian Balakowicz 	image_print_type(hdr);
343570abb0aSMarian Balakowicz 	printf("%sData Size:    ", p);
344570abb0aSMarian Balakowicz 	genimg_print_size(image_get_data_size(hdr));
345570abb0aSMarian Balakowicz 	printf("%sLoad Address: %08x\n", p, image_get_load(hdr));
346570abb0aSMarian Balakowicz 	printf("%sEntry Point:  %08x\n", p, image_get_ep(hdr));
3472242f536SMarian Balakowicz 
348570abb0aSMarian Balakowicz 	if (image_check_type(hdr, IH_TYPE_MULTI) ||
349570abb0aSMarian Balakowicz 			image_check_type(hdr, IH_TYPE_SCRIPT)) {
3502242f536SMarian Balakowicz 		int i;
3512242f536SMarian Balakowicz 		ulong data, len;
3522242f536SMarian Balakowicz 		ulong count = image_multi_count(hdr);
3532242f536SMarian Balakowicz 
354570abb0aSMarian Balakowicz 		printf("%sContents:\n", p);
3552242f536SMarian Balakowicz 		for (i = 0; i < count; i++) {
3562242f536SMarian Balakowicz 			image_multi_getimg(hdr, i, &data, &len);
357570abb0aSMarian Balakowicz 
358570abb0aSMarian Balakowicz 			printf("%s   Image %d: ", p, i);
359570abb0aSMarian Balakowicz 			genimg_print_size(len);
360570abb0aSMarian Balakowicz 
361570abb0aSMarian Balakowicz 			if (image_check_type(hdr, IH_TYPE_SCRIPT) && i > 0) {
362570abb0aSMarian Balakowicz 				/*
363570abb0aSMarian Balakowicz 				 * the user may need to know offsets
364570abb0aSMarian Balakowicz 				 * if planning to do something with
365570abb0aSMarian Balakowicz 				 * multiple files
366570abb0aSMarian Balakowicz 				 */
367570abb0aSMarian Balakowicz 				printf("%s    Offset = 0x%08lx\n", p, data);
368570abb0aSMarian Balakowicz 			}
3692242f536SMarian Balakowicz 		}
370d21bd69bSSven Ebenfeld 	} else if (image_check_type(hdr, IH_TYPE_FIRMWARE_IVT)) {
371d21bd69bSSven Ebenfeld 		printf("HAB Blocks:   0x%08x   0x0000   0x%08x\n",
372d21bd69bSSven Ebenfeld 				image_get_load(hdr) - image_get_header_size(),
373d21bd69bSSven Ebenfeld 				image_get_size(hdr) + image_get_header_size()
374d21bd69bSSven Ebenfeld 						- 0x1FE0);
3752242f536SMarian Balakowicz 	}
3762242f536SMarian Balakowicz }
3772242f536SMarian Balakowicz 
378570abb0aSMarian Balakowicz 
379570abb0aSMarian Balakowicz #ifndef USE_HOSTCC
38021d29f7fSHeiko Schocher #if defined(CONFIG_IMAGE_FORMAT_LEGACY)
3815ad03eb3SMarian Balakowicz /**
3825ad03eb3SMarian Balakowicz  * image_get_ramdisk - get and verify ramdisk image
3835ad03eb3SMarian Balakowicz  * @rd_addr: ramdisk image start address
3845ad03eb3SMarian Balakowicz  * @arch: expected ramdisk architecture
3855ad03eb3SMarian Balakowicz  * @verify: checksum verification flag
3865ad03eb3SMarian Balakowicz  *
3875ad03eb3SMarian Balakowicz  * image_get_ramdisk() returns a pointer to the verified ramdisk image
3885ad03eb3SMarian Balakowicz  * header. Routine receives image start address and expected architecture
3895ad03eb3SMarian Balakowicz  * flag. Verification done covers data and header integrity and os/type/arch
3905ad03eb3SMarian Balakowicz  * fields checking.
3915ad03eb3SMarian Balakowicz  *
3925ad03eb3SMarian Balakowicz  * returns:
3935ad03eb3SMarian Balakowicz  *     pointer to a ramdisk image header, if image was found and valid
394274cea2bSKumar Gala  *     otherwise, return NULL
3955ad03eb3SMarian Balakowicz  */
image_get_ramdisk(ulong rd_addr,uint8_t arch,int verify)3963a2003f6SWolfgang Denk static const image_header_t *image_get_ramdisk(ulong rd_addr, uint8_t arch,
397d985c849SMarian Balakowicz 						int verify)
3985ad03eb3SMarian Balakowicz {
3993a2003f6SWolfgang Denk 	const image_header_t *rd_hdr = (const image_header_t *)rd_addr;
4005ad03eb3SMarian Balakowicz 
4015ad03eb3SMarian Balakowicz 	if (!image_check_magic(rd_hdr)) {
4025ad03eb3SMarian Balakowicz 		puts("Bad Magic Number\n");
403770605e4SSimon Glass 		bootstage_error(BOOTSTAGE_ID_RD_MAGIC);
404274cea2bSKumar Gala 		return NULL;
4055ad03eb3SMarian Balakowicz 	}
4065ad03eb3SMarian Balakowicz 
4075ad03eb3SMarian Balakowicz 	if (!image_check_hcrc(rd_hdr)) {
4085ad03eb3SMarian Balakowicz 		puts("Bad Header Checksum\n");
409770605e4SSimon Glass 		bootstage_error(BOOTSTAGE_ID_RD_HDR_CHECKSUM);
410274cea2bSKumar Gala 		return NULL;
4115ad03eb3SMarian Balakowicz 	}
4125ad03eb3SMarian Balakowicz 
413770605e4SSimon Glass 	bootstage_mark(BOOTSTAGE_ID_RD_MAGIC);
4142242f536SMarian Balakowicz 	image_print_contents(rd_hdr);
4155ad03eb3SMarian Balakowicz 
4165ad03eb3SMarian Balakowicz 	if (verify) {
4175ad03eb3SMarian Balakowicz 		puts("   Verifying Checksum ... ");
4187590378fSBartlomiej Sieka 		if (!image_check_dcrc(rd_hdr)) {
4195ad03eb3SMarian Balakowicz 			puts("Bad Data CRC\n");
420770605e4SSimon Glass 			bootstage_error(BOOTSTAGE_ID_RD_CHECKSUM);
421274cea2bSKumar Gala 			return NULL;
4225ad03eb3SMarian Balakowicz 		}
4235ad03eb3SMarian Balakowicz 		puts("OK\n");
4245ad03eb3SMarian Balakowicz 	}
4255ad03eb3SMarian Balakowicz 
426770605e4SSimon Glass 	bootstage_mark(BOOTSTAGE_ID_RD_HDR_CHECKSUM);
4275ad03eb3SMarian Balakowicz 
4285ad03eb3SMarian Balakowicz 	if (!image_check_os(rd_hdr, IH_OS_LINUX) ||
4295ad03eb3SMarian Balakowicz 	    !image_check_arch(rd_hdr, arch) ||
4305ad03eb3SMarian Balakowicz 	    !image_check_type(rd_hdr, IH_TYPE_RAMDISK)) {
4315ad03eb3SMarian Balakowicz 		printf("No Linux %s Ramdisk Image\n",
4329a4daad0SMarian Balakowicz 				genimg_get_arch_name(arch));
433770605e4SSimon Glass 		bootstage_error(BOOTSTAGE_ID_RAMDISK);
434274cea2bSKumar Gala 		return NULL;
4355ad03eb3SMarian Balakowicz 	}
4365ad03eb3SMarian Balakowicz 
4375ad03eb3SMarian Balakowicz 	return rd_hdr;
4385ad03eb3SMarian Balakowicz }
43921d29f7fSHeiko Schocher #endif
440570abb0aSMarian Balakowicz #endif /* !USE_HOSTCC */
4415ad03eb3SMarian Balakowicz 
4429a4daad0SMarian Balakowicz /*****************************************************************************/
4439a4daad0SMarian Balakowicz /* Shared dual-format routines */
4449a4daad0SMarian Balakowicz /*****************************************************************************/
445570abb0aSMarian Balakowicz #ifndef USE_HOSTCC
4461cf0a8b2SJoe Hershberger ulong load_addr = CONFIG_SYS_LOAD_ADDR;	/* Default Load Address */
4471cf0a8b2SJoe Hershberger ulong save_addr;			/* Default Save Address */
4481cf0a8b2SJoe Hershberger ulong save_size;			/* Default Save Size (in bytes) */
4491cf0a8b2SJoe Hershberger 
on_loadaddr(const char * name,const char * value,enum env_op op,int flags)4501cf0a8b2SJoe Hershberger static int on_loadaddr(const char *name, const char *value, enum env_op op,
4511cf0a8b2SJoe Hershberger 	int flags)
4521cf0a8b2SJoe Hershberger {
4531cf0a8b2SJoe Hershberger 	switch (op) {
4541cf0a8b2SJoe Hershberger 	case env_op_create:
4551cf0a8b2SJoe Hershberger 	case env_op_overwrite:
4561cf0a8b2SJoe Hershberger 		load_addr = simple_strtoul(value, NULL, 16);
4571cf0a8b2SJoe Hershberger 		break;
4581cf0a8b2SJoe Hershberger 	default:
4591cf0a8b2SJoe Hershberger 		break;
4601cf0a8b2SJoe Hershberger 	}
4611cf0a8b2SJoe Hershberger 
4621cf0a8b2SJoe Hershberger 	return 0;
4631cf0a8b2SJoe Hershberger }
4641cf0a8b2SJoe Hershberger U_BOOT_ENV_CALLBACK(loadaddr, on_loadaddr);
4651cf0a8b2SJoe Hershberger 
env_get_bootm_low(void)466723806ccSSimon Glass ulong env_get_bootm_low(void)
4679a4daad0SMarian Balakowicz {
46800caae6dSSimon Glass 	char *s = env_get("bootm_low");
4699a4daad0SMarian Balakowicz 	if (s) {
4709a4daad0SMarian Balakowicz 		ulong tmp = simple_strtoul(s, NULL, 16);
4719a4daad0SMarian Balakowicz 		return tmp;
4729a4daad0SMarian Balakowicz 	}
4739a4daad0SMarian Balakowicz 
4746d0f6bcfSJean-Christophe PLAGNIOL-VILLARD #if defined(CONFIG_SYS_SDRAM_BASE)
4756d0f6bcfSJean-Christophe PLAGNIOL-VILLARD 	return CONFIG_SYS_SDRAM_BASE;
476afe45c87SMarian Balakowicz #elif defined(CONFIG_ARM)
477afe45c87SMarian Balakowicz 	return gd->bd->bi_dram[0].start;
4789a4daad0SMarian Balakowicz #else
4799a4daad0SMarian Balakowicz 	return 0;
4809a4daad0SMarian Balakowicz #endif
4819a4daad0SMarian Balakowicz }
4829a4daad0SMarian Balakowicz 
env_get_bootm_size(void)483723806ccSSimon Glass phys_size_t env_get_bootm_size(void)
4849a4daad0SMarian Balakowicz {
4850cb389ddSMasahiro Yamada 	phys_size_t tmp, size;
4860cb389ddSMasahiro Yamada 	phys_addr_t start;
48700caae6dSSimon Glass 	char *s = env_get("bootm_size");
4889a4daad0SMarian Balakowicz 	if (s) {
489391fd93aSBecky Bruce 		tmp = (phys_size_t)simple_strtoull(s, NULL, 16);
4909a4daad0SMarian Balakowicz 		return tmp;
4919a4daad0SMarian Balakowicz 	}
4920cb389ddSMasahiro Yamada 
4930cb389ddSMasahiro Yamada #if defined(CONFIG_ARM) && defined(CONFIG_NR_DRAM_BANKS)
4940cb389ddSMasahiro Yamada 	start = gd->bd->bi_dram[0].start;
4950cb389ddSMasahiro Yamada 	size = gd->bd->bi_dram[0].size;
4960cb389ddSMasahiro Yamada #else
4970cb389ddSMasahiro Yamada 	start = gd->bd->bi_memstart;
4980cb389ddSMasahiro Yamada 	size = gd->bd->bi_memsize;
4990cb389ddSMasahiro Yamada #endif
5000cb389ddSMasahiro Yamada 
50100caae6dSSimon Glass 	s = env_get("bootm_low");
502c519faccSMatthew McClintock 	if (s)
503c519faccSMatthew McClintock 		tmp = (phys_size_t)simple_strtoull(s, NULL, 16);
504c519faccSMatthew McClintock 	else
5050cb389ddSMasahiro Yamada 		tmp = start;
506c519faccSMatthew McClintock 
5070cb389ddSMasahiro Yamada 	return size - (tmp - start);
5089a4daad0SMarian Balakowicz }
5099a4daad0SMarian Balakowicz 
env_get_bootm_mapsize(void)510723806ccSSimon Glass phys_size_t env_get_bootm_mapsize(void)
511c3624e6eSGrant Likely {
512c3624e6eSGrant Likely 	phys_size_t tmp;
51300caae6dSSimon Glass 	char *s = env_get("bootm_mapsize");
514c3624e6eSGrant Likely 	if (s) {
515c3624e6eSGrant Likely 		tmp = (phys_size_t)simple_strtoull(s, NULL, 16);
516c3624e6eSGrant Likely 		return tmp;
517c3624e6eSGrant Likely 	}
518c3624e6eSGrant Likely 
519c3624e6eSGrant Likely #if defined(CONFIG_SYS_BOOTMAPSZ)
520c3624e6eSGrant Likely 	return CONFIG_SYS_BOOTMAPSZ;
521c3624e6eSGrant Likely #else
522723806ccSSimon Glass 	return env_get_bootm_size();
523c3624e6eSGrant Likely #endif
524c3624e6eSGrant Likely }
525c3624e6eSGrant Likely 
memmove_wd(void * to,void * from,size_t len,ulong chunksz)5269a4daad0SMarian Balakowicz void memmove_wd(void *to, void *from, size_t len, ulong chunksz)
5279a4daad0SMarian Balakowicz {
52854fa2c5bSLarry Johnson 	if (to == from)
52954fa2c5bSLarry Johnson 		return;
53054fa2c5bSLarry Johnson 
5319a4daad0SMarian Balakowicz #if defined(CONFIG_HW_WATCHDOG) || defined(CONFIG_WATCHDOG)
53222cfddc2SSonic Zhang 	if (to > from) {
53322cfddc2SSonic Zhang 		from += len;
53422cfddc2SSonic Zhang 		to += len;
53522cfddc2SSonic Zhang 	}
5369a4daad0SMarian Balakowicz 	while (len > 0) {
5379a4daad0SMarian Balakowicz 		size_t tail = (len > chunksz) ? chunksz : len;
5389a4daad0SMarian Balakowicz 		WATCHDOG_RESET();
53922cfddc2SSonic Zhang 		if (to > from) {
54022cfddc2SSonic Zhang 			to -= tail;
54122cfddc2SSonic Zhang 			from -= tail;
54222cfddc2SSonic Zhang 		}
5439a4daad0SMarian Balakowicz 		memmove(to, from, tail);
54422cfddc2SSonic Zhang 		if (to < from) {
5459a4daad0SMarian Balakowicz 			to += tail;
5469a4daad0SMarian Balakowicz 			from += tail;
54722cfddc2SSonic Zhang 		}
5489a4daad0SMarian Balakowicz 		len -= tail;
5499a4daad0SMarian Balakowicz 	}
5509a4daad0SMarian Balakowicz #else	/* !(CONFIG_HW_WATCHDOG || CONFIG_WATCHDOG) */
5519a4daad0SMarian Balakowicz 	memmove(to, from, len);
5529a4daad0SMarian Balakowicz #endif	/* CONFIG_HW_WATCHDOG || CONFIG_WATCHDOG */
5539a4daad0SMarian Balakowicz }
554570abb0aSMarian Balakowicz #endif /* !USE_HOSTCC */
555570abb0aSMarian Balakowicz 
genimg_print_size(uint32_t size)556f666dea8SPrafulla Wadaskar void genimg_print_size(uint32_t size)
557570abb0aSMarian Balakowicz {
558570abb0aSMarian Balakowicz #ifndef USE_HOSTCC
559570abb0aSMarian Balakowicz 	printf("%d Bytes = ", size);
560570abb0aSMarian Balakowicz 	print_size(size, "\n");
561570abb0aSMarian Balakowicz #else
562cec85d4eSxypron.glpk@gmx.de 	printf("%d Bytes = %.2f KiB = %.2f MiB\n",
563570abb0aSMarian Balakowicz 			size, (double)size / 1.024e3,
564570abb0aSMarian Balakowicz 			(double)size / 1.048576e6);
565570abb0aSMarian Balakowicz #endif
566570abb0aSMarian Balakowicz }
567570abb0aSMarian Balakowicz 
568859e92b7SSimon Glass #if IMAGE_ENABLE_TIMESTAMP
genimg_print_time(time_t timestamp)569859e92b7SSimon Glass void genimg_print_time(time_t timestamp)
570570abb0aSMarian Balakowicz {
571570abb0aSMarian Balakowicz #ifndef USE_HOSTCC
572570abb0aSMarian Balakowicz 	struct rtc_time tm;
573570abb0aSMarian Balakowicz 
5749f9276c3SSimon Glass 	rtc_to_tm(timestamp, &tm);
575570abb0aSMarian Balakowicz 	printf("%4d-%02d-%02d  %2d:%02d:%02d UTC\n",
576570abb0aSMarian Balakowicz 			tm.tm_year, tm.tm_mon, tm.tm_mday,
577570abb0aSMarian Balakowicz 			tm.tm_hour, tm.tm_min, tm.tm_sec);
578570abb0aSMarian Balakowicz #else
579570abb0aSMarian Balakowicz 	printf("%s", ctime(&timestamp));
580570abb0aSMarian Balakowicz #endif
581570abb0aSMarian Balakowicz }
582859e92b7SSimon Glass #endif
583570abb0aSMarian Balakowicz 
get_table_entry(const table_entry_t * table,int id)5845b9d44dfSSimon Glass const table_entry_t *get_table_entry(const table_entry_t *table, int id)
5855b9d44dfSSimon Glass {
5865b9d44dfSSimon Glass 	for (; table->id >= 0; ++table) {
5875b9d44dfSSimon Glass 		if (table->id == id)
5885b9d44dfSSimon Glass 			return table;
5895b9d44dfSSimon Glass 	}
5905b9d44dfSSimon Glass 	return NULL;
5915b9d44dfSSimon Glass }
5925b9d44dfSSimon Glass 
unknown_msg(enum ih_category category)5931426220bSSimon Glass static const char *unknown_msg(enum ih_category category)
5941426220bSSimon Glass {
595ae3de0d8SSimon Glass 	static const char unknown_str[] = "Unknown ";
5961426220bSSimon Glass 	static char msg[30];
5971426220bSSimon Glass 
598ae3de0d8SSimon Glass 	strcpy(msg, unknown_str);
599ae3de0d8SSimon Glass 	strncat(msg, table_info[category].desc,
600ae3de0d8SSimon Glass 		sizeof(msg) - sizeof(unknown_str));
6011426220bSSimon Glass 
6021426220bSSimon Glass 	return msg;
6031426220bSSimon Glass }
6041426220bSSimon Glass 
6051426220bSSimon Glass /**
6061426220bSSimon Glass  * get_cat_table_entry_name - translate entry id to long name
6071426220bSSimon Glass  * @category: category to look up (enum ih_category)
6081426220bSSimon Glass  * @id: entry id to be translated
6091426220bSSimon Glass  *
6101426220bSSimon Glass  * This will scan the translation table trying to find the entry that matches
6111426220bSSimon Glass  * the given id.
6121426220bSSimon Glass  *
6131426220bSSimon Glass  * @retur long entry name if translation succeeds; error string on failure
6141426220bSSimon Glass  */
genimg_get_cat_name(enum ih_category category,uint id)6151426220bSSimon Glass const char *genimg_get_cat_name(enum ih_category category, uint id)
6161426220bSSimon Glass {
6171426220bSSimon Glass 	const table_entry_t *entry;
6181426220bSSimon Glass 
6191426220bSSimon Glass 	entry = get_table_entry(table_info[category].table, id);
6201426220bSSimon Glass 	if (!entry)
6211426220bSSimon Glass 		return unknown_msg(category);
6221426220bSSimon Glass #if defined(USE_HOSTCC) || !defined(CONFIG_NEEDS_MANUAL_RELOC)
6231426220bSSimon Glass 	return entry->lname;
6241426220bSSimon Glass #else
6251426220bSSimon Glass 	return entry->lname + gd->reloc_off;
6261426220bSSimon Glass #endif
6271426220bSSimon Glass }
6281426220bSSimon Glass 
6291426220bSSimon Glass /**
6301426220bSSimon Glass  * get_cat_table_entry_short_name - translate entry id to short name
6311426220bSSimon Glass  * @category: category to look up (enum ih_category)
6321426220bSSimon Glass  * @id: entry id to be translated
6331426220bSSimon Glass  *
6341426220bSSimon Glass  * This will scan the translation table trying to find the entry that matches
6351426220bSSimon Glass  * the given id.
6361426220bSSimon Glass  *
6371426220bSSimon Glass  * @retur short entry name if translation succeeds; error string on failure
6381426220bSSimon Glass  */
genimg_get_cat_short_name(enum ih_category category,uint id)6391426220bSSimon Glass const char *genimg_get_cat_short_name(enum ih_category category, uint id)
6401426220bSSimon Glass {
6411426220bSSimon Glass 	const table_entry_t *entry;
6421426220bSSimon Glass 
6431426220bSSimon Glass 	entry = get_table_entry(table_info[category].table, id);
6441426220bSSimon Glass 	if (!entry)
6451426220bSSimon Glass 		return unknown_msg(category);
6461426220bSSimon Glass #if defined(USE_HOSTCC) || !defined(CONFIG_NEEDS_MANUAL_RELOC)
6471426220bSSimon Glass 	return entry->sname;
6481426220bSSimon Glass #else
6491426220bSSimon Glass 	return entry->sname + gd->reloc_off;
6501426220bSSimon Glass #endif
6511426220bSSimon Glass }
6521426220bSSimon Glass 
genimg_get_cat_count(enum ih_category category)6531426220bSSimon Glass int genimg_get_cat_count(enum ih_category category)
6541426220bSSimon Glass {
6551426220bSSimon Glass 	return table_info[category].count;
6561426220bSSimon Glass }
6571426220bSSimon Glass 
genimg_get_cat_desc(enum ih_category category)6581426220bSSimon Glass const char *genimg_get_cat_desc(enum ih_category category)
6591426220bSSimon Glass {
6601426220bSSimon Glass 	return table_info[category].desc;
6611426220bSSimon Glass }
6621426220bSSimon Glass 
663570abb0aSMarian Balakowicz /**
664570abb0aSMarian Balakowicz  * get_table_entry_name - translate entry id to long name
665570abb0aSMarian Balakowicz  * @table: pointer to a translation table for entries of a specific type
666570abb0aSMarian Balakowicz  * @msg: message to be returned when translation fails
667570abb0aSMarian Balakowicz  * @id: entry id to be translated
668570abb0aSMarian Balakowicz  *
669570abb0aSMarian Balakowicz  * get_table_entry_name() will go over translation table trying to find
670570abb0aSMarian Balakowicz  * entry that matches given id. If matching entry is found, its long
671570abb0aSMarian Balakowicz  * name is returned to the caller.
672570abb0aSMarian Balakowicz  *
673570abb0aSMarian Balakowicz  * returns:
674570abb0aSMarian Balakowicz  *     long entry name if translation succeeds
675570abb0aSMarian Balakowicz  *     msg otherwise
676570abb0aSMarian Balakowicz  */
get_table_entry_name(const table_entry_t * table,char * msg,int id)6777edb186fSMike Frysinger char *get_table_entry_name(const table_entry_t *table, char *msg, int id)
678570abb0aSMarian Balakowicz {
6795b9d44dfSSimon Glass 	table = get_table_entry(table, id);
6805b9d44dfSSimon Glass 	if (!table)
6815b9d44dfSSimon Glass 		return msg;
6822e5167ccSWolfgang Denk #if defined(USE_HOSTCC) || !defined(CONFIG_NEEDS_MANUAL_RELOC)
683e3d1ac7bSScott Wood 	return table->lname;
684e3d1ac7bSScott Wood #else
685e3d1ac7bSScott Wood 	return table->lname + gd->reloc_off;
686e3d1ac7bSScott Wood #endif
687570abb0aSMarian Balakowicz }
6889a4daad0SMarian Balakowicz 
genimg_get_os_name(uint8_t os)6899a4daad0SMarian Balakowicz const char *genimg_get_os_name(uint8_t os)
6909a4daad0SMarian Balakowicz {
691570abb0aSMarian Balakowicz 	return (get_table_entry_name(uimage_os, "Unknown OS", os));
6929a4daad0SMarian Balakowicz }
6939a4daad0SMarian Balakowicz 
genimg_get_arch_name(uint8_t arch)6949a4daad0SMarian Balakowicz const char *genimg_get_arch_name(uint8_t arch)
6959a4daad0SMarian Balakowicz {
696712fbcf3SStephen Warren 	return (get_table_entry_name(uimage_arch, "Unknown Architecture",
697712fbcf3SStephen Warren 					arch));
6989a4daad0SMarian Balakowicz }
6999a4daad0SMarian Balakowicz 
genimg_get_type_name(uint8_t type)7009a4daad0SMarian Balakowicz const char *genimg_get_type_name(uint8_t type)
7019a4daad0SMarian Balakowicz {
702570abb0aSMarian Balakowicz 	return (get_table_entry_name(uimage_type, "Unknown Image", type));
7039a4daad0SMarian Balakowicz }
7049a4daad0SMarian Balakowicz 
genimg_get_short_name(const table_entry_t * table,int val)705cef2e514SSimon Glass static const char *genimg_get_short_name(const table_entry_t *table, int val)
7065b9d44dfSSimon Glass {
707cef2e514SSimon Glass 	table = get_table_entry(table, val);
7085b9d44dfSSimon Glass 	if (!table)
7095b9d44dfSSimon Glass 		return "unknown";
7105b9d44dfSSimon Glass #if defined(USE_HOSTCC) || !defined(CONFIG_NEEDS_MANUAL_RELOC)
7115b9d44dfSSimon Glass 	return table->sname;
7125b9d44dfSSimon Glass #else
7135b9d44dfSSimon Glass 	return table->sname + gd->reloc_off;
7145b9d44dfSSimon Glass #endif
7155b9d44dfSSimon Glass }
7165b9d44dfSSimon Glass 
genimg_get_type_short_name(uint8_t type)717cef2e514SSimon Glass const char *genimg_get_type_short_name(uint8_t type)
718cef2e514SSimon Glass {
719cef2e514SSimon Glass 	return genimg_get_short_name(uimage_type, type);
720cef2e514SSimon Glass }
721cef2e514SSimon Glass 
genimg_get_comp_name(uint8_t comp)7229a4daad0SMarian Balakowicz const char *genimg_get_comp_name(uint8_t comp)
7239a4daad0SMarian Balakowicz {
724712fbcf3SStephen Warren 	return (get_table_entry_name(uimage_comp, "Unknown Compression",
725712fbcf3SStephen Warren 					comp));
7269a4daad0SMarian Balakowicz }
7279a4daad0SMarian Balakowicz 
genimg_get_comp_short_name(uint8_t comp)728cef2e514SSimon Glass const char *genimg_get_comp_short_name(uint8_t comp)
729cef2e514SSimon Glass {
730cef2e514SSimon Glass 	return genimg_get_short_name(uimage_comp, comp);
731cef2e514SSimon Glass }
732cef2e514SSimon Glass 
genimg_get_os_short_name(uint8_t os)733cef2e514SSimon Glass const char *genimg_get_os_short_name(uint8_t os)
734cef2e514SSimon Glass {
735cef2e514SSimon Glass 	return genimg_get_short_name(uimage_os, os);
736cef2e514SSimon Glass }
737cef2e514SSimon Glass 
genimg_get_arch_short_name(uint8_t arch)738cef2e514SSimon Glass const char *genimg_get_arch_short_name(uint8_t arch)
739cef2e514SSimon Glass {
740cef2e514SSimon Glass 	return genimg_get_short_name(uimage_arch, arch);
741cef2e514SSimon Glass }
742cef2e514SSimon Glass 
743570abb0aSMarian Balakowicz /**
744570abb0aSMarian Balakowicz  * get_table_entry_id - translate short entry name to id
745570abb0aSMarian Balakowicz  * @table: pointer to a translation table for entries of a specific type
746570abb0aSMarian Balakowicz  * @table_name: to be used in case of error
747570abb0aSMarian Balakowicz  * @name: entry short name to be translated
748570abb0aSMarian Balakowicz  *
749570abb0aSMarian Balakowicz  * get_table_entry_id() will go over translation table trying to find
750570abb0aSMarian Balakowicz  * entry that matches given short name. If matching entry is found,
751570abb0aSMarian Balakowicz  * its id returned to the caller.
752570abb0aSMarian Balakowicz  *
753570abb0aSMarian Balakowicz  * returns:
754570abb0aSMarian Balakowicz  *     entry id if translation succeeds
755570abb0aSMarian Balakowicz  *     -1 otherwise
756570abb0aSMarian Balakowicz  */
get_table_entry_id(const table_entry_t * table,const char * table_name,const char * name)7577edb186fSMike Frysinger int get_table_entry_id(const table_entry_t *table,
758570abb0aSMarian Balakowicz 		const char *table_name, const char *name)
759570abb0aSMarian Balakowicz {
7607edb186fSMike Frysinger 	const table_entry_t *t;
761570abb0aSMarian Balakowicz 
762570abb0aSMarian Balakowicz 	for (t = table; t->id >= 0; ++t) {
7632e5167ccSWolfgang Denk #ifdef CONFIG_NEEDS_MANUAL_RELOC
7645b9d44dfSSimon Glass 		if (t->sname && strcasecmp(t->sname + gd->reloc_off, name) == 0)
7652e5167ccSWolfgang Denk #else
7665b9d44dfSSimon Glass 		if (t->sname && strcasecmp(t->sname, name) == 0)
767521af04dSPeter Tyser #endif
768570abb0aSMarian Balakowicz 			return (t->id);
769570abb0aSMarian Balakowicz 	}
770570abb0aSMarian Balakowicz 	debug("Invalid %s Type: %s\n", table_name, name);
7715b9d44dfSSimon Glass 
7725b9d44dfSSimon Glass 	return -1;
773570abb0aSMarian Balakowicz }
774570abb0aSMarian Balakowicz 
genimg_get_os_id(const char * name)775570abb0aSMarian Balakowicz int genimg_get_os_id(const char *name)
776570abb0aSMarian Balakowicz {
777570abb0aSMarian Balakowicz 	return (get_table_entry_id(uimage_os, "OS", name));
778570abb0aSMarian Balakowicz }
779570abb0aSMarian Balakowicz 
genimg_get_arch_id(const char * name)780570abb0aSMarian Balakowicz int genimg_get_arch_id(const char *name)
781570abb0aSMarian Balakowicz {
782570abb0aSMarian Balakowicz 	return (get_table_entry_id(uimage_arch, "CPU", name));
783570abb0aSMarian Balakowicz }
784570abb0aSMarian Balakowicz 
genimg_get_type_id(const char * name)785570abb0aSMarian Balakowicz int genimg_get_type_id(const char *name)
786570abb0aSMarian Balakowicz {
787570abb0aSMarian Balakowicz 	return (get_table_entry_id(uimage_type, "Image", name));
788570abb0aSMarian Balakowicz }
789570abb0aSMarian Balakowicz 
genimg_get_comp_id(const char * name)790570abb0aSMarian Balakowicz int genimg_get_comp_id(const char *name)
791570abb0aSMarian Balakowicz {
792570abb0aSMarian Balakowicz 	return (get_table_entry_id(uimage_comp, "Compression", name));
793570abb0aSMarian Balakowicz }
794570abb0aSMarian Balakowicz 
795570abb0aSMarian Balakowicz #ifndef USE_HOSTCC
7965ad03eb3SMarian Balakowicz /**
7976c454fedSBryan Wu  * genimg_get_kernel_addr_fit - get the real kernel address and return 2
7986c454fedSBryan Wu  *                              FIT strings
7990f64140bSBryan Wu  * @img_addr: a string might contain real image address
8006c454fedSBryan Wu  * @fit_uname_config: double pointer to a char, will hold pointer to a
8016c454fedSBryan Wu  *                    configuration unit name
8026c454fedSBryan Wu  * @fit_uname_kernel: double pointer to a char, will hold pointer to a subimage
8036c454fedSBryan Wu  *                    name
8040f64140bSBryan Wu  *
8056c454fedSBryan Wu  * genimg_get_kernel_addr_fit get the real kernel start address from a string
8060f64140bSBryan Wu  * which is normally the first argv of bootm/bootz
8070f64140bSBryan Wu  *
8080f64140bSBryan Wu  * returns:
8090f64140bSBryan Wu  *     kernel start address
8100f64140bSBryan Wu  */
genimg_get_kernel_addr_fit(char * const img_addr,const char ** fit_uname_config,const char ** fit_uname_kernel)8116c454fedSBryan Wu ulong genimg_get_kernel_addr_fit(char * const img_addr,
8126c454fedSBryan Wu 			     const char **fit_uname_config,
8136c454fedSBryan Wu 			     const char **fit_uname_kernel)
8140f64140bSBryan Wu {
8150f64140bSBryan Wu 	ulong kernel_addr;
8160f64140bSBryan Wu 
8170f64140bSBryan Wu 	/* find out kernel image address */
8180f64140bSBryan Wu 	if (!img_addr) {
8190f64140bSBryan Wu 		kernel_addr = load_addr;
8200f64140bSBryan Wu 		debug("*  kernel: default image load address = 0x%08lx\n",
8210f64140bSBryan Wu 		      load_addr);
82273223f0eSSimon Glass #if CONFIG_IS_ENABLED(FIT)
8230f64140bSBryan Wu 	} else if (fit_parse_conf(img_addr, load_addr, &kernel_addr,
8246c454fedSBryan Wu 				  fit_uname_config)) {
8250f64140bSBryan Wu 		debug("*  kernel: config '%s' from image at 0x%08lx\n",
8266c454fedSBryan Wu 		      *fit_uname_config, kernel_addr);
8270f64140bSBryan Wu 	} else if (fit_parse_subimage(img_addr, load_addr, &kernel_addr,
8286c454fedSBryan Wu 				     fit_uname_kernel)) {
8290f64140bSBryan Wu 		debug("*  kernel: subimage '%s' from image at 0x%08lx\n",
8306c454fedSBryan Wu 		      *fit_uname_kernel, kernel_addr);
8310f64140bSBryan Wu #endif
8320f64140bSBryan Wu 	} else {
8330f64140bSBryan Wu 		kernel_addr = simple_strtoul(img_addr, NULL, 16);
8340f64140bSBryan Wu 		debug("*  kernel: cmdline image address = 0x%08lx\n",
8350f64140bSBryan Wu 		      kernel_addr);
8360f64140bSBryan Wu 	}
8370f64140bSBryan Wu 
8380f64140bSBryan Wu 	return kernel_addr;
8390f64140bSBryan Wu }
8400f64140bSBryan Wu 
8410f64140bSBryan Wu /**
8426c454fedSBryan Wu  * genimg_get_kernel_addr() is the simple version of
8436c454fedSBryan Wu  * genimg_get_kernel_addr_fit(). It ignores those return FIT strings
8446c454fedSBryan Wu  */
genimg_get_kernel_addr(char * const img_addr)8456c454fedSBryan Wu ulong genimg_get_kernel_addr(char * const img_addr)
8466c454fedSBryan Wu {
8476c454fedSBryan Wu 	const char *fit_uname_config = NULL;
8486c454fedSBryan Wu 	const char *fit_uname_kernel = NULL;
8496c454fedSBryan Wu 
8506c454fedSBryan Wu 	return genimg_get_kernel_addr_fit(img_addr, &fit_uname_config,
8516c454fedSBryan Wu 					  &fit_uname_kernel);
8526c454fedSBryan Wu }
8536c454fedSBryan Wu 
8546c454fedSBryan Wu /**
8559a4daad0SMarian Balakowicz  * genimg_get_format - get image format type
8569a4daad0SMarian Balakowicz  * @img_addr: image start address
8579a4daad0SMarian Balakowicz  *
8589a4daad0SMarian Balakowicz  * genimg_get_format() checks whether provided address points to a valid
8599a4daad0SMarian Balakowicz  * legacy or FIT image.
8609a4daad0SMarian Balakowicz  *
8619a4daad0SMarian Balakowicz  * New uImage format and FDT blob are based on a libfdt. FDT blob
8629a4daad0SMarian Balakowicz  * may be passed directly or embedded in a FIT image. In both situations
8639a4daad0SMarian Balakowicz  * genimg_get_format() must be able to dectect libfdt header.
8649a4daad0SMarian Balakowicz  *
8659a4daad0SMarian Balakowicz  * returns:
8669a4daad0SMarian Balakowicz  *     image format type or IMAGE_FORMAT_INVALID if no image is present
8679a4daad0SMarian Balakowicz  */
genimg_get_format(const void * img_addr)86835e7b0f1SSimon Glass int genimg_get_format(const void *img_addr)
8699a4daad0SMarian Balakowicz {
87021d29f7fSHeiko Schocher #if defined(CONFIG_IMAGE_FORMAT_LEGACY)
8713a2003f6SWolfgang Denk 	const image_header_t *hdr;
8729a4daad0SMarian Balakowicz 
8733a2003f6SWolfgang Denk 	hdr = (const image_header_t *)img_addr;
8749a4daad0SMarian Balakowicz 	if (image_check_magic(hdr))
87521d29f7fSHeiko Schocher 		return IMAGE_FORMAT_LEGACY;
87621d29f7fSHeiko Schocher #endif
877aa34fbc0SSimon Glass #if IMAGE_ENABLE_FIT || IMAGE_ENABLE_OF_LIBFDT
87821d29f7fSHeiko Schocher 	if (fdt_check_header(img_addr) == 0)
87921d29f7fSHeiko Schocher 		return IMAGE_FORMAT_FIT;
8809ace3fc8SSebastian Siewior #endif
8819ace3fc8SSebastian Siewior #ifdef CONFIG_ANDROID_BOOT_IMAGE
88221d29f7fSHeiko Schocher 	if (android_image_check_header(img_addr) == 0)
88321d29f7fSHeiko Schocher 		return IMAGE_FORMAT_ANDROID;
8849a4daad0SMarian Balakowicz #endif
8859a4daad0SMarian Balakowicz 
88621d29f7fSHeiko Schocher 	return IMAGE_FORMAT_INVALID;
8879a4daad0SMarian Balakowicz }
8889a4daad0SMarian Balakowicz 
8899a4daad0SMarian Balakowicz /**
890f773bea8SMarian Balakowicz  * fit_has_config - check if there is a valid FIT configuration
891f773bea8SMarian Balakowicz  * @images: pointer to the bootm command headers structure
892f773bea8SMarian Balakowicz  *
893f773bea8SMarian Balakowicz  * fit_has_config() checks if there is a FIT configuration in use
894f773bea8SMarian Balakowicz  * (if FTI support is present).
895f773bea8SMarian Balakowicz  *
896f773bea8SMarian Balakowicz  * returns:
897f773bea8SMarian Balakowicz  *     0, no FIT support or no configuration found
898f773bea8SMarian Balakowicz  *     1, configuration found
899f773bea8SMarian Balakowicz  */
genimg_has_config(bootm_headers_t * images)900f773bea8SMarian Balakowicz int genimg_has_config(bootm_headers_t *images)
901f773bea8SMarian Balakowicz {
90273223f0eSSimon Glass #if IMAGE_ENABLE_FIT
903f773bea8SMarian Balakowicz 	if (images->fit_uname_cfg)
904f773bea8SMarian Balakowicz 		return 1;
905f773bea8SMarian Balakowicz #endif
906f773bea8SMarian Balakowicz 	return 0;
907f773bea8SMarian Balakowicz }
908f773bea8SMarian Balakowicz 
909f773bea8SMarian Balakowicz /**
9109a4daad0SMarian Balakowicz  * boot_get_ramdisk - main ramdisk handling routine
9115ad03eb3SMarian Balakowicz  * @argc: command argument count
9125ad03eb3SMarian Balakowicz  * @argv: command argument list
9138a5ea3e6SMarian Balakowicz  * @images: pointer to the bootm images structure
9145ad03eb3SMarian Balakowicz  * @arch: expected ramdisk architecture
9155ad03eb3SMarian Balakowicz  * @rd_start: pointer to a ulong variable, will hold ramdisk start address
9165ad03eb3SMarian Balakowicz  * @rd_end: pointer to a ulong variable, will hold ramdisk end
9175ad03eb3SMarian Balakowicz  *
9189a4daad0SMarian Balakowicz  * boot_get_ramdisk() is responsible for finding a valid ramdisk image.
9195ad03eb3SMarian Balakowicz  * Curently supported are the following ramdisk sources:
9205ad03eb3SMarian Balakowicz  *      - multicomponent kernel/ramdisk image,
9215ad03eb3SMarian Balakowicz  *      - commandline provided address of decicated ramdisk image.
9225ad03eb3SMarian Balakowicz  *
9235ad03eb3SMarian Balakowicz  * returns:
924d985c849SMarian Balakowicz  *     0, if ramdisk image was found and valid, or skiped
9255ad03eb3SMarian Balakowicz  *     rd_start and rd_end are set to ramdisk start/end addresses if
9265ad03eb3SMarian Balakowicz  *     ramdisk image is found and valid
927d985c849SMarian Balakowicz  *
928ea86b9e6SKumar Gala  *     1, if ramdisk image is found but corrupted, or invalid
9295ad03eb3SMarian Balakowicz  *     rd_start and rd_end are set to 0 if no ramdisk exists
9305ad03eb3SMarian Balakowicz  */
boot_get_ramdisk(int argc,char * const argv[],bootm_headers_t * images,uint8_t arch,ulong * rd_start,ulong * rd_end)93154841ab5SWolfgang Denk int boot_get_ramdisk(int argc, char * const argv[], bootm_headers_t *images,
932d985c849SMarian Balakowicz 		uint8_t arch, ulong *rd_start, ulong *rd_end)
9335ad03eb3SMarian Balakowicz {
934d5934ad7SMarian Balakowicz 	ulong rd_addr, rd_load;
9355ad03eb3SMarian Balakowicz 	ulong rd_data, rd_len;
93621d29f7fSHeiko Schocher #if defined(CONFIG_IMAGE_FORMAT_LEGACY)
9373a2003f6SWolfgang Denk 	const image_header_t *rd_hdr;
93821d29f7fSHeiko Schocher #endif
93935e7b0f1SSimon Glass 	void *buf;
94057d40ab7SMarek Vasut #ifdef CONFIG_SUPPORT_RAW_INITRD
941017e1f3fSMarek Vasut 	char *end;
94257d40ab7SMarek Vasut #endif
94373223f0eSSimon Glass #if IMAGE_ENABLE_FIT
944f320a4d8SSimon Glass 	const char	*fit_uname_config = images->fit_uname_cfg;
945d5934ad7SMarian Balakowicz 	const char	*fit_uname_ramdisk = NULL;
946d5934ad7SMarian Balakowicz 	ulong		default_addr;
947c8779648SMarian Balakowicz 	int		rd_noffset;
948d5934ad7SMarian Balakowicz #endif
949983c72f4SSimon Glass 	const char *select = NULL;
9505ad03eb3SMarian Balakowicz 
951c8779648SMarian Balakowicz 	*rd_start = 0;
952c8779648SMarian Balakowicz 	*rd_end = 0;
953c8779648SMarian Balakowicz 
9541fec3c5dSTom Rini #ifdef CONFIG_ANDROID_BOOT_IMAGE
9551fec3c5dSTom Rini 	/*
9561fec3c5dSTom Rini 	 * Look for an Android boot image.
9571fec3c5dSTom Rini 	 */
9581fec3c5dSTom Rini 	buf = map_sysmem(images->os.start, 0);
959c139b5ffSTom Rini 	if (buf && genimg_get_format(buf) == IMAGE_FORMAT_ANDROID)
9601fec3c5dSTom Rini 		select = argv[0];
9611fec3c5dSTom Rini #endif
9621fec3c5dSTom Rini 
963983c72f4SSimon Glass 	if (argc >= 2)
964983c72f4SSimon Glass 		select = argv[1];
9652dd46328SRob Herring 
9665ad03eb3SMarian Balakowicz 	/*
9675ad03eb3SMarian Balakowicz 	 * Look for a '-' which indicates to ignore the
9685ad03eb3SMarian Balakowicz 	 * ramdisk argument
9695ad03eb3SMarian Balakowicz 	 */
970983c72f4SSimon Glass 	if (select && strcmp(select, "-") ==  0) {
9715ad03eb3SMarian Balakowicz 		debug("## Skipping init Ramdisk\n");
9725ad03eb3SMarian Balakowicz 		rd_len = rd_data = 0;
973983c72f4SSimon Glass 	} else if (select || genimg_has_config(images)) {
97473223f0eSSimon Glass #if IMAGE_ENABLE_FIT
975983c72f4SSimon Glass 		if (select) {
976d5934ad7SMarian Balakowicz 			/*
977f773bea8SMarian Balakowicz 			 * If the init ramdisk comes from the FIT image and
978f773bea8SMarian Balakowicz 			 * the FIT image address is omitted in the command
979f773bea8SMarian Balakowicz 			 * line argument, try to use os FIT image address or
980f773bea8SMarian Balakowicz 			 * default load address.
981d5934ad7SMarian Balakowicz 			 */
982d5934ad7SMarian Balakowicz 			if (images->fit_uname_os)
983d5934ad7SMarian Balakowicz 				default_addr = (ulong)images->fit_hdr_os;
984d5934ad7SMarian Balakowicz 			else
985d5934ad7SMarian Balakowicz 				default_addr = load_addr;
986d5934ad7SMarian Balakowicz 
987983c72f4SSimon Glass 			if (fit_parse_conf(select, default_addr,
988d5934ad7SMarian Balakowicz 					   &rd_addr, &fit_uname_config)) {
989712fbcf3SStephen Warren 				debug("*  ramdisk: config '%s' from image at "
990712fbcf3SStephen Warren 						"0x%08lx\n",
991d5934ad7SMarian Balakowicz 						fit_uname_config, rd_addr);
992983c72f4SSimon Glass 			} else if (fit_parse_subimage(select, default_addr,
993d5934ad7SMarian Balakowicz 						&rd_addr, &fit_uname_ramdisk)) {
994712fbcf3SStephen Warren 				debug("*  ramdisk: subimage '%s' from image at "
995712fbcf3SStephen Warren 						"0x%08lx\n",
996d5934ad7SMarian Balakowicz 						fit_uname_ramdisk, rd_addr);
997d5934ad7SMarian Balakowicz 			} else
998d5934ad7SMarian Balakowicz #endif
999d5934ad7SMarian Balakowicz 			{
1000983c72f4SSimon Glass 				rd_addr = simple_strtoul(select, NULL, 16);
1001712fbcf3SStephen Warren 				debug("*  ramdisk: cmdline image address = "
1002712fbcf3SStephen Warren 						"0x%08lx\n",
1003d5934ad7SMarian Balakowicz 						rd_addr);
1004d5934ad7SMarian Balakowicz 			}
100573223f0eSSimon Glass #if IMAGE_ENABLE_FIT
1006f773bea8SMarian Balakowicz 		} else {
1007f773bea8SMarian Balakowicz 			/* use FIT configuration provided in first bootm
1008a51ec63bSSimon Glass 			 * command argument. If the property is not defined,
1009a51ec63bSSimon Glass 			 * quit silently.
1010f773bea8SMarian Balakowicz 			 */
101135e7b0f1SSimon Glass 			rd_addr = map_to_sysmem(images->fit_hdr_os);
1012a51ec63bSSimon Glass 			rd_noffset = fit_get_node_from_config(images,
1013a51ec63bSSimon Glass 					FIT_RAMDISK_PROP, rd_addr);
1014bd86ef11SPaul Burton 			if (rd_noffset == -ENOENT)
101541266c9bSPeter Tyser 				return 0;
1016a51ec63bSSimon Glass 			else if (rd_noffset < 0)
1017a51ec63bSSimon Glass 				return 1;
1018f773bea8SMarian Balakowicz 		}
1019f773bea8SMarian Balakowicz #endif
1020d5934ad7SMarian Balakowicz 
10215ad03eb3SMarian Balakowicz 		/*
10225ad03eb3SMarian Balakowicz 		 * Check if there is an initrd image at the
10235ad03eb3SMarian Balakowicz 		 * address provided in the second bootm argument
1024d5934ad7SMarian Balakowicz 		 * check image type, for FIT images get FIT node.
10255ad03eb3SMarian Balakowicz 		 */
102635e7b0f1SSimon Glass 		buf = map_sysmem(rd_addr, 0);
102735e7b0f1SSimon Glass 		switch (genimg_get_format(buf)) {
102821d29f7fSHeiko Schocher #if defined(CONFIG_IMAGE_FORMAT_LEGACY)
1029d5934ad7SMarian Balakowicz 		case IMAGE_FORMAT_LEGACY:
1030c8779648SMarian Balakowicz 			printf("## Loading init Ramdisk from Legacy "
1031c8779648SMarian Balakowicz 					"Image at %08lx ...\n", rd_addr);
10325ad03eb3SMarian Balakowicz 
1033770605e4SSimon Glass 			bootstage_mark(BOOTSTAGE_ID_CHECK_RAMDISK);
1034d985c849SMarian Balakowicz 			rd_hdr = image_get_ramdisk(rd_addr, arch,
1035d985c849SMarian Balakowicz 							images->verify);
10365ad03eb3SMarian Balakowicz 
1037c8779648SMarian Balakowicz 			if (rd_hdr == NULL)
1038274cea2bSKumar Gala 				return 1;
1039274cea2bSKumar Gala 
10405ad03eb3SMarian Balakowicz 			rd_data = image_get_data(rd_hdr);
10415ad03eb3SMarian Balakowicz 			rd_len = image_get_data_size(rd_hdr);
1042d5934ad7SMarian Balakowicz 			rd_load = image_get_load(rd_hdr);
1043d5934ad7SMarian Balakowicz 			break;
104421d29f7fSHeiko Schocher #endif
104573223f0eSSimon Glass #if IMAGE_ENABLE_FIT
1046d5934ad7SMarian Balakowicz 		case IMAGE_FORMAT_FIT:
1047126cc864SSimon Glass 			rd_noffset = fit_image_load(images,
1048a51ec63bSSimon Glass 					rd_addr, &fit_uname_ramdisk,
1049f320a4d8SSimon Glass 					&fit_uname_config, arch,
1050a51ec63bSSimon Glass 					IH_TYPE_RAMDISK,
1051a51ec63bSSimon Glass 					BOOTSTAGE_ID_FIT_RD_START,
1052fe20a81aSSimon Glass 					FIT_LOAD_OPTIONAL_NON_ZERO,
1053fe20a81aSSimon Glass 					&rd_data, &rd_len);
1054a51ec63bSSimon Glass 			if (rd_noffset < 0)
1055c78fce69SMichal Simek 				return 1;
1056c8779648SMarian Balakowicz 
1057a51ec63bSSimon Glass 			images->fit_hdr_rd = map_sysmem(rd_addr, 0);
1058c8779648SMarian Balakowicz 			images->fit_uname_rd = fit_uname_ramdisk;
10593dfe1101SMarian Balakowicz 			images->fit_noffset_rd = rd_noffset;
1060c8779648SMarian Balakowicz 			break;
1061d5934ad7SMarian Balakowicz #endif
10622dd46328SRob Herring #ifdef CONFIG_ANDROID_BOOT_IMAGE
10632dd46328SRob Herring 		case IMAGE_FORMAT_ANDROID:
10642dd46328SRob Herring 			android_image_get_ramdisk((void *)images->os.start,
10652dd46328SRob Herring 				&rd_data, &rd_len);
10662dd46328SRob Herring 			break;
10672dd46328SRob Herring #endif
1068d5934ad7SMarian Balakowicz 		default:
1069017e1f3fSMarek Vasut #ifdef CONFIG_SUPPORT_RAW_INITRD
1070983c72f4SSimon Glass 			end = NULL;
1071983c72f4SSimon Glass 			if (select)
1072983c72f4SSimon Glass 				end = strchr(select, ':');
1073983c72f4SSimon Glass 			if (end) {
1074017e1f3fSMarek Vasut 				rd_len = simple_strtoul(++end, NULL, 16);
1075017e1f3fSMarek Vasut 				rd_data = rd_addr;
1076017e1f3fSMarek Vasut 			} else
1077017e1f3fSMarek Vasut #endif
1078017e1f3fSMarek Vasut 			{
1079d985c849SMarian Balakowicz 				puts("Wrong Ramdisk Image Format\n");
1080c8779648SMarian Balakowicz 				rd_data = rd_len = rd_load = 0;
1081ea86b9e6SKumar Gala 				return 1;
1082d5934ad7SMarian Balakowicz 			}
1083017e1f3fSMarek Vasut 		}
1084d5934ad7SMarian Balakowicz 	} else if (images->legacy_hdr_valid &&
1085712fbcf3SStephen Warren 			image_check_type(&images->legacy_hdr_os_copy,
1086712fbcf3SStephen Warren 						IH_TYPE_MULTI)) {
1087712fbcf3SStephen Warren 
10885ad03eb3SMarian Balakowicz 		/*
1089d5934ad7SMarian Balakowicz 		 * Now check if we have a legacy mult-component image,
1090d5934ad7SMarian Balakowicz 		 * get second entry data start address and len.
10915ad03eb3SMarian Balakowicz 		 */
1092770605e4SSimon Glass 		bootstage_mark(BOOTSTAGE_ID_RAMDISK);
10935ad03eb3SMarian Balakowicz 		printf("## Loading init Ramdisk from multi component "
1094c8779648SMarian Balakowicz 				"Legacy Image at %08lx ...\n",
1095d5934ad7SMarian Balakowicz 				(ulong)images->legacy_hdr_os);
1096d5934ad7SMarian Balakowicz 
1097d5934ad7SMarian Balakowicz 		image_multi_getimg(images->legacy_hdr_os, 1, &rd_data, &rd_len);
10982dd46328SRob Herring 	} else {
10995ad03eb3SMarian Balakowicz 		/*
11005ad03eb3SMarian Balakowicz 		 * no initrd image
11015ad03eb3SMarian Balakowicz 		 */
1102770605e4SSimon Glass 		bootstage_mark(BOOTSTAGE_ID_NO_RAMDISK);
11035ad03eb3SMarian Balakowicz 		rd_len = rd_data = 0;
11045ad03eb3SMarian Balakowicz 	}
11055ad03eb3SMarian Balakowicz 
11065ad03eb3SMarian Balakowicz 	if (!rd_data) {
11075ad03eb3SMarian Balakowicz 		debug("## No init Ramdisk\n");
11085ad03eb3SMarian Balakowicz 	} else {
11095ad03eb3SMarian Balakowicz 		*rd_start = rd_data;
11105ad03eb3SMarian Balakowicz 		*rd_end = rd_data + rd_len;
11115ad03eb3SMarian Balakowicz 	}
11125ad03eb3SMarian Balakowicz 	debug("   ramdisk start = 0x%08lx, ramdisk end = 0x%08lx\n",
11135ad03eb3SMarian Balakowicz 			*rd_start, *rd_end);
1114274cea2bSKumar Gala 
1115274cea2bSKumar Gala 	return 0;
11165ad03eb3SMarian Balakowicz }
1117ceaed2b1SMarian Balakowicz 
1118fca43cc8SJohn Rigby #ifdef CONFIG_SYS_BOOT_RAMDISK_HIGH
1119ceaed2b1SMarian Balakowicz /**
11209a4daad0SMarian Balakowicz  * boot_ramdisk_high - relocate init ramdisk
1121e822d7fcSKumar Gala  * @lmb: pointer to lmb handle, will be used for memory mgmt
1122ceaed2b1SMarian Balakowicz  * @rd_data: ramdisk data start address
1123ceaed2b1SMarian Balakowicz  * @rd_len: ramdisk data length
1124ceaed2b1SMarian Balakowicz  * @initrd_start: pointer to a ulong variable, will hold final init ramdisk
1125ceaed2b1SMarian Balakowicz  *      start address (after possible relocation)
1126ceaed2b1SMarian Balakowicz  * @initrd_end: pointer to a ulong variable, will hold final init ramdisk
1127ceaed2b1SMarian Balakowicz  *      end address (after possible relocation)
1128ceaed2b1SMarian Balakowicz  *
11291bce2aebSRobert P. J. Day  * boot_ramdisk_high() takes a relocation hint from "initrd_high" environment
1130ceaed2b1SMarian Balakowicz  * variable and if requested ramdisk data is moved to a specified location.
1131ceaed2b1SMarian Balakowicz  *
11329a4daad0SMarian Balakowicz  * Initrd_start and initrd_end are set to final (after relocation) ramdisk
11339a4daad0SMarian Balakowicz  * start/end addresses if ramdisk image start and len were provided,
11349a4daad0SMarian Balakowicz  * otherwise set initrd_start and initrd_end set to zeros.
11359a4daad0SMarian Balakowicz  *
1136ceaed2b1SMarian Balakowicz  * returns:
1137e822d7fcSKumar Gala  *      0 - success
1138e822d7fcSKumar Gala  *     -1 - failure
1139ceaed2b1SMarian Balakowicz  */
boot_ramdisk_high(struct lmb * lmb,ulong rd_data,ulong rd_len,ulong * initrd_start,ulong * initrd_end)11409a4daad0SMarian Balakowicz int boot_ramdisk_high(struct lmb *lmb, ulong rd_data, ulong rd_len,
1141b6b0fe64SMarian Balakowicz 		  ulong *initrd_start, ulong *initrd_end)
1142ceaed2b1SMarian Balakowicz {
1143ceaed2b1SMarian Balakowicz 	char	*s;
1144ceaed2b1SMarian Balakowicz 	ulong	initrd_high;
1145ceaed2b1SMarian Balakowicz 	int	initrd_copy_to_ram = 1;
1146ceaed2b1SMarian Balakowicz 
114700caae6dSSimon Glass 	s = env_get("initrd_high");
114800caae6dSSimon Glass 	if (s) {
1149ceaed2b1SMarian Balakowicz 		/* a value of "no" or a similar string will act like 0,
1150ceaed2b1SMarian Balakowicz 		 * turning the "load high" feature off. This is intentional.
1151ceaed2b1SMarian Balakowicz 		 */
1152ceaed2b1SMarian Balakowicz 		initrd_high = simple_strtoul(s, NULL, 16);
1153ceaed2b1SMarian Balakowicz 		if (initrd_high == ~0)
1154ceaed2b1SMarian Balakowicz 			initrd_copy_to_ram = 0;
1155ceaed2b1SMarian Balakowicz 	} else {
1156723806ccSSimon Glass 		initrd_high = env_get_bootm_mapsize() + env_get_bootm_low();
1157ceaed2b1SMarian Balakowicz 	}
1158ceaed2b1SMarian Balakowicz 
115995d449adSMarian Balakowicz 
1160ceaed2b1SMarian Balakowicz 	debug("## initrd_high = 0x%08lx, copy_to_ram = %d\n",
1161ceaed2b1SMarian Balakowicz 			initrd_high, initrd_copy_to_ram);
1162ceaed2b1SMarian Balakowicz 
1163ceaed2b1SMarian Balakowicz 	if (rd_data) {
1164ceaed2b1SMarian Balakowicz 		if (!initrd_copy_to_ram) {	/* zero-copy ramdisk support */
1165ceaed2b1SMarian Balakowicz 			debug("   in-place initrd\n");
1166ceaed2b1SMarian Balakowicz 			*initrd_start = rd_data;
1167ceaed2b1SMarian Balakowicz 			*initrd_end = rd_data + rd_len;
1168e822d7fcSKumar Gala 			lmb_reserve(lmb, rd_data, rd_len);
1169ceaed2b1SMarian Balakowicz 		} else {
1170e822d7fcSKumar Gala 			if (initrd_high)
1171712fbcf3SStephen Warren 				*initrd_start = (ulong)lmb_alloc_base(lmb,
1172712fbcf3SStephen Warren 						rd_len, 0x1000, initrd_high);
1173e822d7fcSKumar Gala 			else
1174712fbcf3SStephen Warren 				*initrd_start = (ulong)lmb_alloc(lmb, rd_len,
1175712fbcf3SStephen Warren 								 0x1000);
1176ceaed2b1SMarian Balakowicz 
1177e822d7fcSKumar Gala 			if (*initrd_start == 0) {
1178e822d7fcSKumar Gala 				puts("ramdisk - allocation error\n");
1179e822d7fcSKumar Gala 				goto error;
1180b6b0fe64SMarian Balakowicz 			}
1181770605e4SSimon Glass 			bootstage_mark(BOOTSTAGE_ID_COPY_RAMDISK);
1182ceaed2b1SMarian Balakowicz 
1183ceaed2b1SMarian Balakowicz 			*initrd_end = *initrd_start + rd_len;
1184ceaed2b1SMarian Balakowicz 			printf("   Loading Ramdisk to %08lx, end %08lx ... ",
1185ceaed2b1SMarian Balakowicz 					*initrd_start, *initrd_end);
1186ceaed2b1SMarian Balakowicz 
1187ceaed2b1SMarian Balakowicz 			memmove_wd((void *)*initrd_start,
1188ceaed2b1SMarian Balakowicz 					(void *)rd_data, rd_len, CHUNKSZ);
1189ceaed2b1SMarian Balakowicz 
11903b200110SKumar Gala #ifdef CONFIG_MP
11913b200110SKumar Gala 			/*
11923b200110SKumar Gala 			 * Ensure the image is flushed to memory to handle
11933b200110SKumar Gala 			 * AMP boot scenarios in which we might not be
11943b200110SKumar Gala 			 * HW cache coherent
11953b200110SKumar Gala 			 */
11961a1e7072SHeiko Schocher 			flush_cache((unsigned long)*initrd_start,
11971a1e7072SHeiko Schocher 				    ALIGN(rd_len, ARCH_DMA_MINALIGN));
11983b200110SKumar Gala #endif
1199ceaed2b1SMarian Balakowicz 			puts("OK\n");
1200ceaed2b1SMarian Balakowicz 		}
1201ceaed2b1SMarian Balakowicz 	} else {
1202ceaed2b1SMarian Balakowicz 		*initrd_start = 0;
1203ceaed2b1SMarian Balakowicz 		*initrd_end = 0;
1204ceaed2b1SMarian Balakowicz 	}
1205ceaed2b1SMarian Balakowicz 	debug("   ramdisk load start = 0x%08lx, ramdisk load end = 0x%08lx\n",
1206ceaed2b1SMarian Balakowicz 			*initrd_start, *initrd_end);
12079a4daad0SMarian Balakowicz 
1208e822d7fcSKumar Gala 	return 0;
1209b6b0fe64SMarian Balakowicz 
1210e822d7fcSKumar Gala error:
1211e822d7fcSKumar Gala 	return -1;
1212b6b0fe64SMarian Balakowicz }
1213fca43cc8SJohn Rigby #endif /* CONFIG_SYS_BOOT_RAMDISK_HIGH */
1214b6b0fe64SMarian Balakowicz 
boot_get_setup(bootm_headers_t * images,uint8_t arch,ulong * setup_start,ulong * setup_len)121590268b87SSimon Glass int boot_get_setup(bootm_headers_t *images, uint8_t arch,
121690268b87SSimon Glass 		   ulong *setup_start, ulong *setup_len)
121790268b87SSimon Glass {
121873223f0eSSimon Glass #if IMAGE_ENABLE_FIT
121990268b87SSimon Glass 	return boot_get_setup_fit(images, arch, setup_start, setup_len);
122090268b87SSimon Glass #else
122190268b87SSimon Glass 	return -ENOENT;
122290268b87SSimon Glass #endif
122390268b87SSimon Glass }
122490268b87SSimon Glass 
122573223f0eSSimon Glass #if IMAGE_ENABLE_FIT
12268b93a92fSGoldschmidt Simon #if defined(CONFIG_FPGA)
boot_get_fpga(int argc,char * const argv[],bootm_headers_t * images,uint8_t arch,const ulong * ld_start,ulong * const ld_len)122762afc601SMichal Simek int boot_get_fpga(int argc, char * const argv[], bootm_headers_t *images,
122862afc601SMichal Simek 		  uint8_t arch, const ulong *ld_start, ulong * const ld_len)
122962afc601SMichal Simek {
123062afc601SMichal Simek 	ulong tmp_img_addr, img_data, img_len;
123162afc601SMichal Simek 	void *buf;
123262afc601SMichal Simek 	int conf_noffset;
123362afc601SMichal Simek 	int fit_img_result;
1234b02e4044SSimon Glass 	const char *uname, *name;
123562afc601SMichal Simek 	int err;
123662afc601SMichal Simek 	int devnum = 0; /* TODO support multi fpga platforms */
123762afc601SMichal Simek 
123862afc601SMichal Simek 	/* Check to see if the images struct has a FIT configuration */
123962afc601SMichal Simek 	if (!genimg_has_config(images)) {
124062afc601SMichal Simek 		debug("## FIT configuration was not specified\n");
124162afc601SMichal Simek 		return 0;
124262afc601SMichal Simek 	}
124362afc601SMichal Simek 
124462afc601SMichal Simek 	/*
124562afc601SMichal Simek 	 * Obtain the os FIT header from the images struct
124662afc601SMichal Simek 	 */
124762afc601SMichal Simek 	tmp_img_addr = map_to_sysmem(images->fit_hdr_os);
124862afc601SMichal Simek 	buf = map_sysmem(tmp_img_addr, 0);
124962afc601SMichal Simek 	/*
125062afc601SMichal Simek 	 * Check image type. For FIT images get FIT node
125162afc601SMichal Simek 	 * and attempt to locate a generic binary.
125262afc601SMichal Simek 	 */
125362afc601SMichal Simek 	switch (genimg_get_format(buf)) {
125462afc601SMichal Simek 	case IMAGE_FORMAT_FIT:
125562afc601SMichal Simek 		conf_noffset = fit_conf_get_node(buf, images->fit_uname_cfg);
125662afc601SMichal Simek 
1257b02e4044SSimon Glass 		uname = fdt_stringlist_get(buf, conf_noffset, FIT_FPGA_PROP, 0,
1258b02e4044SSimon Glass 					   NULL);
1259b02e4044SSimon Glass 		if (!uname) {
126062afc601SMichal Simek 			debug("## FPGA image is not specified\n");
126162afc601SMichal Simek 			return 0;
126262afc601SMichal Simek 		}
126362afc601SMichal Simek 		fit_img_result = fit_image_load(images,
126462afc601SMichal Simek 						tmp_img_addr,
126562afc601SMichal Simek 						(const char **)&uname,
126662afc601SMichal Simek 						&(images->fit_uname_cfg),
126762afc601SMichal Simek 						arch,
126862afc601SMichal Simek 						IH_TYPE_FPGA,
126962afc601SMichal Simek 						BOOTSTAGE_ID_FPGA_INIT,
127062afc601SMichal Simek 						FIT_LOAD_OPTIONAL_NON_ZERO,
127162afc601SMichal Simek 						&img_data, &img_len);
127262afc601SMichal Simek 
127362afc601SMichal Simek 		debug("FPGA image (%s) loaded to 0x%lx/size 0x%lx\n",
127462afc601SMichal Simek 		      uname, img_data, img_len);
127562afc601SMichal Simek 
127662afc601SMichal Simek 		if (fit_img_result < 0) {
127762afc601SMichal Simek 			/* Something went wrong! */
127862afc601SMichal Simek 			return fit_img_result;
127962afc601SMichal Simek 		}
128062afc601SMichal Simek 
12818b93a92fSGoldschmidt Simon 		if (!fpga_is_partial_data(devnum, img_len)) {
128262afc601SMichal Simek 			name = "full";
128362afc601SMichal Simek 			err = fpga_loadbitstream(devnum, (char *)img_data,
128462afc601SMichal Simek 						 img_len, BIT_FULL);
128562afc601SMichal Simek 			if (err)
128662afc601SMichal Simek 				err = fpga_load(devnum, (const void *)img_data,
128762afc601SMichal Simek 						img_len, BIT_FULL);
128862afc601SMichal Simek 		} else {
128962afc601SMichal Simek 			name = "partial";
129062afc601SMichal Simek 			err = fpga_loadbitstream(devnum, (char *)img_data,
129162afc601SMichal Simek 						 img_len, BIT_PARTIAL);
129262afc601SMichal Simek 			if (err)
129362afc601SMichal Simek 				err = fpga_load(devnum, (const void *)img_data,
129462afc601SMichal Simek 						img_len, BIT_PARTIAL);
129562afc601SMichal Simek 		}
129662afc601SMichal Simek 
129762afc601SMichal Simek 		if (err)
1298611a9428SMichal Simek 			return err;
1299611a9428SMichal Simek 
1300611a9428SMichal Simek 		printf("   Programming %s bitstream... OK\n", name);
130162afc601SMichal Simek 		break;
130262afc601SMichal Simek 	default:
130362afc601SMichal Simek 		printf("The given image format is not supported (corrupt?)\n");
130462afc601SMichal Simek 		return 1;
130562afc601SMichal Simek 	}
130662afc601SMichal Simek 
130762afc601SMichal Simek 	return 0;
130862afc601SMichal Simek }
130962afc601SMichal Simek #endif
131062afc601SMichal Simek 
fit_loadable_process(uint8_t img_type,ulong img_data,ulong img_len)1311d7be5092SAndrew F. Davis static void fit_loadable_process(uint8_t img_type,
1312d7be5092SAndrew F. Davis 				 ulong img_data,
1313d7be5092SAndrew F. Davis 				 ulong img_len)
1314d7be5092SAndrew F. Davis {
1315d7be5092SAndrew F. Davis 	int i;
1316d7be5092SAndrew F. Davis 	const unsigned int count =
1317d7be5092SAndrew F. Davis 			ll_entry_count(struct fit_loadable_tbl, fit_loadable);
1318d7be5092SAndrew F. Davis 	struct fit_loadable_tbl *fit_loadable_handler =
1319d7be5092SAndrew F. Davis 			ll_entry_start(struct fit_loadable_tbl, fit_loadable);
1320d7be5092SAndrew F. Davis 	/* For each loadable handler */
1321d7be5092SAndrew F. Davis 	for (i = 0; i < count; i++, fit_loadable_handler++)
1322d7be5092SAndrew F. Davis 		/* matching this type */
1323d7be5092SAndrew F. Davis 		if (fit_loadable_handler->type == img_type)
1324d7be5092SAndrew F. Davis 			/* call that handler with this image data */
1325d7be5092SAndrew F. Davis 			fit_loadable_handler->handler(img_data, img_len);
1326d7be5092SAndrew F. Davis }
1327d7be5092SAndrew F. Davis 
boot_get_loadable(int argc,char * const argv[],bootm_headers_t * images,uint8_t arch,const ulong * ld_start,ulong * const ld_len)132884a07dbfSKarl Apsite int boot_get_loadable(int argc, char * const argv[], bootm_headers_t *images,
132984a07dbfSKarl Apsite 		uint8_t arch, const ulong *ld_start, ulong * const ld_len)
133084a07dbfSKarl Apsite {
133184a07dbfSKarl Apsite 	/*
133284a07dbfSKarl Apsite 	 * These variables are used to hold the current image location
133384a07dbfSKarl Apsite 	 * in system memory.
133484a07dbfSKarl Apsite 	 */
133584a07dbfSKarl Apsite 	ulong tmp_img_addr;
133684a07dbfSKarl Apsite 	/*
133784a07dbfSKarl Apsite 	 * These two variables are requirements for fit_image_load, but
133884a07dbfSKarl Apsite 	 * their values are not used
133984a07dbfSKarl Apsite 	 */
134084a07dbfSKarl Apsite 	ulong img_data, img_len;
134184a07dbfSKarl Apsite 	void *buf;
134284a07dbfSKarl Apsite 	int loadables_index;
134384a07dbfSKarl Apsite 	int conf_noffset;
134484a07dbfSKarl Apsite 	int fit_img_result;
1345b02e4044SSimon Glass 	const char *uname;
1346d7be5092SAndrew F. Davis 	uint8_t img_type;
134784a07dbfSKarl Apsite 
134884a07dbfSKarl Apsite 	/* Check to see if the images struct has a FIT configuration */
134984a07dbfSKarl Apsite 	if (!genimg_has_config(images)) {
135084a07dbfSKarl Apsite 		debug("## FIT configuration was not specified\n");
135184a07dbfSKarl Apsite 		return 0;
135284a07dbfSKarl Apsite 	}
135384a07dbfSKarl Apsite 
135484a07dbfSKarl Apsite 	/*
135584a07dbfSKarl Apsite 	 * Obtain the os FIT header from the images struct
135684a07dbfSKarl Apsite 	 */
135784a07dbfSKarl Apsite 	tmp_img_addr = map_to_sysmem(images->fit_hdr_os);
135884a07dbfSKarl Apsite 	buf = map_sysmem(tmp_img_addr, 0);
135984a07dbfSKarl Apsite 	/*
136084a07dbfSKarl Apsite 	 * Check image type. For FIT images get FIT node
136184a07dbfSKarl Apsite 	 * and attempt to locate a generic binary.
136284a07dbfSKarl Apsite 	 */
136384a07dbfSKarl Apsite 	switch (genimg_get_format(buf)) {
136484a07dbfSKarl Apsite 	case IMAGE_FORMAT_FIT:
136584a07dbfSKarl Apsite 		conf_noffset = fit_conf_get_node(buf, images->fit_uname_cfg);
136684a07dbfSKarl Apsite 
136784a07dbfSKarl Apsite 		for (loadables_index = 0;
1368b02e4044SSimon Glass 		     uname = fdt_stringlist_get(buf, conf_noffset,
1369b02e4044SSimon Glass 					FIT_LOADABLE_PROP, loadables_index,
1370b02e4044SSimon Glass 					NULL), uname;
137184a07dbfSKarl Apsite 		     loadables_index++)
137284a07dbfSKarl Apsite 		{
137384a07dbfSKarl Apsite 			fit_img_result = fit_image_load(images,
137484a07dbfSKarl Apsite 				tmp_img_addr,
1375b02e4044SSimon Glass 				&uname,
137684a07dbfSKarl Apsite 				&(images->fit_uname_cfg), arch,
137784a07dbfSKarl Apsite 				IH_TYPE_LOADABLE,
137884a07dbfSKarl Apsite 				BOOTSTAGE_ID_FIT_LOADABLE_START,
137984a07dbfSKarl Apsite 				FIT_LOAD_OPTIONAL_NON_ZERO,
138084a07dbfSKarl Apsite 				&img_data, &img_len);
138184a07dbfSKarl Apsite 			if (fit_img_result < 0) {
138284a07dbfSKarl Apsite 				/* Something went wrong! */
138384a07dbfSKarl Apsite 				return fit_img_result;
138484a07dbfSKarl Apsite 			}
1385d7be5092SAndrew F. Davis 
1386d7be5092SAndrew F. Davis 			fit_img_result = fit_image_get_node(buf, uname);
1387d7be5092SAndrew F. Davis 			if (fit_img_result < 0) {
1388d7be5092SAndrew F. Davis 				/* Something went wrong! */
1389d7be5092SAndrew F. Davis 				return fit_img_result;
1390d7be5092SAndrew F. Davis 			}
1391d7be5092SAndrew F. Davis 			fit_img_result = fit_image_get_type(buf,
1392d7be5092SAndrew F. Davis 							    fit_img_result,
1393d7be5092SAndrew F. Davis 							    &img_type);
1394d7be5092SAndrew F. Davis 			if (fit_img_result < 0) {
1395d7be5092SAndrew F. Davis 				/* Something went wrong! */
1396d7be5092SAndrew F. Davis 				return fit_img_result;
1397d7be5092SAndrew F. Davis 			}
1398d7be5092SAndrew F. Davis 
1399d7be5092SAndrew F. Davis 			fit_loadable_process(img_type, img_data, img_len);
140084a07dbfSKarl Apsite 		}
140184a07dbfSKarl Apsite 		break;
140284a07dbfSKarl Apsite 	default:
140384a07dbfSKarl Apsite 		printf("The given image format is not supported (corrupt?)\n");
140484a07dbfSKarl Apsite 		return 1;
140584a07dbfSKarl Apsite 	}
140684a07dbfSKarl Apsite 
140784a07dbfSKarl Apsite 	return 0;
140884a07dbfSKarl Apsite }
140984a07dbfSKarl Apsite #endif
141084a07dbfSKarl Apsite 
1411fca43cc8SJohn Rigby #ifdef CONFIG_SYS_BOOT_GET_CMDLINE
1412b6b0fe64SMarian Balakowicz /**
14139a4daad0SMarian Balakowicz  * boot_get_cmdline - allocate and initialize kernel cmdline
1414e822d7fcSKumar Gala  * @lmb: pointer to lmb handle, will be used for memory mgmt
1415b6b0fe64SMarian Balakowicz  * @cmd_start: pointer to a ulong variable, will hold cmdline start
1416b6b0fe64SMarian Balakowicz  * @cmd_end: pointer to a ulong variable, will hold cmdline end
1417b6b0fe64SMarian Balakowicz  *
14189a4daad0SMarian Balakowicz  * boot_get_cmdline() allocates space for kernel command line below
1419919d25c9SShyam Saini  * BOOTMAPSZ + env_get_bootm_low() address. If "bootargs" U-Boot environment
1420b6b0fe64SMarian Balakowicz  * variable is present its contents is copied to allocated kernel
1421b6b0fe64SMarian Balakowicz  * command line.
1422b6b0fe64SMarian Balakowicz  *
1423b6b0fe64SMarian Balakowicz  * returns:
1424e822d7fcSKumar Gala  *      0 - success
1425e822d7fcSKumar Gala  *     -1 - failure
1426b6b0fe64SMarian Balakowicz  */
boot_get_cmdline(struct lmb * lmb,ulong * cmd_start,ulong * cmd_end)1427590d3cacSGrant Likely int boot_get_cmdline(struct lmb *lmb, ulong *cmd_start, ulong *cmd_end)
1428b6b0fe64SMarian Balakowicz {
1429b6b0fe64SMarian Balakowicz 	char *cmdline;
1430b6b0fe64SMarian Balakowicz 	char *s;
1431b6b0fe64SMarian Balakowicz 
14326d0f6bcfSJean-Christophe PLAGNIOL-VILLARD 	cmdline = (char *)(ulong)lmb_alloc_base(lmb, CONFIG_SYS_BARGSIZE, 0xf,
1433723806ccSSimon Glass 				env_get_bootm_mapsize() + env_get_bootm_low());
1434e822d7fcSKumar Gala 
1435e822d7fcSKumar Gala 	if (cmdline == NULL)
1436e822d7fcSKumar Gala 		return -1;
1437b6b0fe64SMarian Balakowicz 
143800caae6dSSimon Glass 	s = env_get("bootargs");
143900caae6dSSimon Glass 	if (!s)
1440b6b0fe64SMarian Balakowicz 		s = "";
1441b6b0fe64SMarian Balakowicz 
1442b6b0fe64SMarian Balakowicz 	strcpy(cmdline, s);
1443b6b0fe64SMarian Balakowicz 
1444b6b0fe64SMarian Balakowicz 	*cmd_start = (ulong) & cmdline[0];
1445b6b0fe64SMarian Balakowicz 	*cmd_end = *cmd_start + strlen(cmdline);
1446b6b0fe64SMarian Balakowicz 
1447b6b0fe64SMarian Balakowicz 	debug("## cmdline at 0x%08lx ... 0x%08lx\n", *cmd_start, *cmd_end);
1448b6b0fe64SMarian Balakowicz 
1449e822d7fcSKumar Gala 	return 0;
1450b6b0fe64SMarian Balakowicz }
1451fca43cc8SJohn Rigby #endif /* CONFIG_SYS_BOOT_GET_CMDLINE */
1452b6b0fe64SMarian Balakowicz 
1453fca43cc8SJohn Rigby #ifdef CONFIG_SYS_BOOT_GET_KBD
1454b6b0fe64SMarian Balakowicz /**
14559a4daad0SMarian Balakowicz  * boot_get_kbd - allocate and initialize kernel copy of board info
1456e822d7fcSKumar Gala  * @lmb: pointer to lmb handle, will be used for memory mgmt
1457b6b0fe64SMarian Balakowicz  * @kbd: double pointer to board info data
1458b6b0fe64SMarian Balakowicz  *
14599a4daad0SMarian Balakowicz  * boot_get_kbd() allocates space for kernel copy of board info data below
1460723806ccSSimon Glass  * BOOTMAPSZ + env_get_bootm_low() address and kernel board info is initialized
1461590d3cacSGrant Likely  * with the current u-boot board info data.
1462b6b0fe64SMarian Balakowicz  *
1463b6b0fe64SMarian Balakowicz  * returns:
1464e822d7fcSKumar Gala  *      0 - success
1465e822d7fcSKumar Gala  *     -1 - failure
1466b6b0fe64SMarian Balakowicz  */
boot_get_kbd(struct lmb * lmb,bd_t ** kbd)1467590d3cacSGrant Likely int boot_get_kbd(struct lmb *lmb, bd_t **kbd)
1468b6b0fe64SMarian Balakowicz {
1469391fd93aSBecky Bruce 	*kbd = (bd_t *)(ulong)lmb_alloc_base(lmb, sizeof(bd_t), 0xf,
1470723806ccSSimon Glass 				env_get_bootm_mapsize() + env_get_bootm_low());
1471e822d7fcSKumar Gala 	if (*kbd == NULL)
1472e822d7fcSKumar Gala 		return -1;
1473e822d7fcSKumar Gala 
1474b6b0fe64SMarian Balakowicz 	**kbd = *(gd->bd);
1475b6b0fe64SMarian Balakowicz 
1476b6b0fe64SMarian Balakowicz 	debug("## kernel board info at 0x%08lx\n", (ulong)*kbd);
1477b6b0fe64SMarian Balakowicz 
1478b6b0fe64SMarian Balakowicz #if defined(DEBUG) && defined(CONFIG_CMD_BDI)
1479b6b0fe64SMarian Balakowicz 	do_bdinfo(NULL, 0, 0, NULL);
1480b6b0fe64SMarian Balakowicz #endif
1481b6b0fe64SMarian Balakowicz 
1482e822d7fcSKumar Gala 	return 0;
1483ceaed2b1SMarian Balakowicz }
1484fca43cc8SJohn Rigby #endif /* CONFIG_SYS_BOOT_GET_KBD */
148513d06981SSimon Glass 
148613d06981SSimon Glass #ifdef CONFIG_LMB
image_setup_linux(bootm_headers_t * images)148713d06981SSimon Glass int image_setup_linux(bootm_headers_t *images)
148813d06981SSimon Glass {
148913d06981SSimon Glass 	ulong of_size = images->ft_len;
149013d06981SSimon Glass 	char **of_flat_tree = &images->ft_addr;
149113d06981SSimon Glass 	struct lmb *lmb = &images->lmb;
149213d06981SSimon Glass 	int ret;
149313d06981SSimon Glass 
149413d06981SSimon Glass 	if (IMAGE_ENABLE_OF_LIBFDT)
149513d06981SSimon Glass 		boot_fdt_add_mem_rsv_regions(lmb, *of_flat_tree);
149613d06981SSimon Glass 
149713d06981SSimon Glass 	if (IMAGE_BOOT_GET_CMDLINE) {
149813d06981SSimon Glass 		ret = boot_get_cmdline(lmb, &images->cmdline_start,
149913d06981SSimon Glass 				&images->cmdline_end);
150013d06981SSimon Glass 		if (ret) {
150113d06981SSimon Glass 			puts("ERROR with allocation of cmdline\n");
150213d06981SSimon Glass 			return ret;
150313d06981SSimon Glass 		}
150413d06981SSimon Glass 	}
150513d06981SSimon Glass 
150613d06981SSimon Glass 	if (IMAGE_ENABLE_OF_LIBFDT) {
150713d06981SSimon Glass 		ret = boot_relocate_fdt(lmb, of_flat_tree, &of_size);
150813d06981SSimon Glass 		if (ret)
150913d06981SSimon Glass 			return ret;
151013d06981SSimon Glass 	}
151113d06981SSimon Glass 
151213d06981SSimon Glass 	if (IMAGE_ENABLE_OF_LIBFDT && of_size) {
151313d06981SSimon Glass 		ret = image_setup_libfdt(images, *of_flat_tree, of_size, lmb);
151413d06981SSimon Glass 		if (ret)
151513d06981SSimon Glass 			return ret;
151613d06981SSimon Glass 	}
151713d06981SSimon Glass 
151813d06981SSimon Glass 	return 0;
151913d06981SSimon Glass }
152013d06981SSimon Glass #endif /* CONFIG_LMB */
15215dfb5213SMarian Balakowicz #endif /* !USE_HOSTCC */
1522