X-Git-Url: https://git.sur5r.net/?a=blobdiff_plain;f=common%2Fcmd_bootldr.c;h=bc5c1f95eaff9cdf783347e8ded104d16035bb29;hb=67cd4a63487400317f1586b130bc2475767a5315;hp=e6474aab22bfae66844a05fdda9e2865b9e124f7;hpb=4b7a6dd89633d60dc4b58476d5ce48247f82a3ca;p=u-boot diff --git a/common/cmd_bootldr.c b/common/cmd_bootldr.c index e6474aab22..bc5c1f95ea 100644 --- a/common/cmd_bootldr.c +++ b/common/cmd_bootldr.c @@ -16,6 +16,120 @@ #include #include +/* Simple sanity check on the specified address to make sure it contains + * an LDR image of some sort. + */ +static bool ldr_valid_signature(uint8_t *data) +{ +#if defined(__ADSPBF561__) + + /* BF56x has a 4 byte global header */ + if (data[3] == (GFLAG_56X_SIGN_MAGIC << (GFLAG_56X_SIGN_SHIFT - 24))) + return true; + +#elif defined(__ADSPBF531__) || defined(__ADSPBF532__) || defined(__ADSPBF533__) || \ + defined(__ADSPBF534__) || defined(__ADSPBF536__) || defined(__ADSPBF537__) || \ + defined(__ADSPBF538__) || defined(__ADSPBF539__) + + /* all the BF53x should start at this address mask */ + uint32_t addr; + memmove(&addr, data, sizeof(addr)); + if ((addr & 0xFF0FFF0F) == 0xFF000000) + return true; +#else + + /* everything newer has a magic byte */ + uint32_t count; + memmove(&count, data + 8, sizeof(count)); + if (data[3] == 0xAD && count == 0) + return true; + +#endif + + return false; +} + +/* If the Blackfin is new enough, the Blackfin on-chip ROM supports loading + * LDRs from random memory addresses. So whenever possible, use that. In + * the older cases (BF53x/BF561), parse the LDR format ourselves. + */ +static void ldr_load(uint8_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; + uint32_t count; + uint16_t flags; + + /* the bf56x has a 4 byte global header ... but it is useless to + * us when booting an LDR from a memory address, so skip it + */ +# ifdef __ADSPBF561__ + base_addr += 4; +# endif + + memmove(&flags, base_addr + 8, sizeof(flags)); + bfin_write_EVT1(flags & BFLAG_53X_RESVECT ? 0xFFA00000 : 0xFFA08000); + + do { + /* block header may not be aligned */ + memmove(&addr, base_addr, sizeof(addr)); + memmove(&count, base_addr+4, sizeof(count)); + memmove(&flags, base_addr+8, sizeof(flags)); + base_addr += sizeof(addr) + sizeof(count) + sizeof(flags); + + printf("loading to 0x%08x (%#x bytes) flags: 0x%04x\n", + addr, count, flags); + + if (!(flags & BFLAG_53X_IGNORE)) { + if (flags & BFLAG_53X_ZEROFILL) + memset((void *)addr, 0x00, count); + else + memcpy((void *)addr, base_addr, count); + + if (flags & BFLAG_53X_INIT) { + void (*init)(void) = (void *)addr; + init(); + } + } + + if (!(flags & BFLAG_53X_ZEROFILL)) + base_addr += count; + } while (!(flags & BFLAG_53X_FINAL)); + +#endif +} + +/* For BF537, we use the _BOOTROM_BOOT_DXE_FLASH funky ROM function. + * For all other BF53x/BF56x, we just call the entry point. + * For everything else (newer), we use _BOOTROM_MEMBOOT ROM function. + */ +static void ldr_exec(void *addr) +{ +#if defined(__ADSPBF534__) || defined(__ADSPBF536__) || defined(__ADSPBF537__) + + /* restore EVT1 to reset value as this is what the bootrom uses as + * the default entry point when booting the final block of LDRs + */ + bfin_write_EVT1(L1_INST_SRAM); + __asm__("call (%0);" : : "a"(_BOOTROM_MEMBOOT), "q7"(addr) : "RETS", "memory"); + +#elif defined(__ADSPBF531__) || defined(__ADSPBF532__) || defined(__ADSPBF533__) || \ + defined(__ADSPBF538__) || defined(__ADSPBF539__) || defined(__ADSPBF561__) + + void (*ldr_entry)(void) = (void *)bfin_read_EVT1(); + ldr_entry(); + +#else + + int32_t (*BOOTROM_MEM)(void *, int32_t, int32_t, void *) = (void *)_BOOTROM_MEMBOOT; + BOOTROM_MEM(addr, 0, 0, NULL); + +#endif +} + /* * the bootldr command loads an address, checks to see if there * is a Boot stream that the on-chip BOOTROM can understand, @@ -23,11 +137,9 @@ * to also add booting from SPI, or TWI, but this function does * not currently support that. */ - -int do_bootldr(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) +int do_bootldr(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) { void *addr; - uint32_t *data; /* Get the address */ if (argc < 2) @@ -36,29 +148,23 @@ int do_bootldr(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) addr = (void *)simple_strtoul(argv[1], NULL, 16); /* Check if it is a LDR file */ - data = addr; -#if defined(__ADSPBF54x__) || defined(__ADSPBF52x__) - if ((*data & 0xFF000000) == 0xAD000000 && data[2] == 0x00000000) { -#else - if (*data == 0xFF800060 || *data == 0xFF800040 || *data == 0xFF800020) { -#endif - /* We want to boot from FLASH or SDRAM */ + if (ldr_valid_signature(addr)) { printf("## Booting ldr image at 0x%p ...\n", addr); + ldr_load(addr); icache_disable(); dcache_disable(); - __asm__( - "jump (%1);" - : - : "q7" (addr), "a" (_BOOTROM_MEMBOOT)); + ldr_exec(addr); } else printf("## No ldr image at address 0x%p\n", addr); return 0; } -U_BOOT_CMD(bootldr, 2, 0, do_bootldr, - "bootldr - boot ldr image from memory\n", +U_BOOT_CMD( + bootldr, 2, 0, do_bootldr, + "boot ldr image from memory", "[addr]\n" - " - boot ldr image stored in memory\n"); + "" +);