diff options
| author | Mike Frysinger <vapier@gentoo.org> | 2010-12-26 12:34:49 -0500 | 
|---|---|---|
| committer | Mike Frysinger <vapier@gentoo.org> | 2011-04-08 00:44:27 -0400 | 
| commit | 1ba7fd25679fcccc3fc152df31825359a30585b2 (patch) | |
| tree | 968db1fc99f6392dfed2e71bbc48ff6eec9040e6 /common/cmd_ldrinfo.c | |
| parent | 31488a6f6edbec09d01329e2486578836a1cc008 (diff) | |
| download | olio-uboot-2014.01-1ba7fd25679fcccc3fc152df31825359a30585b2.tar.xz olio-uboot-2014.01-1ba7fd25679fcccc3fc152df31825359a30585b2.zip | |
Blackfin: ldrinfo: new command
Simple command to decode/check an LDR image before we try to boot it.
Signed-off-by: Mike Frysinger <vapier@gentoo.org>
Diffstat (limited to 'common/cmd_ldrinfo.c')
| -rw-r--r-- | common/cmd_ldrinfo.c | 192 | 
1 files changed, 192 insertions, 0 deletions
| diff --git a/common/cmd_ldrinfo.c b/common/cmd_ldrinfo.c new file mode 100644 index 000000000..2aa56bdb6 --- /dev/null +++ b/common/cmd_ldrinfo.c @@ -0,0 +1,192 @@ +/* + * U-boot - ldrinfo + * + * Copyright (c) 2010 Analog Devices Inc. + * + * See file CREDITS for list of people who contributed to this + * project. + * + * Licensed under the GPL-2 or later. + */ + +#include <config.h> +#include <common.h> +#include <command.h> + +#include <asm/blackfin.h> +#include <asm/mach-common/bits/bootrom.h> + +static uint32_t ldrinfo_header(const void *addr) +{ +	uint32_t skip = 0; + +#if defined(__ADSPBF561__) +	/* BF56x has a 4 byte global header */ +	uint32_t header, sign; +	static const char * const spi_speed[] = { +		"500K", "1M", "2M", "??", +	}; + +	memcpy(&header, addr, sizeof(header)); + +	sign = (header & GFLAG_56X_SIGN_MASK) >> GFLAG_56X_SIGN_SHIFT; +	printf("Header: %08X ( %s-bit-flash wait:%i hold:%i spi:%s %s)\n", +		header, +		(header & GFLAG_56X_16BIT_FLASH) ? "16" : "8", +		(header & GFLAG_56X_WAIT_MASK) >> GFLAG_56X_WAIT_SHIFT, +		(header & GFLAG_56X_HOLD_MASK) >> GFLAG_56X_HOLD_SHIFT, +		spi_speed[(header & GFLAG_56X_SPI_MASK) >> GFLAG_56X_SPI_SHIFT], +		sign == GFLAG_56X_SIGN_MAGIC ? "" : "!!hdrsign!! "); + +	skip = 4; +#endif + +	    /* |Block @ 12345678: 12345678 12345678 12345678 12345678 | */ +#if defined(__ADSPBF531__) || defined(__ADSPBF532__) || defined(__ADSPBF533__) || \ +    defined(__ADSPBF534__) || defined(__ADSPBF536__) || defined(__ADSPBF537__) || \ +    defined(__ADSPBF538__) || defined(__ADSPBF539__) || defined(__ADSPBF561__) +	printf("                  Address  Count    Flags\n"); +#else +	printf("                  BCode    Address  Count    Argument\n"); +#endif + +	return skip; +} + +struct ldr_flag { +	uint16_t flag; +	const char *desc; +}; + +static uint32_t ldrinfo_block(const void *base_addr) +{ +	uint32_t count; + +	printf("Block @ %08X: ", (uint32_t)base_addr); + +#if defined(__ADSPBF531__) || defined(__ADSPBF532__) || defined(__ADSPBF533__) || \ +    defined(__ADSPBF534__) || defined(__ADSPBF536__) || defined(__ADSPBF537__) || \ +    defined(__ADSPBF538__) || defined(__ADSPBF539__) || defined(__ADSPBF561__) + +	uint32_t addr, pval; +	uint16_t flags; +	int i; +	static const struct ldr_flag ldr_flags[] = { +		{ BFLAG_53X_ZEROFILL,    "zerofill"  }, +		{ BFLAG_53X_RESVECT,     "resvect"   }, +		{ BFLAG_53X_INIT,        "init"      }, +		{ BFLAG_53X_IGNORE,      "ignore"    }, +		{ BFLAG_53X_COMPRESSED,  "compressed"}, +		{ BFLAG_53X_FINAL,       "final"     }, +	}; + +	memcpy(&addr, base_addr, sizeof(addr)); +	memcpy(&count, base_addr+4, sizeof(count)); +	memcpy(&flags, base_addr+8, sizeof(flags)); + +	printf("%08X %08X %04X ( ", addr, count, flags); + +	for (i = 0; i < ARRAY_SIZE(ldr_flags); ++i) +		if (flags & ldr_flags[i].flag) +			printf("%s ", ldr_flags[i].desc); + +	pval = (flags & BFLAG_53X_PFLAG_MASK) >> BFLAG_53X_PFLAG_SHIFT; +	if (pval) +		printf("gpio%i ", pval); +	pval = (flags & BFLAG_53X_PPORT_MASK) >> BFLAG_53X_PPORT_SHIFT; +	if (pval) +		printf("port%c ", 'e' + pval); + +	if (flags & BFLAG_53X_ZEROFILL) +		count = 0; +	if (flags & BFLAG_53X_FINAL) +		count = 0; +	else +		count += sizeof(addr) + sizeof(count) + sizeof(flags); + +#else + +	const uint8_t *raw8 = base_addr; +	uint32_t bcode, addr, arg, sign, chk; +	int i; +	static const struct ldr_flag ldr_flags[] = { +		{ BFLAG_SAFE,        "safe"      }, +		{ BFLAG_AUX,         "aux"       }, +		{ BFLAG_FILL,        "fill"      }, +		{ BFLAG_QUICKBOOT,   "quickboot" }, +		{ BFLAG_CALLBACK,    "callback"  }, +		{ BFLAG_INIT,        "init"      }, +		{ BFLAG_IGNORE,      "ignore"    }, +		{ BFLAG_INDIRECT,    "indirect"  }, +		{ BFLAG_FIRST,       "first"     }, +		{ BFLAG_FINAL,       "final"     }, +	}; + +	memcpy(&bcode, base_addr, sizeof(bcode)); +	memcpy(&addr, base_addr+4, sizeof(addr)); +	memcpy(&count, base_addr+8, sizeof(count)); +	memcpy(&arg, base_addr+12, sizeof(arg)); + +	printf("%08X %08X %08X %08X ( ", bcode, addr, count, arg); + +	if (addr % 4) +		printf("!!addralgn!! "); +	if (count % 4) +		printf("!!cntalgn!! "); + +	sign = (bcode & BFLAG_HDRSIGN_MASK) >> BFLAG_HDRSIGN_SHIFT; +	if (sign != BFLAG_HDRSIGN_MAGIC) +		printf("!!hdrsign!! "); + +	chk = 0; +	for (i = 0; i < 16; ++i) +		chk ^= raw8[i]; +	if (chk) +		printf("!!hdrchk!! "); + +	printf("dma:%i ", bcode & BFLAG_DMACODE_MASK); + +	for (i = 0; i < ARRAY_SIZE(ldr_flags); ++i) +		if (bcode & ldr_flags[i].flag) +			printf("%s ", ldr_flags[i].desc); + +	if (bcode & BFLAG_FILL) +		count = 0; +	if (bcode & BFLAG_FINAL) +		count = 0; +	else +		count += sizeof(bcode) + sizeof(addr) + sizeof(count) + sizeof(arg); + +#endif + +	printf(")\n"); + +	return count; +} + +static int do_ldrinfo(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) +{ +	const void *addr; +	uint32_t skip; + +	/* Get the address */ +	if (argc < 2) +		addr = (void *)load_addr; +	else +		addr = (void *)simple_strtoul(argv[1], NULL, 16); + +	/* Walk the LDR */ +	addr += ldrinfo_header(addr); +	do { +		skip = ldrinfo_block(addr); +		addr += skip; +	} while (skip); + +	return 0; +} + +U_BOOT_CMD( +	ldrinfo, 2, 0, do_ldrinfo, +	"validate ldr image in memory", +	"[addr]\n" +); |