common_util.c 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630
  1. /*
  2. * (C) Copyright 2001
  3. * Denis Peter, MPL AG Switzerland, d.peter@mpl.ch
  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 <video_fb.h>
  27. #include "common_util.h"
  28. #include <asm/processor.h>
  29. #include <asm/byteorder.h>
  30. #include <i2c.h>
  31. #include <devices.h>
  32. #include <pci.h>
  33. #include <malloc.h>
  34. #include <bzlib.h>
  35. #ifdef CONFIG_PIP405
  36. #include "../pip405/pip405.h"
  37. #include <405gp_pci.h>
  38. #endif
  39. #ifdef CONFIG_MIP405
  40. #include "../mip405/mip405.h"
  41. #include <405gp_pci.h>
  42. #endif
  43. extern int gunzip(void *, int, uchar *, int *);
  44. extern int mem_test(ulong start, ulong ramsize, int quiet);
  45. #define I2C_BACKUP_ADDR 0x7C00 /* 0x200 bytes for backup */
  46. #define IMAGE_SIZE CFG_MONITOR_LEN /* ugly, but it works for now */
  47. extern flash_info_t flash_info[]; /* info for FLASH chips */
  48. static image_header_t header;
  49. static int
  50. mpl_prg(uchar *src, ulong size)
  51. {
  52. ulong start;
  53. flash_info_t *info;
  54. int i, rc;
  55. #if defined(CONFIG_PIP405) || defined(CONFIG_MIP405)
  56. char *copystr = (char *)src;
  57. ulong *magic = (ulong *)src;
  58. #endif
  59. info = &flash_info[0];
  60. #if defined(CONFIG_PIP405) || defined(CONFIG_MIP405)
  61. if (ntohl(magic[0]) != IH_MAGIC) {
  62. puts("Bad Magic number\n");
  63. return -1;
  64. }
  65. /* some more checks before we delete the Flash... */
  66. /* Checking the ISO_STRING prevents to program a
  67. * wrong Firmware Image into the flash.
  68. */
  69. i = 4; /* skip Magic number */
  70. while (1) {
  71. if (strncmp(&copystr[i], "MEV-", 4) == 0)
  72. break;
  73. if (i++ >= 0x100) {
  74. puts("Firmware Image for unknown Target\n");
  75. return -1;
  76. }
  77. }
  78. /* we have the ISO STRING, check */
  79. if (strncmp(&copystr[i], CONFIG_ISO_STRING, sizeof(CONFIG_ISO_STRING)-1) != 0) {
  80. printf("Wrong Firmware Image: %s\n", &copystr[i]);
  81. return -1;
  82. }
  83. start = 0 - size;
  84. for (i = info->sector_count-1; i > 0; i--) {
  85. info->protect[i] = 0; /* unprotect this sector */
  86. if (start >= info->start[i])
  87. break;
  88. }
  89. /* set-up flash location */
  90. /* now erase flash */
  91. printf("Erasing at %lx (sector %d) (start %lx)\n",
  92. start,i,info->start[i]);
  93. if ((rc = flash_erase (info, i, info->sector_count-1)) != 0) {
  94. puts("ERROR ");
  95. flash_perror(rc);
  96. return (1);
  97. }
  98. #elif defined(CONFIG_VCMA9)
  99. start = 0;
  100. for (i = 0; i <info->sector_count; i++) {
  101. info->protect[i] = 0; /* unprotect this sector */
  102. if (size < info->start[i])
  103. break;
  104. }
  105. /* set-up flash location */
  106. /* now erase flash */
  107. printf("Erasing at %lx (sector %d) (start %lx)\n",
  108. start,0,info->start[0]);
  109. if ((rc = flash_erase (info, 0, i)) != 0) {
  110. puts("ERROR ");
  111. flash_perror(rc);
  112. return (1);
  113. }
  114. #endif
  115. printf("flash erased, programming from 0x%lx 0x%lx Bytes\n",src,size);
  116. if ((rc = flash_write (src, start, size)) != 0) {
  117. puts("ERROR ");
  118. flash_perror(rc);
  119. return (1);
  120. }
  121. puts("OK programming done\n");
  122. return 0;
  123. }
  124. static int
  125. mpl_prg_image(uchar *ld_addr)
  126. {
  127. unsigned long len, checksum;
  128. uchar *data;
  129. image_header_t *hdr = &header;
  130. int rc;
  131. /* Copy header so we can blank CRC field for re-calculation */
  132. memcpy (&header, (char *)ld_addr, sizeof(image_header_t));
  133. if (ntohl(hdr->ih_magic) != IH_MAGIC) {
  134. puts("Bad Magic Number\n");
  135. return 1;
  136. }
  137. print_image_hdr(hdr);
  138. if (hdr->ih_os != IH_OS_U_BOOT) {
  139. puts("No U-Boot Image\n");
  140. return 1;
  141. }
  142. if (hdr->ih_type != IH_TYPE_FIRMWARE) {
  143. puts("No Firmware Image\n");
  144. return 1;
  145. }
  146. data = (uchar *)&header;
  147. len = sizeof(image_header_t);
  148. checksum = ntohl(hdr->ih_hcrc);
  149. hdr->ih_hcrc = 0;
  150. if (crc32 (0, (char *)data, len) != checksum) {
  151. puts("Bad Header Checksum\n");
  152. return 1;
  153. }
  154. data = ld_addr + sizeof(image_header_t);
  155. len = ntohl(hdr->ih_size);
  156. puts("Verifying Checksum ... ");
  157. if (crc32 (0, (char *)data, len) != ntohl(hdr->ih_dcrc)) {
  158. puts("Bad Data CRC\n");
  159. return 1;
  160. }
  161. puts("OK\n");
  162. if (hdr->ih_comp != IH_COMP_NONE) {
  163. uchar *buf;
  164. /* reserve space for uncompressed image */
  165. if ((buf = malloc(IMAGE_SIZE)) == NULL) {
  166. puts("Insufficient space for decompression\n");
  167. return 1;
  168. }
  169. switch (hdr->ih_comp) {
  170. case IH_COMP_GZIP:
  171. puts("Uncompressing (GZIP) ... ");
  172. rc = gunzip ((void *)(buf), IMAGE_SIZE, data, (int *)&len);
  173. if (rc != 0) {
  174. puts("GUNZIP ERROR\n");
  175. free(buf);
  176. return 1;
  177. }
  178. puts("OK\n");
  179. break;
  180. #if CONFIG_BZIP2
  181. case IH_COMP_BZIP2:
  182. puts("Uncompressing (BZIP2) ... ");
  183. {
  184. uint retlen = IMAGE_SIZE;
  185. rc = BZ2_bzBuffToBuffDecompress ((char *)(buf), &retlen,
  186. (char *)data, len, 0, 0);
  187. len = retlen;
  188. }
  189. if (rc != BZ_OK) {
  190. printf ("BUNZIP2 ERROR: %d\n", rc);
  191. free(buf);
  192. return 1;
  193. }
  194. puts("OK\n");
  195. break;
  196. #endif
  197. default:
  198. printf ("Unimplemented compression type %d\n", hdr->ih_comp);
  199. free(buf);
  200. return 1;
  201. }
  202. rc = mpl_prg(buf, len);
  203. free(buf);
  204. } else {
  205. rc = mpl_prg(data, len);
  206. }
  207. return(rc);
  208. }
  209. void get_backup_values(backup_t *buf)
  210. {
  211. i2c_read(CFG_DEF_EEPROM_ADDR, I2C_BACKUP_ADDR,2,(void *)buf,sizeof(backup_t));
  212. }
  213. void set_backup_values(int overwrite)
  214. {
  215. backup_t back;
  216. int i;
  217. get_backup_values(&back);
  218. if(!overwrite) {
  219. if(strncmp(back.signature,"MPL\0",4)==0) {
  220. puts("Not possible to write Backup\n");
  221. return;
  222. }
  223. }
  224. memcpy(back.signature,"MPL\0",4);
  225. i = getenv_r("serial#",back.serial_name,16);
  226. if(i < 0) {
  227. puts("Not possible to write Backup\n");
  228. return;
  229. }
  230. back.serial_name[16]=0;
  231. i = getenv_r("ethaddr",back.eth_addr,20);
  232. if(i < 0) {
  233. puts("Not possible to write Backup\n");
  234. return;
  235. }
  236. back.eth_addr[20]=0;
  237. i2c_write(CFG_DEF_EEPROM_ADDR, I2C_BACKUP_ADDR,2,(void *)&back,sizeof(backup_t));
  238. }
  239. void clear_env_values(void)
  240. {
  241. backup_t back;
  242. unsigned char env_crc[4];
  243. memset(&back,0xff,sizeof(backup_t));
  244. memset(env_crc,0x00,4);
  245. i2c_write(CFG_DEF_EEPROM_ADDR,I2C_BACKUP_ADDR,2,(void *)&back,sizeof(backup_t));
  246. i2c_write(CFG_DEF_EEPROM_ADDR,CFG_ENV_OFFSET,2,(void *)env_crc,4);
  247. }
  248. /*
  249. * check crc of "older" environment
  250. */
  251. int check_env_old_size(ulong oldsize)
  252. {
  253. ulong crc, len, new;
  254. unsigned off;
  255. uchar buf[64];
  256. /* read old CRC */
  257. eeprom_read (CFG_DEF_EEPROM_ADDR,
  258. CFG_ENV_OFFSET,
  259. (uchar *)&crc, sizeof(ulong));
  260. new = 0;
  261. len = oldsize;
  262. off = sizeof(long);
  263. len = oldsize-off;
  264. while (len > 0) {
  265. int n = (len > sizeof(buf)) ? sizeof(buf) : len;
  266. eeprom_read (CFG_DEF_EEPROM_ADDR, CFG_ENV_OFFSET+off, buf, n);
  267. new = crc32 (new, buf, n);
  268. len -= n;
  269. off += n;
  270. }
  271. return (crc == new);
  272. }
  273. static ulong oldsizes[] = {
  274. 0x200,
  275. 0x800,
  276. 0
  277. };
  278. void copy_old_env(ulong size)
  279. {
  280. uchar name_buf[64];
  281. uchar value_buf[0x800];
  282. uchar c;
  283. ulong len;
  284. unsigned off;
  285. uchar *name, *value;
  286. name=&name_buf[0];
  287. value=&value_buf[0];
  288. len=size;
  289. off = sizeof(long);
  290. while (len > off) {
  291. eeprom_read (CFG_DEF_EEPROM_ADDR, CFG_ENV_OFFSET+off, &c, 1);
  292. if(c != '=') {
  293. *name++=c;
  294. off++;
  295. }
  296. else {
  297. *name++='\0';
  298. off++;
  299. do {
  300. eeprom_read (CFG_DEF_EEPROM_ADDR, CFG_ENV_OFFSET+off, &c, 1);
  301. *value++=c;
  302. off++;
  303. if(c == '\0')
  304. break;
  305. } while(len > off);
  306. name=&name_buf[0];
  307. value=&value_buf[0];
  308. if(strncmp(name,"baudrate",8)!=0) {
  309. setenv(name,value);
  310. }
  311. }
  312. }
  313. }
  314. void check_env(void)
  315. {
  316. unsigned char *s;
  317. int i=0;
  318. char buf[32];
  319. backup_t back;
  320. s=getenv("serial#");
  321. if(!s) {
  322. while(oldsizes[i]) {
  323. if(check_env_old_size(oldsizes[i]))
  324. break;
  325. i++;
  326. }
  327. if(!oldsizes[i]) {
  328. /* no old environment has been found */
  329. get_backup_values (&back);
  330. if (strncmp (back.signature, "MPL\0", 4) == 0) {
  331. sprintf (buf, "%s", back.serial_name);
  332. setenv ("serial#", buf);
  333. sprintf (buf, "%s", back.eth_addr);
  334. setenv ("ethaddr", buf);
  335. printf ("INFO: serial# and ethaddr recovered, use saveenv\n");
  336. return;
  337. }
  338. }
  339. else {
  340. copy_old_env(oldsizes[i]);
  341. puts("INFO: old environment ajusted, use saveenv\n");
  342. }
  343. }
  344. else {
  345. /* check if back up is set */
  346. get_backup_values(&back);
  347. if(strncmp(back.signature,"MPL\0",4)!=0) {
  348. set_backup_values(0);
  349. }
  350. }
  351. }
  352. extern device_t *stdio_devices[];
  353. extern char *stdio_names[];
  354. void show_stdio_dev(void)
  355. {
  356. /* Print information */
  357. puts("In: ");
  358. if (stdio_devices[stdin] == NULL) {
  359. puts("No input devices available!\n");
  360. } else {
  361. printf ("%s\n", stdio_devices[stdin]->name);
  362. }
  363. puts("Out: ");
  364. if (stdio_devices[stdout] == NULL) {
  365. puts("No output devices available!\n");
  366. } else {
  367. printf ("%s\n", stdio_devices[stdout]->name);
  368. }
  369. puts("Err: ");
  370. if (stdio_devices[stderr] == NULL) {
  371. puts("No error devices available!\n");
  372. } else {
  373. printf ("%s\n", stdio_devices[stderr]->name);
  374. }
  375. }
  376. int do_mplcommon(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
  377. {
  378. ulong size,src,ld_addr;
  379. int result;
  380. backup_t back;
  381. src = MULTI_PURPOSE_SOCKET_ADDR;
  382. size = IMAGE_SIZE;
  383. if (strcmp(argv[1], "flash") == 0)
  384. {
  385. #if (CONFIG_COMMANDS & CFG_CMD_FDC)
  386. if (strcmp(argv[2], "floppy") == 0) {
  387. char *local_args[3];
  388. extern int do_fdcboot (cmd_tbl_t *, int, int, char *[]);
  389. puts("\nupdating bootloader image from floppy\n");
  390. local_args[0] = argv[0];
  391. if(argc==4) {
  392. local_args[1] = argv[3];
  393. local_args[2] = NULL;
  394. ld_addr=simple_strtoul(argv[3], NULL, 16);
  395. result=do_fdcboot(cmdtp, 0, 2, local_args);
  396. }
  397. else {
  398. local_args[1] = NULL;
  399. ld_addr=CFG_LOAD_ADDR;
  400. result=do_fdcboot(cmdtp, 0, 1, local_args);
  401. }
  402. result=mpl_prg_image(ld_addr);
  403. return result;
  404. }
  405. #endif /* (CONFIG_COMMANDS & CFG_CMD_FDC) */
  406. if (strcmp(argv[2], "mem") == 0) {
  407. if(argc==4) {
  408. ld_addr=simple_strtoul(argv[3], NULL, 16);
  409. }
  410. else {
  411. ld_addr=load_addr;
  412. }
  413. printf ("\nupdating bootloader image from memory at %lX\n",ld_addr);
  414. result=mpl_prg_image((uchar *)ld_addr);
  415. return result;
  416. }
  417. if (strcmp(argv[2], "mps") == 0) {
  418. puts("\nupdating bootloader image from MPS\n");
  419. result=mpl_prg((uchar *)src,size);
  420. return result;
  421. }
  422. }
  423. if (strcmp(argv[1], "mem") == 0)
  424. {
  425. result=0;
  426. if(argc==3)
  427. {
  428. result = (int)simple_strtol(argv[2], NULL, 16);
  429. }
  430. src=(unsigned long)&result;
  431. src-=CFG_MEMTEST_START;
  432. src-=(100*1024); /* - 100k */
  433. src&=0xfff00000;
  434. size=0;
  435. do {
  436. size++;
  437. printf("\n\nPass %ld\n",size);
  438. mem_test(CFG_MEMTEST_START,src,1);
  439. if(ctrlc())
  440. break;
  441. if(result>0)
  442. result--;
  443. }while(result);
  444. return 0;
  445. }
  446. if (strcmp(argv[1], "clearenvvalues") == 0)
  447. {
  448. if (strcmp(argv[2], "yes") == 0)
  449. {
  450. clear_env_values();
  451. return 0;
  452. }
  453. }
  454. if (strcmp(argv[1], "getback") == 0) {
  455. get_backup_values(&back);
  456. back.signature[3]=0;
  457. back.serial_name[16]=0;
  458. back.eth_addr[20]=0;
  459. printf("GetBackUp: signature: %s\n",back.signature);
  460. printf(" serial#: %s\n",back.serial_name);
  461. printf(" ethaddr: %s\n",back.eth_addr);
  462. return 0;
  463. }
  464. if (strcmp(argv[1], "setback") == 0) {
  465. set_backup_values(1);
  466. return 0;
  467. }
  468. printf("Usage:\n%s\n", cmdtp->usage);
  469. return 1;
  470. }
  471. #if (CONFIG_COMMANDS & CFG_CMD_DOC)
  472. extern void doc_probe(ulong physadr);
  473. void doc_init (void)
  474. {
  475. doc_probe(MULTI_PURPOSE_SOCKET_ADDR);
  476. }
  477. #endif
  478. #ifdef CONFIG_VIDEO
  479. /******************************************************
  480. * Routines to display the Board information
  481. * to the screen (since the VGA will be initialized as last,
  482. * we must resend the infos)
  483. */
  484. #ifdef CONFIG_CONSOLE_EXTRA_INFO
  485. extern GraphicDevice ctfb;
  486. extern int get_boot_mode(void);
  487. void video_get_info_str (int line_number, char *info)
  488. {
  489. /* init video info strings for graphic console */
  490. DECLARE_GLOBAL_DATA_PTR;
  491. PPC405_SYS_INFO sys_info;
  492. char rev;
  493. int i,boot;
  494. unsigned long pvr;
  495. char buf[64];
  496. char tmp[16];
  497. char cpustr[16];
  498. unsigned char *s, *e, bc;
  499. switch (line_number)
  500. {
  501. case 2:
  502. /* CPU and board infos */
  503. pvr=get_pvr();
  504. get_sys_info (&sys_info);
  505. switch (pvr) {
  506. case PVR_405GP_RB: rev='B'; break;
  507. case PVR_405GP_RC: rev='C'; break;
  508. case PVR_405GP_RD: rev='D'; break;
  509. case PVR_405GP_RE: rev='E'; break;
  510. case PVR_405GPR_RB: rev='B'; break;
  511. default: rev='?'; break;
  512. }
  513. if(pvr==PVR_405GPR_RB)
  514. sprintf(cpustr,"PPC405GPr %c",rev);
  515. else
  516. sprintf(cpustr,"PPC405GP %c",rev);
  517. /* Board info */
  518. i=0;
  519. s=getenv ("serial#");
  520. #ifdef CONFIG_PIP405
  521. if (!s || strncmp (s, "PIP405", 6)) {
  522. sprintf(buf,"### No HW ID - assuming PIP405");
  523. }
  524. #endif
  525. #ifdef CONFIG_MIP405
  526. if (!s || strncmp (s, "MIP405", 6)) {
  527. sprintf(buf,"### No HW ID - assuming MIP405");
  528. }
  529. #endif
  530. else {
  531. for (e = s; *e; ++e) {
  532. if (*e == ' ')
  533. break;
  534. }
  535. for (; s < e; ++s) {
  536. if (*s == '_') {
  537. ++s;
  538. break;
  539. }
  540. buf[i++]=*s;
  541. }
  542. sprintf(&buf[i]," SN ");
  543. i+=4;
  544. for (; s < e; ++s) {
  545. buf[i++]=*s;
  546. }
  547. buf[i++]=0;
  548. }
  549. sprintf (info," %s %s %s MHz (%lu/%lu/%lu MHz)",
  550. buf, cpustr,
  551. strmhz (tmp, gd->cpu_clk), sys_info.freqPLB / 1000000,
  552. sys_info.freqPLB / sys_info.pllOpbDiv / 1000000,
  553. sys_info.freqPLB / sys_info.pllExtBusDiv / 1000000);
  554. return;
  555. case 3:
  556. /* Memory Info */
  557. boot = get_boot_mode();
  558. bc = in8 (CONFIG_PORT_ADDR);
  559. sprintf(info, " %luMB RAM, %luMB Flash Cfg 0x%02X %s %s",
  560. gd->bd->bi_memsize / 0x100000,
  561. gd->bd->bi_flashsize / 0x100000,
  562. bc,
  563. (boot & BOOT_MPS) ? "MPS boot" : "Flash boot",
  564. ctfb.modeIdent);
  565. return;
  566. case 1:
  567. sprintf (buf, "%s",CONFIG_IDENT_STRING);
  568. sprintf (info, " %s", &buf[1]);
  569. return;
  570. }
  571. /* no more info lines */
  572. *info = 0;
  573. return;
  574. }
  575. #endif /* CONFIG_CONSOLE_EXTRA_INFO */
  576. #endif /* CONFIG_VIDEO */