diff options
author | Simon Glass <sjg@chromium.org> | 2016-01-17 20:53:51 -0700 |
---|---|---|
committer | Tom Rini <trini@konsulko.com> | 2016-01-25 10:39:43 -0500 |
commit | 72a8cf8dccf6f8b86d1683205e032a94eaa86938 (patch) | |
tree | b29378eb8af182f0faf2028cb52465a021de40cc /cmd/cmd_bootldr.c | |
parent | 25d5352c71dcc599030a4a764d8087185ed537d3 (diff) | |
download | u-boot-72a8cf8dccf6f8b86d1683205e032a94eaa86938.tar.gz |
Move all command code into its own directory
There are a lot of unrelated files in common, including all of the commands.
Moving them into their own directory makes them easier to find and is more
logical.
Some commands include non-command code, such as cmd_scsi.c. This should be
sorted out at some point so that the function can be enabled with or without
the associated command.
Unfortunately, with m68k I get this error:
m68k: + M5329AFEE
+arch/m68k/cpu/mcf532x/start.o: In function `_start':
+arch/m68k/cpu/mcf532x/start.S:159:(.text+0x452): relocation truncated to fit: R_68K_PC16 against symbol `board_init_f' defined in .text.board_init_f section in common/built-in.o
I hope someone can shed some light on what this means. I hope it isn't
depending on the position of code in the image.
Signed-off-by: Simon Glass <sjg@chromium.org>
Reviewed-by: Bin Meng <bmeng.cn@gmail.com>
Reviewed-by: Heiko Schocher <hs@denx.de>
Acked-by: Stefan Roese <sr@denx.de>
Acked-by: Przemyslaw Marczak <p.marczak@samsung.com>
Diffstat (limited to 'cmd/cmd_bootldr.c')
-rw-r--r-- | cmd/cmd_bootldr.c | 170 |
1 files changed, 170 insertions, 0 deletions
diff --git a/cmd/cmd_bootldr.c b/cmd/cmd_bootldr.c new file mode 100644 index 0000000000..bc5c1f95ea --- /dev/null +++ b/cmd/cmd_bootldr.c @@ -0,0 +1,170 @@ +/* + * U-boot - bootldr.c + * + * Copyright (c) 2005-2008 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> + +/* 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, + * and loads it via the BOOTROM Callback. It is possible + * 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 * const argv[]) +{ + void *addr; + + /* Get the address */ + if (argc < 2) + addr = (void *)load_addr; + else + addr = (void *)simple_strtoul(argv[1], NULL, 16); + + /* Check if it is a LDR file */ + if (ldr_valid_signature(addr)) { + printf("## Booting ldr image at 0x%p ...\n", addr); + ldr_load(addr); + + icache_disable(); + dcache_disable(); + + ldr_exec(addr); + } else + printf("## No ldr image at address 0x%p\n", addr); + + return 0; +} + +U_BOOT_CMD( + bootldr, 2, 0, do_bootldr, + "boot ldr image from memory", + "[addr]\n" + "" +); |