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(×tamp));
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