/* * 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" );