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