添加了牛皮藓,主要方便不知情的人联系我。有洁癖者自己去除代码,在
[ddnasgpl.git] / lib_arm / armlinux.c
blobebba12afb2074d9b752d29ff9709028f5f97e369
1 /*
2 * (C) Copyright 2002
3 * Sysgo Real-Time Solutions, GmbH <www.elinos.com>
4 * Marius Groeger <mgroeger@sysgo.de>
6 * Copyright (C) 2001 Erik Mouw (J.A.K.Mouw@its.tudelft.nl)
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.
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.
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
24 #include <common.h>
25 #include <command.h>
26 #include <image.h>
27 #include <zlib.h>
28 #include <asm/byteorder.h>
29 #ifdef CONFIG_HAS_DATAFLASH
30 #include <dataflash.h>
31 #endif
32 //Patch by QNAP:Fix detect LCM
33 extern unsigned long mvGppValueGet(unsigned int group, unsigned long mask);
34 ///////////////////////////////////////
35 /*cmd_boot.c*/
36 extern int do_reset (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]);
37 extern void mvEgigaStrToMac( char *source , char *dest );
39 #if defined (CONFIG_SETUP_MEMORY_TAGS) || \
40 defined (CONFIG_CMDLINE_TAG) || \
41 defined (CONFIG_INITRD_TAG) || \
42 defined (CONFIG_SERIAL_TAG) || \
43 defined (CONFIG_REVISION_TAG) || \
44 defined (CONFIG_VFD) || \
45 defined (CONFIG_LCD) || \
46 defined (CONFIG_MARVELL_TAG)
49 static void setup_start_tag (bd_t *bd);
51 # ifdef CONFIG_SETUP_MEMORY_TAGS
52 static void setup_memory_tags (bd_t *bd);
53 # endif
54 static void setup_commandline_tag (bd_t *bd, char *commandline);
56 #if 0
57 static void setup_ramdisk_tag (bd_t *bd);
58 #endif
59 # ifdef CONFIG_INITRD_TAG
60 static void setup_initrd_tag (bd_t *bd, ulong initrd_start,
61 ulong initrd_end);
62 # endif
63 static void setup_end_tag (bd_t *bd);
65 # if defined (CONFIG_VFD) || defined (CONFIG_LCD)
66 static void setup_videolfb_tag (gd_t *gd);
67 # endif
69 #if defined (CONFIG_MARVELL_TAG)
70 static void setup_marvell_tag(void);
71 #endif
73 #if defined(MV78200) && defined(DUAL_OS_SHARED_MEM_78200)
74 static struct tag *params[2];
75 #else
76 static struct tag *params[1];
77 #endif
78 #endif /* CONFIG_SETUP_MEMORY_TAGS || CONFIG_CMDLINE_TAG || CONFIG_INITRD_TAG */
80 #ifdef CONFIG_SHOW_BOOT_PROGRESS
81 # include <status_led.h>
82 # define SHOW_BOOT_PROGRESS(arg) show_boot_progress(arg)
83 #else
84 # define SHOW_BOOT_PROGRESS(arg)
85 #endif
87 #if defined(MV78200) && defined(DUAL_OS_SHARED_MEM_78200)
88 extern image_header_t header[2]; /* from cmd_bootm.c */
89 #else
90 extern image_header_t header[1]; /* from cmd_bootm.c */
91 #endif
92 //Patch by QNAP:Fix detect LCM
93 extern int model_name_number;
94 //////////////////////////////
95 void do_bootm_linux (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[],
96 ulong addr, ulong *len_ptr, int verify)
98 DECLARE_GLOBAL_DATA_PTR;
100 ulong len = 0, checksum;
101 ulong initrd_start, initrd_end;
102 ulong data;
103 void (*theKernel)(int zero, int arch, uint params);
104 image_header_t *hdr;
105 bd_t *bd = gd->bd;
106 unsigned int cpu = 0;
107 unsigned int cpuindex = 0;
109 #ifdef CONFIG_CMDLINE_TAG
110 char *commandline;
111 #ifdef CONFIG_MARVELL
112 #if defined(MV78200)
113 cpu = whoAmI();
114 if (cpu == 0)
115 #endif
116 commandline = getenv ("bootargs");
117 #if defined(MV78200)
118 else
119 commandline = getenv ("bootargs2");
120 #endif
121 #else
122 commandline = getenv ("bootargs");
123 #endif
124 //Patch by QNAP:Fix detect LCM
125 if(model_name_number <= 7){ // Model = TS419x
126 if(!mvGppValueGet(1,0x00002000)){
127 //LCM
128 char *ptr = strstr(commandline,"console");
129 if(ptr != NULL){
130 int i;
131 for(i=0;i< strlen(commandline);i++,ptr++){
132 if(*ptr != ' ' && *ptr != '\n' && *ptr != 0x0)
133 *ptr = ' ';
134 else break;
139 ////////////////////////////////////
140 #endif
141 #if defined(DUAL_OS_SHARED_MEM_78200)
142 cpuindex = cpu;
143 #endif
144 hdr = &header[cpuindex];
145 theKernel = (void (*)(int, int, uint))ntohl(hdr->ih_ep);
147 debug(" theKernel %x\n", theKernel);
150 * Check if there is an initrd image
152 if (argc >= 3) {
153 SHOW_BOOT_PROGRESS (9);
155 addr = simple_strtoul (argv[2], NULL, 16);
157 printf ("## Loading Ramdisk Image at %08lx ...\n", addr);
159 /* Copy header so we can blank CRC field for re-calculation */
160 #ifdef CONFIG_HAS_DATAFLASH
161 if (addr_dataflash (addr)) {
162 read_dataflash (addr, sizeof (image_header_t),
163 (char *) &header[cpuindex]);
164 } else
165 #endif
166 memcpy (&header[cpuindex], (char *) addr,
167 sizeof (image_header_t));
169 if (ntohl (hdr->ih_magic) != IH_MAGIC) {
170 printf ("Bad Magic Number\n");
171 SHOW_BOOT_PROGRESS (-10);
172 do_reset (cmdtp, flag, argc, argv);
175 data = (ulong) &header[cpuindex];
176 len = sizeof (image_header_t);
178 checksum = ntohl (hdr->ih_hcrc);
179 hdr->ih_hcrc = 0;
181 if (crc32 (0, (const char *) data, len) != checksum) {
182 printf ("Bad Header Checksum\n");
183 SHOW_BOOT_PROGRESS (-11);
184 do_reset (cmdtp, flag, argc, argv);
187 SHOW_BOOT_PROGRESS (10);
189 print_image_hdr (hdr);
191 data = addr + sizeof (image_header_t);
192 len = ntohl (hdr->ih_size);
194 #ifdef CONFIG_HAS_DATAFLASH
195 if (addr_dataflash (addr)) {
196 read_dataflash (data, len, (char *) CFG_LOAD_ADDR);
197 data = CFG_LOAD_ADDR;
199 #endif
201 if (verify) {
202 ulong csum = 0;
204 printf (" Verifying Checksum ... ");
205 csum = crc32 (0, (const char *) data, len);
206 if (csum != ntohl (hdr->ih_dcrc)) {
207 printf ("Bad Data CRC\n");
208 SHOW_BOOT_PROGRESS (-12);
209 do_reset (cmdtp, flag, argc, argv);
211 printf ("OK\n");
214 SHOW_BOOT_PROGRESS (11);
216 if ((hdr->ih_os != IH_OS_LINUX) ||
217 (hdr->ih_arch != IH_CPU_ARM) ||
218 (hdr->ih_type != IH_TYPE_RAMDISK)) {
219 printf ("No Linux ARM Ramdisk Image\n");
220 SHOW_BOOT_PROGRESS (-13);
221 do_reset (cmdtp, flag, argc, argv);
224 #if defined(CONFIG_B2) || defined(CONFIG_EVB4510) || defined(CONFIG_ARMADILLO)
226 *we need to copy the ramdisk to SRAM to let Linux boot
228 memmove ((void *) ntohl(hdr->ih_load), (uchar *)data, len);
229 data = ntohl(hdr->ih_load);
230 #endif /* CONFIG_B2 || CONFIG_EVB4510 */
233 * Now check if we have a multifile image
235 } else if ((hdr->ih_type == IH_TYPE_MULTI) && (len_ptr[1])) {
236 ulong tail = ntohl (len_ptr[0]) % 4;
237 int i;
239 SHOW_BOOT_PROGRESS (13);
241 /* skip kernel length and terminator */
242 data = (ulong) (&len_ptr[2]);
243 /* skip any additional image length fields */
244 for (i = 1; len_ptr[i]; ++i)
245 data += 4;
246 /* add kernel length, and align */
247 data += ntohl (len_ptr[0]);
248 if (tail) {
249 data += 4 - tail;
252 len = ntohl (len_ptr[1]);
254 } else {
256 * no initrd image
258 SHOW_BOOT_PROGRESS (14);
260 len = data = 0;
263 #ifdef DEBUG
264 if (!data) {
265 printf ("No initrd\n");
267 #endif
269 if (data) {
270 initrd_start = data;
271 initrd_end = initrd_start + len;
272 } else {
273 initrd_start = 0;
274 initrd_end = 0;
277 SHOW_BOOT_PROGRESS (15);
279 debug ("## Transferring control to Linux (at address %08lx) ...\n",
280 (ulong) theKernel);
282 #if defined(MV78200) && defined(DUAL_OS_SHARED_MEM_78200)
283 /*Calculate boot params offset*/
284 bd->bi_boot_params = ntohl(hdr->ih_ep)-0x8000+0x100;
285 #endif
287 #if defined (CONFIG_SETUP_MEMORY_TAGS) || \
288 defined (CONFIG_CMDLINE_TAG) || \
289 defined (CONFIG_INITRD_TAG) || \
290 defined (CONFIG_SERIAL_TAG) || \
291 defined (CONFIG_REVISION_TAG) || \
292 defined (CONFIG_LCD) || \
293 defined (CONFIG_VFD) || \
294 defined (CONFIG_MARVELL_TAG)
295 setup_start_tag (bd);
296 #ifdef CONFIG_SERIAL_TAG
297 setup_serial_tag (&params[cpuindex]);
298 #endif
299 #ifdef CONFIG_REVISION_TAG
300 setup_revision_tag (&params[cpuindex]);
301 #endif
302 #ifdef CONFIG_SETUP_MEMORY_TAGS
303 setup_memory_tags (bd);
304 #endif
305 #ifdef CONFIG_CMDLINE_TAG
306 setup_commandline_tag (bd, commandline);
307 #endif
308 #ifdef CONFIG_INITRD_TAG
309 if (initrd_start && initrd_end)
310 setup_initrd_tag (bd, initrd_start, initrd_end);
311 #endif
312 #if defined (CONFIG_VFD) || defined (CONFIG_LCD)
313 setup_videolfb_tag ((gd_t *) gd);
314 #endif
315 #if defined (CONFIG_MARVELL_TAG)
316 /* Linux open port doesn't support the Marvell TAG */
317 char *env = getenv("mainlineLinux");
318 if(!env || ((strcmp(env,"no") == 0) || (strcmp(env,"No") == 0)))
319 setup_marvell_tag ();
320 #endif
321 setup_end_tag (bd);
322 #endif
324 /* we assume that the kernel is in place */
325 printf ("\nStarting kernel ...\n\n");
327 #ifdef CONFIG_USB_DEVICE
329 extern void udc_disconnect (void);
330 udc_disconnect ();
332 #endif
334 cleanup_before_linux ();
335 #if defined(CONFIG_MARVELL) && defined(DUAL_OS_SHARED_MEM_78200)
336 mvSemaUnlock(1);
337 #endif
338 theKernel (0, bd->bi_arch_number, bd->bi_boot_params);
342 #if defined (CONFIG_SETUP_MEMORY_TAGS) || \
343 defined (CONFIG_CMDLINE_TAG) || \
344 defined (CONFIG_INITRD_TAG) || \
345 defined (CONFIG_SERIAL_TAG) || \
346 defined (CONFIG_REVISION_TAG) || \
347 defined (CONFIG_LCD) || \
348 defined (CONFIG_VFD) || \
349 defined (CONFIG_MARVELL_TAG)
350 static void setup_start_tag (bd_t *bd)
352 unsigned int cpu = 0;
353 #if defined(MV78200) && defined(DUAL_OS_SHARED_MEM_78200)
354 cpu = whoAmI();
355 #endif
356 params[cpu] = (struct tag *) bd->bi_boot_params;
357 params[cpu]->hdr.tag = ATAG_CORE;
358 params[cpu]->hdr.size = tag_size (tag_core);
360 params[cpu]->u.core.flags = 0;
361 params[cpu]->u.core.pagesize = 0;
362 params[cpu]->u.core.rootdev = 0;
364 params[cpu] = tag_next (params[cpu]);
368 #ifdef CONFIG_SETUP_MEMORY_TAGS
369 static void setup_memory_tags (bd_t *bd)
371 int i;
372 unsigned int cpu = 0;
373 #if defined(MV78200) && defined(DUAL_OS_SHARED_MEM_78200)
374 cpu = whoAmI();
375 #endif
377 for (i = 0; i < CONFIG_NR_DRAM_BANKS; i++) {
378 params[cpu]->hdr.tag = ATAG_MEM;
379 params[cpu]->hdr.size = tag_size (tag_mem32);
381 params[cpu]->u.mem.start = bd->bi_dram[i].start;
382 params[cpu]->u.mem.size = bd->bi_dram[i].size;
384 params[cpu] = tag_next (params[cpu]);
387 #endif /* CONFIG_SETUP_MEMORY_TAGS */
390 static void setup_commandline_tag (bd_t *bd, char *commandline)
392 char *p;
393 unsigned int cpu = 0;
394 #if defined(MV78200) && defined(DUAL_OS_SHARED_MEM_78200)
395 cpu = whoAmI();
396 #endif
398 if (!commandline)
399 return;
401 /* eat leading white space */
402 for (p = commandline; *p == ' '; p++);
404 /* skip non-existent command lines so the kernel will still
405 * use its default command line.
407 if (*p == '\0')
408 return;
410 params[cpu]->hdr.tag = ATAG_CMDLINE;
411 params[cpu]->hdr.size =
412 (sizeof (struct tag_header) + strlen (p) + 1 + 4) >> 2;
414 strcpy (params[cpu]->u.cmdline.cmdline, p);
415 params[cpu] = tag_next (params[cpu]);
419 #ifdef CONFIG_INITRD_TAG
420 static void setup_initrd_tag (bd_t *bd, ulong initrd_start, ulong initrd_end)
422 unsigned int cpu = 0;
423 #if defined(MV78200) && defined(DUAL_OS_SHARED_MEM_78200)
424 cpu = whoAmI();
425 #endif
427 /* an ATAG_INITRD node tells the kernel where the compressed
428 * ramdisk can be found. ATAG_RDIMG is a better name, actually.
430 params[cpu]->hdr.tag = ATAG_INITRD2;
431 params[cpu]->hdr.size = tag_size (tag_initrd);
433 params[cpu]->u.initrd.start = initrd_start;
434 params[cpu]->u.initrd.size = initrd_end - initrd_start;
436 params[cpu] = tag_next (params[cpu]);
438 #endif /* CONFIG_INITRD_TAG */
441 #if defined (CONFIG_VFD) || defined (CONFIG_LCD)
442 extern ulong calc_fbsize (void);
443 static void setup_videolfb_tag (gd_t *gd)
445 unsigned int cpu = 0;
446 #if defined(MV78200) && defined(DUAL_OS_SHARED_MEM_78200)
447 cpu = whoAmI();
448 #endif
450 /* An ATAG_VIDEOLFB node tells the kernel where and how large
451 * the framebuffer for video was allocated (among other things).
452 * Note that a _physical_ address is passed !
454 * We only use it to pass the address and size, the other entries
455 * in the tag_videolfb are not of interest.
457 params[cpu]->hdr.tag = ATAG_VIDEOLFB;
458 params[cpu]->hdr.size = tag_size (tag_videolfb);
460 params[cpu]->u.videolfb.lfb_base = (u32) gd->fb_base;
461 /* Fb size is calculated according to parameters for our panel
463 params[cpu]->u.videolfb.lfb_size = calc_fbsize();
465 params[cpu] = tag_next (params[cpu]);
467 #endif /* CONFIG_VFD || CONFIG_LCD */
469 #if defined(CONFIG_MARVELL_TAG)
470 static void setup_marvell_tag (void)
472 char *env;
473 char temp[20];
474 int i;
475 unsigned int boardId;
476 unsigned int cpu = 0;
477 #if defined(MV78200) && defined(DUAL_OS_SHARED_MEM_78200)
478 cpu = whoAmI();
479 #endif
481 params[cpu]->hdr.tag = ATAG_MARVELL;
482 params[cpu]->hdr.size = tag_size (tag_mv_uboot);
484 params[cpu]->u.mv_uboot.uboot_version = VER_NUM;
485 if(strcmp(getenv("nandEcc"), "4bit") == 0)
487 params[cpu]->u.mv_uboot.nand_ecc = 4;
489 else if(strcmp(getenv("nandEcc"), "1bit") == 0)
491 params[cpu]->u.mv_uboot.nand_ecc = 1;
494 extern unsigned int mvBoardIdGet(void);
496 boardId = mvBoardIdGet();
497 params[cpu]->u.mv_uboot.uboot_version |= boardId;
499 params[cpu]->u.mv_uboot.tclk = CFG_TCLK;
500 params[cpu]->u.mv_uboot.sysclk = CFG_BUS_CLK;
502 #if defined(MV78XX0)
503 /* Dual CPU Firmware load address */
504 env = getenv("fw_image_base");
505 if(env)
506 params[cpu]->u.mv_uboot.fw_image_base = simple_strtoul(env, NULL, 16);
507 else
508 params[cpu]->u.mv_uboot.fw_image_base = 0;
510 /* Dual CPU Firmware size */
511 env = getenv("fw_image_size");
512 if(env)
513 params[cpu]->u.mv_uboot.fw_image_size = simple_strtoul(env, NULL, 16);
514 else
515 params[cpu]->u.mv_uboot.fw_image_size = 0;
516 #endif
518 #if defined(MV_INCLUDE_USB)
519 extern unsigned int mvCtrlUsbMaxGet(void);
521 for (i = 0 ; i < mvCtrlUsbMaxGet(); i++)
523 sprintf( temp, "usb%dMode", i);
524 env = getenv(temp);
525 if((!env) || (strcmp(env,"Host") == 0 ) || (strcmp(env,"host") == 0) )
526 params[cpu]->u.mv_uboot.isUsbHost |= (1 << i);
527 else
528 params[cpu]->u.mv_uboot.isUsbHost &= ~(1 << i);
531 #endif /*#if defined(MV_INCLUDE_USB)*/
532 #if defined(MV_INCLUDE_GIG_ETH) || defined(MV_INCLUDE_UNM_ETH)
533 extern unsigned int mvCtrlEthMaxPortGet(void);
534 extern int mvMacStrToHex(const char* macStr, unsigned char* macHex);
536 for (i = 0 ;i < 4;i++)
538 memset(params[cpu]->u.mv_uboot.macAddr[i], 0, sizeof(params[cpu]->u.mv_uboot.macAddr[i]));
539 params[cpu]->u.mv_uboot.mtu[i] = 0;
542 for (i = 0 ;i < mvCtrlEthMaxPortGet();i++)
544 /* only on RD-6281-A egiga0 defined as eth1 */
545 #if defined (RD_88F6281A)
546 sprintf( temp,(i==0 ? "eth1addr" : "ethaddr"));
547 #else
548 sprintf( temp,(i ? "eth%daddr" : "ethaddr"), i);
549 #endif
551 env = getenv(temp);
552 if (env)
553 mvMacStrToHex(env, params[cpu]->u.mv_uboot.macAddr[i]);
555 /* only on RD-6281-A egiga0 defined as eth1 */
556 #if defined (RD_88F6281A)
557 sprintf( temp,(i==0 ? "eth1mtu" : "ethmtu"));
558 #else
559 sprintf( temp,(i ? "eth%dmtu" : "ethmtu"), i);
560 #endif
562 env = getenv(temp);
563 if (env)
564 params[cpu]->u.mv_uboot.mtu[i] = simple_strtoul(env, NULL, 10);
566 #endif /* (MV_INCLUDE_GIG_ETH) || defined(MV_INCLUDE_UNM_ETH) */
568 params[cpu] = tag_next (params[cpu]);
570 #endif
572 #ifdef CONFIG_SERIAL_TAG
573 void setup_serial_tag (struct tag **tmp)
575 struct tag *params = *tmp;
576 struct tag_serialnr serialnr;
577 void get_board_serial(struct tag_serialnr *serialnr);
578 unsigned int cpu = 0;
579 #if defined(MV78200) && defined(DUAL_OS_SHARED_MEM_78200)
580 cpu = whoAmI();
581 #endif
583 get_board_serial(&serialnr);
584 params[cpu]->hdr.tag = ATAG_SERIAL;
585 params[cpu]->hdr.size = tag_size (tag_serialnr);
586 params[cpu]->u.serialnr.low = serialnr.low;
587 params[cpu]->u.serialnr.high= serialnr.high;
588 params[cpu] = tag_next (params[cpu]);
589 *tmp = params;
591 #endif
593 #ifdef CONFIG_REVISION_TAG
594 void setup_revision_tag(struct tag **in_params)
596 u32 rev = 0;
597 u32 get_board_rev(void);
598 unsigned int cpu = 0;
599 #if defined(MV78200) && defined(DUAL_OS_SHARED_MEM_78200)
600 cpu = whoAmI();
601 #endif
603 rev = get_board_rev();
604 params[cpu]->hdr.tag = ATAG_REVISION;
605 params[cpu]->hdr.size = tag_size (tag_revision);
606 params[cpu]->u.revision.rev = rev;
607 params[cpu] = tag_next (params[cpu]);
609 #endif /* CONFIG_REVISION_TAG */
612 static void setup_end_tag (bd_t *bd)
614 unsigned int cpu = 0;
615 #if defined(MV78200) && defined(DUAL_OS_SHARED_MEM_78200)
616 cpu = whoAmI();
617 #endif
619 params[cpu]->hdr.tag = ATAG_NONE;
620 params[cpu]->hdr.size = 0;
623 #endif /* CONFIG_SETUP_MEMORY_TAGS || CONFIG_CMDLINE_TAG || CONFIG_INITRD_TAG */