xref: /OK3568_Linux_fs/u-boot/common/bootm.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1*4882a593Smuzhiyun /*
2*4882a593Smuzhiyun  * (C) Copyright 2000-2009
3*4882a593Smuzhiyun  * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
4*4882a593Smuzhiyun  *
5*4882a593Smuzhiyun  * SPDX-License-Identifier:	GPL-2.0+
6*4882a593Smuzhiyun  */
7*4882a593Smuzhiyun 
8*4882a593Smuzhiyun #ifndef USE_HOSTCC
9*4882a593Smuzhiyun #include <common.h>
10*4882a593Smuzhiyun #include <bootstage.h>
11*4882a593Smuzhiyun #include <bzlib.h>
12*4882a593Smuzhiyun #include <errno.h>
13*4882a593Smuzhiyun #include <fdt_support.h>
14*4882a593Smuzhiyun #include <lmb.h>
15*4882a593Smuzhiyun #include <malloc.h>
16*4882a593Smuzhiyun #include <mapmem.h>
17*4882a593Smuzhiyun #include <asm/io.h>
18*4882a593Smuzhiyun #include <linux/lzo.h>
19*4882a593Smuzhiyun #include <lzma/LzmaTypes.h>
20*4882a593Smuzhiyun #include <lzma/LzmaDec.h>
21*4882a593Smuzhiyun #include <lzma/LzmaTools.h>
22*4882a593Smuzhiyun #if defined(CONFIG_CMD_USB)
23*4882a593Smuzhiyun #include <usb.h>
24*4882a593Smuzhiyun #endif
25*4882a593Smuzhiyun #else
26*4882a593Smuzhiyun #include "mkimage.h"
27*4882a593Smuzhiyun #endif
28*4882a593Smuzhiyun 
29*4882a593Smuzhiyun #include <command.h>
30*4882a593Smuzhiyun #include <bootm.h>
31*4882a593Smuzhiyun #include <image.h>
32*4882a593Smuzhiyun 
33*4882a593Smuzhiyun #ifdef USE_HOSTCC
34*4882a593Smuzhiyun #define CONFIG_SYS_BOOTM_LEN	0x10000000
35*4882a593Smuzhiyun #endif
36*4882a593Smuzhiyun 
37*4882a593Smuzhiyun #ifndef CONFIG_SYS_BOOTM_LEN
38*4882a593Smuzhiyun /* use 8MByte as default max gunzip size */
39*4882a593Smuzhiyun #define CONFIG_SYS_BOOTM_LEN	0x800000
40*4882a593Smuzhiyun #endif
41*4882a593Smuzhiyun 
42*4882a593Smuzhiyun #define IH_INITRD_ARCH IH_ARCH_DEFAULT
43*4882a593Smuzhiyun 
44*4882a593Smuzhiyun #ifndef USE_HOSTCC
45*4882a593Smuzhiyun 
46*4882a593Smuzhiyun DECLARE_GLOBAL_DATA_PTR;
47*4882a593Smuzhiyun 
48*4882a593Smuzhiyun bootm_headers_t images;		/* pointers to os/initrd/fdt images */
49*4882a593Smuzhiyun 
board_do_bootm(int argc,char * const argv[])50*4882a593Smuzhiyun __weak int board_do_bootm(int argc, char * const argv[])
51*4882a593Smuzhiyun {
52*4882a593Smuzhiyun 	return 0;
53*4882a593Smuzhiyun }
54*4882a593Smuzhiyun 
bootm_board_start(void)55*4882a593Smuzhiyun __weak int bootm_board_start(void)
56*4882a593Smuzhiyun {
57*4882a593Smuzhiyun 	return 0;
58*4882a593Smuzhiyun }
59*4882a593Smuzhiyun 
60*4882a593Smuzhiyun static const void *boot_get_kernel(cmd_tbl_t *cmdtp, int flag, int argc,
61*4882a593Smuzhiyun 				   char * const argv[], bootm_headers_t *images,
62*4882a593Smuzhiyun 				   ulong *os_data, ulong *os_len);
63*4882a593Smuzhiyun 
64*4882a593Smuzhiyun #ifdef CONFIG_LMB
boot_start_lmb(bootm_headers_t * images)65*4882a593Smuzhiyun static void boot_start_lmb(bootm_headers_t *images)
66*4882a593Smuzhiyun {
67*4882a593Smuzhiyun 
68*4882a593Smuzhiyun 	lmb_init(&images->lmb);
69*4882a593Smuzhiyun #ifdef CONFIG_NR_DRAM_BANKS
70*4882a593Smuzhiyun 	int i;
71*4882a593Smuzhiyun 
72*4882a593Smuzhiyun 	for (i = 0; i < CONFIG_NR_DRAM_BANKS; i++) {
73*4882a593Smuzhiyun 		lmb_add(&images->lmb, gd->bd->bi_dram[i].start,
74*4882a593Smuzhiyun 			gd->bd->bi_dram[i].size);
75*4882a593Smuzhiyun 	}
76*4882a593Smuzhiyun #else
77*4882a593Smuzhiyun 	ulong		mem_start;
78*4882a593Smuzhiyun 	phys_size_t	mem_size;
79*4882a593Smuzhiyun 
80*4882a593Smuzhiyun 	mem_start = env_get_bootm_low();
81*4882a593Smuzhiyun 	mem_size = env_get_bootm_size();
82*4882a593Smuzhiyun 	lmb_add(&images->lmb, (phys_addr_t)mem_start, mem_size);
83*4882a593Smuzhiyun #endif
84*4882a593Smuzhiyun 	arch_lmb_reserve(&images->lmb);
85*4882a593Smuzhiyun 	board_lmb_reserve(&images->lmb);
86*4882a593Smuzhiyun }
87*4882a593Smuzhiyun #else
88*4882a593Smuzhiyun #define lmb_reserve(lmb, base, size)
boot_start_lmb(bootm_headers_t * images)89*4882a593Smuzhiyun static inline void boot_start_lmb(bootm_headers_t *images) { }
90*4882a593Smuzhiyun #endif
91*4882a593Smuzhiyun 
bootm_start(cmd_tbl_t * cmdtp,int flag,int argc,char * const argv[])92*4882a593Smuzhiyun static int bootm_start(cmd_tbl_t *cmdtp, int flag, int argc,
93*4882a593Smuzhiyun 		       char * const argv[])
94*4882a593Smuzhiyun {
95*4882a593Smuzhiyun 	memset((void *)&images, 0, sizeof(images));
96*4882a593Smuzhiyun 	images.verify = env_get_yesno("verify");
97*4882a593Smuzhiyun 
98*4882a593Smuzhiyun 	boot_start_lmb(&images);
99*4882a593Smuzhiyun 
100*4882a593Smuzhiyun 	bootstage_mark_name(BOOTSTAGE_ID_BOOTM_START, "bootm_start");
101*4882a593Smuzhiyun 	images.state = BOOTM_STATE_START;
102*4882a593Smuzhiyun 
103*4882a593Smuzhiyun 	return bootm_board_start();
104*4882a593Smuzhiyun }
105*4882a593Smuzhiyun 
bootm_find_os(cmd_tbl_t * cmdtp,int flag,int argc,char * const argv[])106*4882a593Smuzhiyun static int bootm_find_os(cmd_tbl_t *cmdtp, int flag, int argc,
107*4882a593Smuzhiyun 			 char * const argv[])
108*4882a593Smuzhiyun {
109*4882a593Smuzhiyun 	const void *os_hdr;
110*4882a593Smuzhiyun 	bool ep_found = false;
111*4882a593Smuzhiyun 	int ret;
112*4882a593Smuzhiyun 
113*4882a593Smuzhiyun 	/* get kernel image header, start address and length */
114*4882a593Smuzhiyun 	os_hdr = boot_get_kernel(cmdtp, flag, argc, argv,
115*4882a593Smuzhiyun 			&images, &images.os.image_start, &images.os.image_len);
116*4882a593Smuzhiyun 	if (images.os.image_len == 0) {
117*4882a593Smuzhiyun 		puts("ERROR: can't get kernel image!\n");
118*4882a593Smuzhiyun 		return 1;
119*4882a593Smuzhiyun 	}
120*4882a593Smuzhiyun 
121*4882a593Smuzhiyun 	/* get image parameters */
122*4882a593Smuzhiyun 	switch (genimg_get_format(os_hdr)) {
123*4882a593Smuzhiyun #if defined(CONFIG_IMAGE_FORMAT_LEGACY)
124*4882a593Smuzhiyun 	case IMAGE_FORMAT_LEGACY:
125*4882a593Smuzhiyun 		images.os.type = image_get_type(os_hdr);
126*4882a593Smuzhiyun 		images.os.comp = image_get_comp(os_hdr);
127*4882a593Smuzhiyun 		images.os.os = image_get_os(os_hdr);
128*4882a593Smuzhiyun 
129*4882a593Smuzhiyun 		images.os.end = image_get_image_end(os_hdr);
130*4882a593Smuzhiyun 		images.os.load = image_get_load(os_hdr);
131*4882a593Smuzhiyun 		images.os.arch = image_get_arch(os_hdr);
132*4882a593Smuzhiyun 		break;
133*4882a593Smuzhiyun #endif
134*4882a593Smuzhiyun #if IMAGE_ENABLE_FIT
135*4882a593Smuzhiyun 	case IMAGE_FORMAT_FIT:
136*4882a593Smuzhiyun 		if (fit_image_get_type(images.fit_hdr_os,
137*4882a593Smuzhiyun 				       images.fit_noffset_os,
138*4882a593Smuzhiyun 				       &images.os.type)) {
139*4882a593Smuzhiyun 			puts("Can't get image type!\n");
140*4882a593Smuzhiyun 			bootstage_error(BOOTSTAGE_ID_FIT_TYPE);
141*4882a593Smuzhiyun 			return 1;
142*4882a593Smuzhiyun 		}
143*4882a593Smuzhiyun 
144*4882a593Smuzhiyun 		if (fit_image_get_comp(images.fit_hdr_os,
145*4882a593Smuzhiyun 				       images.fit_noffset_os,
146*4882a593Smuzhiyun 				       &images.os.comp)) {
147*4882a593Smuzhiyun 			puts("Can't get image compression!\n");
148*4882a593Smuzhiyun 			bootstage_error(BOOTSTAGE_ID_FIT_COMPRESSION);
149*4882a593Smuzhiyun 			return 1;
150*4882a593Smuzhiyun 		}
151*4882a593Smuzhiyun 
152*4882a593Smuzhiyun 		if (fit_image_get_os(images.fit_hdr_os, images.fit_noffset_os,
153*4882a593Smuzhiyun 				     &images.os.os)) {
154*4882a593Smuzhiyun 			puts("Can't get image OS!\n");
155*4882a593Smuzhiyun 			bootstage_error(BOOTSTAGE_ID_FIT_OS);
156*4882a593Smuzhiyun 			return 1;
157*4882a593Smuzhiyun 		}
158*4882a593Smuzhiyun 
159*4882a593Smuzhiyun 		if (fit_image_get_arch(images.fit_hdr_os,
160*4882a593Smuzhiyun 				       images.fit_noffset_os,
161*4882a593Smuzhiyun 				       &images.os.arch)) {
162*4882a593Smuzhiyun 			puts("Can't get image ARCH!\n");
163*4882a593Smuzhiyun 			return 1;
164*4882a593Smuzhiyun 		}
165*4882a593Smuzhiyun 
166*4882a593Smuzhiyun 		images.os.end = fit_get_end(images.fit_hdr_os);
167*4882a593Smuzhiyun 
168*4882a593Smuzhiyun 		if (fit_image_get_load(images.fit_hdr_os, images.fit_noffset_os,
169*4882a593Smuzhiyun 				       &images.os.load)) {
170*4882a593Smuzhiyun 			puts("Can't get image load address!\n");
171*4882a593Smuzhiyun 			bootstage_error(BOOTSTAGE_ID_FIT_LOADADDR);
172*4882a593Smuzhiyun 			return 1;
173*4882a593Smuzhiyun 		}
174*4882a593Smuzhiyun 		break;
175*4882a593Smuzhiyun #endif
176*4882a593Smuzhiyun #ifdef CONFIG_ANDROID_BOOT_IMAGE
177*4882a593Smuzhiyun 	case IMAGE_FORMAT_ANDROID:
178*4882a593Smuzhiyun 		images.os.type = IH_TYPE_KERNEL;
179*4882a593Smuzhiyun 		images.os.comp = android_image_get_comp(os_hdr);
180*4882a593Smuzhiyun 		images.os.os = IH_OS_LINUX;
181*4882a593Smuzhiyun 
182*4882a593Smuzhiyun 		images.os.end = android_image_get_end(os_hdr);
183*4882a593Smuzhiyun 		images.os.load = android_image_get_kload(os_hdr);
184*4882a593Smuzhiyun 		images.ep = images.os.load;
185*4882a593Smuzhiyun 		ep_found = true;
186*4882a593Smuzhiyun 		break;
187*4882a593Smuzhiyun #endif
188*4882a593Smuzhiyun 	default:
189*4882a593Smuzhiyun 		puts("ERROR: unknown image format type!\n");
190*4882a593Smuzhiyun 		return 1;
191*4882a593Smuzhiyun 	}
192*4882a593Smuzhiyun 
193*4882a593Smuzhiyun 	/* If we have a valid setup.bin, we will use that for entry (x86) */
194*4882a593Smuzhiyun 	if (images.os.arch == IH_ARCH_I386 ||
195*4882a593Smuzhiyun 	    images.os.arch == IH_ARCH_X86_64) {
196*4882a593Smuzhiyun 		ulong len;
197*4882a593Smuzhiyun 
198*4882a593Smuzhiyun 		ret = boot_get_setup(&images, IH_ARCH_I386, &images.ep, &len);
199*4882a593Smuzhiyun 		if (ret < 0 && ret != -ENOENT) {
200*4882a593Smuzhiyun 			puts("Could not find a valid setup.bin for x86\n");
201*4882a593Smuzhiyun 			return 1;
202*4882a593Smuzhiyun 		}
203*4882a593Smuzhiyun 		/* Kernel entry point is the setup.bin */
204*4882a593Smuzhiyun 	} else if (images.legacy_hdr_valid) {
205*4882a593Smuzhiyun 		images.ep = image_get_ep(&images.legacy_hdr_os_copy);
206*4882a593Smuzhiyun #if IMAGE_ENABLE_FIT
207*4882a593Smuzhiyun 	} else if (images.fit_uname_os) {
208*4882a593Smuzhiyun 		int ret;
209*4882a593Smuzhiyun 
210*4882a593Smuzhiyun 		ret = fit_image_get_entry(images.fit_hdr_os,
211*4882a593Smuzhiyun 					  images.fit_noffset_os, &images.ep);
212*4882a593Smuzhiyun 		if (ret) {
213*4882a593Smuzhiyun 			puts("Can't get entry point property!\n");
214*4882a593Smuzhiyun 			return 1;
215*4882a593Smuzhiyun 		}
216*4882a593Smuzhiyun #endif
217*4882a593Smuzhiyun 	} else if (!ep_found) {
218*4882a593Smuzhiyun 		puts("Could not find kernel entry point!\n");
219*4882a593Smuzhiyun 		return 1;
220*4882a593Smuzhiyun 	}
221*4882a593Smuzhiyun 
222*4882a593Smuzhiyun 	if (images.os.type == IH_TYPE_KERNEL_NOLOAD) {
223*4882a593Smuzhiyun 		images.os.load = images.os.image_start;
224*4882a593Smuzhiyun 		images.ep += images.os.load;
225*4882a593Smuzhiyun 	}
226*4882a593Smuzhiyun 
227*4882a593Smuzhiyun 	images.os.start = map_to_sysmem(os_hdr);
228*4882a593Smuzhiyun 
229*4882a593Smuzhiyun 	return 0;
230*4882a593Smuzhiyun }
231*4882a593Smuzhiyun 
232*4882a593Smuzhiyun /**
233*4882a593Smuzhiyun  * bootm_find_images - wrapper to find and locate various images
234*4882a593Smuzhiyun  * @flag: Ignored Argument
235*4882a593Smuzhiyun  * @argc: command argument count
236*4882a593Smuzhiyun  * @argv: command argument list
237*4882a593Smuzhiyun  *
238*4882a593Smuzhiyun  * boot_find_images() will attempt to load an available ramdisk,
239*4882a593Smuzhiyun  * flattened device tree, as well as specifically marked
240*4882a593Smuzhiyun  * "loadable" images (loadables are FIT only)
241*4882a593Smuzhiyun  *
242*4882a593Smuzhiyun  * Note: bootm_find_images will skip an image if it is not found
243*4882a593Smuzhiyun  *
244*4882a593Smuzhiyun  * @return:
245*4882a593Smuzhiyun  *     0, if all existing images were loaded correctly
246*4882a593Smuzhiyun  *     1, if an image is found but corrupted, or invalid
247*4882a593Smuzhiyun  */
bootm_find_images(int flag,int argc,char * const argv[])248*4882a593Smuzhiyun int bootm_find_images(int flag, int argc, char * const argv[])
249*4882a593Smuzhiyun {
250*4882a593Smuzhiyun 	int ret;
251*4882a593Smuzhiyun 
252*4882a593Smuzhiyun 	/* find ramdisk */
253*4882a593Smuzhiyun 	ret = boot_get_ramdisk(argc, argv, &images, IH_INITRD_ARCH,
254*4882a593Smuzhiyun 			       &images.rd_start, &images.rd_end);
255*4882a593Smuzhiyun 	if (ret) {
256*4882a593Smuzhiyun 		puts("Ramdisk image is corrupt or invalid\n");
257*4882a593Smuzhiyun 		return 1;
258*4882a593Smuzhiyun 	}
259*4882a593Smuzhiyun 
260*4882a593Smuzhiyun #if IMAGE_ENABLE_OF_LIBFDT
261*4882a593Smuzhiyun 	/* find flattened device tree */
262*4882a593Smuzhiyun 	ret = boot_get_fdt(flag, argc, argv, IH_ARCH_DEFAULT, &images,
263*4882a593Smuzhiyun 			   &images.ft_addr, &images.ft_len);
264*4882a593Smuzhiyun 	if (ret) {
265*4882a593Smuzhiyun 		puts("Could not find a valid device tree\n");
266*4882a593Smuzhiyun 		return 1;
267*4882a593Smuzhiyun 	}
268*4882a593Smuzhiyun #ifdef CONFIG_CMD_FDT
269*4882a593Smuzhiyun 	set_working_fdt_addr((ulong)images.ft_addr);
270*4882a593Smuzhiyun #endif
271*4882a593Smuzhiyun 	lmb_reserve(&images.lmb, (ulong)images.ft_addr, (ulong)images.ft_len);
272*4882a593Smuzhiyun #endif
273*4882a593Smuzhiyun 
274*4882a593Smuzhiyun #if IMAGE_ENABLE_FIT
275*4882a593Smuzhiyun #if defined(CONFIG_FPGA) && defined(CONFIG_FPGA_XILINX)
276*4882a593Smuzhiyun 	/* find bitstreams */
277*4882a593Smuzhiyun 	ret = boot_get_fpga(argc, argv, &images, IH_ARCH_DEFAULT,
278*4882a593Smuzhiyun 			    NULL, NULL);
279*4882a593Smuzhiyun 	if (ret) {
280*4882a593Smuzhiyun 		printf("FPGA image is corrupted or invalid\n");
281*4882a593Smuzhiyun 		return 1;
282*4882a593Smuzhiyun 	}
283*4882a593Smuzhiyun #endif
284*4882a593Smuzhiyun 
285*4882a593Smuzhiyun 	/* find all of the loadables */
286*4882a593Smuzhiyun 	ret = boot_get_loadable(argc, argv, &images, IH_ARCH_DEFAULT,
287*4882a593Smuzhiyun 			       NULL, NULL);
288*4882a593Smuzhiyun 	if (ret) {
289*4882a593Smuzhiyun 		printf("Loadable(s) is corrupt or invalid\n");
290*4882a593Smuzhiyun 		return 1;
291*4882a593Smuzhiyun 	}
292*4882a593Smuzhiyun #endif
293*4882a593Smuzhiyun 
294*4882a593Smuzhiyun 	return 0;
295*4882a593Smuzhiyun }
296*4882a593Smuzhiyun 
bootm_find_other(cmd_tbl_t * cmdtp,int flag,int argc,char * const argv[])297*4882a593Smuzhiyun static int bootm_find_other(cmd_tbl_t *cmdtp, int flag, int argc,
298*4882a593Smuzhiyun 			    char * const argv[])
299*4882a593Smuzhiyun {
300*4882a593Smuzhiyun 	if (((images.os.type == IH_TYPE_KERNEL) ||
301*4882a593Smuzhiyun 	     (images.os.type == IH_TYPE_KERNEL_NOLOAD) ||
302*4882a593Smuzhiyun 	     (images.os.type == IH_TYPE_MULTI)) &&
303*4882a593Smuzhiyun 	    (images.os.os == IH_OS_LINUX ||
304*4882a593Smuzhiyun 		 images.os.os == IH_OS_VXWORKS))
305*4882a593Smuzhiyun 		return bootm_find_images(flag, argc, argv);
306*4882a593Smuzhiyun 
307*4882a593Smuzhiyun 	return 0;
308*4882a593Smuzhiyun }
309*4882a593Smuzhiyun #endif /* USE_HOSTC */
310*4882a593Smuzhiyun 
311*4882a593Smuzhiyun /**
312*4882a593Smuzhiyun  * print_decomp_msg() - Print a suitable decompression/loading message
313*4882a593Smuzhiyun  *
314*4882a593Smuzhiyun  * @type:	OS type (IH_OS_...)
315*4882a593Smuzhiyun  * @comp_type:	Compression type being used (IH_COMP_...)
316*4882a593Smuzhiyun  * @is_xip:	true if the load address matches the image start
317*4882a593Smuzhiyun  */
print_decomp_msg(int comp_type,int type,bool is_xip,ulong src,ulong dst)318*4882a593Smuzhiyun static void print_decomp_msg(int comp_type, int type, bool is_xip,
319*4882a593Smuzhiyun 			     ulong src, ulong dst)
320*4882a593Smuzhiyun {
321*4882a593Smuzhiyun 	const char *name = genimg_get_type_name(type);
322*4882a593Smuzhiyun 	const char *comp_name[] = {
323*4882a593Smuzhiyun 		[IH_COMP_NONE]  = "",
324*4882a593Smuzhiyun 		[IH_COMP_GZIP]  = "GZIP",
325*4882a593Smuzhiyun 		[IH_COMP_BZIP2] = "BZIP2",
326*4882a593Smuzhiyun 		[IH_COMP_LZMA]  = "LZMA",
327*4882a593Smuzhiyun 		[IH_COMP_LZO]   = "LZO",
328*4882a593Smuzhiyun 		[IH_COMP_LZ4]   = "LZ4",
329*4882a593Smuzhiyun 		[IH_COMP_ZIMAGE]= "ZIMAGE",
330*4882a593Smuzhiyun 	};
331*4882a593Smuzhiyun 
332*4882a593Smuzhiyun 	if (comp_type == IH_COMP_NONE)
333*4882a593Smuzhiyun 		printf("   %s %s from 0x%08lx to 0x%08lx ... ",
334*4882a593Smuzhiyun 		       is_xip ? "XIP" : "Loading", name, src, dst);
335*4882a593Smuzhiyun 	else
336*4882a593Smuzhiyun 		printf("   Uncompressing %s %s from 0x%08lx to 0x%08lx ... ",
337*4882a593Smuzhiyun 		       comp_name[comp_type], name, src, dst);
338*4882a593Smuzhiyun }
339*4882a593Smuzhiyun 
340*4882a593Smuzhiyun /**
341*4882a593Smuzhiyun  * handle_decomp_error() - display a decompression error
342*4882a593Smuzhiyun  *
343*4882a593Smuzhiyun  * This function tries to produce a useful message. In the case where the
344*4882a593Smuzhiyun  * uncompressed size is the same as the available space, we can assume that
345*4882a593Smuzhiyun  * the image is too large for the buffer.
346*4882a593Smuzhiyun  *
347*4882a593Smuzhiyun  * @comp_type:		Compression type being used (IH_COMP_...)
348*4882a593Smuzhiyun  * @uncomp_size:	Number of bytes uncompressed
349*4882a593Smuzhiyun  * @unc_len:		Amount of space available for decompression
350*4882a593Smuzhiyun  * @ret:		Error code to report
351*4882a593Smuzhiyun  * @return BOOTM_ERR_RESET, indicating that the board must be reset
352*4882a593Smuzhiyun  */
handle_decomp_error(int comp_type,size_t uncomp_size,size_t unc_len,int ret)353*4882a593Smuzhiyun static int handle_decomp_error(int comp_type, size_t uncomp_size,
354*4882a593Smuzhiyun 			       size_t unc_len, int ret)
355*4882a593Smuzhiyun {
356*4882a593Smuzhiyun 	const char *name = genimg_get_comp_name(comp_type);
357*4882a593Smuzhiyun 
358*4882a593Smuzhiyun 	if (uncomp_size >= unc_len)
359*4882a593Smuzhiyun 		printf("Image too large(0x%lx >= 0x%lx): increase CONFIG_SYS_BOOTM_LEN\n",
360*4882a593Smuzhiyun 		       (ulong)uncomp_size, (ulong)unc_len);
361*4882a593Smuzhiyun 	else
362*4882a593Smuzhiyun 		printf("%s: uncompress error %d\n", name, ret);
363*4882a593Smuzhiyun 
364*4882a593Smuzhiyun 	/*
365*4882a593Smuzhiyun 	 * The decompression routines are now safe, so will not write beyond
366*4882a593Smuzhiyun 	 * their bounds. Probably it is not necessary to reset, but maintain
367*4882a593Smuzhiyun 	 * the current behaviour for now.
368*4882a593Smuzhiyun 	 */
369*4882a593Smuzhiyun 	printf("Must RESET board to recover\n");
370*4882a593Smuzhiyun #ifndef USE_HOSTCC
371*4882a593Smuzhiyun 	bootstage_error(BOOTSTAGE_ID_DECOMP_IMAGE);
372*4882a593Smuzhiyun #endif
373*4882a593Smuzhiyun 
374*4882a593Smuzhiyun 	return BOOTM_ERR_RESET;
375*4882a593Smuzhiyun }
376*4882a593Smuzhiyun 
bootm_parse_comp(const unsigned char * hdr)377*4882a593Smuzhiyun int bootm_parse_comp(const unsigned char *hdr)
378*4882a593Smuzhiyun {
379*4882a593Smuzhiyun #if defined(CONFIG_CMD_BOOTZ)
380*4882a593Smuzhiyun 	ulong start, end;
381*4882a593Smuzhiyun 
382*4882a593Smuzhiyun 	if (!bootz_setup((ulong)hdr, &start, &end))
383*4882a593Smuzhiyun 		return IH_COMP_ZIMAGE;
384*4882a593Smuzhiyun #endif
385*4882a593Smuzhiyun #if defined(CONFIG_LZ4)
386*4882a593Smuzhiyun 	if (lz4_is_valid_header(hdr))
387*4882a593Smuzhiyun 		return IH_COMP_LZ4;
388*4882a593Smuzhiyun #endif
389*4882a593Smuzhiyun #if defined(CONFIG_LZO)
390*4882a593Smuzhiyun 	if (lzop_is_valid_header(hdr))
391*4882a593Smuzhiyun 		return IH_COMP_LZO;
392*4882a593Smuzhiyun #endif
393*4882a593Smuzhiyun #if defined(CONFIG_GZIP)
394*4882a593Smuzhiyun 	if (gzip_parse_header(hdr, 0xffff) > 0)
395*4882a593Smuzhiyun 		return IH_COMP_GZIP;
396*4882a593Smuzhiyun #endif
397*4882a593Smuzhiyun #if defined(CONFIG_BZIP2)
398*4882a593Smuzhiyun 	if ((hdr[0] == 'B') && (hdr[1] == 'Z') && (hdr[2] == 'h'))
399*4882a593Smuzhiyun 		return IH_COMP_BZIP2;
400*4882a593Smuzhiyun #endif
401*4882a593Smuzhiyun #if defined(CONFIG_LZMA)
402*4882a593Smuzhiyun 	if (lzma_is_valid(hdr))
403*4882a593Smuzhiyun 		return IH_COMP_LZMA;
404*4882a593Smuzhiyun #endif
405*4882a593Smuzhiyun 
406*4882a593Smuzhiyun 	return IH_COMP_NONE;
407*4882a593Smuzhiyun }
408*4882a593Smuzhiyun 
bootm_decomp_image(int comp,ulong load,ulong image_start,int type,void * load_buf,void * image_buf,ulong image_len,uint unc_len,ulong * load_end)409*4882a593Smuzhiyun int bootm_decomp_image(int comp, ulong load, ulong image_start, int type,
410*4882a593Smuzhiyun 		       void *load_buf, void *image_buf, ulong image_len,
411*4882a593Smuzhiyun 		       uint unc_len, ulong *load_end)
412*4882a593Smuzhiyun {
413*4882a593Smuzhiyun 	int ret = 0;
414*4882a593Smuzhiyun 
415*4882a593Smuzhiyun 	*load_end = load;
416*4882a593Smuzhiyun 	print_decomp_msg(comp, type, load == image_start,
417*4882a593Smuzhiyun 		(ulong)image_buf, (ulong)load_buf);
418*4882a593Smuzhiyun 
419*4882a593Smuzhiyun 	/*
420*4882a593Smuzhiyun 	 * Load the image to the right place, decompressing if needed. After
421*4882a593Smuzhiyun 	 * this, image_len will be set to the number of uncompressed bytes
422*4882a593Smuzhiyun 	 * loaded, ret will be non-zero on error.
423*4882a593Smuzhiyun 	 */
424*4882a593Smuzhiyun 	switch (comp) {
425*4882a593Smuzhiyun 	case IH_COMP_NONE:
426*4882a593Smuzhiyun 		if (load == image_start)
427*4882a593Smuzhiyun 			break;
428*4882a593Smuzhiyun 		if (image_len <= unc_len)
429*4882a593Smuzhiyun 			memmove_wd(load_buf, image_buf, image_len, CHUNKSZ);
430*4882a593Smuzhiyun 		else
431*4882a593Smuzhiyun 			ret = 1;
432*4882a593Smuzhiyun 		break;
433*4882a593Smuzhiyun #ifdef CONFIG_GZIP
434*4882a593Smuzhiyun 	case IH_COMP_GZIP: {
435*4882a593Smuzhiyun 		ret = gunzip(load_buf, unc_len, image_buf, &image_len);
436*4882a593Smuzhiyun 		break;
437*4882a593Smuzhiyun 	}
438*4882a593Smuzhiyun #endif /* CONFIG_GZIP */
439*4882a593Smuzhiyun #ifdef CONFIG_BZIP2
440*4882a593Smuzhiyun 	case IH_COMP_BZIP2: {
441*4882a593Smuzhiyun 		uint size = unc_len;
442*4882a593Smuzhiyun 
443*4882a593Smuzhiyun 		/*
444*4882a593Smuzhiyun 		 * If we've got less than 4 MB of malloc() space,
445*4882a593Smuzhiyun 		 * use slower decompression algorithm which requires
446*4882a593Smuzhiyun 		 * at most 2300 KB of memory.
447*4882a593Smuzhiyun 		 */
448*4882a593Smuzhiyun 		ret = BZ2_bzBuffToBuffDecompress(load_buf, &size,
449*4882a593Smuzhiyun 			image_buf, image_len,
450*4882a593Smuzhiyun 			CONFIG_SYS_MALLOC_LEN < (4096 * 1024), 0);
451*4882a593Smuzhiyun 		image_len = size;
452*4882a593Smuzhiyun 		break;
453*4882a593Smuzhiyun 	}
454*4882a593Smuzhiyun #endif /* CONFIG_BZIP2 */
455*4882a593Smuzhiyun #ifdef CONFIG_LZMA
456*4882a593Smuzhiyun 	case IH_COMP_LZMA: {
457*4882a593Smuzhiyun 		SizeT lzma_len = unc_len;
458*4882a593Smuzhiyun 
459*4882a593Smuzhiyun 		ret = lzmaBuffToBuffDecompress(load_buf, &lzma_len,
460*4882a593Smuzhiyun 					       image_buf, image_len);
461*4882a593Smuzhiyun 		image_len = lzma_len;
462*4882a593Smuzhiyun 		break;
463*4882a593Smuzhiyun 	}
464*4882a593Smuzhiyun #endif /* CONFIG_LZMA */
465*4882a593Smuzhiyun #ifdef CONFIG_LZO
466*4882a593Smuzhiyun 	case IH_COMP_LZO: {
467*4882a593Smuzhiyun 		size_t size = unc_len;
468*4882a593Smuzhiyun 
469*4882a593Smuzhiyun 		ret = lzop_decompress(image_buf, image_len, load_buf, &size);
470*4882a593Smuzhiyun 		image_len = size;
471*4882a593Smuzhiyun 		break;
472*4882a593Smuzhiyun 	}
473*4882a593Smuzhiyun #endif /* CONFIG_LZO */
474*4882a593Smuzhiyun #ifdef CONFIG_LZ4
475*4882a593Smuzhiyun 	case IH_COMP_LZ4: {
476*4882a593Smuzhiyun 		size_t size = unc_len;
477*4882a593Smuzhiyun 
478*4882a593Smuzhiyun 		ret = ulz4fn(image_buf, image_len, load_buf, &size);
479*4882a593Smuzhiyun 		image_len = size;
480*4882a593Smuzhiyun 		break;
481*4882a593Smuzhiyun 	}
482*4882a593Smuzhiyun #endif /* CONFIG_LZ4 */
483*4882a593Smuzhiyun 	default:
484*4882a593Smuzhiyun 		printf("Unimplemented compression type %d\n", comp);
485*4882a593Smuzhiyun 		return BOOTM_ERR_UNIMPLEMENTED;
486*4882a593Smuzhiyun 	}
487*4882a593Smuzhiyun 
488*4882a593Smuzhiyun 	if (ret)
489*4882a593Smuzhiyun 		return handle_decomp_error(comp, image_len, unc_len, ret);
490*4882a593Smuzhiyun 	*load_end = load + image_len;
491*4882a593Smuzhiyun 
492*4882a593Smuzhiyun 	if (comp == IH_COMP_NONE || comp == IH_COMP_ZIMAGE)
493*4882a593Smuzhiyun 		puts("OK\n");
494*4882a593Smuzhiyun 	else
495*4882a593Smuzhiyun 		printf("with %08lx bytes OK\n", image_len);
496*4882a593Smuzhiyun 
497*4882a593Smuzhiyun 	return 0;
498*4882a593Smuzhiyun }
499*4882a593Smuzhiyun 
500*4882a593Smuzhiyun #ifndef USE_HOSTCC
bootm_load_os(bootm_headers_t * images,unsigned long * load_end,int boot_progress)501*4882a593Smuzhiyun static int bootm_load_os(bootm_headers_t *images, unsigned long *load_end,
502*4882a593Smuzhiyun 			 int boot_progress)
503*4882a593Smuzhiyun {
504*4882a593Smuzhiyun 	image_info_t os = images->os;
505*4882a593Smuzhiyun 	ulong load = os.load;
506*4882a593Smuzhiyun 	ulong blob_start = os.start;
507*4882a593Smuzhiyun 	ulong blob_end = os.end;
508*4882a593Smuzhiyun 	ulong image_start = os.image_start;
509*4882a593Smuzhiyun 	ulong image_len = os.image_len;
510*4882a593Smuzhiyun 	bool no_overlap;
511*4882a593Smuzhiyun 	void *load_buf, *image_buf;
512*4882a593Smuzhiyun 	int err;
513*4882a593Smuzhiyun 
514*4882a593Smuzhiyun 	load_buf = map_sysmem(load, 0);
515*4882a593Smuzhiyun 	image_buf = map_sysmem(os.image_start, image_len);
516*4882a593Smuzhiyun 	err = bootm_decomp_image(os.comp, load, os.image_start, os.type,
517*4882a593Smuzhiyun 				 load_buf, image_buf, image_len,
518*4882a593Smuzhiyun 				 CONFIG_SYS_BOOTM_LEN, load_end);
519*4882a593Smuzhiyun 	if (err) {
520*4882a593Smuzhiyun 		bootstage_error(BOOTSTAGE_ID_DECOMP_IMAGE);
521*4882a593Smuzhiyun 		return err;
522*4882a593Smuzhiyun 	}
523*4882a593Smuzhiyun 	flush_cache(load, ALIGN(*load_end - load, ARCH_DMA_MINALIGN));
524*4882a593Smuzhiyun 
525*4882a593Smuzhiyun 	printf("   kernel loaded at 0x%08lx, end = 0x%08lx\n", load, *load_end);
526*4882a593Smuzhiyun 	bootstage_mark(BOOTSTAGE_ID_KERNEL_LOADED);
527*4882a593Smuzhiyun 
528*4882a593Smuzhiyun 	no_overlap = (os.comp == IH_COMP_NONE && load == image_start);
529*4882a593Smuzhiyun 
530*4882a593Smuzhiyun 	if (!no_overlap && (load < blob_end) && (*load_end > blob_start)) {
531*4882a593Smuzhiyun 		printf("images.os.start = 0x%lX, images.os.end = 0x%lx\n",
532*4882a593Smuzhiyun 		       blob_start, blob_end);
533*4882a593Smuzhiyun 		printf("images.os.load = 0x%lx, load_end = 0x%lx\n", load,
534*4882a593Smuzhiyun 		       *load_end);
535*4882a593Smuzhiyun 
536*4882a593Smuzhiyun 		/* Check what type of image this is. */
537*4882a593Smuzhiyun 		if (images->legacy_hdr_valid) {
538*4882a593Smuzhiyun 			if (image_get_type(&images->legacy_hdr_os_copy)
539*4882a593Smuzhiyun 					== IH_TYPE_MULTI)
540*4882a593Smuzhiyun 				puts("WARNING: legacy format multi component image overwritten\n");
541*4882a593Smuzhiyun 			return BOOTM_ERR_OVERLAP;
542*4882a593Smuzhiyun 		} else {
543*4882a593Smuzhiyun 			puts("ERROR: new format image overwritten - must RESET the board to recover\n");
544*4882a593Smuzhiyun 			bootstage_error(BOOTSTAGE_ID_OVERWRITTEN);
545*4882a593Smuzhiyun 			return BOOTM_ERR_RESET;
546*4882a593Smuzhiyun 		}
547*4882a593Smuzhiyun 	}
548*4882a593Smuzhiyun 
549*4882a593Smuzhiyun 	/* update image len as decompressed kernel size for late use */
550*4882a593Smuzhiyun 	images->os.image_len = *load_end - load;
551*4882a593Smuzhiyun 
552*4882a593Smuzhiyun 	return 0;
553*4882a593Smuzhiyun }
554*4882a593Smuzhiyun 
555*4882a593Smuzhiyun /**
556*4882a593Smuzhiyun  * bootm_disable_interrupts() - Disable interrupts in preparation for load/boot
557*4882a593Smuzhiyun  *
558*4882a593Smuzhiyun  * @return interrupt flag (0 if interrupts were disabled, non-zero if they were
559*4882a593Smuzhiyun  *	enabled)
560*4882a593Smuzhiyun  */
bootm_disable_interrupts(void)561*4882a593Smuzhiyun ulong bootm_disable_interrupts(void)
562*4882a593Smuzhiyun {
563*4882a593Smuzhiyun 	ulong iflag;
564*4882a593Smuzhiyun 
565*4882a593Smuzhiyun 	/*
566*4882a593Smuzhiyun 	 * Do not go further if usb is boot device,
567*4882a593Smuzhiyun 	 * We may access usb at late sequence.
568*4882a593Smuzhiyun 	 */
569*4882a593Smuzhiyun 	if (!strcmp(env_get("devtype"), "usb"))
570*4882a593Smuzhiyun 		return 0;
571*4882a593Smuzhiyun 
572*4882a593Smuzhiyun 	/*
573*4882a593Smuzhiyun 	 * We have reached the point of no return: we are going to
574*4882a593Smuzhiyun 	 * overwrite all exception vector code, so we cannot easily
575*4882a593Smuzhiyun 	 * recover from any failures any more...
576*4882a593Smuzhiyun 	 */
577*4882a593Smuzhiyun 	iflag = disable_interrupts();
578*4882a593Smuzhiyun #ifdef CONFIG_NETCONSOLE
579*4882a593Smuzhiyun 	/* Stop the ethernet stack if NetConsole could have left it up */
580*4882a593Smuzhiyun 	eth_halt();
581*4882a593Smuzhiyun # ifndef CONFIG_DM_ETH
582*4882a593Smuzhiyun 	eth_unregister(eth_get_dev());
583*4882a593Smuzhiyun # endif
584*4882a593Smuzhiyun #endif
585*4882a593Smuzhiyun 
586*4882a593Smuzhiyun #if defined(CONFIG_CMD_USB)
587*4882a593Smuzhiyun 	/*
588*4882a593Smuzhiyun 	 * turn off USB to prevent the host controller from writing to the
589*4882a593Smuzhiyun 	 * SDRAM while Linux is booting. This could happen (at least for OHCI
590*4882a593Smuzhiyun 	 * controller), because the HCCA (Host Controller Communication Area)
591*4882a593Smuzhiyun 	 * lies within the SDRAM and the host controller writes continously to
592*4882a593Smuzhiyun 	 * this area (as busmaster!). The HccaFrameNumber is for example
593*4882a593Smuzhiyun 	 * updated every 1 ms within the HCCA structure in SDRAM! For more
594*4882a593Smuzhiyun 	 * details see the OpenHCI specification.
595*4882a593Smuzhiyun 	 */
596*4882a593Smuzhiyun 	usb_stop();
597*4882a593Smuzhiyun #endif
598*4882a593Smuzhiyun 	return iflag;
599*4882a593Smuzhiyun }
600*4882a593Smuzhiyun 
601*4882a593Smuzhiyun #if defined(CONFIG_SILENT_CONSOLE) && !defined(CONFIG_SILENT_U_BOOT_ONLY)
602*4882a593Smuzhiyun 
603*4882a593Smuzhiyun #define CONSOLE_ARG     "console="
604*4882a593Smuzhiyun #define CONSOLE_ARG_LEN (sizeof(CONSOLE_ARG) - 1)
605*4882a593Smuzhiyun 
fixup_silent_linux(void)606*4882a593Smuzhiyun static void fixup_silent_linux(void)
607*4882a593Smuzhiyun {
608*4882a593Smuzhiyun 	char *buf;
609*4882a593Smuzhiyun 	const char *env_val;
610*4882a593Smuzhiyun 	char *cmdline = env_get("bootargs");
611*4882a593Smuzhiyun 	int want_silent;
612*4882a593Smuzhiyun 
613*4882a593Smuzhiyun 	/*
614*4882a593Smuzhiyun 	 * Only fix cmdline when requested. The environment variable can be:
615*4882a593Smuzhiyun 	 *
616*4882a593Smuzhiyun 	 *	no - we never fixup
617*4882a593Smuzhiyun 	 *	yes - we always fixup
618*4882a593Smuzhiyun 	 *	unset - we rely on the console silent flag
619*4882a593Smuzhiyun 	 */
620*4882a593Smuzhiyun 	want_silent = env_get_yesno("silent_linux");
621*4882a593Smuzhiyun 	if (want_silent == 0)
622*4882a593Smuzhiyun 		return;
623*4882a593Smuzhiyun 	else if (want_silent == -1 && !(gd->flags & GD_FLG_SILENT))
624*4882a593Smuzhiyun 		return;
625*4882a593Smuzhiyun 
626*4882a593Smuzhiyun 	debug("before silent fix-up: %s\n", cmdline);
627*4882a593Smuzhiyun 	if (cmdline && (cmdline[0] != '\0')) {
628*4882a593Smuzhiyun 		char *start = strstr(cmdline, CONSOLE_ARG);
629*4882a593Smuzhiyun 
630*4882a593Smuzhiyun 		/* Allocate space for maximum possible new command line */
631*4882a593Smuzhiyun 		buf = malloc(strlen(cmdline) + 1 + CONSOLE_ARG_LEN + 1);
632*4882a593Smuzhiyun 		if (!buf) {
633*4882a593Smuzhiyun 			debug("%s: out of memory\n", __func__);
634*4882a593Smuzhiyun 			return;
635*4882a593Smuzhiyun 		}
636*4882a593Smuzhiyun 
637*4882a593Smuzhiyun 		if (start) {
638*4882a593Smuzhiyun 			char *end = strchr(start, ' ');
639*4882a593Smuzhiyun 			int num_start_bytes = start - cmdline + CONSOLE_ARG_LEN;
640*4882a593Smuzhiyun 
641*4882a593Smuzhiyun 			strncpy(buf, cmdline, num_start_bytes);
642*4882a593Smuzhiyun 			if (end)
643*4882a593Smuzhiyun 				strcpy(buf + num_start_bytes, end);
644*4882a593Smuzhiyun 			else
645*4882a593Smuzhiyun 				buf[num_start_bytes] = '\0';
646*4882a593Smuzhiyun 		} else {
647*4882a593Smuzhiyun 			sprintf(buf, "%s %s", cmdline, CONSOLE_ARG);
648*4882a593Smuzhiyun 		}
649*4882a593Smuzhiyun 		env_val = buf;
650*4882a593Smuzhiyun 	} else {
651*4882a593Smuzhiyun 		buf = NULL;
652*4882a593Smuzhiyun 		env_val = CONSOLE_ARG;
653*4882a593Smuzhiyun 	}
654*4882a593Smuzhiyun 
655*4882a593Smuzhiyun 	env_set("bootargs", env_val);
656*4882a593Smuzhiyun 	debug("after silent fix-up: %s\n", env_val);
657*4882a593Smuzhiyun 	free(buf);
658*4882a593Smuzhiyun }
659*4882a593Smuzhiyun #endif /* CONFIG_SILENT_CONSOLE */
660*4882a593Smuzhiyun 
661*4882a593Smuzhiyun /**
662*4882a593Smuzhiyun  * Execute selected states of the bootm command.
663*4882a593Smuzhiyun  *
664*4882a593Smuzhiyun  * Note the arguments to this state must be the first argument, Any 'bootm'
665*4882a593Smuzhiyun  * or sub-command arguments must have already been taken.
666*4882a593Smuzhiyun  *
667*4882a593Smuzhiyun  * Note that if states contains more than one flag it MUST contain
668*4882a593Smuzhiyun  * BOOTM_STATE_START, since this handles and consumes the command line args.
669*4882a593Smuzhiyun  *
670*4882a593Smuzhiyun  * Also note that aside from boot_os_fn functions and bootm_load_os no other
671*4882a593Smuzhiyun  * functions we store the return value of in 'ret' may use a negative return
672*4882a593Smuzhiyun  * value, without special handling.
673*4882a593Smuzhiyun  *
674*4882a593Smuzhiyun  * @param cmdtp		Pointer to bootm command table entry
675*4882a593Smuzhiyun  * @param flag		Command flags (CMD_FLAG_...)
676*4882a593Smuzhiyun  * @param argc		Number of subcommand arguments (0 = no arguments)
677*4882a593Smuzhiyun  * @param argv		Arguments
678*4882a593Smuzhiyun  * @param states	Mask containing states to run (BOOTM_STATE_...)
679*4882a593Smuzhiyun  * @param images	Image header information
680*4882a593Smuzhiyun  * @param boot_progress 1 to show boot progress, 0 to not do this
681*4882a593Smuzhiyun  * @return 0 if ok, something else on error. Some errors will cause this
682*4882a593Smuzhiyun  *	function to perform a reboot! If states contains BOOTM_STATE_OS_GO
683*4882a593Smuzhiyun  *	then the intent is to boot an OS, so this function will not return
684*4882a593Smuzhiyun  *	unless the image type is standalone.
685*4882a593Smuzhiyun  */
do_bootm_states(cmd_tbl_t * cmdtp,int flag,int argc,char * const argv[],int states,bootm_headers_t * images,int boot_progress)686*4882a593Smuzhiyun int do_bootm_states(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[],
687*4882a593Smuzhiyun 		    int states, bootm_headers_t *images, int boot_progress)
688*4882a593Smuzhiyun {
689*4882a593Smuzhiyun 	boot_os_fn *boot_fn;
690*4882a593Smuzhiyun 	ulong iflag = 0;
691*4882a593Smuzhiyun 	int ret = 0, need_boot_fn;
692*4882a593Smuzhiyun 	u32 unmask;
693*4882a593Smuzhiyun 
694*4882a593Smuzhiyun 	unmask = env_get_ulong("bootm_states_unmask", 16, 0);
695*4882a593Smuzhiyun 	if (unmask)
696*4882a593Smuzhiyun 		states &= ~unmask;
697*4882a593Smuzhiyun 
698*4882a593Smuzhiyun 	images->state |= states;
699*4882a593Smuzhiyun 
700*4882a593Smuzhiyun 	/*
701*4882a593Smuzhiyun 	 * Work through the states and see how far we get. We stop on
702*4882a593Smuzhiyun 	 * any error.
703*4882a593Smuzhiyun 	 */
704*4882a593Smuzhiyun 	if (states & BOOTM_STATE_START)
705*4882a593Smuzhiyun 		ret = bootm_start(cmdtp, flag, argc, argv);
706*4882a593Smuzhiyun 
707*4882a593Smuzhiyun 	if (!ret && (states & BOOTM_STATE_FINDOS))
708*4882a593Smuzhiyun 		ret = bootm_find_os(cmdtp, flag, argc, argv);
709*4882a593Smuzhiyun 
710*4882a593Smuzhiyun 	if (!ret && (states & BOOTM_STATE_FINDOTHER))
711*4882a593Smuzhiyun 		ret = bootm_find_other(cmdtp, flag, argc, argv);
712*4882a593Smuzhiyun 
713*4882a593Smuzhiyun 	/* Load the OS */
714*4882a593Smuzhiyun 	if (!ret && (states & BOOTM_STATE_LOADOS)) {
715*4882a593Smuzhiyun 		ulong load_end;
716*4882a593Smuzhiyun 
717*4882a593Smuzhiyun 		iflag = bootm_disable_interrupts();
718*4882a593Smuzhiyun 		ret = bootm_load_os(images, &load_end, 0);
719*4882a593Smuzhiyun 		if (ret == 0)
720*4882a593Smuzhiyun 			lmb_reserve(&images->lmb, images->os.load,
721*4882a593Smuzhiyun 				    (load_end - images->os.load));
722*4882a593Smuzhiyun 		else if (ret && ret != BOOTM_ERR_OVERLAP)
723*4882a593Smuzhiyun 			goto err;
724*4882a593Smuzhiyun 		else if (ret == BOOTM_ERR_OVERLAP)
725*4882a593Smuzhiyun 			ret = 0;
726*4882a593Smuzhiyun 	}
727*4882a593Smuzhiyun 
728*4882a593Smuzhiyun 	/* Resever memory before any lmb_alloc, as early as possible */
729*4882a593Smuzhiyun #if IMAGE_ENABLE_OF_LIBFDT && defined(CONFIG_LMB)
730*4882a593Smuzhiyun 	if (!ret && ((states & BOOTM_STATE_RAMDISK) ||
731*4882a593Smuzhiyun 	    (states & BOOTM_STATE_FDT)))
732*4882a593Smuzhiyun 		boot_fdt_add_mem_rsv_regions(&images->lmb, images->ft_addr);
733*4882a593Smuzhiyun #endif
734*4882a593Smuzhiyun 	/* Relocate the ramdisk */
735*4882a593Smuzhiyun #ifdef CONFIG_SYS_BOOT_RAMDISK_HIGH
736*4882a593Smuzhiyun 	if (!ret && (states & BOOTM_STATE_RAMDISK)) {
737*4882a593Smuzhiyun 		ulong rd_len = images->rd_end - images->rd_start;
738*4882a593Smuzhiyun 
739*4882a593Smuzhiyun 		ret = boot_ramdisk_high(&images->lmb, images->rd_start,
740*4882a593Smuzhiyun 			rd_len, &images->initrd_start, &images->initrd_end);
741*4882a593Smuzhiyun 		if (!ret) {
742*4882a593Smuzhiyun 			env_set_hex("initrd_start", images->initrd_start);
743*4882a593Smuzhiyun 			env_set_hex("initrd_end", images->initrd_end);
744*4882a593Smuzhiyun 		}
745*4882a593Smuzhiyun 	}
746*4882a593Smuzhiyun #endif
747*4882a593Smuzhiyun #if IMAGE_ENABLE_OF_LIBFDT && defined(CONFIG_LMB)
748*4882a593Smuzhiyun 	if (!ret && (states & BOOTM_STATE_FDT)) {
749*4882a593Smuzhiyun 		ret = boot_relocate_fdt(&images->lmb, &images->ft_addr,
750*4882a593Smuzhiyun 					&images->ft_len);
751*4882a593Smuzhiyun 	}
752*4882a593Smuzhiyun #endif
753*4882a593Smuzhiyun 
754*4882a593Smuzhiyun 	/* From now on, we need the OS boot function */
755*4882a593Smuzhiyun 	if (ret)
756*4882a593Smuzhiyun 		return ret;
757*4882a593Smuzhiyun 	boot_fn = bootm_os_get_boot_func(images->os.os);
758*4882a593Smuzhiyun 	need_boot_fn = states & (BOOTM_STATE_OS_CMDLINE |
759*4882a593Smuzhiyun 			BOOTM_STATE_OS_BD_T | BOOTM_STATE_OS_PREP |
760*4882a593Smuzhiyun 			BOOTM_STATE_OS_FAKE_GO | BOOTM_STATE_OS_GO);
761*4882a593Smuzhiyun 	if (boot_fn == NULL && need_boot_fn) {
762*4882a593Smuzhiyun 		if (iflag)
763*4882a593Smuzhiyun 			enable_interrupts();
764*4882a593Smuzhiyun 		printf("ERROR: booting os '%s' (%d) is not supported\n",
765*4882a593Smuzhiyun 		       genimg_get_os_name(images->os.os), images->os.os);
766*4882a593Smuzhiyun 		bootstage_error(BOOTSTAGE_ID_CHECK_BOOT_OS);
767*4882a593Smuzhiyun 		return 1;
768*4882a593Smuzhiyun 	}
769*4882a593Smuzhiyun 
770*4882a593Smuzhiyun 
771*4882a593Smuzhiyun 	/* Call various other states that are not generally used */
772*4882a593Smuzhiyun 	if (!ret && (states & BOOTM_STATE_OS_CMDLINE))
773*4882a593Smuzhiyun 		ret = boot_fn(BOOTM_STATE_OS_CMDLINE, argc, argv, images);
774*4882a593Smuzhiyun 	if (!ret && (states & BOOTM_STATE_OS_BD_T))
775*4882a593Smuzhiyun 		ret = boot_fn(BOOTM_STATE_OS_BD_T, argc, argv, images);
776*4882a593Smuzhiyun 	if (!ret && (states & BOOTM_STATE_OS_PREP)) {
777*4882a593Smuzhiyun #if defined(CONFIG_SILENT_CONSOLE) && !defined(CONFIG_SILENT_U_BOOT_ONLY)
778*4882a593Smuzhiyun 		if (images->os.os == IH_OS_LINUX)
779*4882a593Smuzhiyun 			fixup_silent_linux();
780*4882a593Smuzhiyun #endif
781*4882a593Smuzhiyun 		arch_preboot_os(BOOTM_STATE_OS_PREP, images);
782*4882a593Smuzhiyun 
783*4882a593Smuzhiyun 		ret = boot_fn(BOOTM_STATE_OS_PREP, argc, argv, images);
784*4882a593Smuzhiyun 	}
785*4882a593Smuzhiyun 
786*4882a593Smuzhiyun #ifdef CONFIG_TRACE
787*4882a593Smuzhiyun 	/* Pretend to run the OS, then run a user command */
788*4882a593Smuzhiyun 	if (!ret && (states & BOOTM_STATE_OS_FAKE_GO)) {
789*4882a593Smuzhiyun 		char *cmd_list = env_get("fakegocmd");
790*4882a593Smuzhiyun 
791*4882a593Smuzhiyun 		ret = boot_selected_os(argc, argv, BOOTM_STATE_OS_FAKE_GO,
792*4882a593Smuzhiyun 				images, boot_fn);
793*4882a593Smuzhiyun 		if (!ret && cmd_list)
794*4882a593Smuzhiyun 			ret = run_command_list(cmd_list, -1, flag);
795*4882a593Smuzhiyun 	}
796*4882a593Smuzhiyun #endif
797*4882a593Smuzhiyun 
798*4882a593Smuzhiyun 	/* Check for unsupported subcommand. */
799*4882a593Smuzhiyun 	if (ret) {
800*4882a593Smuzhiyun 		puts("subcommand not supported\n");
801*4882a593Smuzhiyun 		return ret;
802*4882a593Smuzhiyun 	}
803*4882a593Smuzhiyun 
804*4882a593Smuzhiyun 	/* Now run the OS! We hope this doesn't return */
805*4882a593Smuzhiyun 	if (!ret && (states & BOOTM_STATE_OS_GO))
806*4882a593Smuzhiyun 		ret = boot_selected_os(argc, argv, BOOTM_STATE_OS_GO,
807*4882a593Smuzhiyun 				images, boot_fn);
808*4882a593Smuzhiyun 
809*4882a593Smuzhiyun 	/* Deal with any fallout */
810*4882a593Smuzhiyun err:
811*4882a593Smuzhiyun 	if (iflag)
812*4882a593Smuzhiyun 		enable_interrupts();
813*4882a593Smuzhiyun 
814*4882a593Smuzhiyun 	if (ret == BOOTM_ERR_UNIMPLEMENTED)
815*4882a593Smuzhiyun 		bootstage_error(BOOTSTAGE_ID_DECOMP_UNIMPL);
816*4882a593Smuzhiyun 	else if (ret == BOOTM_ERR_RESET)
817*4882a593Smuzhiyun 		do_reset(cmdtp, flag, argc, argv);
818*4882a593Smuzhiyun 
819*4882a593Smuzhiyun 	return ret;
820*4882a593Smuzhiyun }
821*4882a593Smuzhiyun 
822*4882a593Smuzhiyun #if defined(CONFIG_IMAGE_FORMAT_LEGACY)
823*4882a593Smuzhiyun /**
824*4882a593Smuzhiyun  * image_get_kernel - verify legacy format kernel image
825*4882a593Smuzhiyun  * @img_addr: in RAM address of the legacy format image to be verified
826*4882a593Smuzhiyun  * @verify: data CRC verification flag
827*4882a593Smuzhiyun  *
828*4882a593Smuzhiyun  * image_get_kernel() verifies legacy image integrity and returns pointer to
829*4882a593Smuzhiyun  * legacy image header if image verification was completed successfully.
830*4882a593Smuzhiyun  *
831*4882a593Smuzhiyun  * returns:
832*4882a593Smuzhiyun  *     pointer to a legacy image header if valid image was found
833*4882a593Smuzhiyun  *     otherwise return NULL
834*4882a593Smuzhiyun  */
image_get_kernel(ulong img_addr,int verify)835*4882a593Smuzhiyun static image_header_t *image_get_kernel(ulong img_addr, int verify)
836*4882a593Smuzhiyun {
837*4882a593Smuzhiyun 	image_header_t *hdr = (image_header_t *)img_addr;
838*4882a593Smuzhiyun 
839*4882a593Smuzhiyun 	if (!image_check_magic(hdr)) {
840*4882a593Smuzhiyun 		puts("Bad Magic Number\n");
841*4882a593Smuzhiyun 		bootstage_error(BOOTSTAGE_ID_CHECK_MAGIC);
842*4882a593Smuzhiyun 		return NULL;
843*4882a593Smuzhiyun 	}
844*4882a593Smuzhiyun 	bootstage_mark(BOOTSTAGE_ID_CHECK_HEADER);
845*4882a593Smuzhiyun 
846*4882a593Smuzhiyun 	if (!image_check_hcrc(hdr)) {
847*4882a593Smuzhiyun 		puts("Bad Header Checksum\n");
848*4882a593Smuzhiyun 		bootstage_error(BOOTSTAGE_ID_CHECK_HEADER);
849*4882a593Smuzhiyun 		return NULL;
850*4882a593Smuzhiyun 	}
851*4882a593Smuzhiyun 
852*4882a593Smuzhiyun 	bootstage_mark(BOOTSTAGE_ID_CHECK_CHECKSUM);
853*4882a593Smuzhiyun 	image_print_contents(hdr);
854*4882a593Smuzhiyun 
855*4882a593Smuzhiyun 	if (verify) {
856*4882a593Smuzhiyun 		puts("   Verifying Checksum ... ");
857*4882a593Smuzhiyun 		if (!image_check_dcrc(hdr)) {
858*4882a593Smuzhiyun 			printf("Bad Data CRC\n");
859*4882a593Smuzhiyun 			bootstage_error(BOOTSTAGE_ID_CHECK_CHECKSUM);
860*4882a593Smuzhiyun 			return NULL;
861*4882a593Smuzhiyun 		}
862*4882a593Smuzhiyun 		puts("OK\n");
863*4882a593Smuzhiyun 	}
864*4882a593Smuzhiyun 	bootstage_mark(BOOTSTAGE_ID_CHECK_ARCH);
865*4882a593Smuzhiyun 
866*4882a593Smuzhiyun 	if (!image_check_target_arch(hdr)) {
867*4882a593Smuzhiyun 		printf("Unsupported Architecture 0x%x\n", image_get_arch(hdr));
868*4882a593Smuzhiyun 		bootstage_error(BOOTSTAGE_ID_CHECK_ARCH);
869*4882a593Smuzhiyun 		return NULL;
870*4882a593Smuzhiyun 	}
871*4882a593Smuzhiyun 	return hdr;
872*4882a593Smuzhiyun }
873*4882a593Smuzhiyun #endif
874*4882a593Smuzhiyun 
875*4882a593Smuzhiyun /**
876*4882a593Smuzhiyun  * boot_get_kernel - find kernel image
877*4882a593Smuzhiyun  * @os_data: pointer to a ulong variable, will hold os data start address
878*4882a593Smuzhiyun  * @os_len: pointer to a ulong variable, will hold os data length
879*4882a593Smuzhiyun  *
880*4882a593Smuzhiyun  * boot_get_kernel() tries to find a kernel image, verifies its integrity
881*4882a593Smuzhiyun  * and locates kernel data.
882*4882a593Smuzhiyun  *
883*4882a593Smuzhiyun  * returns:
884*4882a593Smuzhiyun  *     pointer to image header if valid image was found, plus kernel start
885*4882a593Smuzhiyun  *     address and length, otherwise NULL
886*4882a593Smuzhiyun  */
boot_get_kernel(cmd_tbl_t * cmdtp,int flag,int argc,char * const argv[],bootm_headers_t * images,ulong * os_data,ulong * os_len)887*4882a593Smuzhiyun static const void *boot_get_kernel(cmd_tbl_t *cmdtp, int flag, int argc,
888*4882a593Smuzhiyun 				   char * const argv[], bootm_headers_t *images,
889*4882a593Smuzhiyun 				   ulong *os_data, ulong *os_len)
890*4882a593Smuzhiyun {
891*4882a593Smuzhiyun #if defined(CONFIG_IMAGE_FORMAT_LEGACY)
892*4882a593Smuzhiyun 	image_header_t	*hdr;
893*4882a593Smuzhiyun #endif
894*4882a593Smuzhiyun 	ulong		img_addr;
895*4882a593Smuzhiyun 	const void *buf;
896*4882a593Smuzhiyun 	const char	*fit_uname_config = NULL;
897*4882a593Smuzhiyun 	const char	*fit_uname_kernel = NULL;
898*4882a593Smuzhiyun #if IMAGE_ENABLE_FIT
899*4882a593Smuzhiyun 	int		os_noffset;
900*4882a593Smuzhiyun #endif
901*4882a593Smuzhiyun 
902*4882a593Smuzhiyun 	img_addr = genimg_get_kernel_addr_fit(argc < 1 ? NULL : argv[0],
903*4882a593Smuzhiyun 					      &fit_uname_config,
904*4882a593Smuzhiyun 					      &fit_uname_kernel);
905*4882a593Smuzhiyun 
906*4882a593Smuzhiyun 	bootstage_mark(BOOTSTAGE_ID_CHECK_MAGIC);
907*4882a593Smuzhiyun 
908*4882a593Smuzhiyun 	/* check image type, for FIT images get FIT kernel node */
909*4882a593Smuzhiyun 	*os_data = *os_len = 0;
910*4882a593Smuzhiyun 	buf = map_sysmem(img_addr, 0);
911*4882a593Smuzhiyun 	switch (genimg_get_format(buf)) {
912*4882a593Smuzhiyun #if defined(CONFIG_IMAGE_FORMAT_LEGACY)
913*4882a593Smuzhiyun 	case IMAGE_FORMAT_LEGACY:
914*4882a593Smuzhiyun 		printf("## Booting kernel from Legacy Image at %08lx ...\n",
915*4882a593Smuzhiyun 		       img_addr);
916*4882a593Smuzhiyun 		hdr = image_get_kernel(img_addr, images->verify);
917*4882a593Smuzhiyun 		if (!hdr)
918*4882a593Smuzhiyun 			return NULL;
919*4882a593Smuzhiyun 		bootstage_mark(BOOTSTAGE_ID_CHECK_IMAGETYPE);
920*4882a593Smuzhiyun 
921*4882a593Smuzhiyun 		/* get os_data and os_len */
922*4882a593Smuzhiyun 		switch (image_get_type(hdr)) {
923*4882a593Smuzhiyun 		case IH_TYPE_KERNEL:
924*4882a593Smuzhiyun 		case IH_TYPE_KERNEL_NOLOAD:
925*4882a593Smuzhiyun 			*os_data = image_get_data(hdr);
926*4882a593Smuzhiyun 			*os_len = image_get_data_size(hdr);
927*4882a593Smuzhiyun 			break;
928*4882a593Smuzhiyun 		case IH_TYPE_MULTI:
929*4882a593Smuzhiyun 			image_multi_getimg(hdr, 0, os_data, os_len);
930*4882a593Smuzhiyun 			break;
931*4882a593Smuzhiyun 		case IH_TYPE_STANDALONE:
932*4882a593Smuzhiyun 			*os_data = image_get_data(hdr);
933*4882a593Smuzhiyun 			*os_len = image_get_data_size(hdr);
934*4882a593Smuzhiyun 			break;
935*4882a593Smuzhiyun 		default:
936*4882a593Smuzhiyun 			if (cmdtp)
937*4882a593Smuzhiyun 				printf("Wrong Image Type for %s command\n",
938*4882a593Smuzhiyun 				       cmdtp->name);
939*4882a593Smuzhiyun 			bootstage_error(BOOTSTAGE_ID_CHECK_IMAGETYPE);
940*4882a593Smuzhiyun 			return NULL;
941*4882a593Smuzhiyun 		}
942*4882a593Smuzhiyun 
943*4882a593Smuzhiyun 		/*
944*4882a593Smuzhiyun 		 * copy image header to allow for image overwrites during
945*4882a593Smuzhiyun 		 * kernel decompression.
946*4882a593Smuzhiyun 		 */
947*4882a593Smuzhiyun 		memmove(&images->legacy_hdr_os_copy, hdr,
948*4882a593Smuzhiyun 			sizeof(image_header_t));
949*4882a593Smuzhiyun 
950*4882a593Smuzhiyun 		/* save pointer to image header */
951*4882a593Smuzhiyun 		images->legacy_hdr_os = hdr;
952*4882a593Smuzhiyun 
953*4882a593Smuzhiyun 		images->legacy_hdr_valid = 1;
954*4882a593Smuzhiyun 		bootstage_mark(BOOTSTAGE_ID_DECOMP_IMAGE);
955*4882a593Smuzhiyun 		break;
956*4882a593Smuzhiyun #endif
957*4882a593Smuzhiyun #if IMAGE_ENABLE_FIT
958*4882a593Smuzhiyun 	case IMAGE_FORMAT_FIT:
959*4882a593Smuzhiyun 		os_noffset = fit_image_load(images, img_addr,
960*4882a593Smuzhiyun 				&fit_uname_kernel, &fit_uname_config,
961*4882a593Smuzhiyun 				IH_ARCH_DEFAULT, IH_TYPE_KERNEL,
962*4882a593Smuzhiyun 				BOOTSTAGE_ID_FIT_KERNEL_START,
963*4882a593Smuzhiyun 				FIT_LOAD_IGNORED, os_data, os_len);
964*4882a593Smuzhiyun 		if (os_noffset < 0)
965*4882a593Smuzhiyun 			return NULL;
966*4882a593Smuzhiyun 
967*4882a593Smuzhiyun 		images->fit_hdr_os = map_sysmem(img_addr, 0);
968*4882a593Smuzhiyun 		images->fit_uname_os = fit_uname_kernel;
969*4882a593Smuzhiyun 		images->fit_uname_cfg = fit_uname_config;
970*4882a593Smuzhiyun 		images->fit_noffset_os = os_noffset;
971*4882a593Smuzhiyun 		break;
972*4882a593Smuzhiyun #endif
973*4882a593Smuzhiyun #ifdef CONFIG_ANDROID_BOOT_IMAGE
974*4882a593Smuzhiyun 	case IMAGE_FORMAT_ANDROID:
975*4882a593Smuzhiyun 		printf("## Booting Android Image at 0x%08lx ...\n", img_addr);
976*4882a593Smuzhiyun 		if (android_image_get_kernel(buf, images->verify,
977*4882a593Smuzhiyun 					     os_data, os_len))
978*4882a593Smuzhiyun 			return NULL;
979*4882a593Smuzhiyun 		break;
980*4882a593Smuzhiyun #endif
981*4882a593Smuzhiyun 	default:
982*4882a593Smuzhiyun 		if (cmdtp)
983*4882a593Smuzhiyun 			printf("Wrong Image Format for %s command\n",
984*4882a593Smuzhiyun 			       cmdtp->name);
985*4882a593Smuzhiyun 		bootstage_error(BOOTSTAGE_ID_FIT_KERNEL_INFO);
986*4882a593Smuzhiyun 		return NULL;
987*4882a593Smuzhiyun 	}
988*4882a593Smuzhiyun 
989*4882a593Smuzhiyun 	debug("   kernel data at 0x%08lx, len = 0x%08lx (%ld)\n",
990*4882a593Smuzhiyun 	      *os_data, *os_len, *os_len);
991*4882a593Smuzhiyun 
992*4882a593Smuzhiyun 	return buf;
993*4882a593Smuzhiyun }
994*4882a593Smuzhiyun #else /* USE_HOSTCC */
995*4882a593Smuzhiyun 
memmove_wd(void * to,void * from,size_t len,ulong chunksz)996*4882a593Smuzhiyun void memmove_wd(void *to, void *from, size_t len, ulong chunksz)
997*4882a593Smuzhiyun {
998*4882a593Smuzhiyun 	memmove(to, from, len);
999*4882a593Smuzhiyun }
1000*4882a593Smuzhiyun 
bootm_host_load_image(const void * fit,int req_image_type,int index)1001*4882a593Smuzhiyun static int bootm_host_load_image(const void *fit, int req_image_type, int index)
1002*4882a593Smuzhiyun {
1003*4882a593Smuzhiyun 	const char *fit_uname_config = NULL;
1004*4882a593Smuzhiyun 	ulong data, len;
1005*4882a593Smuzhiyun 	bootm_headers_t images;
1006*4882a593Smuzhiyun 	int noffset;
1007*4882a593Smuzhiyun 	ulong load_end;
1008*4882a593Smuzhiyun 	uint8_t image_type;
1009*4882a593Smuzhiyun 	uint8_t imape_comp;
1010*4882a593Smuzhiyun 	void *load_buf;
1011*4882a593Smuzhiyun 	int ret;
1012*4882a593Smuzhiyun 
1013*4882a593Smuzhiyun 	memset(&images, '\0', sizeof(images));
1014*4882a593Smuzhiyun 	images.verify = 1;
1015*4882a593Smuzhiyun 	noffset = fit_image_load_index(&images, (ulong)fit,
1016*4882a593Smuzhiyun 		NULL, &fit_uname_config,
1017*4882a593Smuzhiyun 		IH_ARCH_DEFAULT, req_image_type, index, -1,
1018*4882a593Smuzhiyun 		FIT_LOAD_IGNORED, &data, &len);
1019*4882a593Smuzhiyun 	if (noffset < 0)
1020*4882a593Smuzhiyun 		return noffset;
1021*4882a593Smuzhiyun 	if (fit_image_get_type(fit, noffset, &image_type)) {
1022*4882a593Smuzhiyun 		puts("Can't get image type!\n");
1023*4882a593Smuzhiyun 		return -EINVAL;
1024*4882a593Smuzhiyun 	}
1025*4882a593Smuzhiyun 
1026*4882a593Smuzhiyun 	if (fit_image_get_comp(fit, noffset, &imape_comp)) {
1027*4882a593Smuzhiyun 		puts("Can't get image compression!\n");
1028*4882a593Smuzhiyun 		return -EINVAL;
1029*4882a593Smuzhiyun 	}
1030*4882a593Smuzhiyun 
1031*4882a593Smuzhiyun 	/* Allow the image to expand by a factor of 4, should be safe */
1032*4882a593Smuzhiyun 	load_buf = malloc((1 << 20) + len * 4);
1033*4882a593Smuzhiyun 	ret = bootm_decomp_image(imape_comp, 0, data, image_type, load_buf,
1034*4882a593Smuzhiyun 				 (void *)data, len, CONFIG_SYS_BOOTM_LEN,
1035*4882a593Smuzhiyun 				 &load_end);
1036*4882a593Smuzhiyun 	free(load_buf);
1037*4882a593Smuzhiyun 
1038*4882a593Smuzhiyun 	if (ret && ret != BOOTM_ERR_UNIMPLEMENTED)
1039*4882a593Smuzhiyun 		return ret;
1040*4882a593Smuzhiyun 
1041*4882a593Smuzhiyun 	return 0;
1042*4882a593Smuzhiyun }
1043*4882a593Smuzhiyun 
bootm_host_load_images(const void * fit,int cfg_noffset,int is_spl)1044*4882a593Smuzhiyun int bootm_host_load_images(const void *fit, int cfg_noffset, int is_spl)
1045*4882a593Smuzhiyun {
1046*4882a593Smuzhiyun 	static uint8_t image_types[] = {
1047*4882a593Smuzhiyun 		IH_TYPE_KERNEL,
1048*4882a593Smuzhiyun 		IH_TYPE_FLATDT,
1049*4882a593Smuzhiyun 		IH_TYPE_RAMDISK,
1050*4882a593Smuzhiyun 	};
1051*4882a593Smuzhiyun #ifdef CONFIG_SPL_ATF
1052*4882a593Smuzhiyun 	static uint8_t image_types_spl[] = {
1053*4882a593Smuzhiyun 		IH_TYPE_FLATDT,
1054*4882a593Smuzhiyun 		IH_TYPE_FIRMWARE,
1055*4882a593Smuzhiyun 		IH_TYPE_LOADABLE,
1056*4882a593Smuzhiyun 		IH_TYPE_LOADABLE,
1057*4882a593Smuzhiyun 		IH_TYPE_LOADABLE,
1058*4882a593Smuzhiyun 	};
1059*4882a593Smuzhiyun #else
1060*4882a593Smuzhiyun 	static uint8_t image_types_spl[] = {
1061*4882a593Smuzhiyun 		IH_TYPE_FLATDT,
1062*4882a593Smuzhiyun 		IH_TYPE_FIRMWARE,
1063*4882a593Smuzhiyun 		IH_TYPE_LOADABLE,
1064*4882a593Smuzhiyun 	};
1065*4882a593Smuzhiyun #endif
1066*4882a593Smuzhiyun 	int loadable_index = 0;
1067*4882a593Smuzhiyun 	int err = 0;
1068*4882a593Smuzhiyun 	int index;
1069*4882a593Smuzhiyun 	int i;
1070*4882a593Smuzhiyun 
1071*4882a593Smuzhiyun 	for (i = 0; !is_spl && i < ARRAY_SIZE(image_types); i++) {
1072*4882a593Smuzhiyun 		int ret;
1073*4882a593Smuzhiyun 
1074*4882a593Smuzhiyun 		ret = bootm_host_load_image(fit, image_types[i], 0);
1075*4882a593Smuzhiyun 		if (!err && ret && ret != -ENOENT)
1076*4882a593Smuzhiyun 			err = ret;
1077*4882a593Smuzhiyun 	}
1078*4882a593Smuzhiyun 
1079*4882a593Smuzhiyun 	for (i = 0; is_spl && i < ARRAY_SIZE(image_types_spl); i++) {
1080*4882a593Smuzhiyun 		int ret;
1081*4882a593Smuzhiyun 
1082*4882a593Smuzhiyun 		if (image_types_spl[i] == IH_TYPE_LOADABLE)
1083*4882a593Smuzhiyun 			index = loadable_index++;
1084*4882a593Smuzhiyun 		else
1085*4882a593Smuzhiyun 			index = 0;
1086*4882a593Smuzhiyun 
1087*4882a593Smuzhiyun 		ret = bootm_host_load_image(fit, image_types_spl[i], index);
1088*4882a593Smuzhiyun 		if (!err && ret && ret != -ENOENT)
1089*4882a593Smuzhiyun 			err = ret;
1090*4882a593Smuzhiyun 	}
1091*4882a593Smuzhiyun 
1092*4882a593Smuzhiyun 	/* Return the first error we found */
1093*4882a593Smuzhiyun 	return err;
1094*4882a593Smuzhiyun }
1095*4882a593Smuzhiyun 
1096*4882a593Smuzhiyun #endif /* ndef USE_HOSTCC */
1097