blob: 54ecbb16c1ff7eddbf250b342558baef8467a96a [file] [log] [blame]
yuezonghe824eb0c2024-06-27 02:32:26 -07001/*
2 * (C) Copyright 2002
3 * Sysgo Real-Time Solutions, GmbH <www.elinos.com>
4 * Marius Groeger <mgroeger@sysgo.de>
5 *
6 * Copyright (C) 2001 Erik Mouw (J.A.K.Mouw@its.tudelft.nl)
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (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, MA 02111-1307 USA
21 *
22 */
23
24#include <common.h>
25#include <command.h>
26#include <image.h>
27#include <u-boot/zlib.h>
28#include <asm/byteorder.h>
29#include <fdt.h>
30#include <libfdt.h>
31#include <fdt_support.h>
32#include <bootimg.h>
33#include <load_image.h>
34#include <asm/arch/cpu.h>
35#include <asm/io.h>
36
37
38DECLARE_GLOBAL_DATA_PTR;
39
40#if defined (CONFIG_SETUP_MEMORY_TAGS) || \
41 defined (CONFIG_CMDLINE_TAG) || \
42 defined (CONFIG_INITRD_TAG) || \
43 defined (CONFIG_SERIAL_TAG) || \
44 defined (CONFIG_REVISION_TAG)
45static void setup_start_tag (bd_t *bd);
46
47# ifdef CONFIG_SETUP_MEMORY_TAGS
48static void setup_memory_tags (bd_t *bd);
49# endif
50static void setup_commandline_tag (bd_t *bd, char *commandline);
51
52# ifdef CONFIG_INITRD_TAG
53static void setup_initrd_tag (bd_t *bd, ulong initrd_start,
54 ulong initrd_end);
55# endif
56static void setup_end_tag (bd_t *bd);
57
58static struct tag *params;
59#endif /* CONFIG_SETUP_MEMORY_TAGS || CONFIG_CMDLINE_TAG || CONFIG_INITRD_TAG */
60
61static ulong get_sp(void);
62#if defined(CONFIG_OF_LIBFDT)
63static int bootm_linux_fdt(int machid, bootm_headers_t *images);
64#endif
65extern int rd_offset ;
66extern int rd_size;
67extern unsigned int g_sys_kernel_sdram_size;
68
69
70void arch_lmb_reserve(struct lmb *lmb)
71{
72 ulong sp;
73
74 /*
75 * Booting a (Linux) kernel image
76 *
77 * Allocate space for command line and board info - the
78 * address should be as high as possible within the reach of
79 * the kernel (see CONFIG_SYS_BOOTMAPSZ settings), but in unused
80 * memory, which means far enough below the current stack
81 * pointer.
82 */
83 sp = get_sp();
84 debug("## Current stack ends at 0x%08lx ", sp);
85
86 /* adjust sp by 1K to be safe */
87 sp -= 1024;
88 lmb_reserve(lmb, sp,
89 gd->bd->bi_dram[0].start + gd->bd->bi_dram[0].size - sp);
90}
91
92static void announce_and_cleanup(void)
93{
94 printf("\nStarting kernel ...\n");
95
96#ifdef CONFIG_USB_DEVICE
97 {
98 extern void udc_disconnect(void);
99 udc_disconnect();
100 }
101#endif
102 cleanup_before_linux();
103}
104
105#ifdef CONFIG_ZX297520V3E_WATCH_CAP
106#define SYS_CPUCAP_PARAM_ADDR 0x10200C
107extern uint32_t arm_cpucap_ep;
108void set_cpucap_tag(int arch, uint parameter)
109{
110 uint32_t cap_tag_addr = 0;
111
112 cap_tag_addr = arm_cpucap_ep - 0x8000 + 0x100;
113
114 writel(0x0, SYS_CPUCAP_PARAM_ADDR);
115 writel(arch, SYS_CPUCAP_PARAM_ADDR+0x4);
116 writel(cap_tag_addr, SYS_CPUCAP_PARAM_ADDR+0x8);
117
118 memcpy(cap_tag_addr, parameter, 0x800);
119}
120#endif
121
122int do_bootm_linux(int flag, int argc, char *argv[], bootm_headers_t *images)
123{
124 bd_t *bd = gd->bd;
125 char *s;
126 int machid = bd->bi_arch_number;
127 void (*kernel_entry)(int zero, int arch, uint params);
128
129
130#ifdef CONFIG_CMDLINE_TAG
131 char *commandline = getenv ("bootargs");
132#endif
133
134 if ((flag != 0) && (flag != BOOTM_STATE_OS_GO))
135 {
136 return 1;
137 }
138
139
140 s = getenv ("machid");
141 if (s)
142 {
143 machid = simple_strtoul (s, NULL, 16);
144 printf ("Using machid 0x%x from environment\n", machid);
145 }
146
147 show_boot_progress (15);
148
149#ifdef CONFIG_OF_LIBFDT
150 if (images->ft_len)
151 {
152 return bootm_linux_fdt(machid, images);
153 }
154#endif
155
156 kernel_entry = (void (*)(int, int, uint))images->ep;
157
158 debug ("## Transferring control to Linux (at address %08lx) ...\n",
159 (ulong) kernel_entry);
160
161#if defined (CONFIG_SETUP_MEMORY_TAGS) || \
162 defined (CONFIG_CMDLINE_TAG) || \
163 defined (CONFIG_INITRD_TAG) || \
164 defined (CONFIG_SERIAL_TAG) || \
165 defined (CONFIG_REVISION_TAG)
166 setup_start_tag (bd);
167#ifdef CONFIG_SERIAL_TAG
168 setup_serial_tag (&params);
169#endif
170#ifdef CONFIG_REVISION_TAG
171 setup_revision_tag (&params);
172#endif
173#ifdef CONFIG_SETUP_MEMORY_TAGS
174 setup_memory_tags (bd);
175#endif
176#ifdef CONFIG_CMDLINE_TAG
177 setup_commandline_tag (bd, commandline);
178#endif
179#ifdef CONFIG_INITRD_TAG
180 if (images->rd_start && images->rd_end)
181 setup_initrd_tag (bd, images->rd_start, images->rd_end);
182#endif
183 setup_end_tag(bd);
184#endif
185
186#ifdef CONFIG_ZX297520V3E_WATCH_CAP
187 if(!read_fota_update_flag())
188 {
189 cap_poweron();
190 set_cpucap_tag(machid, bd->bi_boot_params);
191 start_cpucap_cores();
192 }
193#endif
194 printf("===chiid=0x%x,boot_params=0x%x\n", machid, bd->bi_boot_params);
195 announce_and_cleanup();
196 kernel_entry(0, machid, bd->bi_boot_params);
197
198 /* does not return */
199 return 1;
200}
201
202//add by zhouqi
203int do_booti_linux( boot_img_hdr *hdr )
204{
205 bd_t *bd = gd->bd;
206 char *s;
207 int machid = bd->bi_arch_number;
208 void (*kernel_entry)(int zero, int arch, uint params);
209
210#ifdef CONFIG_CMDLINE_TAG
211 char *commandline = getenv ("bootargs");
212#endif
213
214 s = getenv ("machid");
215 if (s) {
216 machid = simple_strtoul (s, NULL, 16);
217 printf ("Using machid 0x%x from environment\n", machid);
218 }
219
220 show_boot_progress (15);
221
222#ifdef CONFIG_OF_LIBFDT
223 if (images->ft_len)
224 return bootm_linux_fdt(machid, images);
225#endif
226
227 kernel_entry = (void (*)(int, int, uint))hdr->kernel_addr;
228
229 debug ("## Transferring control to Linux (at address %08lx) ...\n",
230 (ulong) kernel_entry);
231
232#if defined (CONFIG_SETUP_MEMORY_TAGS) || \
233 defined (CONFIG_CMDLINE_TAG) || \
234 defined (CONFIG_INITRD_TAG) || \
235 defined (CONFIG_SERIAL_TAG) || \
236 defined (CONFIG_REVISION_TAG)
237 setup_start_tag (bd);
238#ifdef CONFIG_SERIAL_TAG
239 setup_serial_tag (&params);
240#endif
241#ifdef CONFIG_REVISION_TAG
242 setup_revision_tag (&params);
243#endif
244#ifdef CONFIG_SETUP_MEMORY_TAGS
245 setup_memory_tags (bd);
246#endif
247#ifdef CONFIG_CMDLINE_TAG
248 setup_commandline_tag (bd, commandline);
249#endif
250#ifdef CONFIG_INITRD_TAG
251 if (hdr->ramdisk_size)
252 setup_initrd_tag (bd, hdr->ramdisk_addr, hdr->ramdisk_size + hdr->ramdisk_addr);
253#endif
254 setup_end_tag(bd);
255#endif
256
257 announce_and_cleanup();
258
259 kernel_entry(0, machid, bd->bi_boot_params);
260 /* does not return */
261
262 return 1;
263}
264
265
266#if defined(CONFIG_OF_LIBFDT)
267static int fixup_memory_node(void *blob)
268{
269 bd_t *bd = gd->bd;
270 int bank;
271 u64 start[CONFIG_NR_DRAM_BANKS];
272 u64 size[CONFIG_NR_DRAM_BANKS];
273
274 for (bank = 0; bank < CONFIG_NR_DRAM_BANKS; bank++) {
275 start[bank] = bd->bi_dram[bank].start;
276 size[bank] = bd->bi_dram[bank].size;
277 }
278
279 return fdt_fixup_memory_banks(blob, start, size, CONFIG_NR_DRAM_BANKS);
280}
281
282static int bootm_linux_fdt(int machid, bootm_headers_t *images)
283{
284 ulong rd_len;
285 void (*kernel_entry)(int zero, int dt_machid, void *dtblob);
286 ulong of_size = images->ft_len;
287 char **of_flat_tree = &images->ft_addr;
288 ulong *initrd_start = &images->initrd_start;
289 ulong *initrd_end = &images->initrd_end;
290 struct lmb *lmb = &images->lmb;
291 int ret;
292
293 kernel_entry = (void (*)(int, int, void *))images->ep;
294
295 boot_fdt_add_mem_rsv_regions(lmb, *of_flat_tree);
296
297 rd_len = images->rd_end - images->rd_start;
298 ret = boot_ramdisk_high(lmb, images->rd_start, rd_len,
299 initrd_start, initrd_end);
300 if (ret)
301 return ret;
302
303 ret = boot_relocate_fdt(lmb, of_flat_tree, &of_size);
304 if (ret)
305 return ret;
306
307 debug("## Transferring control to Linux (at address %08lx) ...\n",
308 (ulong) kernel_entry);
309
310 fdt_chosen(*of_flat_tree, 1);
311
312 fixup_memory_node(*of_flat_tree);
313
314 fdt_initrd(*of_flat_tree, *initrd_start, *initrd_end, 1);
315
316 announce_and_cleanup();
317
318 kernel_entry(0, machid, *of_flat_tree);
319 /* does not return */
320
321 return 1;
322}
323#endif
324
325#if defined (CONFIG_SETUP_MEMORY_TAGS) || \
326 defined (CONFIG_CMDLINE_TAG) || \
327 defined (CONFIG_INITRD_TAG) || \
328 defined (CONFIG_SERIAL_TAG) || \
329 defined (CONFIG_REVISION_TAG)
330static void setup_start_tag (bd_t *bd)
331{
332 params = (struct tag *) bd->bi_boot_params;
333
334 params->hdr.tag = ATAG_CORE;
335 params->hdr.size = tag_size (tag_core);
336
337 params->u.core.flags = 0x1;//0;
338 params->u.core.pagesize =0x1000; //0;
339 params->u.core.rootdev = 0x0;//0;
340
341 params = tag_next (params);
342}
343
344
345#ifdef CONFIG_SETUP_MEMORY_TAGS
346static void setup_memory_tags (bd_t *bd)
347{
348 int i;
349
350 for (i = 0; i < CONFIG_NR_DRAM_BANKS; i++)
351 {
352 params->hdr.tag = ATAG_MEM;
353 params->hdr.size = tag_size (tag_mem32);
354
355 /* modify by zhouqi 2013/06/27 */
356 params->u.mem.start = read_sys_ddr_kernel_start();
357 params->u.mem.size = g_sys_kernel_sdram_size; //CONFIG_SYS_SDRAM_A9_SIZE;
358
359 params = tag_next (params);
360 }
361}
362#endif /* CONFIG_SETUP_MEMORY_TAGS */
363
364
365static void setup_commandline_tag (bd_t *bd, char *commandline)
366{
367 char *p;
368
369 if (!commandline)
370 return;
371
372 /* eat leading white space */
373 for (p = commandline; *p == ' '; p++);
374
375 /* skip non-existent command lines so the kernel will still
376 * use its default command line.
377 */
378 if (*p == '\0')
379 return;
380
381 params->hdr.tag = ATAG_CMDLINE;
382 params->hdr.size =
383 (sizeof (struct tag_header) + strlen (p) + 1 + 4) >> 2;
384
385 strcpy (params->u.cmdline.cmdline, p);
386
387 params = tag_next (params);
388}
389
390
391#ifdef CONFIG_INITRD_TAG
392static void setup_initrd_tag (bd_t *bd, ulong initrd_start, ulong initrd_end)
393{
394 /* an ATAG_INITRD node tells the kernel where the compressed
395 * ramdisk can be found. ATAG_RDIMG is a better name, actually.
396 */
397 params->hdr.tag = ATAG_INITRD2;
398 params->hdr.size = tag_size (tag_initrd);
399
400 params->u.initrd.start = rd_offset;//initrd_start;
401 params->u.initrd.size =rd_size;//initrd_end - initrd_start;
402
403
404 params = tag_next (params);
405}
406#endif /* CONFIG_INITRD_TAG */
407
408#ifdef CONFIG_SERIAL_TAG
409void setup_serial_tag (struct tag **tmp)
410{
411 struct tag *params = *tmp;
412 struct tag_serialnr serialnr;
413 void get_board_serial(struct tag_serialnr *serialnr);
414
415 get_board_serial(&serialnr);
416 params->hdr.tag = ATAG_SERIAL;
417 params->hdr.size = tag_size (tag_serialnr);
418 params->u.serialnr.low = serialnr.low;
419 params->u.serialnr.high= serialnr.high;
420 params = tag_next (params);
421 *tmp = params;
422}
423#endif
424
425#ifdef CONFIG_REVISION_TAG
426void setup_revision_tag(struct tag **in_params)
427{
428 u32 rev = 0;
429 u32 get_board_rev(void);
430
431 rev = get_board_rev();
432 params->hdr.tag = ATAG_REVISION;
433 params->hdr.size = tag_size (tag_revision);
434 params->u.revision.rev = rev;
435 params = tag_next (params);
436}
437#endif /* CONFIG_REVISION_TAG */
438
439static void setup_end_tag (bd_t *bd)
440{
441 params->hdr.tag = ATAG_NONE;
442 params->hdr.size = 0;
443}
444#endif /* CONFIG_SETUP_MEMORY_TAGS || CONFIG_CMDLINE_TAG || CONFIG_INITRD_TAG */
445
446static ulong get_sp(void)
447{
448 ulong ret;
449
450 asm("mov %0, sp" : "=r"(ret) : );
451 return ret;
452}