Blame view

common/cmd_bootldr.c 4.48 KB
86a20fb92   Mike Frysinger   Blackfin: move bo...
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
  /*
   * 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>
29d4ea0a9   Mike Frysinger   Blackfin: bootldr...
18
19
20
21
22
23
24
25
  /* 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 */
31488a6f6   Mike Frysinger   Blackfin: bootldr...
26
  	if (data[3] == (GFLAG_56X_SIGN_MAGIC << (GFLAG_56X_SIGN_SHIFT - 24)))
29d4ea0a9   Mike Frysinger   Blackfin: bootldr...
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
  		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.
   */
29d4ea0a9   Mike Frysinger   Blackfin: bootldr...
55
56
57
58
59
  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__)
29d4ea0a9   Mike Frysinger   Blackfin: bootldr...
60
61
62
63
64
65
66
67
68
69
70
71
  	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));
31488a6f6   Mike Frysinger   Blackfin: bootldr...
72
  	bfin_write_EVT1(flags & BFLAG_53X_RESVECT ? 0xFFA00000 : 0xFFA08000);
29d4ea0a9   Mike Frysinger   Blackfin: bootldr...
73
74
75
76
77
78
79
  
  	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);
31488a6f6   Mike Frysinger   Blackfin: bootldr...
80
81
  		printf("loading to 0x%08x (%#x bytes) flags: 0x%04x
  ",
29d4ea0a9   Mike Frysinger   Blackfin: bootldr...
82
  			addr, count, flags);
31488a6f6   Mike Frysinger   Blackfin: bootldr...
83
84
  		if (!(flags & BFLAG_53X_IGNORE)) {
  			if (flags & BFLAG_53X_ZEROFILL)
29d4ea0a9   Mike Frysinger   Blackfin: bootldr...
85
86
87
  				memset((void *)addr, 0x00, count);
  			else
  				memcpy((void *)addr, base_addr, count);
31488a6f6   Mike Frysinger   Blackfin: bootldr...
88
  			if (flags & BFLAG_53X_INIT) {
29d4ea0a9   Mike Frysinger   Blackfin: bootldr...
89
90
91
92
  				void (*init)(void) = (void *)addr;
  				init();
  			}
  		}
31488a6f6   Mike Frysinger   Blackfin: bootldr...
93
  		if (!(flags & BFLAG_53X_ZEROFILL))
29d4ea0a9   Mike Frysinger   Blackfin: bootldr...
94
  			base_addr += count;
31488a6f6   Mike Frysinger   Blackfin: bootldr...
95
  	} while (!(flags & BFLAG_53X_FINAL));
29d4ea0a9   Mike Frysinger   Blackfin: bootldr...
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
  
  #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__)
fe033ad6d   Mike Frysinger   Blackfin: fixup m...
116
  	void (*ldr_entry)(void) = (void *)bfin_read_EVT1();
29d4ea0a9   Mike Frysinger   Blackfin: bootldr...
117
118
119
120
121
122
123
124
125
  	ldr_entry();
  
  #else
  
  	int32_t (*BOOTROM_MEM)(void *, int32_t, int32_t, void *) = (void *)_BOOTROM_MEMBOOT;
  	BOOTROM_MEM(addr, 0, 0, NULL);
  
  #endif
  }
86a20fb92   Mike Frysinger   Blackfin: move bo...
126
127
128
129
130
131
132
  /*
   * 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.
   */
54841ab50   Wolfgang Denk   Make sure that ar...
133
  int do_bootldr(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
86a20fb92   Mike Frysinger   Blackfin: move bo...
134
135
  {
  	void *addr;
86a20fb92   Mike Frysinger   Blackfin: move bo...
136
137
138
139
140
141
142
143
  
  	/* 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 */
29d4ea0a9   Mike Frysinger   Blackfin: bootldr...
144
  	if (ldr_valid_signature(addr)) {
86a20fb92   Mike Frysinger   Blackfin: move bo...
145
146
  		printf("## Booting ldr image at 0x%p ...
  ", addr);
29d4ea0a9   Mike Frysinger   Blackfin: bootldr...
147
  		ldr_load(addr);
86a20fb92   Mike Frysinger   Blackfin: move bo...
148
149
150
  
  		icache_disable();
  		dcache_disable();
29d4ea0a9   Mike Frysinger   Blackfin: bootldr...
151
  		ldr_exec(addr);
86a20fb92   Mike Frysinger   Blackfin: move bo...
152
153
154
155
156
157
  	} else
  		printf("## No ldr image at address 0x%p
  ", addr);
  
  	return 0;
  }
388a29d02   Frans Meulenbroeks   various cmd_* fil...
158
159
  U_BOOT_CMD(
  	bootldr, 2, 0, do_bootldr,
2fb2604d5   Peter Tyser   Command usage cle...
160
  	"boot ldr image from memory",
86a20fb92   Mike Frysinger   Blackfin: move bo...
161
162
  	"[addr]
  "
a89c33db9   Wolfgang Denk   General help mess...
163
164
  	""
  );