common_util.c 13 KB

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