blob: 49d6141a58fb1e1ae6afa79ed7346b8881f390e7 [file] [log] [blame]
lh9ed821d2023-04-07 01:36:19 -07001/*
2 * (C) Copyright 2011
3 * Yuesheng Wang, ZIXC Corporation, WangYueSheng@zte.com.cn.
4 *
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU General Public License as
7 * published by the Free Software Foundation; either version 2 of
8 * the License, or (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
18 * MA 02111-1307 USA
19 */
20
21
22/*
23 * Multi Image extract
24 */
25#include <config.h>
26#include <common.h>
27#include <command.h>
28#include <net.h>
29#include <linux/mtd/mtd.h>
30#include <config.h>
31#include <watchdog.h>
32#include <environment.h>
33#include <version.h>
34#include <search.h>
35#include <asm/byteorder.h>
36#include <cmd_downver.h>
37
38#define SZ_16M 0x1000000
39
40#include <nand.h>
41
42DECLARE_GLOBAL_DATA_PTR;
43
44extern enum net_loop_state net_state;
45extern ulong NetBootFileXferSize;
46
47#define CONFIG_SYS_BOOT_LEN 0x40000 //Ô¤Áôboot´óС256K
48#define CFG_FLASH_SECTOR_SIZE 0x20000
49#define CFG_FLASH_BASE 0
50
51/* locals & globals */
52search_desc g_search;
53
54#define hex2int(c) ((c>='0') && (c<='9') ? (c-'0') : ((c&0xf)+9))
55
56/* Table of CRC32 constants */
57static unsigned int crc32_tbl[256];
58
59int do_downver (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
60{
61 int i = 0, region = 1;
62 char arg[256] = {0};
63 hd_magic_desc *magic = NULL;
64 header_version *header = NULL;
65
66 if (argc < 2 || argc > CONFIG_SYS_MAXARGS)
67 {
68 printf ("Usage:\n%s\n", cmdtp->usage);
69 return 1;
70 }
71
72 for (i = 1; i < argc; i++)
73 {
74 /* Download & upgrade intergrated version */
75 if (! strcmp(argv[i], "allbins"))
76 {
77 //sprintf(arg, "tftp %lx $(bootfile)", (ulong)CONFIG_SYS_LOAD_ADDR);
78 sprintf(arg, "tftp %lx $(bootfile)", (ulong)CONFIG_LOADADDR);
79 if (run_command(arg, flag) >= 0)
80 {
81 /* Return if network loop failed */
82 if (net_state != NETLOOP_SUCCESS)
83 return 1;
84
85 /* if (NetBootFileXferSize >= ( nand_info[0].parts->boot_size
86 +nand_info[0].parts->soft0_size)) {
87 printf("Please check file downloaded.\n");
88 return 1;
89 }
90
91 magic = (hd_magic_desc *) CONFIG_SYS_LOAD_ADDR;
92 if (magic->ih_magic[0] != CSP_MAGIC0 ||
93 magic->ih_magic[1] != CSP_MAGIC1 ||
94 magic->ih_magic[2] != CSP_MAGIC2 ||
95 magic->ih_magic[3] != CSP_MAGIC3)
96 {
97 printf("Please check file downloaded.\n");
98 return 1;
99 }
100
101 header = (header_version *) (CONFIG_SYS_LOAD_ADDR +
102 sizeof(hd_magic_desc) + magic->ih_signatureSize);
103
104 if (argc >= 3) {
105 region = (int) simple_strtol(argv[2], NULL, 10);
106 if ((region != 1) && (region != 2))
107 region = 1;
108 }
109
110 sprintf(arg, "nand erase %lx %lx; nand write %lx %lx %lx;",
111 nand_info[0].parts->soft0_offs,
112 nand_info[0].parts->soft0_size,
113 (ulong)CONFIG_SYS_LOAD_ADDR,
114 nand_info[0].parts->soft0_offs,
115 (ulong)(CSP_HEADER_LEN + header->contend.ih_kern_size));
116
117 if (region == 2) {
118 sprintf(arg, "nand erase %lx %lx; nand write %lx %lx %lx;",
119 nand_info[0].parts->soft1_offs,
120 nand_info[0].parts->soft1_size,
121 (ulong)CONFIG_SYS_LOAD_ADDR,
122 nand_info[0].parts->soft1_offs,
123 (ulong)(CSP_HEADER_LEN + header->contend.ih_kern_size));
124 }
125
126#ifndef CFG_HUSH_PARSER
127 if (run_command (arg, flag) == -1)
128 return 1;
129#else
130 if (parse_string_outer(arg,
131 FLAG_PARSE_SEMICOLON | FLAG_EXIT_FROM_LOOP) != 0)
132 return 1;
133#endif
134
135 // BootLoader is included in combined software
136 if (header->contend.ih_boot_included)
137 {
138 sprintf(arg, "nand erase %lx %lx; nand write %lx %lx %lx;",
139 nand_info[0].parts->boot_offs,
140 nand_info[0].parts->boot_size,
141 (ulong)(CONFIG_SYS_LOAD_ADDR + header->contend.ih_boot_offset),
142 nand_info[0].parts->boot_offs,
143 (ulong)header->contend.ih_boot_size);
144
145#ifndef CFG_HUSH_PARSER
146 if (run_command (arg, flag) == -1)
147 return 1;
148#else
149 if (parse_string_outer(arg,
150 FLAG_PARSE_SEMICOLON | FLAG_EXIT_FROM_LOOP) != 0)
151 return 1;
152#endif
153 }*/
154 }
155 else
156 {
157 return -2;
158 }
159 }
160 }
161
162 return 0;
163}
164
165static unsigned int crc32_reflect (unsigned int ref, char ch)
166{
167 unsigned int i;
168 unsigned int result=0;
169
170 /* Swap bit 0 for bit 7, bit 1 for bit 6, etc. */
171 for (i=1; i<(ch+1); i++)
172 {
173 if (ref & 1)
174 result |= 1 << (ch-i);
175 ref >>= 1;
176 }
177
178 return (result);
179}
180
181static void crc32_init (void)
182{
183 /* This is the official polynomial used by CRC32 */
184 /* in PKZip, WinZip and Ethernet. */
185 unsigned int i, j;
186 unsigned int ulPolynomial=0x04c11db7;
187
188 /* 256 values representing ASCII character codes */
189 for (i=0; i<=0xFF; i++)
190 {
191 crc32_tbl[i] = crc32_reflect(i, 8) << 24;
192
193 for (j = 0; j < 8; j++)
194 crc32_tbl[i] = (crc32_tbl[i]<<1) ^ (crc32_tbl[i]&(1<<31) ? ulPolynomial:0);
195
196 crc32_tbl[i] = crc32_reflect(crc32_tbl[i], 32);
197 }
198}
199
200#if 0
201static unsigned int crc32_accumulate (char *s, unsigned int len)
202{
203 /*
204 * Be sure to use unsigned variables, because negative
205 * values introduce high bits where zero bits are required
206 */
207 unsigned int total;
208 unsigned char *data;
209 unsigned int crc=0xffffffff;
210
211 total = len;
212 data = (unsigned char*)s;
213
214 /*
215 * Perform the algorithm on each character in the string,
216 * using the lookup table values
217 */
218 while (total--)
219 {
220 crc = (crc>>8) ^ crc32_tbl[(crc&0xff) ^ *data++];
221
222#if defined(CONFIG_HW_WATCHDOG) || defined(CONFIG_WATCHDOG)
223 if(total%0x80000 == 0)
224 {
225 WATCHDOG_RESET();
226 }
227#endif
228 }
229
230 /* Exclusive OR the result with the beginning value */
231 return (crc^0xffffffff);
232}
233
234#ifdef CONFIG_ZTE_NAND_SKIP_BAD_IN_MTD
235/******************************************************************
236* º¯ÊýÃû³Æ£º do_search
237* ¹¦ÄÜÃèÊö£º ËÑË÷FlashÉϵÄÍêÕûµÄ°æ±¾
238* ÊäÈë²ÎÊý£º long start : ËÑË÷ÆðʼµØÖ·
239* long end : ËÑË÷½áÊøµØÖ·
240* long step : ËÑË÷²½½ø³¤¶È
241* search_desc *search : ËÑË÷½á¹û
242* Êä³ö²ÎÊý£º ÎÞ
243* ·µ »Ø Öµ£º ³É¹¦·µ»Ø0
244* ÆäËü˵Ã÷£º ÎÞ
245* ÐÞ¸ÄÈÕÆÚ °æ±¾ºÅ ÐÞ¸ÄÈË ÐÞ¸ÄÄÚÈÝ
246* ----------------------------------------------------------------
247* 2009/11/30 V1.0 ÍõÔÂÉú ´´½¨
248******************************************************************/
249int do_search (unsigned int start, unsigned int end, unsigned int step,
250 search_desc *search)
251{
252 long rate=0, index=-1;
253 loff_t addr = 0, addrEnd = 0;
254 unsigned int lseek=0;
255 hd_magic_desc *magic=NULL;
256 header_version *header=NULL;
257 unsigned int crcret=0, crclen=0;
258 unsigned char flags=0;
259#if defined(CONFIG_CMD_NAND)
260 nand_info_t *nand=&nand_info[nand_curr_device];
261 size_t readlen = CSP_HEADER_LEN;
262 unsigned char *pbuff = (unsigned char *) CONFIG_SYS_LOAD_ADDR;
263#endif
264
265#if defined(CONFIG_HW_WATCHDOG) || defined(CONFIG_WATCHDOG)
266 WATCHDOG_RESET ();
267#endif
268
269 memset ((char *)search, 0, sizeof(search_desc));
270
271 if (step != 0) /* ËÑË÷²½½ø³¤¶È */
272 rate = step;
273 else
274 rate = CFG_FLASH_SECTOR_SIZE;
275
276 crc32_init ();
277
278 addr = CFG_FLASH_BASE + start; /* ËÑË÷ÆðʼµØÖ· */
279 addrEnd = CFG_FLASH_BASE + end; /* ËÑË÷½áÊøµØÖ· */
280
281 while (addr < addrEnd) /* ´ÓµÍµØÖ·¿Õ¼äÏò¸ßµØÖ·¿Õ¼äËÑË÷ */
282 {
283#if defined(CONFIG_CMD_NAND)
284 if (nand_block_isbad (nand, addr & ~(nand->erasesize - 1))) {
285 printf("skip bad block...addr=0x%llx\n", addr);
286 addr += rate;
287 continue;
288 }
289
290 /* nand read 256 bytes */
291 nand_read(nand, addr, &readlen, pbuff);
292 magic = (hd_magic_desc *) pbuff;
293#else
294 magic = (hd_magic_desc *)addr;
295#endif
296
297 /* ¼ì²é°æ±¾Í·µÄ»ÃÊýÊÇ·ñ´æÔÚ */
298 if ((magic->ih_magic[0] == CSP_MAGIC0) &&
299 (magic->ih_magic[1] == CSP_MAGIC1) &&
300 (magic->ih_magic[2] == CSP_MAGIC2) &&
301 (magic->ih_magic[3] == CSP_MAGIC3))
302 {
303 flags = 0x00; index++;
304 printf("addr=%x\n", (int)addr);
305
306 /* ¼ì²é°æ±¾Í·µÄºÍУÑé */
307 lseek = (unsigned int)(pbuff + sizeof(hd_magic_desc) + magic->ih_signatureSize);
308 header = (header_version *)(lseek);
309 crclen = sizeof(hd_general_desc) + IH_HCRC_OFFSET;
310 crcret = crc32_accumulate ((char *)lseek, crclen);
311
312 if (crcret == header->contend.ih_hcrc)
313 {
314 flags |= CFG_TB_HEADER;
315 search->result[index].flags = flags;
316 /* ÄÚºËÈë¿ÚµØÖ· = °æ±¾Í·Æ«ÒÆ + °æ±¾Í·³¤¶È */
317 search->result[index].entry = addr + CSP_HEADER_LEN;
318 }
319 else
320 {
321 printf("header crc error 0x%08x,add=0x%08x\n,binheadercrc=0x%08x\n",
322 crcret,(int)addr,header->contend.ih_hcrc);
323 addr += rate; /* ÏÂÒ»¸öËÑË÷µØÖ· */
324 continue;
325 }
326
327#if defined(CONFIG_HW_WATCHDOG) || defined(CONFIG_WATCHDOG)
328 WATCHDOG_RESET();
329#endif
330
331 if (header->contend.ih_isnewly==IMAGE_NEW)
332 flags |= CFG_TB_LATELY;
333 if (header->contend.ih_fromsync!=IMAGE_UPGRADE)
334 flags |= CFG_TB_SYNCED;
335
336#if defined(CONFIG_CMD_NAND)
337 if (header->contend.ih_isfull == CFG_IMAGE_OKAY)
338#else
339 if ((flags & CFG_TB_KERNEL) && (flags & CFG_TB_ROOTFS))
340#endif
341 {
342 flags |= CFG_TB_INTACT;
343
344 search->result[index].flags = flags;
345 /* ÄÚºËÈë¿ÚµØÖ· = °æ±¾Í·Æ«ÒÆ + °æ±¾Í·³¤¶È */
346 search->result[index].entry = addr + CSP_HEADER_LEN;
347 search->result[index].ih_size = ALIGN_SIZE16(CSP_HEADER_LEN +
348 header->contend.ih_kern_size);
349 search->total = index + 1; /* ÓÐЧ°æ±¾¸öÊý */
350 }
351 }
352
353 if (search->total >= 2)
354 break;
355 addr += rate; /* ÏÂÒ»¸öËÑË÷µØÖ· */
356 }
357
358 if (search->total <= 0) {
359 printf("none fully-formed version\n");
360 }
361
362 return (0);
363}
364
365/*******************************************************************************
366*
367* do_startup - select a valid runnable version and startup it
368*
369* This function select a valid runnable version and startup it. If there are
370* more runnable versions than one, this function can judge which version is
371* usable according to its integrality, where form upgrading or synchronization
372* and whether it is a new version.
373*
374* RETURNS: OK.
375*/
376
377int do_startup (search_desc *search)
378{
379 int select=-1, retry_cnt = -1;
380 unsigned char buffer[4096] = {0};
381 int iret = -1, i = 0;
382 char tmp[20] = {0};
383 unsigned int crcret=0, crclen=0, lseek=0;
384 hd_magic_desc *magic=NULL;
385 header_version *header=NULL;
386 loff_t mtd_offset = 0;
387 uint32_t mtd_length = 0;
388 int mtdpart = 0;
389
390 if (search->total == 1)
391 {
392 if ((search->result[0].flags & CFG_TB_HEADER) &&
393 (search->result[0].flags & CFG_TB_INTACT))
394 {
395 select = 0;
396 }
397 else if ((search->result[1].flags & CFG_TB_HEADER) &&
398 (search->result[1].flags & CFG_TB_INTACT))
399 {
400 select = 1;
401 }
402 }
403 else if (search->total == 2)
404 {
405 retry_cnt = 1;
406 /* °æ±¾0ÍêÕûÇÒΪа汾 */
407 if ((search->result[0].flags & CFG_TB_HEADER) &&
408 (search->result[0].flags & CFG_TB_INTACT) &&
409 (search->result[0].flags & CFG_TB_LATELY))
410 {
411 select = 0;
412 }
413 /* °æ±¾1ÍêÕûÇÒΪа汾 */
414 else if ((search->result[1].flags & CFG_TB_HEADER) &&
415 (search->result[1].flags & CFG_TB_INTACT) &&
416 (search->result[1].flags & CFG_TB_LATELY))
417 {
418 select = 1;
419 }
420 else
421 {
422 select = 0;
423 }
424 }
425
426 printf("select=0x%x\n",select);
427
428/* ËÑË÷OMCIÆô¶¯Ñ¡Ïî²ÎÊýÇø£¬Æô¶¯OMCIÖ¸¶¨µÄ»î¶¯°æ±¾ */
429#undef CFG_OMCI_OFFSET
430#define CFG_OMCI_OFFSET 0x02a00000
431 mtd_offset = 0;
432 mtd_length = 4096;
433 mtdpart = MTD_OTHER;
434
435 iret = nand_read_skip_bad_(mtdpart, mtd_offset, mtd_length, &buffer[0]);
436 if (iret < 0)
437 {
438 printf("read other failed!\n");
439 }
440
441 if (buffer[0]!=0xff || buffer[1]!=0xff ||
442 buffer[2]!=0xff || buffer[3]!=0xff)
443 {
444 for (i=0; i<sizeof(buffer)-strlen("BootImageNum"); )
445 {
446 iret = memcmp(&buffer[i], "BootImageNum", strlen("BootImageNum"));
447 if (iret==0)
448 {
449 if (i==0) break;
450
451 if ((i>0) && (buffer[i-1]==',') &&
452 (buffer[i+strlen("BootImageNum")]=='='))
453 {
454 break;
455 }
456 else
457 {
458 i++;
459 continue;
460 }
461 }
462 else
463 {
464 i++;
465 }
466 }
467
468 if (iret==0) /* Æ¥Åäµ½ "BootImageNum" ¹Ø¼ü×Ö */
469 {
470 if (i >= 4096 - strlen("BootImageNum=0x00000001"))
471 {
472 printf("buffer overflow!!!\n");
473 return -1;
474 }
475
476 strncpy(tmp, (char *)&buffer[i + strlen("BootImageNum") + 1], 10);
477 printf("BootImageNum=%s,%ld\n", tmp, simple_strtol(tmp, NULL, 16));
478 if (simple_strtol(tmp, NULL, 16)==0 ||
479 simple_strtol(tmp, NULL, 16)==1)
480 {
481 if (search->total >= 2)
482 {
483 select = simple_strtol(tmp, NULL, 16);
484 if (!(search->result[select].flags & CFG_TB_INTACT) &&
485 (search->result[select?0:1].flags & CFG_TB_INTACT))
486 {
487 select = select ? 0 : 1;
488 }
489 }
490 }
491 }
492 }
493
494 printf("select=0x%x\n",select);
495 printf("search=0x%x\n",search->total);
496
497 if ( select < 0 ) /* ûÓпÉÔËÐеÄÍêÕû°æ±¾ */
498 {
499 return (-1);
500 }
501
502#if defined(CONFIG_CMD_NAND)
503retry_find:
504 mtd_offset = 0;
505 mtd_length = search->result[select].ih_size;
506 printf("search->result[select].entry=%lx\n", search->result[select].entry);
507 if (((search->result[select].entry - CSP_HEADER_LEN) >= nand_info[0].parts->soft1_offs)
508 &&((search->result[select].entry - CSP_HEADER_LEN) < nand_info[0].parts->soft1_offs +nand_info[0].parts->soft1_size))
509 {
510 mtdpart = MTD_KERNEL1;
511 }
512 else
513 {
514 mtdpart = MTD_KERNEL;
515 }
516
517 iret = nand_read_skip_bad_(mtdpart, mtd_offset, mtd_length, (u_char *)CONFIG_SYS_LOAD_ADDR);
518
519 if (iret == 0) {
520 magic = (hd_magic_desc *) CONFIG_SYS_LOAD_ADDR;
521 if (magic->ih_magic[0] == CSP_MAGIC0 &&
522 magic->ih_magic[1] == CSP_MAGIC1 &&
523 magic->ih_magic[2] == CSP_MAGIC2 &&
524 magic->ih_magic[3] == CSP_MAGIC3)
525 {
526 header = (header_version *)(CONFIG_SYS_LOAD_ADDR +
527 sizeof(hd_magic_desc) + magic->ih_signatureSize);
528 lseek = CONFIG_SYS_LOAD_ADDR + CSP_HEADER_LEN;
529 crclen = header->contend.ih_kern_size;
530 crcret = crc32_accumulate ((char *)lseek, crclen);
531
532 if (crcret == header->contend.ih_kern_dcrc)
533 {
534 /* Has independent root filesystem */
535 if (header->contend.ih_fs_size > 0)
536 {
537 printf("invalid fs type, %s, %d!\n", __FUNCTION__, __LINE__);
538 return -1;
539 }
540 else {
541 search->result[select].fstype = CFG_FS_INITRAM;
542 }
543 }
544 else {
545 printf("vmlinuz crc error 0x%08x\n", crcret);
546 goto fail_out;
547 }
548 }
549 else {
550 printf("magic not found\n");
551 goto fail_out;
552 }
553 }
554
555 return (select);
556
557fail_out:
558 if ((search->total >= 2) && (--retry_cnt >= 0)) {
559 select = (select > 0) ? 0 : 1;
560 goto retry_find;
561 }
562 else {
563 return (-1);
564 }
565#endif
566}
567
568
569/*******************************************************************************
570*
571* do_settings - configure necessary envirnment variables and save them in flash
572*
573* This function configure necessary envirnment variables, such as bootversion,
574* baseaddress, bootcmd, memsize and etc., and save them in flash.
575*
576* RETURNS: OK.
577*/
578
579int do_settings (int num, const search_desc *search)
580{
581 long bSaved=0, lseek=0;
582 char *s = NULL;
583 char arg[64] = {0}, cmdline[256] = {0};
584 int select=num;
585
586 loff_t mtd_offset = 0;
587 uint32_t mtd_length = 0;
588 int mtdpart = MTD_BOOT;
589
590#if defined(CONFIG_HW_WATCHDOG) || defined(CONFIG_WATCHDOG)
591 WATCHDOG_RESET();
592#endif
593
594 setenv("ipaddr", "192.168.1.1");
595 setenv("serverip", "192.168.1.100");
596
597 sprintf (arg, "%dM", CONFIG_SYS_SDRAM_SIZE>>20);
598 s = getenv ("memsize");
599 if (((s!=NULL) && (strncmp(s, arg, 3)!=0)) ||
600 (s==NULL)) {
601 setenv ("memsize", arg);
602 bSaved = 1;
603 }
604
605 /* ÉèÖû·¾³±äÁ¿£­bootcmd */
606 if (select >= 0)
607 {
608 if (search->result[select].fstype == CFG_FS_SQUASH)
609 {
610 sprintf (cmdline, "%s %s",
611 "setenv bootargs root=/dev/mtdblock4 rootfstype=squashfs",
612 "console=$(consoledev),$(baudrate);");
613 }
614
615 switch (search->result[select].fstype)
616 {
617 case CFG_FS_JFFS2:
618 case CFG_FS_SQUASH:
619 if (search->result[select].entry >=
620 (nand_info[0].parts->soft0_offs +
621 nand_info[0].parts->soft0_size))
622 {
623 sprintf (cmdline, "%s %s %s",
624 (search->result[select].fstype==CFG_FS_JFFS2) ?
625 "setenv bootargs root=/dev/mtdblock7 rw rootfstype=jffs2" :
626 "setenv bootargs root=/dev/mtdblock7 rootfstype=squashfs",
627 "console=$(consoledev),$(baudrate)",
628 "flashsize=$(flashsize) mem=$(memsize);");
629 }
630 break;
631
632 case CFG_FS_INITRAM:
633 sprintf (cmdline, "%s",
634 "setenv bootargs console=$(console) root=/dev/ram0 rw rdinit=/sbin/init mem=$(memsize);");
635 break;
636 case CFG_FS_NONE:
637 default:
638 printf("invalid fstype...!\n");
639 break;
640 }
641 }
642
643 sprintf (arg, "bootm 0x%x;", CONFIG_SYS_LOAD_ADDR + CSP_HEADER_LEN);
644 strcat (cmdline, arg);
645 s = getenv ("bootcmd");
646 if (((s!=NULL) && (strncmp(s, cmdline, strlen(cmdline))!=0)) ||
647 (s==NULL)) {
648 setenv ("bootcmd", cmdline);
649 bSaved = 1;
650 }
651
652 if (select < 0) { /* ûÓпÉÔËÐеÄÍêÕû°æ±¾ */
653 run_command ("setenv bootcmd", 0);
654 return -1;
655 }
656
657 if (bSaved) { /* ±£´æ»·¾³±äÁ¿ */
658 run_command ("saveenv", 0);
659 }
660
661 mtd_offset = 0;
662
663 mtd_length = CONFIG_SYS_BOOT_LEN;
664
665 nand_read_skip_bad_(mtdpart, mtd_offset, mtd_length, (u_char *)(CONFIG_SYS_LOAD_ADDR + SZ_16M));
666
667 for (lseek = (CONFIG_SYS_LOAD_ADDR + SZ_16M + CONFIG_SYS_BOOT_LEN);
668 lseek > CONFIG_SYS_LOAD_ADDR + SZ_16M;
669 lseek -= CFG_ALLIGN_SIZE)
670 {
671 if ((((hd_boot_file *)lseek)->btMagic[0]==CSP_MAGIC3) &&
672 (((hd_boot_file *)lseek)->btMagic[1]==CSP_MAGIC2) &&
673 (((hd_boot_file *)lseek)->btMagic[2]==CSP_MAGIC1) &&
674 (((hd_boot_file *)lseek)->btMagic[3]==CSP_MAGIC0))
675 {
676 printf("lseek=0x%lx\n", lseek);
677 memset(cmdline, 0, sizeof(cmdline));
678 sprintf(cmdline, "U-Boot %s %c%c%c%c%c%c%c%c%c%c%c%c%c%c ", ((hd_boot_file *)lseek)->btNumbers,
679 ((hd_boot_file *)lseek)->btCtime[0],
680 ((hd_boot_file *)lseek)->btCtime[1],
681 ((hd_boot_file *)lseek)->btCtime[2],
682 ((hd_boot_file *)lseek)->btCtime[3],
683 ((hd_boot_file *)lseek)->btCtime[5],
684 ((hd_boot_file *)lseek)->btCtime[6],
685 ((hd_boot_file *)lseek)->btCtime[8],
686 ((hd_boot_file *)lseek)->btCtime[9],
687 ((hd_boot_file *)lseek)->btCtime[11],
688 ((hd_boot_file *)lseek)->btCtime[12],
689 ((hd_boot_file *)lseek)->btCtime[14],
690 ((hd_boot_file *)lseek)->btCtime[15],
691 ((hd_boot_file *)lseek)->btCtime[17],
692 ((hd_boot_file *)lseek)->btCtime[18]);
693
694 printf("cmdline=%s\n", cmdline);
695 break;
696 }
697 }
698 if(lseek>=(CONFIG_SYS_LOAD_ADDR + SZ_16M + CONFIG_SYS_BOOT_LEN))
699 {
700 printf("error in do_settings!\n");
701 return -1;
702 }
703
704 sprintf (arg, "0x%lx ", search->result[select].entry-CSP_HEADER_LEN);
705 strcat (cmdline, arg);
706 if(search->total==1)
707 {/*Ë«°æ±¾µÄÒì³£Çé¿ö:Ö»Óа汾2*/
708 if(search->result[select].entry <(nand_info[0].parts->soft0_offs + nand_info[0].parts->soft0_size))
709 {
710 sprintf (arg, "0x%1x 0x%02x 0x%02x", 0, search->result[0].flags, search->result[1].flags);
711 }
712 else
713 {
714 sprintf (arg, "0x%1x 0x%02x 0x%02x", 1, search->result[1].flags, search->result[0].flags);
715 }
716 }
717 else
718 {
719 sprintf (arg, "0x%1x 0x%02x 0x%02x", select, search->result[0].flags, search->result[1].flags);
720 }
721
722 strcat (cmdline, arg);
723 s = getenv ("versioninfo");
724 if (((s!=NULL) && (strncmp(s, cmdline, strlen(cmdline))!=0)) ||
725 (s==NULL))
726 {
727 setenv ("versioninfo", cmdline);
728 bSaved = 1;
729 }
730
731
732 if (bSaved) /* ±£´æ»·¾³±äÁ¿ */
733 {
734 run_command ("saveenv", 0);
735 }
736
737#if defined(CONFIG_HW_WATCHDOG) || defined(CONFIG_WATCHDOG)
738 WATCHDOG_RESET();
739#endif
740
741 return (0);
742}
743#else
744
745/******************************************************************
746* º¯ÊýÃû³Æ£º do_search
747* ¹¦ÄÜÃèÊö£º ËÑË÷FlashÉϵÄÍêÕûµÄ°æ±¾
748* ÊäÈë²ÎÊý£º long start : ËÑË÷ÆðʼµØÖ·
749* long end : ËÑË÷½áÊøµØÖ·
750* long step : ËÑË÷²½½ø³¤¶È
751* search_desc *search : ËÑË÷½á¹û
752* Êä³ö²ÎÊý£º ÎÞ
753* ·µ »Ø Öµ£º ³É¹¦·µ»Ø0
754* ÆäËü˵Ã÷£º ÎÞ
755* ÐÞ¸ÄÈÕÆÚ °æ±¾ºÅ ÐÞ¸ÄÈË ÐÞ¸ÄÄÚÈÝ
756* ----------------------------------------------------------------
757* 2009/11/30 V1.0 ÍõÔÂÉú ´´½¨
758******************************************************************/
759int do_search (unsigned int start, unsigned int end, unsigned int step,
760 search_desc *search)
761{
762 long rate=0, index=-1;
763 unsigned int addr = 0, addrEnd = 0;
764 unsigned int lseek=0;
765 hd_magic_desc *magic=NULL;
766 header_version *header=NULL;
767 unsigned int crcret=0, crclen=0;
768 unsigned char flags=0;
769#if defined(CONFIG_CMD_NAND)
770 nand_info_t *nand=&nand_info[nand_curr_device];
771 unsigned int readlen = CSP_HEADER_LEN;
772 unsigned int pbuff = CONFIG_SYS_LOAD_ADDR;
773 unsigned int len_inc_bad = 0;
774#endif
775
776#if defined(CONFIG_HW_WATCHDOG) || defined(CONFIG_WATCHDOG)
777 WATCHDOG_RESET ();
778#endif
779
780 memset ((char *)search, 0, sizeof(search_desc));
781
782 if (step != 0) /* ËÑË÷²½½ø³¤¶È */
783 rate = step;
784 else
785 rate = CFG_FLASH_SECTOR_SIZE;
786
787 crc32_init ();
788
789 addr = CFG_FLASH_BASE + start; /* ËÑË÷ÆðʼµØÖ· */
790 addrEnd = CFG_FLASH_BASE + end; /* ËÑË÷½áÊøµØÖ· */
791
792 while (addr < addrEnd) /* ´ÓµÍµØÖ·¿Õ¼äÏò¸ßµØÖ·¿Õ¼äËÑË÷ */
793 {
794#if defined(CONFIG_CMD_NAND)
795 if (nand_block_isbad (nand, addr & ~(nand->erasesize - 1))) {
796 printf("skip bad block...addr=0x%8x\n", addr);
797 addr += rate;
798 len_inc_bad += rate;
799 continue;
800 }
801
802 /* nand read 256 bytes */
803 nand_read(nand, addr, &readlen, (unsigned char *)pbuff);
804 magic = (hd_magic_desc *) pbuff;
805#else
806 magic = (hd_magic_desc *)addr;
807#endif
808
809 /* ¼ì²é°æ±¾Í·µÄ»ÃÊýÊÇ·ñ´æÔÚ */
810 if ((magic->ih_magic[0] == CSP_MAGIC0) &&
811 (magic->ih_magic[1] == CSP_MAGIC1) &&
812 (magic->ih_magic[2] == CSP_MAGIC2) &&
813 (magic->ih_magic[3] == CSP_MAGIC3))
814 {
815 flags = 0x00; index++;
816 printf("addr=%x\n", (int)addr);
817
818 /* ¼ì²é°æ±¾Í·µÄºÍУÑé */
819 lseek = pbuff + sizeof(hd_magic_desc) + magic->ih_signatureSize;
820 header = (header_version *)(lseek);
821 crclen = sizeof(hd_general_desc) + IH_HCRC_OFFSET;
822 crcret = crc32_accumulate ((char *)lseek, crclen);
823
824 if (crcret == header->contend.ih_hcrc)
825 {
826 flags |= CFG_TB_HEADER;
827 search->result[index].flags = flags;
828 /* ÄÚºËÈë¿ÚµØÖ· = °æ±¾Í·Æ«ÒÆ + °æ±¾Í·³¤¶È */
829 search->result[index].entry = addr + CSP_HEADER_LEN;
830 }
831 else
832 {
833 printf("header crc error 0x%08x,add=0x%08x\n,binheadercrc=0x%08x\n",
834 crcret,addr,header->contend.ih_hcrc);
835 addr += rate; /* ÏÂÒ»¸öËÑË÷µØÖ· */
836 continue;
837 }
838
839#if defined(CONFIG_HW_WATCHDOG) || defined(CONFIG_WATCHDOG)
840 WATCHDOG_RESET();
841#endif
842
843 if (header->contend.ih_isnewly==IMAGE_NEW)
844 flags |= CFG_TB_LATELY;
845 if (header->contend.ih_fromsync!=IMAGE_UPGRADE)
846 flags |= CFG_TB_SYNCED;
847
848#if defined(CONFIG_CMD_NAND)
849 if (header->contend.ih_isfull == CFG_IMAGE_OKAY)
850#else
851 if ((flags & CFG_TB_KERNEL) && (flags & CFG_TB_ROOTFS))
852#endif
853 {
854 flags |= CFG_TB_INTACT;
855
856 search->result[index].flags = flags;
857 /* ÄÚºËÈë¿ÚµØÖ· = °æ±¾Í·Æ«ÒÆ + °æ±¾Í·³¤¶È */
858 search->result[index].entry = addr + CSP_HEADER_LEN-len_inc_bad;
859 search->result[index].ih_size = ALIGN_SIZE16(CSP_HEADER_LEN +
860 header->contend.ih_kern_size);
861 search->total = index + 1; /* ÓÐЧ°æ±¾¸öÊý */
862 }
863 }
864
865 if (search->total >= 2)
866 break;
867 addr += rate; /* ÏÂÒ»¸öËÑË÷µØÖ· */
868 }
869
870 if (search->total <= 0) {
871 printf("none fully-formed version\n");
872 }
873
874 return (0);
875}
876
877/*******************************************************************************
878*
879* do_startup - select a valid runnable version and startup it
880*
881* This function select a valid runnable version and startup it. If there are
882* more runnable versions than one, this function can judge which version is
883* usable according to its integrality, where form upgrading or synchronization
884* and whether it is a new version.
885*
886* RETURNS: OK.
887*/
888
889int do_startup (search_desc *search)
890{
891 int select=-1, retry_cnt = -1;
892 unsigned char buffer[256] = {0};
893 char cmd[64] = {0};
894 int iret = -1, i = 0;
895 char tmp[20] = {0};
896 unsigned int badlen=0, versize=0, readlen=4, node = 0;
897 unsigned int crcret=0, crclen=0, lseek=0;
898 hd_magic_desc *magic=NULL;
899 header_version *header=NULL;
900#if defined(CONFIG_CMD_NAND)
901 nand_info_t *nand=&nand_info[nand_curr_device];
902#endif
903
904 if (search->total == 1)
905 {
906 if ((search->result[0].flags & CFG_TB_HEADER) &&
907 (search->result[0].flags & CFG_TB_INTACT))
908 {
909 select = 0;
910 }
911 else if ((search->result[1].flags & CFG_TB_HEADER) &&
912 (search->result[1].flags & CFG_TB_INTACT))
913 {
914 select = 1;
915 }
916 }
917 else if (search->total == 2)
918 {
919 retry_cnt = 1;
920 /* °æ±¾0ÍêÕûÇÒΪа汾 */
921 if ((search->result[0].flags & CFG_TB_HEADER) &&
922 (search->result[0].flags & CFG_TB_INTACT) &&
923 (search->result[0].flags & CFG_TB_LATELY))
924 {
925 select = 0;
926 }
927 /* °æ±¾1ÍêÕûÇÒΪа汾 */
928 else if ((search->result[1].flags & CFG_TB_HEADER) &&
929 (search->result[1].flags & CFG_TB_INTACT) &&
930 (search->result[1].flags & CFG_TB_LATELY))
931 {
932 select = 1;
933 }
934 else
935 {
936 select = 0;
937 }
938 }
939
940 printf("select=0x%x\n",select);
941
942/* ËÑË÷OMCIÆô¶¯Ñ¡Ïî²ÎÊýÇø£¬Æô¶¯OMCIÖ¸¶¨µÄ»î¶¯°æ±¾ */
943#undef CFG_OMCI_OFFSET
944#define CFG_OMCI_OFFSET 0x02a00000
945 sprintf(cmd, "nand read %lx %8x %x", (ulong)buffer, CFG_OMCI_OFFSET, 256);
946 iret = run_command(cmd, 0);
947
948 if (buffer[0]!=0xff || buffer[1]!=0xff ||
949 buffer[2]!=0xff || buffer[3]!=0xff)
950 {
951 for (i=0; i<sizeof(buffer)-strlen("BootImageNum"); )
952 {
953 iret = memcmp(&buffer[i], "BootImageNum", strlen("BootImageNum"));
954 if (iret==0)
955 {
956 if (i==0) break;
957
958 if ((i>0) && (buffer[i-1]==',') &&
959 (buffer[i+strlen("BootImageNum")]=='='))
960 {
961 break;
962 }
963 else
964 {
965 i++;
966 continue;
967 }
968 }
969 else
970 {
971 i++;
972 }
973 }
974
975 if (iret==0) /* Æ¥Åäµ½ "BootImageNum" ¹Ø¼ü×Ö */
976 {
977 if (i >= 256 - strlen("BootImageNum=0x00000001"))
978 {
979 printf("buffer overflow!!!\n");
980 return -1;
981 }
982
983 strncpy(tmp, (char *)&buffer[i + strlen("BootImageNum") + 1], 10);
984 printf("BootImageNum=%s,%ld\n", tmp, simple_strtol(tmp, NULL, 16));
985 if (simple_strtol(tmp, NULL, 16)==0 ||
986 simple_strtol(tmp, NULL, 16)==1)
987 {
988 if (search->total >= 2)
989 {
990 select = simple_strtol(tmp, NULL, 16);
991 if (!(search->result[select].flags & CFG_TB_INTACT) &&
992 (search->result[select?0:1].flags & CFG_TB_INTACT))
993 {
994 select = select ? 0 : 1;
995 }
996 }
997 }
998 }
999 }
1000
1001 printf("select=0x%x\n",select);
1002 printf("search=0x%x\n",search->total);
1003
1004 if ( select < 0 ) /* ûÓпÉÔËÐеÄÍêÕû°æ±¾ */
1005 {
1006 return (-1);
1007 }
1008
1009#if defined(CONFIG_CMD_NAND)
1010retry_find:
1011 sprintf(cmd, "nand read %lx %lx %8x;", (ulong)CONFIG_SYS_LOAD_ADDR,
1012 search->result[select].entry - CSP_HEADER_LEN,
1013 search->result[select].ih_size);
1014
1015 if (run_command(cmd, 0) >= 0) {
1016 magic = (hd_magic_desc *) CONFIG_SYS_LOAD_ADDR;
1017 if (magic->ih_magic[0] == CSP_MAGIC0 &&
1018 magic->ih_magic[1] == CSP_MAGIC1 &&
1019 magic->ih_magic[2] == CSP_MAGIC2 &&
1020 magic->ih_magic[3] == CSP_MAGIC3)
1021 {
1022 header = (header_version *)(CONFIG_SYS_LOAD_ADDR +
1023 sizeof(hd_magic_desc) + magic->ih_signatureSize);
1024 lseek = CONFIG_SYS_LOAD_ADDR + CSP_HEADER_LEN;
1025 crclen = header->contend.ih_kern_size;
1026 crcret = crc32_accumulate ((char *)lseek, crclen);
1027
1028 if (crcret == header->contend.ih_kern_dcrc)
1029 {
1030 /* Has independent root filesystem */
1031 if (header->contend.ih_fs_size > 0)
1032 {
1033 printf("invalid fs type, %s, %d!\n", __FUNCTION__, __LINE__);
1034 return -1;
1035 }
1036 else
1037 {
1038 search->result[select].fstype = CFG_FS_INITRAM;
1039 }
1040 }
1041 else {
1042 printf("vmlinuz crc error 0x%08x\n", crcret);
1043 goto fail_out;
1044 }
1045 }
1046 else {
1047 printf("magic not found\n");
1048 goto fail_out;
1049 }
1050 }
1051
1052 return (select);
1053
1054fail_out:
1055 if ((search->total >= 2) && (--retry_cnt >= 0)) {
1056 select = (select > 0) ? 0 : 1;
1057 goto retry_find;
1058 }
1059 else {
1060 return (-1);
1061 }
1062#endif
1063}
1064
1065
1066/*******************************************************************************
1067*
1068* do_settings - configure necessary envirnment variables and save them in flash
1069*
1070* This function configure necessary envirnment variables, such as bootversion,
1071* baseaddress, bootcmd, memsize and etc., and save them in flash.
1072*
1073* RETURNS: OK.
1074*/
1075
1076int do_settings (int num, const search_desc *search)
1077{
1078 long bSaved=0, lseek=0;
1079 char *s = NULL;
1080 char arg[64] = {0}, cmdline[256] = {0};
1081 int select=num;
1082 char parm[64] = {0};
1083
1084#if defined(CONFIG_HW_WATCHDOG) || defined(CONFIG_WATCHDOG)
1085 WATCHDOG_RESET();
1086#endif
1087
1088 setenv("ipaddr", "192.168.1.1");
1089 setenv("serverip", "192.168.1.100");
1090
1091 sprintf (arg, "%dM", CONFIG_SYS_SDRAM_SIZE>>20);
1092 s = getenv ("memsize");
1093 if (((s!=NULL) && (strncmp(s, arg, 3)!=0)) ||
1094 (s==NULL)) {
1095 setenv ("memsize", arg);
1096 bSaved = 1;
1097 }
1098
1099 /* ÉèÖû·¾³±äÁ¿£­bootcmd */
1100 if (select >= 0)
1101 {
1102 if (search->result[select].fstype == CFG_FS_SQUASH)
1103 {
1104 sprintf (cmdline, "%s %s",
1105 "setenv bootargs root=/dev/mtdblock4 rootfstype=squashfs",
1106 "console=$(consoledev),$(baudrate);");
1107 }
1108
1109 switch (search->result[select].fstype)
1110 {
1111 case CFG_FS_JFFS2:
1112 case CFG_FS_SQUASH:
1113 if (search->result[select].entry >=
1114 (nand_info[0].parts->soft0_offs +
1115 nand_info[0].parts->soft0_size))
1116 {
1117 sprintf (cmdline, "%s %s %s",
1118 (search->result[select].fstype==CFG_FS_JFFS2) ?
1119 "setenv bootargs root=/dev/mtdblock7 rw rootfstype=jffs2" :
1120 "setenv bootargs root=/dev/mtdblock7 rootfstype=squashfs",
1121 "console=$(consoledev),$(baudrate)",
1122 "flashsize=$(flashsize) mem=$(memsize);");
1123 }
1124 break;
1125
1126 case CFG_FS_INITRAM:
1127 sprintf (cmdline, "%s",
1128 "setenv bootargs console=$(console) root=/dev/ram0 rw rdinit=/sbin/init mem=$(memsize);");
1129 break;
1130 case CFG_FS_NONE:
1131 default:
1132 printf("invalid fstype...!\n");
1133 break;
1134 }
1135 }
1136
1137 sprintf (arg, "bootm 0x%8x;", CONFIG_SYS_LOAD_ADDR + CSP_HEADER_LEN);
1138 strcat (cmdline, arg);
1139 s = getenv ("bootcmd");
1140 if (((s!=NULL) && (strncmp(s, cmdline, strlen(cmdline))!=0)) ||
1141 (s==NULL)) {
1142 setenv ("bootcmd", cmdline);
1143 bSaved = 1;
1144 }
1145
1146 if (select < 0) { /* ûÓпÉÔËÐеÄÍêÕû°æ±¾ */
1147 run_command ("setenv bootcmd", 0);
1148 return -1;
1149 }
1150
1151 if (bSaved) { /* ±£´æ»·¾³±äÁ¿ */
1152 run_command ("saveenv", 0);
1153 }
1154
1155
1156 sprintf (parm, "nand read %8x %08x %08x;",
1157 CONFIG_SYS_LOAD_ADDR + SZ_16M, 0, CONFIG_SYS_BOOT_LEN);
1158
1159 run_command (parm, 0);
1160
1161 for (lseek = (CONFIG_SYS_LOAD_ADDR + SZ_16M + CONFIG_SYS_BOOT_LEN);
1162 lseek > CONFIG_SYS_LOAD_ADDR + SZ_16M;
1163 lseek -= CFG_ALLIGN_SIZE)
1164 {
1165 if ((((hd_boot_file *)lseek)->btMagic[0]==CSP_MAGIC3) &&
1166 (((hd_boot_file *)lseek)->btMagic[1]==CSP_MAGIC2) &&
1167 (((hd_boot_file *)lseek)->btMagic[2]==CSP_MAGIC1) &&
1168 (((hd_boot_file *)lseek)->btMagic[3]==CSP_MAGIC0))
1169 {
1170 memset(cmdline, 0, sizeof(cmdline));
1171 sprintf(cmdline, "U-Boot %s %c%c%c%c%c%c%c%c%c%c%c%c%c%c ", ((hd_boot_file *)lseek)->btNumbers,
1172 ((hd_boot_file *)lseek)->btCtime[0],
1173 ((hd_boot_file *)lseek)->btCtime[1],
1174 ((hd_boot_file *)lseek)->btCtime[2],
1175 ((hd_boot_file *)lseek)->btCtime[3],
1176 ((hd_boot_file *)lseek)->btCtime[5],
1177 ((hd_boot_file *)lseek)->btCtime[6],
1178 ((hd_boot_file *)lseek)->btCtime[8],
1179 ((hd_boot_file *)lseek)->btCtime[9],
1180 ((hd_boot_file *)lseek)->btCtime[11],
1181 ((hd_boot_file *)lseek)->btCtime[12],
1182 ((hd_boot_file *)lseek)->btCtime[14],
1183 ((hd_boot_file *)lseek)->btCtime[15],
1184 ((hd_boot_file *)lseek)->btCtime[17],
1185 ((hd_boot_file *)lseek)->btCtime[18]);
1186
1187 printf("cmdline=%s\n", cmdline);
1188 break;
1189 }
1190 }
1191 if(lseek>=(CONFIG_SYS_LOAD_ADDR + SZ_16M + CONFIG_SYS_BOOT_LEN))
1192 {
1193 printf("error in do_settings!\n");
1194 return -1;
1195 }
1196
1197 sprintf (arg, "0x%lx ", search->result[select].entry-CSP_HEADER_LEN);
1198 strcat (cmdline, arg);
1199 if(search->total==1)
1200 {/*Ë«°æ±¾µÄÒì³£Çé¿ö:Ö»Óа汾2*/
1201 if(search->result[select].entry <(nand_info[0].parts->soft0_offs + nand_info[0].parts->soft0_size))
1202 {
1203 sprintf (arg, "0x%1x 0x%02x 0x%02x", 0, search->result[0].flags, search->result[1].flags);
1204 }
1205 else
1206 {
1207 sprintf (arg, "0x%1x 0x%02x 0x%02x", 1, search->result[1].flags, search->result[0].flags);
1208 }
1209 }
1210 else
1211 {
1212 sprintf (arg, "0x%1x 0x%02x 0x%02x", select, search->result[0].flags, search->result[1].flags);
1213 }
1214
1215 strcat (cmdline, arg);
1216 s = getenv ("versioninfo");
1217 if (((s!=NULL) && (strncmp(s, cmdline, strlen(cmdline))!=0)) ||
1218 (s==NULL))
1219 {
1220 setenv ("versioninfo", cmdline);
1221 bSaved = 1;
1222 }
1223
1224
1225 if (bSaved) /* ±£´æ»·¾³±äÁ¿ */
1226 {
1227 run_command ("saveenv", 0);
1228 }
1229
1230#if defined(CONFIG_HW_WATCHDOG) || defined(CONFIG_WATCHDOG)
1231 WATCHDOG_RESET();
1232#endif
1233
1234 return (0);
1235}
1236
1237#endif
1238#endif
1239
1240void do_env_restore(void)
1241{
1242 setenv("ipaddr", "192.168.1.1");
1243 setenv("serverip", "192.168.1.100");
1244 return;
1245}
1246
1247U_BOOT_CMD(
1248 downver, CONFIG_SYS_MAXARGS, 1, do_downver,
1249 "upgrade software downloaded from TFTP server",
1250 "name [...]\n"
1251 " - allbins, upgrade allbins\n"
1252 " - kernel, upgrade system software\n"
1253 " - version [1|2], upgrade combined software\n"
1254);