diff options
| author | Simon Glass <sjg@chromium.org> | 2013-05-08 08:06:00 +0000 | 
|---|---|---|
| committer | Tom Rini <trini@ti.com> | 2013-05-14 15:37:25 -0400 | 
| commit | 44d3a3066bc789b9a640e71322e593a9983023bb (patch) | |
| tree | 5f78d96c0ad7659d091684ae290538330bbbc132 | |
| parent | 87ebee39e9d02dba6d36d03d512e7d6e8a5a9abb (diff) | |
| download | olio-uboot-2014.01-44d3a3066bc789b9a640e71322e593a9983023bb.tar.xz olio-uboot-2014.01-44d3a3066bc789b9a640e71322e593a9983023bb.zip | |
image: Split libfdt code into image-fdt.c
The image file is still very large, and some of the code is only used when
libfdt is in use. Move this code into a new file.
Signed-off-by: Simon Glass <sjg@chromium.org>
| -rw-r--r-- | common/Makefile | 1 | ||||
| -rw-r--r-- | common/image-fdt.c | 591 | ||||
| -rw-r--r-- | common/image.c | 566 | 
3 files changed, 592 insertions, 566 deletions
| diff --git a/common/Makefile b/common/Makefile index 2f8a6719c..f50bf2ea9 100644 --- a/common/Makefile +++ b/common/Makefile @@ -231,6 +231,7 @@ COBJS-$(CONFIG_BOUNCE_BUFFER) += bouncebuf.o  COBJS-y += console.o  COBJS-y += dlmalloc.o  COBJS-y += image.o +COBJS-$(CONFIG_OF_LIBFDT) += image-fdt.o  COBJS-$(CONFIG_FIT) += image-fit.o  COBJS-y += memsize.o  COBJS-y += stdio.o diff --git a/common/image-fdt.c b/common/image-fdt.c new file mode 100644 index 000000000..8e8f35c1c --- /dev/null +++ b/common/image-fdt.c @@ -0,0 +1,591 @@ +/* + * Copyright (c) 2013, Google Inc. + * + * (C) Copyright 2008 Semihalf + * + * (C) Copyright 2000-2006 + * Wolfgang Denk, DENX Software Engineering, wd@denx.de. + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +#include <common.h> +#include <fdt_support.h> +#include <errno.h> +#include <image.h> +#include <libfdt.h> +#include <asm/io.h> + +#ifndef CONFIG_SYS_FDT_PAD +#define CONFIG_SYS_FDT_PAD 0x3000 +#endif + +DECLARE_GLOBAL_DATA_PTR; + +static void fdt_error(const char *msg) +{ +	puts("ERROR: "); +	puts(msg); +	puts(" - must RESET the board to recover.\n"); +} + +static const image_header_t *image_get_fdt(ulong fdt_addr) +{ +	const image_header_t *fdt_hdr = map_sysmem(fdt_addr, 0); + +	image_print_contents(fdt_hdr); + +	puts("   Verifying Checksum ... "); +	if (!image_check_hcrc(fdt_hdr)) { +		fdt_error("fdt header checksum invalid"); +		return NULL; +	} + +	if (!image_check_dcrc(fdt_hdr)) { +		fdt_error("fdt checksum invalid"); +		return NULL; +	} +	puts("OK\n"); + +	if (!image_check_type(fdt_hdr, IH_TYPE_FLATDT)) { +		fdt_error("uImage is not a fdt"); +		return NULL; +	} +	if (image_get_comp(fdt_hdr) != IH_COMP_NONE) { +		fdt_error("uImage is compressed"); +		return NULL; +	} +	if (fdt_check_header((char *)image_get_data(fdt_hdr)) != 0) { +		fdt_error("uImage data is not a fdt"); +		return NULL; +	} +	return fdt_hdr; +} + +/** + * boot_fdt_add_mem_rsv_regions - Mark the memreserve sections as unusable + * @lmb: pointer to lmb handle, will be used for memory mgmt + * @fdt_blob: pointer to fdt blob base address + * + * Adds the memreserve regions in the dtb to the lmb block.  Adding the + * memreserve regions prevents u-boot from using them to store the initrd + * or the fdt blob. + */ +void boot_fdt_add_mem_rsv_regions(struct lmb *lmb, void *fdt_blob) +{ +	uint64_t addr, size; +	int i, total; + +	if (fdt_check_header(fdt_blob) != 0) +		return; + +	total = fdt_num_mem_rsv(fdt_blob); +	for (i = 0; i < total; i++) { +		if (fdt_get_mem_rsv(fdt_blob, i, &addr, &size) != 0) +			continue; +		printf("   reserving fdt memory region: addr=%llx size=%llx\n", +		       (unsigned long long)addr, (unsigned long long)size); +		lmb_reserve(lmb, addr, size); +	} +} + +/** + * boot_relocate_fdt - relocate flat device tree + * @lmb: pointer to lmb handle, will be used for memory mgmt + * @of_flat_tree: pointer to a char* variable, will hold fdt start address + * @of_size: pointer to a ulong variable, will hold fdt length + * + * boot_relocate_fdt() allocates a region of memory within the bootmap and + * relocates the of_flat_tree into that region, even if the fdt is already in + * the bootmap.  It also expands the size of the fdt by CONFIG_SYS_FDT_PAD + * bytes. + * + * of_flat_tree and of_size are set to final (after relocation) values + * + * returns: + *      0 - success + *      1 - failure + */ +int boot_relocate_fdt(struct lmb *lmb, char **of_flat_tree, ulong *of_size) +{ +	void	*fdt_blob = *of_flat_tree; +	void	*of_start = NULL; +	char	*fdt_high; +	ulong	of_len = 0; +	int	err; +	int	disable_relocation = 0; + +	/* nothing to do */ +	if (*of_size == 0) +		return 0; + +	if (fdt_check_header(fdt_blob) != 0) { +		fdt_error("image is not a fdt"); +		goto error; +	} + +	/* position on a 4K boundary before the alloc_current */ +	/* Pad the FDT by a specified amount */ +	of_len = *of_size + CONFIG_SYS_FDT_PAD; + +	/* If fdt_high is set use it to select the relocation address */ +	fdt_high = getenv("fdt_high"); +	if (fdt_high) { +		void *desired_addr = (void *)simple_strtoul(fdt_high, NULL, 16); + +		if (((ulong) desired_addr) == ~0UL) { +			/* All ones means use fdt in place */ +			of_start = fdt_blob; +			lmb_reserve(lmb, (ulong)of_start, of_len); +			disable_relocation = 1; +		} else if (desired_addr) { +			of_start = +			    (void *)(ulong) lmb_alloc_base(lmb, of_len, 0x1000, +							   (ulong)desired_addr); +			if (of_start == NULL) { +				puts("Failed using fdt_high value for Device Tree"); +				goto error; +			} +		} else { +			of_start = +			    (void *)(ulong) lmb_alloc(lmb, of_len, 0x1000); +		} +	} else { +		of_start = +		    (void *)(ulong) lmb_alloc_base(lmb, of_len, 0x1000, +						   getenv_bootm_mapsize() +						   + getenv_bootm_low()); +	} + +	if (of_start == NULL) { +		puts("device tree - allocation error\n"); +		goto error; +	} + +	if (disable_relocation) { +		/* +		 * We assume there is space after the existing fdt to use +		 * for padding +		 */ +		fdt_set_totalsize(of_start, of_len); +		printf("   Using Device Tree in place at %p, end %p\n", +		       of_start, of_start + of_len - 1); +	} else { +		debug("## device tree at %p ... %p (len=%ld [0x%lX])\n", +		      fdt_blob, fdt_blob + *of_size - 1, of_len, of_len); + +		printf("   Loading Device Tree to %p, end %p ... ", +		       of_start, of_start + of_len - 1); + +		err = fdt_open_into(fdt_blob, of_start, of_len); +		if (err != 0) { +			fdt_error("fdt move failed"); +			goto error; +		} +		puts("OK\n"); +	} + +	*of_flat_tree = of_start; +	*of_size = of_len; + +	set_working_fdt_addr(*of_flat_tree); +	return 0; + +error: +	return 1; +} + +#if defined(CONFIG_FIT) +/** + * fit_check_fdt - verify FIT format FDT subimage + * @fit_hdr: pointer to the FIT  header + * fdt_noffset: FDT subimage node offset within FIT image + * @verify: data CRC verification flag + * + * fit_check_fdt() verifies integrity of the FDT subimage and from + * specified FIT image. + * + * returns: + *     1, on success + *     0, on failure + */ +static int fit_check_fdt(const void *fit, int fdt_noffset, int verify) +{ +	fit_image_print(fit, fdt_noffset, "   "); + +	if (verify) { +		puts("   Verifying Hash Integrity ... "); +		if (!fit_image_verify(fit, fdt_noffset)) { +			fdt_error("Bad Data Hash"); +			return 0; +		} +		puts("OK\n"); +	} + +	if (!fit_image_check_type(fit, fdt_noffset, IH_TYPE_FLATDT)) { +		fdt_error("Not a FDT image"); +		return 0; +	} + +	if (!fit_image_check_comp(fit, fdt_noffset, IH_COMP_NONE)) { +		fdt_error("FDT image is compressed"); +		return 0; +	} + +	return 1; +} +#endif + +/** + * boot_get_fdt - main fdt handling routine + * @argc: command argument count + * @argv: command argument list + * @images: pointer to the bootm images structure + * @of_flat_tree: pointer to a char* variable, will hold fdt start address + * @of_size: pointer to a ulong variable, will hold fdt length + * + * boot_get_fdt() is responsible for finding a valid flat device tree image. + * Curently supported are the following ramdisk sources: + *      - multicomponent kernel/ramdisk image, + *      - commandline provided address of decicated ramdisk image. + * + * returns: + *     0, if fdt image was found and valid, or skipped + *     of_flat_tree and of_size are set to fdt start address and length if + *     fdt image is found and valid + * + *     1, if fdt image is found but corrupted + *     of_flat_tree and of_size are set to 0 if no fdt exists + */ +int boot_get_fdt(int flag, int argc, char * const argv[], +		bootm_headers_t *images, char **of_flat_tree, ulong *of_size) +{ +	const image_header_t *fdt_hdr; +	ulong		fdt_addr; +	char		*fdt_blob = NULL; +	ulong		image_start, image_data, image_end; +	ulong		load_start, load_end; +	void		*buf; +#if defined(CONFIG_FIT) +	void		*fit_hdr; +	const char	*fit_uname_config = NULL; +	const char	*fit_uname_fdt = NULL; +	ulong		default_addr; +	int		cfg_noffset; +	int		fdt_noffset; +	const void	*data; +	size_t		size; +#endif + +	*of_flat_tree = NULL; +	*of_size = 0; + +	if (argc > 3 || genimg_has_config(images)) { +#if defined(CONFIG_FIT) +		if (argc > 3) { +			/* +			 * If the FDT blob comes from the FIT image and the +			 * FIT image address is omitted in the command line +			 * argument, try to use ramdisk or os FIT image +			 * address or default load address. +			 */ +			if (images->fit_uname_rd) +				default_addr = (ulong)images->fit_hdr_rd; +			else if (images->fit_uname_os) +				default_addr = (ulong)images->fit_hdr_os; +			else +				default_addr = load_addr; + +			if (fit_parse_conf(argv[3], default_addr, +					   &fdt_addr, &fit_uname_config)) { +				debug("*  fdt: config '%s' from image at 0x%08lx\n", +				      fit_uname_config, fdt_addr); +			} else if (fit_parse_subimage(argv[3], default_addr, +				   &fdt_addr, &fit_uname_fdt)) { +				debug("*  fdt: subimage '%s' from image at 0x%08lx\n", +				      fit_uname_fdt, fdt_addr); +			} else +#endif +			{ +				fdt_addr = simple_strtoul(argv[3], NULL, 16); +				debug("*  fdt: cmdline image address = 0x%08lx\n", +				      fdt_addr); +			} +#if defined(CONFIG_FIT) +		} else { +			/* use FIT configuration provided in first bootm +			 * command argument +			 */ +			fdt_addr = map_to_sysmem(images->fit_hdr_os); +			fit_uname_config = images->fit_uname_cfg; +			debug("*  fdt: using config '%s' from image at 0x%08lx\n", +			      fit_uname_config, fdt_addr); + +			/* +			 * Check whether configuration has FDT blob defined, +			 * if not quit silently. +			 */ +			fit_hdr = images->fit_hdr_os; +			cfg_noffset = fit_conf_get_node(fit_hdr, +					fit_uname_config); +			if (cfg_noffset < 0) { +				debug("*  fdt: no such config\n"); +				return 0; +			} + +			fdt_noffset = fit_conf_get_fdt_node(fit_hdr, +					cfg_noffset); +			if (fdt_noffset < 0) { +				debug("*  fdt: no fdt in config\n"); +				return 0; +			} +		} +#endif + +		debug("## Checking for 'FDT'/'FDT Image' at %08lx\n", +		      fdt_addr); + +		/* copy from dataflash if needed */ +		fdt_addr = genimg_get_image(fdt_addr); + +		/* +		 * Check if there is an FDT image at the +		 * address provided in the second bootm argument +		 * check image type, for FIT images get a FIT node. +		 */ +		buf = map_sysmem(fdt_addr, 0); +		switch (genimg_get_format(buf)) { +		case IMAGE_FORMAT_LEGACY: +			/* verify fdt_addr points to a valid image header */ +			printf("## Flattened Device Tree from Legacy Image at %08lx\n", +			       fdt_addr); +			fdt_hdr = image_get_fdt(fdt_addr); +			if (!fdt_hdr) +				goto error; + +			/* +			 * move image data to the load address, +			 * make sure we don't overwrite initial image +			 */ +			image_start = (ulong)fdt_hdr; +			image_data = (ulong)image_get_data(fdt_hdr); +			image_end = image_get_image_end(fdt_hdr); + +			load_start = image_get_load(fdt_hdr); +			load_end = load_start + image_get_data_size(fdt_hdr); + +			if (load_start == image_start || +			    load_start == image_data) { +				fdt_blob = (char *)image_data; +				break; +			} + +			if ((load_start < image_end) && +			    (load_end > image_start)) { +				fdt_error("fdt overwritten"); +				goto error; +			} + +			debug("   Loading FDT from 0x%08lx to 0x%08lx\n", +			      image_data, load_start); + +			memmove((void *)load_start, +				(void *)image_data, +				image_get_data_size(fdt_hdr)); + +			fdt_blob = (char *)load_start; +			break; +		case IMAGE_FORMAT_FIT: +			/* +			 * This case will catch both: new uImage format +			 * (libfdt based) and raw FDT blob (also libfdt +			 * based). +			 */ +#if defined(CONFIG_FIT) +			/* check FDT blob vs FIT blob */ +			if (fit_check_format(buf)) { +				/* +				 * FIT image +				 */ +				fit_hdr = buf; +				printf("## Flattened Device Tree from FIT Image at %08lx\n", +				       fdt_addr); + +				if (!fit_uname_fdt) { +					/* +					 * no FDT blob image node unit name, +					 * try to get config node first. If +					 * config unit node name is NULL +					 * fit_conf_get_node() will try to +					 * find default config node +					 */ +					cfg_noffset = fit_conf_get_node(fit_hdr, +							fit_uname_config); + +					if (cfg_noffset < 0) { +						fdt_error("Could not find configuration node\n"); +						goto error; +					} + +					fit_uname_config = fdt_get_name(fit_hdr, +							cfg_noffset, NULL); +					printf("   Using '%s' configuration\n", +					       fit_uname_config); + +					fdt_noffset = fit_conf_get_fdt_node( +							fit_hdr, +							cfg_noffset); +					fit_uname_fdt = fit_get_name(fit_hdr, +							fdt_noffset, NULL); +				} else { +					/* +					 * get FDT component image node +					 * offset +					 */ +					fdt_noffset = fit_image_get_node( +								fit_hdr, +								fit_uname_fdt); +				} +				if (fdt_noffset < 0) { +					fdt_error("Could not find subimage node\n"); +					goto error; +				} + +				printf("   Trying '%s' FDT blob subimage\n", +				       fit_uname_fdt); + +				if (!fit_check_fdt(fit_hdr, fdt_noffset, +						   images->verify)) +					goto error; + +				/* get ramdisk image data address and length */ +				if (fit_image_get_data(fit_hdr, fdt_noffset, +						       &data, &size)) { +					fdt_error("Could not find FDT subimage data"); +					goto error; +				} + +				/* +				 * verify that image data is a proper FDT +				 * blob +				 */ +				if (fdt_check_header((char *)data) != 0) { +					fdt_error("Subimage data is not a FTD"); +					goto error; +				} + +				/* +				 * move image data to the load address, +				 * make sure we don't overwrite initial image +				 */ +				image_start = (ulong)fit_hdr; +				image_end = fit_get_end(fit_hdr); + +				if (fit_image_get_load(fit_hdr, fdt_noffset, +						       &load_start) == 0) { +					load_end = load_start + size; + +					if ((load_start < image_end) && +					    (load_end > image_start)) { +						fdt_error("FDT overwritten"); +						goto error; +					} + +					printf("   Loading FDT from 0x%08lx to 0x%08lx\n", +					       (ulong)data, load_start); + +					memmove((void *)load_start, +						(void *)data, size); + +					fdt_blob = (char *)load_start; +				} else { +					fdt_blob = (char *)data; +				} + +				images->fit_hdr_fdt = fit_hdr; +				images->fit_uname_fdt = fit_uname_fdt; +				images->fit_noffset_fdt = fdt_noffset; +				break; +			} else +#endif +			{ +				/* +				 * FDT blob +				 */ +				fdt_blob = buf; +				debug("*  fdt: raw FDT blob\n"); +				printf("## Flattened Device Tree blob at %08lx\n", +				       (long)fdt_addr); +			} +			break; +		default: +			puts("ERROR: Did not find a cmdline Flattened Device Tree\n"); +			goto error; +		} + +		printf("   Booting using the fdt blob at 0x%p\n", fdt_blob); + +	} else if (images->legacy_hdr_valid && +			image_check_type(&images->legacy_hdr_os_copy, +					 IH_TYPE_MULTI)) { +		ulong fdt_data, fdt_len; + +		/* +		 * Now check if we have a legacy multi-component image, +		 * get second entry data start address and len. +		 */ +		printf("## Flattened Device Tree from multi component Image at %08lX\n", +		       (ulong)images->legacy_hdr_os); + +		image_multi_getimg(images->legacy_hdr_os, 2, &fdt_data, +				   &fdt_len); +		if (fdt_len) { +			fdt_blob = (char *)fdt_data; +			printf("   Booting using the fdt at 0x%p\n", fdt_blob); + +			if (fdt_check_header(fdt_blob) != 0) { +				fdt_error("image is not a fdt"); +				goto error; +			} + +			if (fdt_totalsize(fdt_blob) != fdt_len) { +				fdt_error("fdt size != image size"); +				goto error; +			} +		} else { +			debug("## No Flattened Device Tree\n"); +			return 0; +		} +	} else { +		debug("## No Flattened Device Tree\n"); +		return 0; +	} + +	*of_flat_tree = fdt_blob; +	*of_size = fdt_totalsize(fdt_blob); +	debug("   of_flat_tree at 0x%08lx size 0x%08lx\n", +	      (ulong)*of_flat_tree, *of_size); + +	return 0; + +error: +	*of_flat_tree = NULL; +	*of_size = 0; +	return 1; +} diff --git a/common/image.c b/common/image.c index d249758d5..0792fdc2e 100644 --- a/common/image.c +++ b/common/image.c @@ -1150,572 +1150,6 @@ error:  }  #endif /* CONFIG_SYS_BOOT_RAMDISK_HIGH */ -#ifdef CONFIG_OF_LIBFDT -static void fdt_error(const char *msg) -{ -	puts("ERROR: "); -	puts(msg); -	puts(" - must RESET the board to recover.\n"); -} - -static const image_header_t *image_get_fdt(ulong fdt_addr) -{ -	const image_header_t *fdt_hdr = map_sysmem(fdt_addr, 0); - -	image_print_contents(fdt_hdr); - -	puts("   Verifying Checksum ... "); -	if (!image_check_hcrc(fdt_hdr)) { -		fdt_error("fdt header checksum invalid"); -		return NULL; -	} - -	if (!image_check_dcrc(fdt_hdr)) { -		fdt_error("fdt checksum invalid"); -		return NULL; -	} -	puts("OK\n"); - -	if (!image_check_type(fdt_hdr, IH_TYPE_FLATDT)) { -		fdt_error("uImage is not a fdt"); -		return NULL; -	} -	if (image_get_comp(fdt_hdr) != IH_COMP_NONE) { -		fdt_error("uImage is compressed"); -		return NULL; -	} -	if (fdt_check_header((char *)image_get_data(fdt_hdr)) != 0) { -		fdt_error("uImage data is not a fdt"); -		return NULL; -	} -	return fdt_hdr; -} - -/** - * fit_check_fdt - verify FIT format FDT subimage - * @fit_hdr: pointer to the FIT  header - * fdt_noffset: FDT subimage node offset within FIT image - * @verify: data CRC verification flag - * - * fit_check_fdt() verifies integrity of the FDT subimage and from - * specified FIT image. - * - * returns: - *     1, on success - *     0, on failure - */ -#if defined(CONFIG_FIT) -static int fit_check_fdt(const void *fit, int fdt_noffset, int verify) -{ -	fit_image_print(fit, fdt_noffset, "   "); - -	if (verify) { -		puts("   Verifying Hash Integrity ... "); -		if (!fit_image_verify(fit, fdt_noffset)) { -			fdt_error("Bad Data Hash"); -			return 0; -		} -		puts("OK\n"); -	} - -	if (!fit_image_check_type(fit, fdt_noffset, IH_TYPE_FLATDT)) { -		fdt_error("Not a FDT image"); -		return 0; -	} - -	if (!fit_image_check_comp(fit, fdt_noffset, IH_COMP_NONE)) { -		fdt_error("FDT image is compressed"); -		return 0; -	} - -	return 1; -} -#endif /* CONFIG_FIT */ - -#ifndef CONFIG_SYS_FDT_PAD -#define CONFIG_SYS_FDT_PAD 0x3000 -#endif - -#if defined(CONFIG_OF_LIBFDT) -/** - * boot_fdt_add_mem_rsv_regions - Mark the memreserve sections as unusable - * @lmb: pointer to lmb handle, will be used for memory mgmt - * @fdt_blob: pointer to fdt blob base address - * - * Adds the memreserve regions in the dtb to the lmb block.  Adding the - * memreserve regions prevents u-boot from using them to store the initrd - * or the fdt blob. - */ -void boot_fdt_add_mem_rsv_regions(struct lmb *lmb, void *fdt_blob) -{ -	uint64_t addr, size; -	int i, total; - -	if (fdt_check_header(fdt_blob) != 0) -		return; - -	total = fdt_num_mem_rsv(fdt_blob); -	for (i = 0; i < total; i++) { -		if (fdt_get_mem_rsv(fdt_blob, i, &addr, &size) != 0) -			continue; -		printf("   reserving fdt memory region: addr=%llx size=%llx\n", -			(unsigned long long)addr, (unsigned long long)size); -		lmb_reserve(lmb, addr, size); -	} -} - -/** - * boot_relocate_fdt - relocate flat device tree - * @lmb: pointer to lmb handle, will be used for memory mgmt - * @of_flat_tree: pointer to a char* variable, will hold fdt start address - * @of_size: pointer to a ulong variable, will hold fdt length - * - * boot_relocate_fdt() allocates a region of memory within the bootmap and - * relocates the of_flat_tree into that region, even if the fdt is already in - * the bootmap.  It also expands the size of the fdt by CONFIG_SYS_FDT_PAD - * bytes. - * - * of_flat_tree and of_size are set to final (after relocation) values - * - * returns: - *      0 - success - *      1 - failure - */ -int boot_relocate_fdt(struct lmb *lmb, char **of_flat_tree, ulong *of_size) -{ -	void	*fdt_blob = *of_flat_tree; -	void	*of_start = NULL; -	char	*fdt_high; -	ulong	of_len = 0; -	int	err; -	int	disable_relocation = 0; - -	/* nothing to do */ -	if (*of_size == 0) -		return 0; - -	if (fdt_check_header(fdt_blob) != 0) { -		fdt_error("image is not a fdt"); -		goto error; -	} - -	/* position on a 4K boundary before the alloc_current */ -	/* Pad the FDT by a specified amount */ -	of_len = *of_size + CONFIG_SYS_FDT_PAD; - -	/* If fdt_high is set use it to select the relocation address */ -	fdt_high = getenv("fdt_high"); -	if (fdt_high) { -		void *desired_addr = (void *)simple_strtoul(fdt_high, NULL, 16); - -		if (((ulong) desired_addr) == ~0UL) { -			/* All ones means use fdt in place */ -			of_start = fdt_blob; -			lmb_reserve(lmb, (ulong)of_start, of_len); -			disable_relocation = 1; -		} else if (desired_addr) { -			of_start = -			    (void *)(ulong) lmb_alloc_base(lmb, of_len, 0x1000, -							   (ulong)desired_addr); -			if (of_start == NULL) { -				puts("Failed using fdt_high value for Device Tree"); -				goto error; -			} -		} else { -			of_start = -			    (void *)(ulong) lmb_alloc(lmb, of_len, 0x1000); -		} -	} else { -		of_start = -		    (void *)(ulong) lmb_alloc_base(lmb, of_len, 0x1000, -						   getenv_bootm_mapsize() -						   + getenv_bootm_low()); -	} - -	if (of_start == NULL) { -		puts("device tree - allocation error\n"); -		goto error; -	} - -	if (disable_relocation) { -		/* We assume there is space after the existing fdt to use for padding */ -		fdt_set_totalsize(of_start, of_len); -		printf("   Using Device Tree in place at %p, end %p\n", -		       of_start, of_start + of_len - 1); -	} else { -		debug("## device tree at %p ... %p (len=%ld [0x%lX])\n", -			fdt_blob, fdt_blob + *of_size - 1, of_len, of_len); - -		printf("   Loading Device Tree to %p, end %p ... ", -			of_start, of_start + of_len - 1); - -		err = fdt_open_into(fdt_blob, of_start, of_len); -		if (err != 0) { -			fdt_error("fdt move failed"); -			goto error; -		} -		puts("OK\n"); -	} - -	*of_flat_tree = of_start; -	*of_size = of_len; - -	set_working_fdt_addr(*of_flat_tree); -	return 0; - -error: -	return 1; -} -#endif /* CONFIG_OF_LIBFDT */ - -/** - * boot_get_fdt - main fdt handling routine - * @argc: command argument count - * @argv: command argument list - * @images: pointer to the bootm images structure - * @of_flat_tree: pointer to a char* variable, will hold fdt start address - * @of_size: pointer to a ulong variable, will hold fdt length - * - * boot_get_fdt() is responsible for finding a valid flat device tree image. - * Curently supported are the following ramdisk sources: - *      - multicomponent kernel/ramdisk image, - *      - commandline provided address of decicated ramdisk image. - * - * returns: - *     0, if fdt image was found and valid, or skipped - *     of_flat_tree and of_size are set to fdt start address and length if - *     fdt image is found and valid - * - *     1, if fdt image is found but corrupted - *     of_flat_tree and of_size are set to 0 if no fdt exists - */ -int boot_get_fdt(int flag, int argc, char * const argv[], -		bootm_headers_t *images, char **of_flat_tree, ulong *of_size) -{ -	const image_header_t *fdt_hdr; -	ulong		fdt_addr; -	char		*fdt_blob = NULL; -	ulong		image_start, image_data, image_end; -	ulong		load_start, load_end; -	void		*buf; -#if defined(CONFIG_FIT) -	void		*fit_hdr; -	const char	*fit_uname_config = NULL; -	const char	*fit_uname_fdt = NULL; -	ulong		default_addr; -	int		cfg_noffset; -	int		fdt_noffset; -	const void	*data; -	size_t		size; -#endif - -	*of_flat_tree = NULL; -	*of_size = 0; - -	if (argc > 3 || genimg_has_config(images)) { -#if defined(CONFIG_FIT) -		if (argc > 3) { -			/* -			 * If the FDT blob comes from the FIT image and the -			 * FIT image address is omitted in the command line -			 * argument, try to use ramdisk or os FIT image -			 * address or default load address. -			 */ -			if (images->fit_uname_rd) -				default_addr = (ulong)images->fit_hdr_rd; -			else if (images->fit_uname_os) -				default_addr = (ulong)images->fit_hdr_os; -			else -				default_addr = load_addr; - -			if (fit_parse_conf(argv[3], default_addr, -						&fdt_addr, &fit_uname_config)) { -				debug("*  fdt: config '%s' from image at " -						"0x%08lx\n", -						fit_uname_config, fdt_addr); -			} else if (fit_parse_subimage(argv[3], default_addr, -						&fdt_addr, &fit_uname_fdt)) { -				debug("*  fdt: subimage '%s' from image at " -						"0x%08lx\n", -						fit_uname_fdt, fdt_addr); -			} else -#endif -			{ -				fdt_addr = simple_strtoul(argv[3], NULL, 16); -				debug("*  fdt: cmdline image address = " -						"0x%08lx\n", -						fdt_addr); -			} -#if defined(CONFIG_FIT) -		} else { -			/* use FIT configuration provided in first bootm -			 * command argument -			 */ -			fdt_addr = map_to_sysmem(images->fit_hdr_os); -			fit_uname_config = images->fit_uname_cfg; -			debug("*  fdt: using config '%s' from image " -					"at 0x%08lx\n", -					fit_uname_config, fdt_addr); - -			/* -			 * Check whether configuration has FDT blob defined, -			 * if not quit silently. -			 */ -			fit_hdr = images->fit_hdr_os; -			cfg_noffset = fit_conf_get_node(fit_hdr, -					fit_uname_config); -			if (cfg_noffset < 0) { -				debug("*  fdt: no such config\n"); -				return 0; -			} - -			fdt_noffset = fit_conf_get_fdt_node(fit_hdr, -					cfg_noffset); -			if (fdt_noffset < 0) { -				debug("*  fdt: no fdt in config\n"); -				return 0; -			} -		} -#endif - -		debug("## Checking for 'FDT'/'FDT Image' at %08lx\n", -				fdt_addr); - -		/* copy from dataflash if needed */ -		fdt_addr = genimg_get_image(fdt_addr); - -		/* -		 * Check if there is an FDT image at the -		 * address provided in the second bootm argument -		 * check image type, for FIT images get a FIT node. -		 */ -		buf = map_sysmem(fdt_addr, 0); -		switch (genimg_get_format(buf)) { -		case IMAGE_FORMAT_LEGACY: -			/* verify fdt_addr points to a valid image header */ -			printf("## Flattened Device Tree from Legacy Image " -					"at %08lx\n", -					fdt_addr); -			fdt_hdr = image_get_fdt(fdt_addr); -			if (!fdt_hdr) -				goto error; - -			/* -			 * move image data to the load address, -			 * make sure we don't overwrite initial image -			 */ -			image_start = (ulong)fdt_hdr; -			image_data = (ulong)image_get_data(fdt_hdr); -			image_end = image_get_image_end(fdt_hdr); - -			load_start = image_get_load(fdt_hdr); -			load_end = load_start + image_get_data_size(fdt_hdr); - -			if (load_start == image_start || -			    load_start == image_data) { -				fdt_blob = (char *)image_data; -				break; -			} - -			if ((load_start < image_end) && (load_end > image_start)) { -				fdt_error("fdt overwritten"); -				goto error; -			} - -			debug("   Loading FDT from 0x%08lx to 0x%08lx\n", -					image_data, load_start); - -			memmove((void *)load_start, -					(void *)image_data, -					image_get_data_size(fdt_hdr)); - -			fdt_blob = (char *)load_start; -			break; -		case IMAGE_FORMAT_FIT: -			/* -			 * This case will catch both: new uImage format -			 * (libfdt based) and raw FDT blob (also libfdt -			 * based). -			 */ -#if defined(CONFIG_FIT) -			/* check FDT blob vs FIT blob */ -			if (fit_check_format(buf)) { -				/* -				 * FIT image -				 */ -				fit_hdr = buf; -				printf("## Flattened Device Tree from FIT " -						"Image at %08lx\n", -						fdt_addr); - -				if (!fit_uname_fdt) { -					/* -					 * no FDT blob image node unit name, -					 * try to get config node first. If -					 * config unit node name is NULL -					 * fit_conf_get_node() will try to -					 * find default config node -					 */ -					cfg_noffset = fit_conf_get_node(fit_hdr, -							fit_uname_config); - -					if (cfg_noffset < 0) { -						fdt_error("Could not find " -							    "configuration " -							    "node\n"); -						goto error; -					} - -					fit_uname_config = fdt_get_name(fit_hdr, -							cfg_noffset, NULL); -					printf("   Using '%s' configuration\n", -							fit_uname_config); - -					fdt_noffset = fit_conf_get_fdt_node( -							fit_hdr, -							cfg_noffset); -					fit_uname_fdt = fit_get_name(fit_hdr, -							fdt_noffset, NULL); -				} else { -					/* get FDT component image node offset */ -					fdt_noffset = fit_image_get_node( -								fit_hdr, -								fit_uname_fdt); -				} -				if (fdt_noffset < 0) { -					fdt_error("Could not find subimage " -							"node\n"); -					goto error; -				} - -				printf("   Trying '%s' FDT blob subimage\n", -						fit_uname_fdt); - -				if (!fit_check_fdt(fit_hdr, fdt_noffset, -							images->verify)) -					goto error; - -				/* get ramdisk image data address and length */ -				if (fit_image_get_data(fit_hdr, fdt_noffset, -							&data, &size)) { -					fdt_error("Could not find FDT " -							"subimage data"); -					goto error; -				} - -				/* verift that image data is a proper FDT blob */ -				if (fdt_check_header((char *)data) != 0) { -					fdt_error("Subimage data is not a FTD"); -					goto error; -				} - -				/* -				 * move image data to the load address, -				 * make sure we don't overwrite initial image -				 */ -				image_start = (ulong)fit_hdr; -				image_end = fit_get_end(fit_hdr); - -				if (fit_image_get_load(fit_hdr, fdt_noffset, -							&load_start) == 0) { -					load_end = load_start + size; - -					if ((load_start < image_end) && -							(load_end > image_start)) { -						fdt_error("FDT overwritten"); -						goto error; -					} - -					printf("   Loading FDT from 0x%08lx " -							"to 0x%08lx\n", -							(ulong)data, -							load_start); - -					memmove((void *)load_start, -							(void *)data, size); - -					fdt_blob = (char *)load_start; -				} else { -					fdt_blob = (char *)data; -				} - -				images->fit_hdr_fdt = fit_hdr; -				images->fit_uname_fdt = fit_uname_fdt; -				images->fit_noffset_fdt = fdt_noffset; -				break; -			} else -#endif -			{ -				/* -				 * FDT blob -				 */ -				fdt_blob = buf; -				debug("*  fdt: raw FDT blob\n"); -				printf("## Flattened Device Tree blob at %08lx\n", -				       (long)fdt_addr); -			} -			break; -		default: -			puts("ERROR: Did not find a cmdline Flattened Device " -				"Tree\n"); -			goto error; -		} - -		printf("   Booting using the fdt blob at 0x%p\n", fdt_blob); - -	} else if (images->legacy_hdr_valid && -			image_check_type(&images->legacy_hdr_os_copy, -						IH_TYPE_MULTI)) { - -		ulong fdt_data, fdt_len; - -		/* -		 * Now check if we have a legacy multi-component image, -		 * get second entry data start address and len. -		 */ -		printf("## Flattened Device Tree from multi " -			"component Image at %08lX\n", -			(ulong)images->legacy_hdr_os); - -		image_multi_getimg(images->legacy_hdr_os, 2, &fdt_data, -					&fdt_len); -		if (fdt_len) { - -			fdt_blob = (char *)fdt_data; -			printf("   Booting using the fdt at 0x%p\n", fdt_blob); - -			if (fdt_check_header(fdt_blob) != 0) { -				fdt_error("image is not a fdt"); -				goto error; -			} - -			if (fdt_totalsize(fdt_blob) != fdt_len) { -				fdt_error("fdt size != image size"); -				goto error; -			} -		} else { -			debug("## No Flattened Device Tree\n"); -			return 0; -		} -	} else { -		debug("## No Flattened Device Tree\n"); -		return 0; -	} - -	*of_flat_tree = fdt_blob; -	*of_size = fdt_totalsize(fdt_blob); -	debug("   of_flat_tree at 0x%08lx size 0x%08lx\n", -			(ulong)*of_flat_tree, *of_size); - -	return 0; - -error: -	*of_flat_tree = NULL; -	*of_size = 0; -	return 1; -} -#endif /* CONFIG_OF_LIBFDT */ -  #ifdef CONFIG_SYS_BOOT_GET_CMDLINE  /**   * boot_get_cmdline - allocate and initialize kernel cmdline |