summaryrefslogtreecommitdiff
path: root/common/cmd_ldrinfo.c
diff options
context:
space:
mode:
authorMike Frysinger <vapier@gentoo.org>2010-12-26 12:34:49 -0500
committerMike Frysinger <vapier@gentoo.org>2011-04-08 00:44:27 -0400
commit1ba7fd25679fcccc3fc152df31825359a30585b2 (patch)
tree968db1fc99f6392dfed2e71bbc48ff6eec9040e6 /common/cmd_ldrinfo.c
parent31488a6f6edbec09d01329e2486578836a1cc008 (diff)
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.c192
1 files changed, 192 insertions, 0 deletions
diff --git a/common/cmd_ldrinfo.c b/common/cmd_ldrinfo.c
new file mode 100644
index 0000000000..2aa56bdb62
--- /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"
+);