ab1797c3881e0fb4b326928671dccb54daa2121a
[oweals/u-boot_mod.git] / u-boot / lib_bootstrap / bootstrap_board.c
1 /*
2  * (C) Copyright 2003
3  * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
4  *
5  * See file CREDITS for list of people who contributed to this
6  * project.
7  *
8  * This program is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU General Public License as
10  * published by the Free Software Foundation; either version 2 of
11  * the License, or (at your option) any later version.
12  *
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License
19  * along with this program; if not, write to the Free Software
20  * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
21  * MA 02111-1307 USA
22  */
23
24 #include <common.h>
25 #include <command.h>
26 #include <malloc.h>
27 #include <devices.h>
28 #include <version.h>
29 #include <net.h>
30 #include <environment.h>
31 #include <tinf.h>
32 #include "LzmaWrapper.h"
33
34 /*#define DEBUG_ENABLE_BOOTSTRAP_PRINTF*/
35
36 DECLARE_GLOBAL_DATA_PTR;
37
38 #if (((CFG_ENV_ADDR+CFG_ENV_SIZE) < BOOTSTRAP_CFG_MONITOR_BASE) || \
39          (CFG_ENV_ADDR >= (BOOTSTRAP_CFG_MONITOR_BASE + CFG_MONITOR_LEN))) \
40          || defined(CFG_ENV_IS_IN_NVRAM)
41         #define TOTAL_MALLOC_LEN        (CFG_MALLOC_LEN + CFG_ENV_SIZE)
42 #else
43         #define TOTAL_MALLOC_LEN        CFG_MALLOC_LEN
44 #endif
45
46 #undef DEBUG
47
48 extern void bootstrap_relocate_code(ulong addr_sp, gd_t *gd, ulong addr_moni);
49
50 extern int timer_init(void);
51
52 extern ulong uboot_end_data_bootstrap;
53 extern ulong uboot_end_bootstrap;
54
55 /*
56  * Begin and End of memory area for malloc(), and current "brk"
57  */
58 static ulong mem_malloc_start;
59 static ulong mem_malloc_end;
60 static ulong mem_malloc_brk;
61
62 /*
63  * The Malloc area is immediately below the monitor copy in DRAM
64  */
65 static void mem_malloc_init(ulong dest_addr)
66 {
67         /* ulong dest_addr = BOOTSTRAP_CFG_MONITOR_BASE + gd->reloc_off; */
68         mem_malloc_end = dest_addr;
69         mem_malloc_start = dest_addr - TOTAL_MALLOC_LEN;
70         mem_malloc_brk = mem_malloc_start;
71
72         memset((void *)mem_malloc_start, 0, mem_malloc_end - mem_malloc_start);
73 }
74
75 void *malloc(unsigned int size)
76 {
77         if (size < (mem_malloc_end - mem_malloc_start)) {
78                 mem_malloc_start += size;
79                 return (void *)(mem_malloc_start - size);
80         }
81
82         return NULL;
83 }
84
85 void *realloc(void *src, unsigned int size)
86 {
87         return NULL;
88 }
89
90 void free(void *src)
91 {
92         return;
93 }
94
95 static int init_func_ram(void)
96 {
97         if ((gd->ram_size = dram_init()) > 0)
98                 return 0;
99
100         return 1;
101 }
102
103 /*
104  * Breath some life into the board...
105  *
106  * The first part of initialization is running from Flash memory;
107  * its main purpose is to initialize the RAM so that we
108  * can relocate the monitor code to RAM.
109  */
110
111 /*
112  * All attempts to come up with a "common" initialization sequence
113  * that works for all boards and architectures failed: some of the
114  * requirements are just _too_ different. To get rid of the resulting
115  * mess of board dependend #ifdef'ed code we now make the whole
116  * initialization sequence configurable to the user.
117  *
118  * The requirements for any new initalization function is simple: it
119  * receives a pointer to the "global data" structure as it's only
120  * argument, and returns an integer return code, where 0 means
121  * "continue" and != 0 means "fatal error, hang the system".
122  */
123 typedef int(init_fnc_t)(void);
124
125 init_fnc_t *init_sequence[] = { init_func_ram,
126                                                                 NULL, };
127
128 void bootstrap_board_init_f(ulong bootflag)
129 {
130         gd_t gd_data, *id;
131         bd_t *bd;
132         init_fnc_t **init_fnc_ptr;
133         ulong addr, addr_sp, len = (ulong)&uboot_end_bootstrap - BOOTSTRAP_CFG_MONITOR_BASE;
134         ulong *s;
135
136         /* Pointer is writable since we allocated a register for it */
137         gd = &gd_data;
138
139         /* Compiler optimization barrier needed for GCC >= 3.4 */
140         __asm__ __volatile__("": : :"memory");
141
142         memset((void *)gd, 0, sizeof(gd_t));
143
144         for (init_fnc_ptr = init_sequence; *init_fnc_ptr; ++init_fnc_ptr) {
145                 if ((*init_fnc_ptr)() != 0)
146                         hang();
147         }
148
149         /*
150          * Now that we have DRAM mapped and working, we can
151          * relocate the code and continue running from DRAM
152          */
153         addr = CFG_SDRAM_BASE + gd->ram_size;
154
155         /*
156          * We can reserve some RAM "on top" here,
157          * round down to next 4 kB limit
158          */
159         addr &= ~(4096 - 1);
160
161         /*
162          * Reserve memory for U-Boot code, data & bss,
163          * round down to next 16 kB limit
164          */
165         addr -= len;
166         addr &= ~(16 * 1024 - 1);
167
168         /* Reserve memory for malloc() arena */
169         addr_sp = addr - TOTAL_MALLOC_LEN;
170
171         /*
172          * (permanently) allocate a Board Info struct
173          * and a permanent copy of the "global" data
174          */
175         addr_sp -= sizeof(bd_t);
176         bd = (bd_t *)addr_sp;
177         gd->bd = bd;
178
179         addr_sp -= sizeof(gd_t);
180         id = (gd_t *)addr_sp;
181
182         /* Reserve memory for boot params */
183         addr_sp -= CFG_BOOTPARAMS_LEN;
184         bd->bi_boot_params = addr_sp;
185
186         /*
187          * Finally, we set up a new (bigger) stack
188          *
189          * Leave some safety gap for SP, force alignment on 16 byte boundary,
190          * clear initial stack frame
191          */
192         addr_sp -= 16;
193         addr_sp &= ~0xF;
194         s = (ulong *)addr_sp;
195         *s-- = 0;
196         *s-- = 0;
197         addr_sp = (ulong)s;
198
199         /*
200          * Save local variables to board info struct:
201          * - start of DRAM memory
202          * - size  of DRAM memory in bytes
203          */
204         bd->bi_memstart = CFG_SDRAM_BASE;
205         bd->bi_memsize  = gd->ram_size;
206
207         memcpy(id, (void *)gd, sizeof(gd_t));
208
209         bootstrap_relocate_code(addr_sp, id, addr);
210         /* NOTREACHED - relocate_code() does not return */
211 }
212
213 /************************************************************************
214  *
215  * This is the next part if the initialization sequence: we are now
216  * running from RAM and have a "normal" C environment, i. e. global
217  * data can be written, BSS has been cleared, the stack size in not
218  * that critical any more, etc.
219  *
220  ************************************************************************
221  */
222 void bootstrap_board_init_r(gd_t *id, ulong dest_addr)
223 {
224         int i;
225         ulong addr;
226         ulong data, len, checksum;
227         image_header_t header;
228         image_header_t *hdr = &header;
229         unsigned int destLen;
230         int (*fn)(int);
231
232         /* Initialize malloc() area */
233         mem_malloc_init(dest_addr);
234
235         addr = (ulong)((char *)(BOOTSTRAP_CFG_MONITOR_BASE + ((ulong)&uboot_end_data_bootstrap - dest_addr)));
236         memmove(&header, (char *)addr, sizeof(image_header_t));
237
238         if (ntohl(hdr->ih_magic) != IH_MAGIC)
239                 return;
240
241         data = (ulong)&header;
242         len = sizeof(image_header_t);
243
244         checksum = ntohl(hdr->ih_hcrc);
245         hdr->ih_hcrc = 0;
246
247         if (tinf_crc32((unsigned char *)data, len) != checksum)
248                 return;
249
250         data = addr + sizeof(image_header_t);
251         len = ntohl(hdr->ih_size);
252
253         /*
254          * If we've got less than 4 MB of malloc() space,
255          * use slower decompression algorithm which requires
256          * at most 2300 KB of memory.
257          */
258         destLen = 0x0;
259
260 #ifdef CONFIG_LZMA
261         i = lzma_inflate((unsigned char *)data, len, (unsigned char*)ntohl(hdr->ih_load), (int *)&destLen);
262
263         if (i != LZMA_RESULT_OK)
264                 return;
265 #endif
266
267         fn = (void *)ntohl(hdr->ih_load);
268
269         (*fn)(gd->ram_size);
270
271         hang();
272 }
273
274 void hang(void)
275 {
276         for (;;)
277                 ;
278 }