image.c 33.9 KB
Newer Older
1 2 3 4 5 6
/*
 * (C) Copyright 2008 Semihalf
 *
 * (C) Copyright 2000-2006
 * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
 *
7
 * SPDX-License-Identifier:	GPL-2.0+
8
 */
9

10
#ifndef USE_HOSTCC
11 12 13 14 15 16 17 18 19 20 21
#include <common.h>
#include <watchdog.h>

#ifdef CONFIG_SHOW_BOOT_PROGRESS
#include <status_led.h>
#endif

#ifdef CONFIG_HAS_DATAFLASH
#include <dataflash.h>
#endif

22 23 24 25
#ifdef CONFIG_LOGBUFFER
#include <logbuff.h>
#endif

26 27
#include <rtc.h>

J
Joe Hershberger 已提交
28
#include <environment.h>
29
#include <image.h>
30
#include <mapmem.h>
31

S
Stephen Warren 已提交
32
#if defined(CONFIG_FIT) || defined(CONFIG_OF_LIBFDT)
33 34
#include <libfdt.h>
#include <fdt_support.h>
35 36
#endif

37
#include <u-boot/md5.h>
38
#include <u-boot/sha1.h>
39
#include <asm/errno.h>
40
#include <asm/io.h>
41

42
#ifdef CONFIG_CMD_BDI
43
extern int do_bdinfo(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]);
44 45 46
#endif

DECLARE_GLOBAL_DATA_PTR;
47

48
#if defined(CONFIG_IMAGE_FORMAT_LEGACY)
S
Stephen Warren 已提交
49
static const image_header_t *image_get_ramdisk(ulong rd_addr, uint8_t arch,
50
						int verify);
51
#endif
52
#else
53
#include "mkimage.h"
54
#include <u-boot/md5.h>
55
#include <time.h>
56
#include <image.h>
57
#endif /* !USE_HOSTCC*/
58

59 60
#include <u-boot/crc.h>

61 62 63 64
#ifndef CONFIG_SYS_BARGSIZE
#define CONFIG_SYS_BARGSIZE 512
#endif

M
Mike Frysinger 已提交
65
static const table_entry_t uimage_arch[] = {
66 67 68 69 70 71 72 73 74 75
	{	IH_ARCH_INVALID,	NULL,		"Invalid ARCH",	},
	{	IH_ARCH_ALPHA,		"alpha",	"Alpha",	},
	{	IH_ARCH_ARM,		"arm",		"ARM",		},
	{	IH_ARCH_I386,		"x86",		"Intel x86",	},
	{	IH_ARCH_IA64,		"ia64",		"IA64",		},
	{	IH_ARCH_M68K,		"m68k",		"M68K",		},
	{	IH_ARCH_MICROBLAZE,	"microblaze",	"MicroBlaze",	},
	{	IH_ARCH_MIPS,		"mips",		"MIPS",		},
	{	IH_ARCH_MIPS64,		"mips64",	"MIPS 64 Bit",	},
	{	IH_ARCH_NIOS2,		"nios2",	"NIOS II",	},
76
	{	IH_ARCH_PPC,		"powerpc",	"PowerPC",	},
77 78 79 80 81 82 83
	{	IH_ARCH_PPC,		"ppc",		"PowerPC",	},
	{	IH_ARCH_S390,		"s390",		"IBM S390",	},
	{	IH_ARCH_SH,		"sh",		"SuperH",	},
	{	IH_ARCH_SPARC,		"sparc",	"SPARC",	},
	{	IH_ARCH_SPARC64,	"sparc64",	"SPARC 64 Bit",	},
	{	IH_ARCH_BLACKFIN,	"blackfin",	"Blackfin",	},
	{	IH_ARCH_AVR32,		"avr32",	"AVR32",	},
84
	{	IH_ARCH_NDS32,		"nds32",	"NDS32",	},
85
	{	IH_ARCH_OPENRISC,	"or1k",		"OpenRISC 1000",},
86
	{	IH_ARCH_SANDBOX,	"sandbox",	"Sandbox",	},
D
David Feng 已提交
87
	{	IH_ARCH_ARM64,		"arm64",	"AArch64",	},
88
	{	IH_ARCH_ARC,		"arc",		"ARC",		},
89
	{	IH_ARCH_X86_64,		"x86_64",	"AMD x86_64",	},
90 91 92
	{	-1,			"",		"",		},
};

M
Mike Frysinger 已提交
93
static const table_entry_t uimage_os[] = {
94 95 96 97 98 99
	{	IH_OS_INVALID,	NULL,		"Invalid OS",		},
	{	IH_OS_LINUX,	"linux",	"Linux",		},
#if defined(CONFIG_LYNXKDI) || defined(USE_HOSTCC)
	{	IH_OS_LYNXOS,	"lynxos",	"LynxOS",		},
#endif
	{	IH_OS_NETBSD,	"netbsd",	"NetBSD",		},
100
	{	IH_OS_OSE,	"ose",		"Enea OSE",		},
S
Steven Stallion 已提交
101
	{	IH_OS_PLAN9,	"plan9",	"Plan 9",		},
102 103
	{	IH_OS_RTEMS,	"rtems",	"RTEMS",		},
	{	IH_OS_U_BOOT,	"u-boot",	"U-Boot",		},
104
	{	IH_OS_VXWORKS,	"vxworks",	"VxWorks",		},
105 106 107
#if defined(CONFIG_CMD_ELF) || defined(USE_HOSTCC)
	{	IH_OS_QNX,	"qnx",		"QNX",			},
#endif
108 109 110
#if defined(CONFIG_INTEGRITY) || defined(USE_HOSTCC)
	{	IH_OS_INTEGRITY,"integrity",	"INTEGRITY",		},
#endif
111 112 113 114 115 116 117 118 119 120 121 122 123
#ifdef USE_HOSTCC
	{	IH_OS_4_4BSD,	"4_4bsd",	"4_4BSD",		},
	{	IH_OS_DELL,	"dell",		"Dell",			},
	{	IH_OS_ESIX,	"esix",		"Esix",			},
	{	IH_OS_FREEBSD,	"freebsd",	"FreeBSD",		},
	{	IH_OS_IRIX,	"irix",		"Irix",			},
	{	IH_OS_NCR,	"ncr",		"NCR",			},
	{	IH_OS_OPENBSD,	"openbsd",	"OpenBSD",		},
	{	IH_OS_PSOS,	"psos",		"pSOS",			},
	{	IH_OS_SCO,	"sco",		"SCO",			},
	{	IH_OS_SOLARIS,	"solaris",	"Solaris",		},
	{	IH_OS_SVR4,	"svr4",		"SVR4",			},
#endif
124 125 126 127
#if defined(CONFIG_BOOTM_OPENRTOS) || defined(USE_HOSTCC)
	{	IH_OS_OPENRTOS,	"openrtos",	"OpenRTOS",		},
#endif

128 129 130
	{	-1,		"",		"",			},
};

M
Mike Frysinger 已提交
131
static const table_entry_t uimage_type[] = {
132
	{	IH_TYPE_AISIMAGE,   "aisimage",   "Davinci AIS image",},
133 134
	{	IH_TYPE_FILESYSTEM, "filesystem", "Filesystem Image",	},
	{	IH_TYPE_FIRMWARE,   "firmware",	  "Firmware",		},
135
	{	IH_TYPE_FLATDT,     "flat_dt",    "Flat Device Tree",	},
136
	{	IH_TYPE_GPIMAGE,    "gpimage",    "TI Keystone SPL Image",},
137
	{	IH_TYPE_KERNEL,	    "kernel",	  "Kernel Image",	},
138
	{	IH_TYPE_KERNEL_NOLOAD, "kernel_noload",  "Kernel Image (no loading done)", },
139 140 141
	{	IH_TYPE_KWBIMAGE,   "kwbimage",   "Kirkwood Boot Image",},
	{	IH_TYPE_IMXIMAGE,   "imximage",   "Freescale i.MX Boot Image",},
	{	IH_TYPE_INVALID,    NULL,	  "Invalid Image",	},
142
	{	IH_TYPE_MULTI,	    "multi",	  "Multi-File Image",	},
143
	{	IH_TYPE_OMAPIMAGE,  "omapimage",  "TI OMAP SPL With GP CH",},
144
	{	IH_TYPE_PBLIMAGE,   "pblimage",   "Freescale PBL Boot Image",},
145 146
	{	IH_TYPE_RAMDISK,    "ramdisk",	  "RAMDisk Image",	},
	{	IH_TYPE_SCRIPT,     "script",	  "Script",		},
147
	{	IH_TYPE_SOCFPGAIMAGE, "socfpgaimage", "Altera SOCFPGA preloader",},
148
	{	IH_TYPE_STANDALONE, "standalone", "Standalone Program", },
149
	{	IH_TYPE_UBLIMAGE,   "ublimage",   "Davinci UBL image",},
150
	{	IH_TYPE_MXSIMAGE,   "mxsimage",   "Freescale MXS Boot Image",},
A
Andreas Bießmann 已提交
151
	{	IH_TYPE_ATMELIMAGE, "atmelimage", "ATMEL ROM-Boot Image",},
152
	{	IH_TYPE_X86_SETUP,  "x86_setup",  "x86 setup.bin",    },
153
	{	IH_TYPE_LPC32XXIMAGE, "lpc32xximage",  "LPC32XX Boot Image", },
154 155 156
	{	-1,		    "",		  "",			},
};

M
Mike Frysinger 已提交
157
static const table_entry_t uimage_comp[] = {
158 159 160
	{	IH_COMP_NONE,	"none",		"uncompressed",		},
	{	IH_COMP_BZIP2,	"bzip2",	"bzip2 compressed",	},
	{	IH_COMP_GZIP,	"gzip",		"gzip compressed",	},
161
	{	IH_COMP_LZMA,	"lzma",		"lzma compressed",	},
P
Peter Korsgaard 已提交
162
	{	IH_COMP_LZO,	"lzo",		"lzo compressed",	},
163 164 165
	{	-1,		"",		"",			},
};

166 167 168
/*****************************************************************************/
/* Legacy format routines */
/*****************************************************************************/
S
Stephen Warren 已提交
169
int image_check_hcrc(const image_header_t *hdr)
170 171
{
	ulong hcrc;
S
Stephen Warren 已提交
172
	ulong len = image_get_header_size();
173 174 175
	image_header_t header;

	/* Copy header so we can blank CRC field for re-calculation */
S
Stephen Warren 已提交
176 177
	memmove(&header, (char *)hdr, image_get_header_size());
	image_set_hcrc(&header, 0);
178

S
Stephen Warren 已提交
179
	hcrc = crc32(0, (unsigned char *)&header, len);
180

S
Stephen Warren 已提交
181
	return (hcrc == image_get_hcrc(hdr));
182 183
}

S
Stephen Warren 已提交
184
int image_check_dcrc(const image_header_t *hdr)
185
{
S
Stephen Warren 已提交
186 187 188
	ulong data = image_get_data(hdr);
	ulong len = image_get_data_size(hdr);
	ulong dcrc = crc32_wd(0, (unsigned char *)data, len, CHUNKSZ_CRC32);
189

S
Stephen Warren 已提交
190
	return (dcrc == image_get_dcrc(hdr));
191 192
}

193 194 195 196 197 198 199 200 201 202 203 204 205
/**
 * image_multi_count - get component (sub-image) count
 * @hdr: pointer to the header of the multi component image
 *
 * image_multi_count() returns number of components in a multi
 * component image.
 *
 * Note: no checking of the image type is done, caller must pass
 * a valid multi component image.
 *
 * returns:
 *     number of components
 */
S
Stephen Warren 已提交
206
ulong image_multi_count(const image_header_t *hdr)
207 208
{
	ulong i, count = 0;
209
	uint32_t *size;
210 211 212

	/* get start of the image payload, which in case of multi
	 * component images that points to a table of component sizes */
S
Stephen Warren 已提交
213
	size = (uint32_t *)image_get_data(hdr);
214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238

	/* count non empty slots */
	for (i = 0; size[i]; ++i)
		count++;

	return count;
}

/**
 * image_multi_getimg - get component data address and size
 * @hdr: pointer to the header of the multi component image
 * @idx: index of the requested component
 * @data: pointer to a ulong variable, will hold component data address
 * @len: pointer to a ulong variable, will hold component size
 *
 * image_multi_getimg() returns size and data address for the requested
 * component in a multi component image.
 *
 * Note: no checking of the image type is done, caller must pass
 * a valid multi component image.
 *
 * returns:
 *     data address and size of the component, if idx is valid
 *     0 in data and len, if idx is out of range
 */
S
Stephen Warren 已提交
239
void image_multi_getimg(const image_header_t *hdr, ulong idx,
240 241 242
			ulong *data, ulong *len)
{
	int i;
243
	uint32_t *size;
244
	ulong offset, count, img_data;
245 246

	/* get number of component */
S
Stephen Warren 已提交
247
	count = image_multi_count(hdr);
248 249 250

	/* get start of the image payload, which in case of multi
	 * component images that points to a table of component sizes */
S
Stephen Warren 已提交
251
	size = (uint32_t *)image_get_data(hdr);
252 253 254

	/* get address of the proper component data start, which means
	 * skipping sizes table (add 1 for last, null entry) */
S
Stephen Warren 已提交
255
	img_data = image_get_data(hdr) + (count + 1) * sizeof(uint32_t);
256 257

	if (idx < count) {
S
Stephen Warren 已提交
258
		*len = uimage_to_cpu(size[idx]);
259 260 261 262
		offset = 0;

		/* go over all indices preceding requested component idx */
		for (i = 0; i < idx; i++) {
263
			/* add up i-th component size, rounding up to 4 bytes */
S
Stephen Warren 已提交
264
			offset += (uimage_to_cpu(size[i]) + 3) & ~3 ;
265 266 267
		}

		/* calculate idx-th component data address */
268
		*data = img_data + offset;
269 270 271 272 273
	} else {
		*len = 0;
		*data = 0;
	}
}
274

S
Stephen Warren 已提交
275
static void image_print_type(const image_header_t *hdr)
276 277 278
{
	const char *os, *arch, *type, *comp;

S
Stephen Warren 已提交
279 280 281 282
	os = genimg_get_os_name(image_get_os(hdr));
	arch = genimg_get_arch_name(image_get_arch(hdr));
	type = genimg_get_type_name(image_get_type(hdr));
	comp = genimg_get_comp_name(image_get_comp(hdr));
283

S
Stephen Warren 已提交
284
	printf("%s %s %s (%s)\n", arch, os, type, comp);
285 286
}

287
/**
288
 * image_print_contents - prints out the contents of the legacy format image
289
 * @ptr: pointer to the legacy format image header
290 291
 * @p: pointer to prefix string
 *
292
 * image_print_contents() formats a multi line legacy image contents description.
293 294 295 296 297 298
 * The routine prints out all header fields followed by the size/offset data
 * for MULTI/SCRIPT images.
 *
 * returns:
 *     no returned results
 */
S
Stephen Warren 已提交
299
void image_print_contents(const void *ptr)
300
{
301
	const image_header_t *hdr = (const image_header_t *)ptr;
302 303
	const char *p;

304
	p = IMAGE_INDENT_STRING;
S
Stephen Warren 已提交
305
	printf("%sImage Name:   %.*s\n", p, IH_NMLEN, image_get_name(hdr));
306 307 308 309
	if (IMAGE_ENABLE_TIMESTAMP) {
		printf("%sCreated:      ", p);
		genimg_print_time((time_t)image_get_time(hdr));
	}
S
Stephen Warren 已提交
310 311 312 313 314 315 316 317 318
	printf("%sImage Type:   ", p);
	image_print_type(hdr);
	printf("%sData Size:    ", p);
	genimg_print_size(image_get_data_size(hdr));
	printf("%sLoad Address: %08x\n", p, image_get_load(hdr));
	printf("%sEntry Point:  %08x\n", p, image_get_ep(hdr));

	if (image_check_type(hdr, IH_TYPE_MULTI) ||
			image_check_type(hdr, IH_TYPE_SCRIPT)) {
319 320
		int i;
		ulong data, len;
S
Stephen Warren 已提交
321
		ulong count = image_multi_count(hdr);
322

S
Stephen Warren 已提交
323
		printf("%sContents:\n", p);
324
		for (i = 0; i < count; i++) {
S
Stephen Warren 已提交
325
			image_multi_getimg(hdr, i, &data, &len);
326

S
Stephen Warren 已提交
327 328
			printf("%s   Image %d: ", p, i);
			genimg_print_size(len);
329

S
Stephen Warren 已提交
330
			if (image_check_type(hdr, IH_TYPE_SCRIPT) && i > 0) {
331 332 333 334 335
				/*
				 * the user may need to know offsets
				 * if planning to do something with
				 * multiple files
				 */
S
Stephen Warren 已提交
336
				printf("%s    Offset = 0x%08lx\n", p, data);
337
			}
338 339 340 341
		}
	}
}

342 343

#ifndef USE_HOSTCC
344
#if defined(CONFIG_IMAGE_FORMAT_LEGACY)
345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362
/**
 * image_get_ramdisk - get and verify ramdisk image
 * @rd_addr: ramdisk image start address
 * @arch: expected ramdisk architecture
 * @verify: checksum verification flag
 *
 * image_get_ramdisk() returns a pointer to the verified ramdisk image
 * header. Routine receives image start address and expected architecture
 * flag. Verification done covers data and header integrity and os/type/arch
 * fields checking.
 *
 * If dataflash support is enabled routine checks for dataflash addresses
 * and handles required dataflash reads.
 *
 * returns:
 *     pointer to a ramdisk image header, if image was found and valid
 *     otherwise, return NULL
 */
S
Stephen Warren 已提交
363
static const image_header_t *image_get_ramdisk(ulong rd_addr, uint8_t arch,
364
						int verify)
365
{
366
	const image_header_t *rd_hdr = (const image_header_t *)rd_addr;
367

S
Stephen Warren 已提交
368 369
	if (!image_check_magic(rd_hdr)) {
		puts("Bad Magic Number\n");
370
		bootstage_error(BOOTSTAGE_ID_RD_MAGIC);
371 372 373
		return NULL;
	}

S
Stephen Warren 已提交
374 375
	if (!image_check_hcrc(rd_hdr)) {
		puts("Bad Header Checksum\n");
376
		bootstage_error(BOOTSTAGE_ID_RD_HDR_CHECKSUM);
377 378 379
		return NULL;
	}

380
	bootstage_mark(BOOTSTAGE_ID_RD_MAGIC);
S
Stephen Warren 已提交
381
	image_print_contents(rd_hdr);
382 383 384

	if (verify) {
		puts("   Verifying Checksum ... ");
S
Stephen Warren 已提交
385 386
		if (!image_check_dcrc(rd_hdr)) {
			puts("Bad Data CRC\n");
387
			bootstage_error(BOOTSTAGE_ID_RD_CHECKSUM);
388 389 390 391 392
			return NULL;
		}
		puts("OK\n");
	}

393
	bootstage_mark(BOOTSTAGE_ID_RD_HDR_CHECKSUM);
394

S
Stephen Warren 已提交
395 396 397 398
	if (!image_check_os(rd_hdr, IH_OS_LINUX) ||
	    !image_check_arch(rd_hdr, arch) ||
	    !image_check_type(rd_hdr, IH_TYPE_RAMDISK)) {
		printf("No Linux %s Ramdisk Image\n",
399
				genimg_get_arch_name(arch));
400
		bootstage_error(BOOTSTAGE_ID_RAMDISK);
401 402 403 404 405
		return NULL;
	}

	return rd_hdr;
}
406
#endif
407
#endif /* !USE_HOSTCC */
408 409 410 411

/*****************************************************************************/
/* Shared dual-format routines */
/*****************************************************************************/
412
#ifndef USE_HOSTCC
J
Joe Hershberger 已提交
413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432
ulong load_addr = CONFIG_SYS_LOAD_ADDR;	/* Default Load Address */
ulong save_addr;			/* Default Save Address */
ulong save_size;			/* Default Save Size (in bytes) */

static int on_loadaddr(const char *name, const char *value, enum env_op op,
	int flags)
{
	switch (op) {
	case env_op_create:
	case env_op_overwrite:
		load_addr = simple_strtoul(value, NULL, 16);
		break;
	default:
		break;
	}

	return 0;
}
U_BOOT_ENV_CALLBACK(loadaddr, on_loadaddr);

433 434
ulong getenv_bootm_low(void)
{
S
Stephen Warren 已提交
435
	char *s = getenv("bootm_low");
436
	if (s) {
S
Stephen Warren 已提交
437
		ulong tmp = simple_strtoul(s, NULL, 16);
438 439 440
		return tmp;
	}

441 442
#if defined(CONFIG_SYS_SDRAM_BASE)
	return CONFIG_SYS_SDRAM_BASE;
443 444
#elif defined(CONFIG_ARM)
	return gd->bd->bi_dram[0].start;
445 446 447 448 449
#else
	return 0;
#endif
}

450
phys_size_t getenv_bootm_size(void)
451
{
452
	phys_size_t tmp;
S
Stephen Warren 已提交
453
	char *s = getenv("bootm_size");
454
	if (s) {
S
Stephen Warren 已提交
455
		tmp = (phys_size_t)simple_strtoull(s, NULL, 16);
456 457
		return tmp;
	}
458 459
	s = getenv("bootm_low");
	if (s)
S
Stephen Warren 已提交
460
		tmp = (phys_size_t)simple_strtoull(s, NULL, 16);
461 462 463
	else
		tmp = 0;

464

465
#if defined(CONFIG_ARM)
466
	return gd->bd->bi_dram[0].size - tmp;
467
#else
468
	return gd->bd->bi_memsize - tmp;
469
#endif
470 471
}

472 473 474
phys_size_t getenv_bootm_mapsize(void)
{
	phys_size_t tmp;
S
Stephen Warren 已提交
475
	char *s = getenv("bootm_mapsize");
476
	if (s) {
S
Stephen Warren 已提交
477
		tmp = (phys_size_t)simple_strtoull(s, NULL, 16);
478 479 480 481 482 483 484 485 486 487
		return tmp;
	}

#if defined(CONFIG_SYS_BOOTMAPSZ)
	return CONFIG_SYS_BOOTMAPSZ;
#else
	return getenv_bootm_size();
#endif
}

S
Stephen Warren 已提交
488
void memmove_wd(void *to, void *from, size_t len, ulong chunksz)
489
{
490 491 492
	if (to == from)
		return;

493
#if defined(CONFIG_HW_WATCHDOG) || defined(CONFIG_WATCHDOG)
494 495 496 497
	if (to > from) {
		from += len;
		to += len;
	}
498 499
	while (len > 0) {
		size_t tail = (len > chunksz) ? chunksz : len;
S
Stephen Warren 已提交
500
		WATCHDOG_RESET();
501 502 503 504
		if (to > from) {
			to -= tail;
			from -= tail;
		}
S
Stephen Warren 已提交
505
		memmove(to, from, tail);
506 507 508 509
		if (to < from) {
			to += tail;
			from += tail;
		}
510 511 512
		len -= tail;
	}
#else	/* !(CONFIG_HW_WATCHDOG || CONFIG_WATCHDOG) */
S
Stephen Warren 已提交
513
	memmove(to, from, len);
514 515
#endif	/* CONFIG_HW_WATCHDOG || CONFIG_WATCHDOG */
}
516
#endif /* !USE_HOSTCC */
517

S
Stephen Warren 已提交
518
void genimg_print_size(uint32_t size)
519
{
520
#ifndef USE_HOSTCC
S
Stephen Warren 已提交
521 522
	printf("%d Bytes = ", size);
	print_size(size, "\n");
523
#else
S
Stephen Warren 已提交
524
	printf("%d Bytes = %.2f kB = %.2f MB\n",
525 526
			size, (double)size / 1.024e3,
			(double)size / 1.048576e6);
527
#endif
528 529
}

530 531
#if IMAGE_ENABLE_TIMESTAMP
void genimg_print_time(time_t timestamp)
532 533 534 535
{
#ifndef USE_HOSTCC
	struct rtc_time tm;

536
	rtc_to_tm(timestamp, &tm);
S
Stephen Warren 已提交
537
	printf("%4d-%02d-%02d  %2d:%02d:%02d UTC\n",
538 539 540
			tm.tm_year, tm.tm_mon, tm.tm_mday,
			tm.tm_hour, tm.tm_min, tm.tm_sec);
#else
S
Stephen Warren 已提交
541
	printf("%s", ctime(&timestamp));
542
#endif
543
}
544
#endif
545

546 547 548 549 550 551 552 553 554 555 556 557 558 559
/**
 * get_table_entry_name - translate entry id to long name
 * @table: pointer to a translation table for entries of a specific type
 * @msg: message to be returned when translation fails
 * @id: entry id to be translated
 *
 * get_table_entry_name() will go over translation table trying to find
 * entry that matches given id. If matching entry is found, its long
 * name is returned to the caller.
 *
 * returns:
 *     long entry name if translation succeeds
 *     msg otherwise
 */
M
Mike Frysinger 已提交
560
char *get_table_entry_name(const table_entry_t *table, char *msg, int id)
561 562 563
{
	for (; table->id >= 0; ++table) {
		if (table->id == id)
564
#if defined(USE_HOSTCC) || !defined(CONFIG_NEEDS_MANUAL_RELOC)
565 566 567 568
			return table->lname;
#else
			return table->lname + gd->reloc_off;
#endif
569
	}
570 571
	return (msg);
}
572

S
Stephen Warren 已提交
573
const char *genimg_get_os_name(uint8_t os)
574
{
S
Stephen Warren 已提交
575
	return (get_table_entry_name(uimage_os, "Unknown OS", os));
576 577
}

S
Stephen Warren 已提交
578
const char *genimg_get_arch_name(uint8_t arch)
579
{
S
Stephen Warren 已提交
580 581
	return (get_table_entry_name(uimage_arch, "Unknown Architecture",
					arch));
582
}
583

S
Stephen Warren 已提交
584
const char *genimg_get_type_name(uint8_t type)
585
{
S
Stephen Warren 已提交
586
	return (get_table_entry_name(uimage_type, "Unknown Image", type));
587
}
588

S
Stephen Warren 已提交
589
const char *genimg_get_comp_name(uint8_t comp)
590
{
S
Stephen Warren 已提交
591 592
	return (get_table_entry_name(uimage_comp, "Unknown Compression",
					comp));
593 594
}

595 596 597 598 599 600 601 602 603 604 605 606 607 608
/**
 * get_table_entry_id - translate short entry name to id
 * @table: pointer to a translation table for entries of a specific type
 * @table_name: to be used in case of error
 * @name: entry short name to be translated
 *
 * get_table_entry_id() will go over translation table trying to find
 * entry that matches given short name. If matching entry is found,
 * its id returned to the caller.
 *
 * returns:
 *     entry id if translation succeeds
 *     -1 otherwise
 */
M
Mike Frysinger 已提交
609
int get_table_entry_id(const table_entry_t *table,
610
		const char *table_name, const char *name)
611
{
M
Mike Frysinger 已提交
612
	const table_entry_t *t;
613 614
#ifdef USE_HOSTCC
	int first = 1;
615

616 617
	for (t = table; t->id >= 0; ++t) {
		if (t->sname && strcasecmp(t->sname, name) == 0)
S
Stephen Warren 已提交
618
			return(t->id);
619 620
	}

S
Stephen Warren 已提交
621
	fprintf(stderr, "\nInvalid %s Type - valid names are", table_name);
622 623 624
	for (t = table; t->id >= 0; ++t) {
		if (t->sname == NULL)
			continue;
S
Stephen Warren 已提交
625
		fprintf(stderr, "%c %s", (first) ? ':' : ',', t->sname);
626 627
		first = 0;
	}
S
Stephen Warren 已提交
628
	fprintf(stderr, "\n");
629 630
#else
	for (t = table; t->id >= 0; ++t) {
631
#ifdef CONFIG_NEEDS_MANUAL_RELOC
632
		if (t->sname && strcmp(t->sname + gd->reloc_off, name) == 0)
633 634
#else
		if (t->sname && strcmp(t->sname, name) == 0)
635
#endif
636 637
			return (t->id);
	}
S
Stephen Warren 已提交
638
	debug("Invalid %s Type: %s\n", table_name, name);
639 640 641 642
#endif /* USE_HOSTCC */
	return (-1);
}

S
Stephen Warren 已提交
643
int genimg_get_os_id(const char *name)
644
{
S
Stephen Warren 已提交
645
	return (get_table_entry_id(uimage_os, "OS", name));
646 647
}

S
Stephen Warren 已提交
648
int genimg_get_arch_id(const char *name)
649
{
S
Stephen Warren 已提交
650
	return (get_table_entry_id(uimage_arch, "CPU", name));
651
}
652

S
Stephen Warren 已提交
653
int genimg_get_type_id(const char *name)
654
{
S
Stephen Warren 已提交
655
	return (get_table_entry_id(uimage_type, "Image", name));
656 657
}

S
Stephen Warren 已提交
658
int genimg_get_comp_id(const char *name)
659
{
S
Stephen Warren 已提交
660
	return (get_table_entry_id(uimage_comp, "Compression", name));
661 662 663
}

#ifndef USE_HOSTCC
664
/**
665 666
 * genimg_get_kernel_addr_fit - get the real kernel address and return 2
 *                              FIT strings
667
 * @img_addr: a string might contain real image address
668 669 670 671
 * @fit_uname_config: double pointer to a char, will hold pointer to a
 *                    configuration unit name
 * @fit_uname_kernel: double pointer to a char, will hold pointer to a subimage
 *                    name
672
 *
673
 * genimg_get_kernel_addr_fit get the real kernel start address from a string
674 675 676 677 678
 * which is normally the first argv of bootm/bootz
 *
 * returns:
 *     kernel start address
 */
679 680 681
ulong genimg_get_kernel_addr_fit(char * const img_addr,
			     const char **fit_uname_config,
			     const char **fit_uname_kernel)
682 683 684 685 686 687 688 689 690 691
{
	ulong kernel_addr;

	/* find out kernel image address */
	if (!img_addr) {
		kernel_addr = load_addr;
		debug("*  kernel: default image load address = 0x%08lx\n",
		      load_addr);
#if defined(CONFIG_FIT)
	} else if (fit_parse_conf(img_addr, load_addr, &kernel_addr,
692
				  fit_uname_config)) {
693
		debug("*  kernel: config '%s' from image at 0x%08lx\n",
694
		      *fit_uname_config, kernel_addr);
695
	} else if (fit_parse_subimage(img_addr, load_addr, &kernel_addr,
696
				     fit_uname_kernel)) {
697
		debug("*  kernel: subimage '%s' from image at 0x%08lx\n",
698
		      *fit_uname_kernel, kernel_addr);
699 700 701 702 703 704 705 706 707 708
#endif
	} else {
		kernel_addr = simple_strtoul(img_addr, NULL, 16);
		debug("*  kernel: cmdline image address = 0x%08lx\n",
		      kernel_addr);
	}

	return kernel_addr;
}

709 710 711 712 713 714 715 716 717 718 719 720 721
/**
 * genimg_get_kernel_addr() is the simple version of
 * genimg_get_kernel_addr_fit(). It ignores those return FIT strings
 */
ulong genimg_get_kernel_addr(char * const img_addr)
{
	const char *fit_uname_config = NULL;
	const char *fit_uname_kernel = NULL;

	return genimg_get_kernel_addr_fit(img_addr, &fit_uname_config,
					  &fit_uname_kernel);
}

722
/**
723
 * genimg_get_format - get image format type
724 725
 * @img_addr: image start address
 *
726
 * genimg_get_format() checks whether provided address points to a valid
727 728
 * legacy or FIT image.
 *
729 730
 * New uImage format and FDT blob are based on a libfdt. FDT blob
 * may be passed directly or embedded in a FIT image. In both situations
731
 * genimg_get_format() must be able to dectect libfdt header.
732
 *
733 734 735
 * returns:
 *     image format type or IMAGE_FORMAT_INVALID if no image is present
 */
736
int genimg_get_format(const void *img_addr)
737
{
738
#if defined(CONFIG_IMAGE_FORMAT_LEGACY)
739
	const image_header_t *hdr;
740

741
	hdr = (const image_header_t *)img_addr;
742
	if (image_check_magic(hdr))
743 744
		return IMAGE_FORMAT_LEGACY;
#endif
745
#if defined(CONFIG_FIT) || defined(CONFIG_OF_LIBFDT)
746 747
	if (fdt_check_header(img_addr) == 0)
		return IMAGE_FORMAT_FIT;
748 749
#endif
#ifdef CONFIG_ANDROID_BOOT_IMAGE
750 751
	if (android_image_check_header(img_addr) == 0)
		return IMAGE_FORMAT_ANDROID;
752 753
#endif

754
	return IMAGE_FORMAT_INVALID;
755 756 757
}

/**
758
 * genimg_get_image - get image from special storage (if necessary)
759 760
 * @img_addr: image start address
 *
761
 * genimg_get_image() checks if provided image start address is located
762 763 764 765 766
 * in a dataflash storage. If so, image is moved to a system RAM memory.
 *
 * returns:
 *     image start address after possible relocation from special storage
 */
S
Stephen Warren 已提交
767
ulong genimg_get_image(ulong img_addr)
768
{
769
	ulong ram_addr = img_addr;
770 771

#ifdef CONFIG_HAS_DATAFLASH
772 773
	ulong h_size, d_size;

S
Stephen Warren 已提交
774
	if (addr_dataflash(img_addr)) {
775 776
		void *buf;

777
		/* ger RAM address */
778
		ram_addr = CONFIG_SYS_LOAD_ADDR;
779 780

		/* get header size */
S
Stephen Warren 已提交
781
		h_size = image_get_header_size();
782 783 784 785 786 787
#if defined(CONFIG_FIT)
		if (sizeof(struct fdt_header) > h_size)
			h_size = sizeof(struct fdt_header);
#endif

		/* read in header */
S
Stephen Warren 已提交
788
		debug("   Reading image header from dataflash address "
789 790
			"%08lx to RAM address %08lx\n", img_addr, ram_addr);

791 792
		buf = map_sysmem(ram_addr, 0);
		read_dataflash(img_addr, h_size, buf);
793

794
		/* get data size */
795
		switch (genimg_get_format(buf)) {
796
#if defined(CONFIG_IMAGE_FORMAT_LEGACY)
797
		case IMAGE_FORMAT_LEGACY:
798
			d_size = image_get_data_size(buf);
S
Stephen Warren 已提交
799 800
			debug("   Legacy format image found at 0x%08lx, "
					"size 0x%08lx\n",
801 802
					ram_addr, d_size);
			break;
803
#endif
804
#if defined(CONFIG_FIT)
805
		case IMAGE_FORMAT_FIT:
806
			d_size = fit_get_size(buf) - h_size;
S
Stephen Warren 已提交
807 808
			debug("   FIT/FDT format image found at 0x%08lx, "
					"size 0x%08lx\n",
809 810
					ram_addr, d_size);
			break;
811
#endif
812
		default:
S
Stephen Warren 已提交
813 814
			printf("   No valid image found at 0x%08lx\n",
				img_addr);
815 816
			return ram_addr;
		}
817

818
		/* read in image data */
S
Stephen Warren 已提交
819
		debug("   Reading image remaining data from dataflash address "
820 821 822
			"%08lx to RAM address %08lx\n", img_addr + h_size,
			ram_addr + h_size);

S
Stephen Warren 已提交
823
		read_dataflash(img_addr + h_size, d_size,
824
				(char *)(buf + h_size));
825

826
	}
827
#endif /* CONFIG_HAS_DATAFLASH */
828 829 830 831

	return ram_addr;
}

832 833 834 835 836 837 838 839 840 841 842
/**
 * fit_has_config - check if there is a valid FIT configuration
 * @images: pointer to the bootm command headers structure
 *
 * fit_has_config() checks if there is a FIT configuration in use
 * (if FTI support is present).
 *
 * returns:
 *     0, no FIT support or no configuration found
 *     1, configuration found
 */
S
Stephen Warren 已提交
843
int genimg_has_config(bootm_headers_t *images)
844 845 846 847 848 849 850 851
{
#if defined(CONFIG_FIT)
	if (images->fit_uname_cfg)
		return 1;
#endif
	return 0;
}

852
/**
853
 * boot_get_ramdisk - main ramdisk handling routine
854 855
 * @argc: command argument count
 * @argv: command argument list
856
 * @images: pointer to the bootm images structure
857 858 859 860
 * @arch: expected ramdisk architecture
 * @rd_start: pointer to a ulong variable, will hold ramdisk start address
 * @rd_end: pointer to a ulong variable, will hold ramdisk end
 *
861
 * boot_get_ramdisk() is responsible for finding a valid ramdisk image.
862 863 864 865 866
 * Curently supported are the following ramdisk sources:
 *      - multicomponent kernel/ramdisk image,
 *      - commandline provided address of decicated ramdisk image.
 *
 * returns:
867
 *     0, if ramdisk image was found and valid, or skiped
868 869
 *     rd_start and rd_end are set to ramdisk start/end addresses if
 *     ramdisk image is found and valid
870
 *
871
 *     1, if ramdisk image is found but corrupted, or invalid
872 873
 *     rd_start and rd_end are set to 0 if no ramdisk exists
 */
S
Stephen Warren 已提交
874
int boot_get_ramdisk(int argc, char * const argv[], bootm_headers_t *images,
875
		uint8_t arch, ulong *rd_start, ulong *rd_end)
876
{
877
	ulong rd_addr, rd_load;
878
	ulong rd_data, rd_len;
879
#if defined(CONFIG_IMAGE_FORMAT_LEGACY)
880
	const image_header_t *rd_hdr;
881
#endif
882
	void *buf;
883
#ifdef CONFIG_SUPPORT_RAW_INITRD
884
	char *end;
885
#endif
886
#if defined(CONFIG_FIT)
887
	const char	*fit_uname_config = images->fit_uname_cfg;
888 889
	const char	*fit_uname_ramdisk = NULL;
	ulong		default_addr;
890
	int		rd_noffset;
891
#endif
S
Simon Glass 已提交
892
	const char *select = NULL;
893

894 895 896
	*rd_start = 0;
	*rd_end = 0;

S
Simon Glass 已提交
897 898
	if (argc >= 2)
		select = argv[1];
899 900 901 902
	/*
	 * Look for a '-' which indicates to ignore the
	 * ramdisk argument
	 */
S
Simon Glass 已提交
903
	if (select && strcmp(select, "-") ==  0) {
S
Stephen Warren 已提交
904
		debug("## Skipping init Ramdisk\n");
905
		rd_len = rd_data = 0;
S
Simon Glass 已提交
906
	} else if (select || genimg_has_config(images)) {
907
#if defined(CONFIG_FIT)
S
Simon Glass 已提交
908
		if (select) {
909 910 911 912 913 914 915 916 917 918 919
			/*
			 * If the init ramdisk comes from the FIT image and
			 * the FIT image address is omitted in the command
			 * line argument, try to use os FIT image address or
			 * default load address.
			 */
			if (images->fit_uname_os)
				default_addr = (ulong)images->fit_hdr_os;
			else
				default_addr = load_addr;

S
Simon Glass 已提交
920 921
			if (fit_parse_conf(select, default_addr,
					   &rd_addr, &fit_uname_config)) {
S
Stephen Warren 已提交
922 923
				debug("*  ramdisk: config '%s' from image at "
						"0x%08lx\n",
924
						fit_uname_config, rd_addr);
S
Simon Glass 已提交
925
			} else if (fit_parse_subimage(select, default_addr,
926
						&rd_addr, &fit_uname_ramdisk)) {
S
Stephen Warren 已提交
927 928
				debug("*  ramdisk: subimage '%s' from image at "
						"0x%08lx\n",
929 930
						fit_uname_ramdisk, rd_addr);
			} else
931
#endif
932
			{
S
Simon Glass 已提交
933
				rd_addr = simple_strtoul(select, NULL, 16);
S
Stephen Warren 已提交
934 935
				debug("*  ramdisk: cmdline image address = "
						"0x%08lx\n",
936 937 938 939 940
						rd_addr);
			}
#if defined(CONFIG_FIT)
		} else {
			/* use FIT configuration provided in first bootm
941 942
			 * command argument. If the property is not defined,
			 * quit silently.
943
			 */
944
			rd_addr = map_to_sysmem(images->fit_hdr_os);
945 946 947
			rd_noffset = fit_get_node_from_config(images,
					FIT_RAMDISK_PROP, rd_addr);
			if (rd_noffset == -ENOLINK)
948
				return 0;
949 950
			else if (rd_noffset < 0)
				return 1;
951
		}
952
#endif
953 954

		/* copy from dataflash if needed */
S
Stephen Warren 已提交
955
		rd_addr = genimg_get_image(rd_addr);
956 957 958 959 960 961

		/*
		 * Check if there is an initrd image at the
		 * address provided in the second bootm argument
		 * check image type, for FIT images get FIT node.
		 */
962 963
		buf = map_sysmem(rd_addr, 0);
		switch (genimg_get_format(buf)) {
964
#if defined(CONFIG_IMAGE_FORMAT_LEGACY)
965
		case IMAGE_FORMAT_LEGACY:
S
Stephen Warren 已提交
966
			printf("## Loading init Ramdisk from Legacy "
967
					"Image at %08lx ...\n", rd_addr);
968

969
			bootstage_mark(BOOTSTAGE_ID_CHECK_RAMDISK);
S
Stephen Warren 已提交
970
			rd_hdr = image_get_ramdisk(rd_addr, arch,
971
							images->verify);
972

973
			if (rd_hdr == NULL)
974 975
				return 1;

S
Stephen Warren 已提交
976 977 978
			rd_data = image_get_data(rd_hdr);
			rd_len = image_get_data_size(rd_hdr);
			rd_load = image_get_load(rd_hdr);
979
			break;
980
#endif
981 982
#if defined(CONFIG_FIT)
		case IMAGE_FORMAT_FIT:
983
			rd_noffset = fit_image_load(images,
984
					rd_addr, &fit_uname_ramdisk,
985
					&fit_uname_config, arch,
986 987
					IH_TYPE_RAMDISK,
					BOOTSTAGE_ID_FIT_RD_START,
988 989
					FIT_LOAD_OPTIONAL_NON_ZERO,
					&rd_data, &rd_len);
990
			if (rd_noffset < 0)
991
				return 1;
992

993
			images->fit_hdr_rd = map_sysmem(rd_addr, 0);
994
			images->fit_uname_rd = fit_uname_ramdisk;
995
			images->fit_noffset_rd = rd_noffset;
996
			break;
997 998
#endif
		default:
999
#ifdef CONFIG_SUPPORT_RAW_INITRD
S
Simon Glass 已提交
1000 1001 1002 1003
			end = NULL;
			if (select)
				end = strchr(select, ':');
			if (end) {
1004 1005 1006 1007 1008 1009 1010 1011 1012
				rd_len = simple_strtoul(++end, NULL, 16);
				rd_data = rd_addr;
			} else
#endif
			{
				puts("Wrong Ramdisk Image Format\n");
				rd_data = rd_len = rd_load = 0;
				return 1;
			}
1013 1014
		}
	} else if (images->legacy_hdr_valid &&
S
Stephen Warren 已提交
1015 1016 1017
			image_check_type(&images->legacy_hdr_os_copy,
						IH_TYPE_MULTI)) {

1018
		/*
1019 1020
		 * Now check if we have a legacy mult-component image,
		 * get second entry data start address and len.
1021
		 */
1022
		bootstage_mark(BOOTSTAGE_ID_RAMDISK);
S
Stephen Warren 已提交
1023
		printf("## Loading init Ramdisk from multi component "
1024
				"Legacy Image at %08lx ...\n",
1025 1026
				(ulong)images->legacy_hdr_os);

S
Stephen Warren 已提交
1027
		image_multi_getimg(images->legacy_hdr_os, 1, &rd_data, &rd_len);
1028 1029
	}
#ifdef CONFIG_ANDROID_BOOT_IMAGE
1030 1031
	else if ((genimg_get_format((void *)images->os.start)
			== IMAGE_FORMAT_ANDROID) &&
1032 1033 1034 1035 1036 1037
		 (!android_image_get_ramdisk((void *)images->os.start,
		 &rd_data, &rd_len))) {
		/* empty */
	}
#endif
	else {
1038 1039 1040
		/*
		 * no initrd image
		 */
1041
		bootstage_mark(BOOTSTAGE_ID_NO_RAMDISK);
1042 1043 1044 1045
		rd_len = rd_data = 0;
	}

	if (!rd_data) {
S
Stephen Warren 已提交
1046
		debug("## No init Ramdisk\n");
1047 1048 1049 1050
	} else {
		*rd_start = rd_data;
		*rd_end = rd_data + rd_len;
	}
S
Stephen Warren 已提交
1051
	debug("   ramdisk start = 0x%08lx, ramdisk end = 0x%08lx\n",
1052
			*rd_start, *rd_end);
1053 1054

	return 0;
1055
}
1056

1057
#ifdef CONFIG_SYS_BOOT_RAMDISK_HIGH
1058
/**
1059
 * boot_ramdisk_high - relocate init ramdisk
1060
 * @lmb: pointer to lmb handle, will be used for memory mgmt
1061 1062 1063 1064 1065 1066 1067
 * @rd_data: ramdisk data start address
 * @rd_len: ramdisk data length
 * @initrd_start: pointer to a ulong variable, will hold final init ramdisk
 *      start address (after possible relocation)
 * @initrd_end: pointer to a ulong variable, will hold final init ramdisk
 *      end address (after possible relocation)
 *
1068
 * boot_ramdisk_high() takes a relocation hint from "initrd_high" environment
1069 1070
 * variable and if requested ramdisk data is moved to a specified location.
 *
1071 1072 1073 1074
 * Initrd_start and initrd_end are set to final (after relocation) ramdisk
 * start/end addresses if ramdisk image start and len were provided,
 * otherwise set initrd_start and initrd_end set to zeros.
 *
1075
 * returns:
1076 1077
 *      0 - success
 *     -1 - failure
1078
 */
S
Stephen Warren 已提交
1079
int boot_ramdisk_high(struct lmb *lmb, ulong rd_data, ulong rd_len,
1080
		  ulong *initrd_start, ulong *initrd_end)
1081 1082 1083 1084 1085
{
	char	*s;
	ulong	initrd_high;
	int	initrd_copy_to_ram = 1;

S
Stephen Warren 已提交
1086
	if ((s = getenv("initrd_high")) != NULL) {
1087 1088 1089
		/* a value of "no" or a similar string will act like 0,
		 * turning the "load high" feature off. This is intentional.
		 */
S
Stephen Warren 已提交
1090
		initrd_high = simple_strtoul(s, NULL, 16);
1091 1092 1093 1094 1095 1096 1097
		if (initrd_high == ~0)
			initrd_copy_to_ram = 0;
	} else {
		/* not set, no restrictions to load high */
		initrd_high = ~0;
	}

1098 1099 1100 1101 1102 1103

#ifdef CONFIG_LOGBUFFER
	/* Prevent initrd from overwriting logbuffer */
	lmb_reserve(lmb, logbuffer_base() - LOGBUFF_OVERHEAD, LOGBUFF_RESERVE);
#endif

S
Stephen Warren 已提交
1104
	debug("## initrd_high = 0x%08lx, copy_to_ram = %d\n",
1105 1106 1107 1108
			initrd_high, initrd_copy_to_ram);

	if (rd_data) {
		if (!initrd_copy_to_ram) {	/* zero-copy ramdisk support */
S
Stephen Warren 已提交
1109
			debug("   in-place initrd\n");
1110 1111
			*initrd_start = rd_data;
			*initrd_end = rd_data + rd_len;
1112
			lmb_reserve(lmb, rd_data, rd_len);
1113
		} else {
1114
			if (initrd_high)
S
Stephen Warren 已提交
1115 1116
				*initrd_start = (ulong)lmb_alloc_base(lmb,
						rd_len, 0x1000, initrd_high);
1117
			else
S
Stephen Warren 已提交
1118 1119
				*initrd_start = (ulong)lmb_alloc(lmb, rd_len,
								 0x1000);
1120 1121

			if (*initrd_start == 0) {
S
Stephen Warren 已提交
1122
				puts("ramdisk - allocation error\n");
1123
				goto error;
1124
			}
1125
			bootstage_mark(BOOTSTAGE_ID_COPY_RAMDISK);
1126 1127

			*initrd_end = *initrd_start + rd_len;
S
Stephen Warren 已提交
1128
			printf("   Loading Ramdisk to %08lx, end %08lx ... ",
1129 1130
					*initrd_start, *initrd_end);

S
Stephen Warren 已提交
1131
			memmove_wd((void *)*initrd_start,
1132 1133
					(void *)rd_data, rd_len, CHUNKSZ);

1134 1135 1136 1137 1138 1139 1140 1141
#ifdef CONFIG_MP
			/*
			 * Ensure the image is flushed to memory to handle
			 * AMP boot scenarios in which we might not be
			 * HW cache coherent
			 */
			flush_cache((unsigned long)*initrd_start, rd_len);
#endif
S
Stephen Warren 已提交
1142
			puts("OK\n");
1143 1144 1145 1146 1147
		}
	} else {
		*initrd_start = 0;
		*initrd_end = 0;
	}
S
Stephen Warren 已提交
1148
	debug("   ramdisk load start = 0x%08lx, ramdisk load end = 0x%08lx\n",
1149
			*initrd_start, *initrd_end);
1150

1151
	return 0;
1152

1153 1154
error:
	return -1;
1155
}
1156
#endif /* CONFIG_SYS_BOOT_RAMDISK_HIGH */
1157

1158 1159 1160 1161 1162 1163 1164 1165 1166 1167
int boot_get_setup(bootm_headers_t *images, uint8_t arch,
		   ulong *setup_start, ulong *setup_len)
{
#if defined(CONFIG_FIT)
	return boot_get_setup_fit(images, arch, setup_start, setup_len);
#else
	return -ENOENT;
#endif
}

1168
#ifdef CONFIG_SYS_BOOT_GET_CMDLINE
1169
/**
1170
 * boot_get_cmdline - allocate and initialize kernel cmdline
1171
 * @lmb: pointer to lmb handle, will be used for memory mgmt
1172 1173 1174
 * @cmd_start: pointer to a ulong variable, will hold cmdline start
 * @cmd_end: pointer to a ulong variable, will hold cmdline end
 *
1175
 * boot_get_cmdline() allocates space for kernel command line below
1176
 * BOOTMAPSZ + getenv_bootm_low() address. If "bootargs" U-boot environemnt
1177 1178 1179 1180
 * variable is present its contents is copied to allocated kernel
 * command line.
 *
 * returns:
1181 1182
 *      0 - success
 *     -1 - failure
1183
 */
S
Stephen Warren 已提交
1184
int boot_get_cmdline(struct lmb *lmb, ulong *cmd_start, ulong *cmd_end)
1185 1186 1187 1188
{
	char *cmdline;
	char *s;

1189
	cmdline = (char *)(ulong)lmb_alloc_base(lmb, CONFIG_SYS_BARGSIZE, 0xf,
1190
				getenv_bootm_mapsize() + getenv_bootm_low());
1191 1192 1193

	if (cmdline == NULL)
		return -1;
1194 1195 1196 1197 1198 1199 1200 1201 1202

	if ((s = getenv("bootargs")) == NULL)
		s = "";

	strcpy(cmdline, s);

	*cmd_start = (ulong) & cmdline[0];
	*cmd_end = *cmd_start + strlen(cmdline);

S
Stephen Warren 已提交
1203
	debug("## cmdline at 0x%08lx ... 0x%08lx\n", *cmd_start, *cmd_end);
1204

1205
	return 0;
1206
}
1207
#endif /* CONFIG_SYS_BOOT_GET_CMDLINE */
1208

1209
#ifdef CONFIG_SYS_BOOT_GET_KBD
1210
/**
1211
 * boot_get_kbd - allocate and initialize kernel copy of board info
1212
 * @lmb: pointer to lmb handle, will be used for memory mgmt
1213 1214
 * @kbd: double pointer to board info data
 *
1215
 * boot_get_kbd() allocates space for kernel copy of board info data below
1216 1217
 * BOOTMAPSZ + getenv_bootm_low() address and kernel board info is initialized
 * with the current u-boot board info data.
1218 1219
 *
 * returns:
1220 1221
 *      0 - success
 *     -1 - failure
1222
 */
S
Stephen Warren 已提交
1223
int boot_get_kbd(struct lmb *lmb, bd_t **kbd)
1224
{
1225
	*kbd = (bd_t *)(ulong)lmb_alloc_base(lmb, sizeof(bd_t), 0xf,
1226
				getenv_bootm_mapsize() + getenv_bootm_low());
1227 1228 1229
	if (*kbd == NULL)
		return -1;

1230 1231
	**kbd = *(gd->bd);

S
Stephen Warren 已提交
1232
	debug("## kernel board info at 0x%08lx\n", (ulong)*kbd);
1233 1234 1235 1236 1237

#if defined(DEBUG) && defined(CONFIG_CMD_BDI)
	do_bdinfo(NULL, 0, 0, NULL);
#endif

1238
	return 0;
1239
}
1240
#endif /* CONFIG_SYS_BOOT_GET_KBD */
1241 1242 1243 1244 1245 1246 1247 1248 1249 1250 1251 1252 1253 1254 1255 1256 1257 1258 1259 1260 1261 1262 1263 1264 1265 1266 1267 1268 1269 1270 1271 1272 1273 1274 1275 1276 1277 1278 1279 1280 1281 1282 1283 1284 1285 1286

#ifdef CONFIG_LMB
int image_setup_linux(bootm_headers_t *images)
{
	ulong of_size = images->ft_len;
	char **of_flat_tree = &images->ft_addr;
	ulong *initrd_start = &images->initrd_start;
	ulong *initrd_end = &images->initrd_end;
	struct lmb *lmb = &images->lmb;
	ulong rd_len;
	int ret;

	if (IMAGE_ENABLE_OF_LIBFDT)
		boot_fdt_add_mem_rsv_regions(lmb, *of_flat_tree);

	if (IMAGE_BOOT_GET_CMDLINE) {
		ret = boot_get_cmdline(lmb, &images->cmdline_start,
				&images->cmdline_end);
		if (ret) {
			puts("ERROR with allocation of cmdline\n");
			return ret;
		}
	}
	if (IMAGE_ENABLE_RAMDISK_HIGH) {
		rd_len = images->rd_end - images->rd_start;
		ret = boot_ramdisk_high(lmb, images->rd_start, rd_len,
				initrd_start, initrd_end);
		if (ret)
			return ret;
	}

	if (IMAGE_ENABLE_OF_LIBFDT) {
		ret = boot_relocate_fdt(lmb, of_flat_tree, &of_size);
		if (ret)
			return ret;
	}

	if (IMAGE_ENABLE_OF_LIBFDT && of_size) {
		ret = image_setup_libfdt(images, *of_flat_tree, of_size, lmb);
		if (ret)
			return ret;
	}

	return 0;
}
#endif /* CONFIG_LMB */
1287
#endif /* !USE_HOSTCC */