xref: /OK3568_Linux_fs/u-boot/common/image-fdt.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1 /*
2  * Copyright (c) 2013, Google Inc.
3  *
4  * (C) Copyright 2008 Semihalf
5  *
6  * (C) Copyright 2000-2006
7  * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
8  *
9  * SPDX-License-Identifier:	GPL-2.0+
10  */
11 
12 #include <common.h>
13 #include <fdtdec.h>
14 #include <fdt_support.h>
15 #include <errno.h>
16 #include <image.h>
17 #include <linux/libfdt.h>
18 #include <mapmem.h>
19 #include <asm/io.h>
20 #include <sysmem.h>
21 
22 #ifndef CONFIG_SYS_FDT_PAD
23 #define CONFIG_SYS_FDT_PAD 0x3000
24 #endif
25 
26 /* adding a ramdisk needs 0x44 bytes in version 2008.10 */
27 #define FDT_RAMDISK_OVERHEAD	0x80
28 
29 DECLARE_GLOBAL_DATA_PTR;
30 
fdt_error(const char * msg)31 static void fdt_error(const char *msg)
32 {
33 	puts("ERROR: ");
34 	puts(msg);
35 	puts(" - must RESET the board to recover.\n");
36 }
37 
38 #if defined(CONFIG_IMAGE_FORMAT_LEGACY)
image_get_fdt(ulong fdt_addr)39 static const image_header_t *image_get_fdt(ulong fdt_addr)
40 {
41 	const image_header_t *fdt_hdr = map_sysmem(fdt_addr, 0);
42 
43 	image_print_contents(fdt_hdr);
44 
45 	puts("   Verifying Checksum ... ");
46 	if (!image_check_hcrc(fdt_hdr)) {
47 		fdt_error("fdt header checksum invalid");
48 		return NULL;
49 	}
50 
51 	if (!image_check_dcrc(fdt_hdr)) {
52 		fdt_error("fdt checksum invalid");
53 		return NULL;
54 	}
55 	puts("OK\n");
56 
57 	/*
58 	 * default image mkimage conflicts with fit mkimage on param: -T "flat_dt".
59 	 *
60 	 * error message:
61 	 * "./tools/mkimage: Can't set header for FIT Image support: Success"
62 	 */
63 #if 0
64 	if (!image_check_type(fdt_hdr, IH_TYPE_FLATDT)) {
65 		fdt_error("uImage is not a fdt");
66 		return NULL;
67 	}
68 #endif
69 	if (image_get_comp(fdt_hdr) != IH_COMP_NONE) {
70 		fdt_error("uImage is compressed");
71 		return NULL;
72 	}
73 	if (fdt_check_header((void *)image_get_data(fdt_hdr)) != 0) {
74 		fdt_error("uImage data is not a fdt");
75 		return NULL;
76 	}
77 	return fdt_hdr;
78 }
79 #endif
80 
boot_mem_rsv_regions(struct lmb * lmb,void * fdt_blob)81 void boot_mem_rsv_regions(struct lmb *lmb, void *fdt_blob)
82 {
83 	int rsv_offset, offset;
84 	fdt_size_t rsv_size;
85 	fdt_addr_t rsv_addr;
86 	const void *prop;
87 	int i = 0;
88 
89 	if (fdt_check_header(fdt_blob) != 0)
90 		return;
91 
92 	rsv_offset = fdt_subnode_offset(fdt_blob, 0, "reserved-memory");
93 	if (rsv_offset == -FDT_ERR_NOTFOUND)
94 		return;
95 
96 	for (offset = fdt_first_subnode(fdt_blob, rsv_offset);
97 	     offset >= 0;
98 	     offset = fdt_next_subnode(fdt_blob, offset)) {
99 		prop = fdt_getprop(fdt_blob, offset, "status", NULL);
100 		if (prop && !strcmp(prop, "disabled"))
101 			continue;
102 
103 		rsv_addr = fdtdec_get_addr_size_auto_noparent(fdt_blob, offset,
104 							      "reg", 0,
105 							      &rsv_size, false);
106 		if (rsv_addr == FDT_ADDR_T_NONE || !rsv_size)
107 			continue;
108 
109 		i++;
110 		/* be quiet while reserve */
111 		if (lmb) {
112 			lmb_reserve(lmb, rsv_addr, rsv_size);
113 		} else {
114 			if (i == 1)
115 				printf("## reserved-memory:\n");
116 
117 			printf("  %s: addr=%llx size=%llx\n",
118 				fdt_get_name(fdt_blob, offset, NULL),
119 				(unsigned long long)rsv_addr, (unsigned long long)rsv_size);
120 		}
121 	}
122 }
123 
124 /**
125  * boot_fdt_add_mem_rsv_regions - Mark the memreserve sections as unusable
126  * @lmb: pointer to lmb handle, will be used for memory mgmt
127  * @fdt_blob: pointer to fdt blob base address
128  *
129  * Adds the memreserve regions in the dtb to the lmb block.  Adding the
130  * memreserve regions prevents u-boot from using them to store the initrd
131  * or the fdt blob.
132  */
boot_fdt_add_mem_rsv_regions(struct lmb * lmb,void * fdt_blob)133 void boot_fdt_add_mem_rsv_regions(struct lmb *lmb, void *fdt_blob)
134 {
135 	uint64_t addr, size;
136 	int i, total;
137 	/* we needn't repeat do reserve, do_bootm_linux would call this again */
138 	static int rsv_done;
139 
140 	if (fdt_check_header(fdt_blob) != 0 || rsv_done)
141 		return;
142 
143 	rsv_done = 1;
144 
145 	total = fdt_num_mem_rsv(fdt_blob);
146 	for (i = 0; i < total; i++) {
147 		if (fdt_get_mem_rsv(fdt_blob, i, &addr, &size) != 0)
148 			continue;
149 		printf("   reserving fdt memory region: addr=%llx size=%llx\n",
150 		       (unsigned long long)addr, (unsigned long long)size);
151 		lmb_reserve(lmb, addr, size);
152 	}
153 
154 	/* lmb_reserve() for "reserved-memory" */
155 	boot_mem_rsv_regions(lmb, fdt_blob);
156 }
157 
158 #ifdef CONFIG_SYSMEM
159 /**
160  * boot_fdt_add_mem_rsv_regions - Mark the memreserve sections as unusable
161  * @sysmem: pointer to sysmem handle, will be used for memory mgmt
162  * @fdt_blob: pointer to fdt blob base address
163  */
boot_fdt_add_sysmem_rsv_regions(void * fdt_blob)164 int boot_fdt_add_sysmem_rsv_regions(void *fdt_blob)
165 {
166 	uint64_t addr, size;
167 	int i, total;
168 	int rsv_offset, offset;
169 	fdt_size_t rsv_size;
170 	fdt_addr_t rsv_addr;
171 	static int rsv_done;
172 	char resvname[32];
173 	const void *prop;
174 
175 	if (fdt_check_header(fdt_blob) != 0 || rsv_done)
176 		return -EINVAL;
177 
178 	rsv_done = 1;
179 
180 	total = fdt_num_mem_rsv(fdt_blob);
181 	for (i = 0; i < total; i++) {
182 		if (fdt_get_mem_rsv(fdt_blob, i, &addr, &size) != 0)
183 			continue;
184 		debug("   sysmem: reserving fdt memory region: addr=%llx size=%llx\n",
185 		      (unsigned long long)addr, (unsigned long long)size);
186 		sprintf(resvname, "fdt-memory-reserved%d", i);
187 		if (!sysmem_fdt_reserve_alloc_base(resvname, addr, size))
188 			return -ENOMEM;
189 	}
190 
191 	rsv_offset = fdt_subnode_offset(fdt_blob, 0, "reserved-memory");
192 	if (rsv_offset == -FDT_ERR_NOTFOUND)
193 		return -EINVAL;
194 
195 	for (offset = fdt_first_subnode(fdt_blob, rsv_offset);
196 	     offset >= 0;
197 	     offset = fdt_next_subnode(fdt_blob, offset)) {
198 		prop = fdt_getprop(fdt_blob, offset, "status", NULL);
199 		if (prop && !strcmp(prop, "disabled"))
200 			continue;
201 
202 		rsv_addr = fdtdec_get_addr_size_auto_noparent(fdt_blob, offset,
203 							      "reg", 0,
204 							      &rsv_size, false);
205 		/*
206 		 * kernel will alloc reserved memory dynamically for the node
207 		 * with start address from 0.
208 		 */
209 		if (rsv_addr == FDT_ADDR_T_NONE || !rsv_addr || !rsv_size)
210 			continue;
211 		debug("  sysmem: 'reserved-memory' %s: addr=%llx size=%llx\n",
212 		      fdt_get_name(fdt_blob, offset, NULL),
213 		      (unsigned long long)rsv_addr, (unsigned long long)rsv_size);
214 		if (!sysmem_fdt_reserve_alloc_base(fdt_get_name(fdt_blob, offset, NULL),
215 					           rsv_addr, rsv_size))
216 			return -ENOMEM;
217 	}
218 
219 	return 0;
220 }
221 #endif
222 
223 /**
224  * boot_relocate_fdt - relocate flat device tree
225  * @lmb: pointer to lmb handle, will be used for memory mgmt
226  * @of_flat_tree: pointer to a char* variable, will hold fdt start address
227  * @of_size: pointer to a ulong variable, will hold fdt length
228  *
229  * boot_relocate_fdt() allocates a region of memory within the bootmap and
230  * relocates the of_flat_tree into that region, even if the fdt is already in
231  * the bootmap.  It also expands the size of the fdt by CONFIG_SYS_FDT_PAD
232  * bytes.
233  *
234  * of_flat_tree and of_size are set to final (after relocation) values
235  *
236  * returns:
237  *      0 - success
238  *      1 - failure
239  */
boot_relocate_fdt(struct lmb * lmb,char ** of_flat_tree,ulong * of_size)240 int boot_relocate_fdt(struct lmb *lmb, char **of_flat_tree, ulong *of_size)
241 {
242 	void	*fdt_blob = *of_flat_tree;
243 	void	*of_start = NULL;
244 	char	*fdt_high;
245 	ulong	of_len = 0;
246 	int	err;
247 	int	disable_relocation = 0;
248 
249 	/* nothing to do */
250 	if (*of_size == 0)
251 		return 0;
252 
253 	if (fdt_check_header(fdt_blob) != 0) {
254 		fdt_error("image is not a fdt");
255 		goto error;
256 	}
257 
258 	/* position on a 4K boundary before the alloc_current */
259 	/* Pad the FDT by a specified amount */
260 	of_len = *of_size + CONFIG_SYS_FDT_PAD;
261 
262 	/* If fdt_high is set use it to select the relocation address */
263 	fdt_high = env_get("fdt_high");
264 	if (fdt_high) {
265 		void *desired_addr = (void *)simple_strtoul(fdt_high, NULL, 16);
266 
267 		if (((ulong) desired_addr) == ~0UL) {
268 			/* All ones means use fdt in place */
269 			of_start = fdt_blob;
270 			lmb_reserve(lmb, (ulong)of_start, of_len);
271 			disable_relocation = 1;
272 		} else if (desired_addr) {
273 
274 			if (desired_addr && env_get_yesno("bootm-reloc-at"))
275 				desired_addr += of_len;
276 
277 			of_start =
278 			    (void *)(ulong) lmb_alloc_base(lmb, of_len, 0x1000,
279 							   (ulong)desired_addr);
280 			if (of_start == NULL) {
281 				puts("Failed using fdt_high value for Device Tree");
282 				goto error;
283 			}
284 		} else {
285 			of_start =
286 			    (void *)(ulong) lmb_alloc(lmb, of_len, 0x1000);
287 		}
288 	} else {
289 		of_start =
290 		    (void *)(ulong) lmb_alloc_base(lmb, of_len, 0x1000,
291 						   env_get_bootm_mapsize()
292 						   + env_get_bootm_low());
293 	}
294 
295 	if (of_start == NULL) {
296 		puts("device tree - allocation error\n");
297 		goto error;
298 	}
299 
300 	if (disable_relocation) {
301 		/*
302 		 * We assume there is space after the existing fdt to use
303 		 * for padding
304 		 */
305 		fdt_set_totalsize(of_start, of_len);
306 		printf("   Using Device Tree in place at %p, end %p\n",
307 		       of_start, of_start + of_len - 1);
308 	} else {
309 		debug("## device tree at %p ... %p (len=%ld [0x%lX])\n",
310 		      fdt_blob, fdt_blob + *of_size - 1, of_len, of_len);
311 
312 		printf("   Loading Device Tree to %p, end %p ... ",
313 		       of_start, of_start + of_len - 1);
314 
315 		err = fdt_open_into(fdt_blob, of_start, of_len);
316 		if (err != 0) {
317 			fdt_error("fdt move failed");
318 			goto error;
319 		}
320 		puts("OK\n");
321 	}
322 
323 	*of_flat_tree = of_start;
324 	*of_size = of_len;
325 
326 #ifdef CONFIG_CMD_FDT
327 	set_working_fdt_addr((ulong)*of_flat_tree);
328 #endif
329 	return 0;
330 
331 error:
332 	return 1;
333 }
334 
335 /**
336  * boot_get_fdt - main fdt handling routine
337  * @argc: command argument count
338  * @argv: command argument list
339  * @arch: architecture (IH_ARCH_...)
340  * @images: pointer to the bootm images structure
341  * @of_flat_tree: pointer to a char* variable, will hold fdt start address
342  * @of_size: pointer to a ulong variable, will hold fdt length
343  *
344  * boot_get_fdt() is responsible for finding a valid flat device tree image.
345  * Curently supported are the following ramdisk sources:
346  *      - multicomponent kernel/ramdisk image,
347  *      - commandline provided address of decicated ramdisk image.
348  *
349  * returns:
350  *     0, if fdt image was found and valid, or skipped
351  *     of_flat_tree and of_size are set to fdt start address and length if
352  *     fdt image is found and valid
353  *
354  *     1, if fdt image is found but corrupted
355  *     of_flat_tree and of_size are set to 0 if no fdt exists
356  */
boot_get_fdt(int flag,int argc,char * const argv[],uint8_t arch,bootm_headers_t * images,char ** of_flat_tree,ulong * of_size)357 int boot_get_fdt(int flag, int argc, char * const argv[], uint8_t arch,
358 		bootm_headers_t *images, char **of_flat_tree, ulong *of_size)
359 {
360 #if defined(CONFIG_IMAGE_FORMAT_LEGACY)
361 	const image_header_t *fdt_hdr;
362 	ulong		load, load_end;
363 	ulong		image_start, image_data, image_end;
364 #endif
365 	ulong		fdt_addr;
366 	char		*fdt_blob = NULL;
367 	void		*buf;
368 #if CONFIG_IS_ENABLED(FIT)
369 	const char	*fit_uname_config = images->fit_uname_cfg;
370 	const char	*fit_uname_fdt = NULL;
371 	ulong		default_addr;
372 	int		fdt_noffset;
373 #endif
374 	const char *select = NULL;
375 	int		ok_no_fdt = 0;
376 
377 	*of_flat_tree = NULL;
378 	*of_size = 0;
379 
380 	if (argc > 2)
381 		select = argv[2];
382 	if (select || genimg_has_config(images)) {
383 #if CONFIG_IS_ENABLED(FIT)
384 		if (select) {
385 			/*
386 			 * If the FDT blob comes from the FIT image and the
387 			 * FIT image address is omitted in the command line
388 			 * argument, try to use ramdisk or os FIT image
389 			 * address or default load address.
390 			 */
391 			if (images->fit_uname_rd)
392 				default_addr = (ulong)images->fit_hdr_rd;
393 			else if (images->fit_uname_os)
394 				default_addr = (ulong)images->fit_hdr_os;
395 			else
396 				default_addr = load_addr;
397 
398 			if (fit_parse_conf(select, default_addr,
399 					   &fdt_addr, &fit_uname_config)) {
400 				debug("*  fdt: config '%s' from image at 0x%08lx\n",
401 				      fit_uname_config, fdt_addr);
402 			} else if (fit_parse_subimage(select, default_addr,
403 				   &fdt_addr, &fit_uname_fdt)) {
404 				debug("*  fdt: subimage '%s' from image at 0x%08lx\n",
405 				      fit_uname_fdt, fdt_addr);
406 			} else
407 #endif
408 			{
409 				fdt_addr = simple_strtoul(select, NULL, 16);
410 				debug("*  fdt: cmdline image address = 0x%08lx\n",
411 				      fdt_addr);
412 			}
413 #if CONFIG_IS_ENABLED(FIT)
414 		} else {
415 			/* use FIT configuration provided in first bootm
416 			 * command argument
417 			 */
418 			fdt_addr = map_to_sysmem(images->fit_hdr_os);
419 			fdt_noffset = fit_get_node_from_config(images,
420 							       FIT_FDT_PROP,
421 							       fdt_addr);
422 			if (fdt_noffset == -ENOENT)
423 				return 0;
424 			else if (fdt_noffset < 0)
425 				return 1;
426 		}
427 #endif
428 		debug("## Checking for 'FDT'/'FDT Image' at %08lx\n",
429 		      fdt_addr);
430 
431 		/*
432 		 * Check if there is an FDT image at the
433 		 * address provided in the second bootm argument
434 		 * check image type, for FIT images get a FIT node.
435 		 */
436 		buf = map_sysmem(fdt_addr, 0);
437 		switch (genimg_get_format(buf)) {
438 #if defined(CONFIG_IMAGE_FORMAT_LEGACY)
439 		case IMAGE_FORMAT_LEGACY:
440 			/* verify fdt_addr points to a valid image header */
441 			printf("## Flattened Device Tree from Legacy Image at %08lx\n",
442 			       fdt_addr);
443 			fdt_hdr = image_get_fdt(fdt_addr);
444 			if (!fdt_hdr)
445 				goto no_fdt;
446 
447 			/*
448 			 * move image data to the load address,
449 			 * make sure we don't overwrite initial image
450 			 */
451 			image_start = (ulong)fdt_hdr;
452 			image_data = (ulong)image_get_data(fdt_hdr);
453 			image_end = image_get_image_end(fdt_hdr);
454 
455 			load = image_get_load(fdt_hdr);
456 			load_end = load + image_get_data_size(fdt_hdr);
457 
458 			if (load == image_start ||
459 			    load == image_data) {
460 				fdt_addr = load;
461 				break;
462 			}
463 
464 			if ((load < image_end) && (load_end > image_start)) {
465 				fdt_error("fdt overwritten");
466 				goto error;
467 			}
468 
469 			debug("   Loading FDT from 0x%08lx to 0x%08lx\n",
470 			      image_data, load);
471 
472 			memmove((void *)load,
473 				(void *)image_data,
474 				image_get_data_size(fdt_hdr));
475 
476 			fdt_addr = load;
477 			break;
478 #endif
479 		case IMAGE_FORMAT_FIT:
480 			/*
481 			 * This case will catch both: new uImage format
482 			 * (libfdt based) and raw FDT blob (also libfdt
483 			 * based).
484 			 */
485 #if CONFIG_IS_ENABLED(FIT)
486 			/* check FDT blob vs FIT blob */
487 			if (fit_check_format(buf)) {
488 				ulong load, len;
489 
490 				fdt_noffset = boot_get_fdt_fit(images,
491 					fdt_addr, &fit_uname_fdt,
492 					&fit_uname_config,
493 					arch, &load, &len);
494 
495 				images->fit_hdr_fdt = map_sysmem(fdt_addr, 0);
496 				images->fit_uname_fdt = fit_uname_fdt;
497 				images->fit_noffset_fdt = fdt_noffset;
498 				fdt_addr = load;
499 
500 				break;
501 			} else
502 #endif
503 			{
504 				/*
505 				 * FDT blob
506 				 */
507 				debug("*  fdt: raw FDT blob\n");
508 				printf("## Flattened Device Tree blob at %#010lx\n",
509 				       (long)fdt_addr);
510 			}
511 			break;
512 		default:
513 			puts("ERROR: Did not find a cmdline Flattened Device Tree\n");
514 			goto no_fdt;
515 		}
516 
517 		printf("   Booting using the fdt blob at %#010lx\n", fdt_addr);
518 		fdt_blob = map_sysmem(fdt_addr, 0);
519 	} else if (images->legacy_hdr_valid &&
520 			image_check_type(&images->legacy_hdr_os_copy,
521 					 IH_TYPE_MULTI)) {
522 		ulong fdt_data, fdt_len;
523 
524 		/*
525 		 * Now check if we have a legacy multi-component image,
526 		 * get second entry data start address and len.
527 		 */
528 		printf("## Flattened Device Tree from multi component Image at %08lX\n",
529 		       (ulong)images->legacy_hdr_os);
530 
531 		image_multi_getimg(images->legacy_hdr_os, 2, &fdt_data,
532 				   &fdt_len);
533 		if (fdt_len) {
534 			fdt_blob = (char *)fdt_data;
535 			printf("   Booting using the fdt at 0x%p\n", fdt_blob);
536 
537 			if (fdt_check_header(fdt_blob) != 0) {
538 				fdt_error("image is not a fdt");
539 				goto error;
540 			}
541 
542 			if (fdt_totalsize(fdt_blob) != fdt_len) {
543 				fdt_error("fdt size != image size");
544 				goto error;
545 			}
546 		} else {
547 			debug("## No Flattened Device Tree\n");
548 			goto no_fdt;
549 		}
550 	} else {
551 		debug("## No Flattened Device Tree\n");
552 		goto no_fdt;
553 	}
554 
555 	*of_flat_tree = fdt_blob;
556 	*of_size = fdt_totalsize(fdt_blob);
557 	debug("   of_flat_tree at 0x%08lx size 0x%08lx\n",
558 	      (ulong)*of_flat_tree, *of_size);
559 
560 	return 0;
561 
562 no_fdt:
563 	ok_no_fdt = 1;
564 error:
565 	*of_flat_tree = NULL;
566 	*of_size = 0;
567 	if (!select && ok_no_fdt) {
568 		debug("Continuing to boot without FDT\n");
569 		return 0;
570 	}
571 	return 1;
572 }
573 
574 /*
575  * Verify the device tree.
576  *
577  * This function is called after all device tree fix-ups have been enacted,
578  * so that the final device tree can be verified.  The definition of "verified"
579  * is up to the specific implementation.  However, it generally means that the
580  * addresses of some of the devices in the device tree are compared with the
581  * actual addresses at which U-Boot has placed them.
582  *
583  * Returns 1 on success, 0 on failure.  If 0 is returned, U-Boot will halt the
584  * boot process.
585  */
ft_verify_fdt(void * fdt)586 __weak int ft_verify_fdt(void *fdt)
587 {
588 	return 1;
589 }
590 
arch_fixup_fdt(void * blob)591 __weak int arch_fixup_fdt(void *blob)
592 {
593 	return 0;
594 }
595 
image_setup_libfdt(bootm_headers_t * images,void * blob,int of_size,struct lmb * lmb)596 int image_setup_libfdt(bootm_headers_t *images, void *blob,
597 		       int of_size, struct lmb *lmb)
598 {
599 	ulong *initrd_start = &images->initrd_start;
600 	ulong *initrd_end = &images->initrd_end;
601 	int ret = -EPERM;
602 	int fdt_ret;
603 
604 	if (arch_fixup_fdt(blob) < 0) {
605 		printf("ERROR: arch-specific fdt fixup failed\n");
606 		goto err;
607 	}
608 
609 #if defined(CONFIG_PASS_DEVICE_SERIAL_BY_FDT)
610 	if (fdt_root(blob) < 0) {
611 		printf("ERROR: root node setup failed\n");
612 		goto err;
613 	}
614 #endif
615 	if (fdt_chosen(blob) < 0) {
616 		printf("ERROR: /chosen node create failed\n");
617 		goto err;
618 	}
619 
620 	/* Update ethernet nodes */
621 	fdt_fixup_ethernet(blob);
622 	if (IMAGE_OF_BOARD_SETUP) {
623 		fdt_ret = ft_board_setup(blob, gd->bd);
624 		if (fdt_ret) {
625 			printf("ERROR: board-specific fdt fixup failed: %s\n",
626 			       fdt_strerror(fdt_ret));
627 			goto err;
628 		}
629 	}
630 	if (IMAGE_OF_SYSTEM_SETUP) {
631 		fdt_ret = ft_system_setup(blob, gd->bd);
632 		if (fdt_ret) {
633 			printf("ERROR: system-specific fdt fixup failed: %s\n",
634 			       fdt_strerror(fdt_ret));
635 			goto err;
636 		}
637 	}
638 
639 	/* Delete the old LMB reservation */
640 	if (lmb)
641 		lmb_free(lmb, (phys_addr_t)(u32)(uintptr_t)blob,
642 			 (phys_size_t)fdt_totalsize(blob));
643 
644 	ret = fdt_shrink_to_minimum(blob, 0);
645 	if (ret < 0)
646 		goto err;
647 	of_size = ret;
648 
649 	if (*initrd_start && *initrd_end) {
650 		of_size += FDT_RAMDISK_OVERHEAD;
651 		fdt_set_totalsize(blob, of_size);
652 	}
653 	/* Create a new LMB reservation */
654 	if (lmb)
655 		lmb_reserve(lmb, (ulong)blob, of_size);
656 
657 	fdt_initrd(blob, *initrd_start, *initrd_end);
658 	if (!ft_verify_fdt(blob))
659 		goto err;
660 
661 #if defined(CONFIG_SOC_KEYSTONE)
662 	if (IMAGE_OF_BOARD_SETUP)
663 		ft_board_setup_ex(blob, gd->bd);
664 #endif
665 
666 	return 0;
667 err:
668 	printf(" - must RESET the board to recover.\n\n");
669 
670 	return ret;
671 }
672