1/* 2 * This program is free software; you can redistribute it and/or 3 * modify it under the terms of the GNU General Public License as 4 * published by the Free Software Foundation; either version 2 of 5 * the License, or (at your option) any later version. 6 * 7 * This program is distributed in the hope that it will be useful, 8 * but WITHOUT ANY WARRANTY; without even the implied warranty of 9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 10 * GNU General Public License for more details. 11 * 12 * You should have received a copy of the GNU General Public License 13 * along with this program; if not, write to the Free Software 14 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, 15 * MA 02111-1307 USA 16 */ 17/* 18 * ASUS Home Gateway Reference Design 19 * Web Page Configuration Support Routines 20 * 21 * Copyright 2004, ASUSTeK Inc. 22 * All Rights Reserved. 23 * 24 * THIS SOFTWARE IS OFFERED "AS IS", AND BROADCOM GRANTS NO WARRANTIES OF ANY 25 * KIND, EXPRESS OR IMPLIED, BY STATUTE, COMMUNICATION OR OTHERWISE. BROADCOM 26 * SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS 27 * FOR A SPECIFIC PURPOSE OR NONINFRINGEMENT CONCERNING THIS SOFTWARE. 28 */ 29 30#ifdef WEBS 31#include <webs.h> 32#include <uemf.h> 33#include <ej.h> 34#else /* !WEBS */ 35#include <stdio.h> 36#include <stdlib.h> 37#include <string.h> 38#include <ctype.h> 39#include <errno.h> 40#include <unistd.h> 41#include <limits.h> 42#include <sys/types.h> 43#include <sys/stat.h> 44#include <sys/socket.h> 45#include <netinet/in.h> 46#include <arpa/inet.h> 47#include <assert.h> 48#endif /* WEBS */ 49#include <asm/types.h> 50#include <typedefs.h> 51#include <bcmnvram.h> 52#include <bcmutils.h> 53#include <shutils.h> 54#ifdef RTCONFIG_RALINK 55#include <ralink.h> 56#include <iwlib.h> 57#include <stapriv.h> 58#include <ethutils.h> 59#endif 60#include <shared.h> 61#include <sys/mman.h> 62#ifndef O_BINARY 63#define O_BINARY 0 64#endif 65#ifndef MAP_FAILED 66#define MAP_FAILED (-1) 67#endif 68 69#include "tc_ver.h" 70#include "dsl-upg.h" 71 72#define SWAP_LONG(x) \ 73 ((__u32)( \ 74 (((__u32)(x) & (__u32)0x000000ffUL) << 24) | \ 75 (((__u32)(x) & (__u32)0x0000ff00UL) << 8) | \ 76 (((__u32)(x) & (__u32)0x00ff0000UL) >> 8) | \ 77 (((__u32)(x) & (__u32)0xff000000UL) >> 24) )) 78 79 80 81static int update_tc_fw = 0; 82 83#define IH_NMLEN 32 84 85typedef struct { 86 unsigned int ih_magic; 87 unsigned int ih_hcrc; 88 unsigned int ih_time; 89 unsigned int ih_size; 90 unsigned int ih_load; 91 unsigned int ih_ep; 92 unsigned int ih_dcrc; 93 unsigned char ih_os; 94 unsigned char ih_arch; 95 unsigned char ih_type; 96 unsigned char ih_comp; 97 unsigned char ih_name[IH_NMLEN]; 98} IMAGE_HEADER_TRX; 99 100int separate_tc_fw_from_trx() 101{ 102 IMAGE_HEADER_TRX* TrxHdr; 103 FILE* FpTrx; 104 char TrxHdrBuf[512]; 105 char buf[4096]; 106 unsigned int* pTrxSize; 107 unsigned int TrxSize; 108 unsigned int filelen; 109 unsigned int TcFwSize; 110 int TcFwExist = 0; 111 int RetVal = 0; 112 113 FILE* fpSrc = NULL; 114 FILE* fpDst = NULL; 115 116 FpTrx = fopen("/tmp/linux.trx","rb"); 117 if (FpTrx == NULL) goto err; 118 fread(TrxHdrBuf,1,sizeof(TrxHdrBuf),FpTrx); 119 fseek( FpTrx, 0, SEEK_END); 120 filelen = ftell( FpTrx ); 121 fclose(FpTrx); 122 123 pTrxSize = &TrxHdrBuf[12]; 124 TrxSize = SWAP_LONG(*pTrxSize) + 64; 125 _dprintf("trx size %x , file size %x\n",TrxSize,filelen); 126 if (filelen > TrxSize) 127 { 128 TcFwSize = filelen - TrxSize; 129 _dprintf("tcfw size %x\n",TcFwSize); 130 131 // 132 // linux trx has several bytes garbage in the file tail 133 // only save tc fw if the tc fw size is a valid number 134 // 135 if (TcFwSize > 0x100) 136 { 137 fpSrc = fopen("/tmp/linux.trx", "rb"); 138 if (fpSrc==NULL) goto err; 139 fpDst = fopen("/tmp/tcfw.bin", "wb"); 140 if (fpDst==NULL) goto err; 141 142 fseek(fpSrc,TrxSize,SEEK_SET); 143 while (TcFwSize > 0) 144 { 145 if (TcFwSize > sizeof(buf)) 146 { 147 fread(buf, 1, sizeof(buf), fpSrc); 148 fwrite(buf, 1, sizeof(buf), fpDst); 149 TcFwSize -= sizeof(buf); 150 } 151 else 152 { 153 fread(buf, 1, TcFwSize, fpSrc); 154 fwrite(buf, 1, TcFwSize, fpDst); 155 TcFwSize = 0; 156 } 157 } 158 159 update_tc_fw = 1; 160 } 161 } 162 else if (TrxSize == filelen) 163 { 164 // only trx, no tc fw 165 _dprintf("no tc fw\n"); 166 } 167 168 RetVal = 1; 169 170err: 171 if (fpSrc) 172 fclose(fpSrc); 173 174 if (fpDst) 175 fclose(fpDst); 176 177 return RetVal; 178} 179 180static int crc_table_empty = 1; 181static unsigned long crc_table[256]; 182 183static void make_crc_table() 184{ 185 unsigned long c; 186 int n, k; 187 unsigned long poly; /* polynomial exclusive-or pattern */ 188 /* terms of polynomial defining this crc (except x^32): */ 189 static const unsigned char p[] = {0,1,2,4,5,7,8,10,11,12,16,22,23,26}; 190 191 /* make exclusive-or pattern from polynomial (0xedb88320L) */ 192 poly = 0L; 193 for (n = 0; n < sizeof(p)/sizeof(unsigned char); n++) 194 poly |= 1L << (31 - p[n]); 195 196 for (n = 0; n < 256; n++) 197 { 198 c = (unsigned long)n; 199 for (k = 0; k < 8; k++) 200 c = c & 1 ? poly ^ (c >> 1) : c >> 1; 201 crc_table[n] = c; 202 } 203 crc_table_empty = 0; 204} 205 206 207#define DO1(buf) crc = crc_table[((int)crc ^ (*buf++)) & 0xff] ^ (crc >> 8); 208#define DO2(buf) DO1(buf); DO1(buf); 209#define DO4(buf) DO2(buf); DO2(buf); 210#define DO8(buf) DO4(buf); DO4(buf); 211 212unsigned long crc32_no_comp(unsigned long crc,const unsigned char* buf, int len) 213{ 214 if (crc_table_empty) 215 make_crc_table(); 216 217 while (len >= 8) 218 { 219 DO8(buf); 220 len -= 8; 221 } 222 if (len) do { 223 DO1(buf); 224 } while (--len); 225 226 return crc; 227} 228int check_tc_firmware_crc(void) 229{ 230 FILE* fpSrc = NULL; 231 FILE* fpDst = NULL; 232 unsigned long crc_value; 233 unsigned long* crc_value_ptr; 234 unsigned long calc_crc; 235 long tcfilelen; 236 long filelen, *filelenptr; 237 int cmpHeaderErr = 0; 238 int RetVal = 0; 239 char buf[4096]; 240 int new_modem_trx_ver; 241 int curr_modem_trx_ver; 242 unsigned char bBuf[4096]; 243 unsigned char tag[] = {0x3C, 0x23, 0x24, 0x3E}; //<#$> 244 int bBufsize = sizeof(bBuf); 245 246 if (update_tc_fw == 0) return 0; 247 248 249 fpSrc = fopen("/tmp/tcfw.bin", "rb"); 250 if (fpSrc==NULL) 251 { 252 cmpHeaderErr = 1; 253 goto exit; 254 } 255 fpDst = fopen("/tmp/ras.bin", "wb"); 256 if (fpDst==NULL) 257 { 258 cmpHeaderErr = 1; 259 goto exit; 260 } 261 262 fread(buf, 1, 0x100, fpSrc); 263 264 _dprintf("TC FW VER : %c%c%c , %s , %s\n",buf[0],buf[1],buf[2],TC_DSL_FW_VER,TC_DSL_FW_VER_FROM_MODEM); 265 266 267 //read tcfw.bin and find the driver ras info, date ... 268 fseek(fpSrc, 0xF000, SEEK_SET); 269 fread(bBuf, 1, bBufsize, fpSrc); 270 271 int read_idx = bBufsize; 272 while (read_idx--) { 273 if(bBuf[read_idx] == tag[3]) 274 if(bBuf[--read_idx] == tag[2]) 275 if(bBuf[--read_idx] == tag[1]) 276 if(bBuf[--read_idx] == tag[0]) 277 break; 278 else 279 continue; 280 else 281 continue; 282 else 283 continue; 284 else 285 continue; 286 } 287 _dprintf("bin date: %s\n", (char*)bBuf+read_idx-14); 288 _dprintf("bin ras: %s\n", (char*)bBuf+read_idx+4); 289 290 fseek(fpSrc, 0x0100, SEEK_SET); 291 292 //check Annex mode 293#ifdef RTCONFIG_DSL_ANNEX_B 294 if(bBuf[read_idx+14] != 'B') { //ASUS_Annex'B'_.. 295 if(bBuf[read_idx+9] != '1') { //check for the old ras info ASUS_1020 296 RetVal = -1; 297 _dprintf("check annex failed\n"); 298 goto exit; 299 } 300 } 301#else 302 if(bBuf[read_idx+14] != 'A') { //ASUS_ANNEX'A'IJLM_.. 303 if(bBuf[read_idx+9] != '1') { //check for the old ras info ASUS_1020 304 RetVal = -1; 305 _dprintf("check annex failed\n"); 306 goto exit; 307 } 308 } 309#endif 310 //check driver release date 311 // /tmp/adsl # cat tc_ver_info.txt 312 // Bootbase:VTC_SPI_BR1.6 | 2010/7/30 313 // RAS:ASUS_ANNEXAIJLM_20120423 314 // System:3.6.18.0(BE.C3)3.16.18.0| 2011/10/31 20111031_v012 [Oct 31 2011 12:53:59] 315 FILE *fpCur; 316 char ver_info_buf[256]; 317 int line_idx = 3; 318 int ver_idx = 0; 319 fpCur = fopen("/tmp/adsl/tc_ver_info.txt", "r"); 320 if(fpCur != NULL) { 321 while(line_idx--) 322 fgets(ver_info_buf, 256, fpCur); 323 fclose(fpCur); 324 while(++ver_idx < 256) { 325 if(ver_info_buf[ver_idx] == 0x7C) { 326 *(ver_info_buf + ver_idx + 12) = '\0'; 327 _dprintf("cur date: %s\n", ver_info_buf+ver_idx+2); 328 if(!strncmp(ver_info_buf+ver_idx+2, (char*)bBuf+read_idx-14, 10)) 329 update_tc_fw = 0; 330 else 331 update_tc_fw = 1; 332 break; 333 }else 334 continue; 335 } 336 } 337 338 //check RAS 339 fpCur = fopen("/tmp/adsl/tc_ras_ver.txt", "r"); 340 if(fpCur != NULL) { 341 fgets(ver_info_buf, 256, fpCur); 342 fclose(fpCur); 343 _dprintf("cur ras: %s\n", ver_info_buf); 344#ifdef RTCONFIG_DSL_ANNEX_B 345 if(!strncmp(ver_info_buf, (char*)bBuf+read_idx+4, 20)) //ASUS_AnnexB_20111031 346#else 347 if(!strncmp(ver_info_buf, (char*)bBuf+read_idx+4, 24)) //ASUS_ANNEXAIJLM_20120423 348#endif 349 update_tc_fw = 0; 350 else 351 update_tc_fw = 1; 352 } 353 _dprintf("update tc fw or not: %d (0 is not)\n", update_tc_fw); 354 355#if 0 //disable by Sam, 2012/07/12 356 357// There are two firmware on single TRX. One is router firmware and the other is modem firmware. 358// Router firmware could upgrade or downgrade depends on end-user. 359// For ADSL firmware , we will allow end-user to upgrade only because modem firmware updating is really dangerous. 360// That��s okay even uses new modem firmware on old router firmware. 361// End-user could downgrade router firmware below 1.021 first and then upgrade old TRX again. The modem firmware will be downgraded. 362 363 // get ver number from trx 364 buf[3] = 0; 365 new_modem_trx_ver = atoi(buf); 366#ifdef DSL_N55U_ANNEX_B 367 curr_modem_trx_ver = atoi(TC_DSL_FW_VER_ANNEX_B); 368#else 369 curr_modem_trx_ver = atoi(TC_DSL_FW_VER); 370#endif 371 if(curr_modem_trx_ver > new_modem_trx_ver) 372 { 373 update_tc_fw = 0; 374 } 375 else 376 { 377#define TC_BUF_SZIE 256 378 int buf_idx; 379 int tc_fw_ver_diff = 0; 380 int tc_ras_ver_diff = 0; 381 char buf_tc_fw_ver[TC_BUF_SZIE]; 382 FILE *fp; 383 fp = fopen("/tmp/adsl/tc_fw_ver_short.txt", "r"); 384 if (fp != NULL) { 385 memset(buf_tc_fw_ver, 0, TC_BUF_SZIE); 386 fgets(buf_tc_fw_ver, TC_BUF_SZIE, fp); 387 fclose(fp); 388 // normalize string 389 for (buf_idx=0; buf_idx<TC_BUF_SZIE; buf_idx++) { 390 if (buf_tc_fw_ver[buf_idx]==0x0d || buf_tc_fw_ver[buf_idx]==0x0a) buf_tc_fw_ver[buf_idx] = 0; 391 if (buf_tc_fw_ver[buf_idx] == 0) break; 392 } 393#ifdef DSL_N55U_ANNEX_B 394 if(strcmp(buf_tc_fw_ver, TC_DSL_FW_VER_FROM_MODEM_ANNEX_B) == 0) 395 { 396 _dprintf("annex b firmware is the same\n"); 397 } 398 else 399 { 400 tc_fw_ver_diff = 1; 401 } 402#else 403 if(strcmp(buf_tc_fw_ver, TC_DSL_FW_VER_FROM_MODEM) == 0) 404 { 405 _dprintf("annex a firmware is the same\n"); 406 } 407 else 408 { 409 tc_fw_ver_diff = 1; 410 } 411#endif 412 } 413 414 fp = fopen("/tmp/adsl/tc_ras_ver.txt", "r"); 415 if (fp != NULL) { 416 memset(buf_tc_fw_ver, 0, TC_BUF_SZIE); 417 fgets(buf_tc_fw_ver, TC_BUF_SZIE, fp); 418 fclose(fp); 419 // normalize string 420 for (buf_idx=0; buf_idx<TC_BUF_SZIE; buf_idx++) { 421 if (buf_tc_fw_ver[buf_idx]==0x0d || buf_tc_fw_ver[buf_idx]==0x0a) buf_tc_fw_ver[buf_idx] = 0; 422 if (buf_tc_fw_ver[buf_idx] == 0) break; 423 } 424#ifdef DSL_N55U_ANNEX_B 425 if(strcmp(buf_tc_fw_ver, TC_DSL_RAS_VER_FROM_MODEM_ANNEX_B) == 0) 426 { 427 _dprintf("annex b firmware is the same\n"); 428 } 429 else 430 { 431 tc_ras_ver_diff = 1; 432 } 433 //check Annex mode, Sam 2012/06/20 434 if(buf_tc_fw_ver[10] != 'B') { //ASUS_Annex'B'_.. 435 RetVal = -1; 436 goto exit; 437 } 438#else 439 if(strcmp(buf_tc_fw_ver, TC_DSL_RAS_VER_FROM_MODEM) == 0) 440 { 441 _dprintf("annex a firmware is the same\n"); 442 } 443 else 444 { 445 tc_ras_ver_diff = 1; 446 } 447 //check Annex mode, Sam 2012/06/20 448 if(buf_tc_fw_ver[10] != 'A') { //ASUS_ANNEX'A'IJLM_.. 449 RetVal = -1; 450 goto exit; 451 } 452#endif 453 } 454 455 if (tc_fw_ver_diff || tc_ras_ver_diff) 456 { 457 // fw ver or ras ver is differnt 458 // then , upgrade the modem firmware 459 } 460 else 461 { 462 update_tc_fw = 0; 463 } 464 } 465#endif //#if 0 466 467 _dprintf("tcfw magic : %x %x %x\n",buf[4],buf[5],buf[6]); 468 469 if (strncmp(&buf[4], TC_DSL_MAGIC_NUMBER, 3) == 0) 470 { 471 // magic number OK 472 } 473 else 474 { 475 cmpHeaderErr = 1; 476 goto exit; 477 } 478 479 480 filelenptr=(long*)(buf+22); 481 filelen=*filelenptr; 482 _dprintf("tcfw Filelen: %d\n", filelen); 483 tcfilelen=filelen-0x100; 484 485 crc_value_ptr=(unsigned long*)(buf+34); 486 crc_value=*crc_value_ptr; 487 crc_value=SWAP_LONG(crc_value); 488 _dprintf("tcfw crc: %x\n", crc_value); 489 490 calc_crc = 0xffffffff; 491 492 while(tcfilelen>0) 493 { 494 if (tcfilelen > sizeof(buf)) 495 { 496 fread(buf, 1, sizeof(buf), fpSrc); 497 fwrite(buf, 1, sizeof(buf), fpDst); 498 calc_crc = crc32_no_comp(calc_crc,buf,sizeof(buf)); 499 tcfilelen-=sizeof(buf); 500 } 501 else 502 { 503 fread(buf, 1, tcfilelen, fpSrc); 504 fwrite(buf, 1, tcfilelen, fpDst); 505 calc_crc = crc32_no_comp(calc_crc,buf,tcfilelen); 506 tcfilelen=0; 507 } 508 } 509 510 511 _dprintf("tcfw calc crc is %x\n", calc_crc); 512 _dprintf("tcfw done\n"); 513 514 515exit: 516 517 if((calc_crc != crc_value) || cmpHeaderErr) 518 { 519 _dprintf("header crc error\n"); 520 RetVal = -1; 521 } 522 523 524 if (fpSrc) 525 fclose(fpSrc); 526 527 if (fpDst) 528 fclose(fpDst); 529 530 return RetVal; 531} 532 533/* 534 * 0: illegal image 535 * 1: legal image 536 * 537 * check product id, crc .. 538 */ 539 540// ANNEX A 541//DSL-N55U_1.0.0.9_Annex_A.trx 542// ANNEX B 543//DSL-N55U_1.0.0.9_Annex_B.trx 544 545 546int dsl_check_imagefile_str(char *fname) 547{ 548 int len; 549 char end_char; 550 len = strlen(fname); 551 if (len > 0) len--; 552 end_char = *(fname+len); 553#ifdef DSL_N55U_ANNEX_B 554 if (end_char != 'B') return 0; 555#else 556 if (end_char != 'A') return 0; 557#endif 558 return 1; 559} 560 561 562int truncate_trx(void) 563{ 564 IMAGE_HEADER_TRX* TrxHdr; 565 FILE* FpTrx; 566 char TrxHdrBuf[512]; 567 unsigned int* pTrxSize; 568 unsigned int TrxSize; 569 570// if (update_tc_fw == 0) return 0; 571 572 FpTrx = fopen("/tmp/linux.trx","rb"); 573 if (FpTrx == NULL) return 0; 574 fread(TrxHdrBuf,1,sizeof(TrxHdrBuf),FpTrx); 575 fclose(FpTrx); 576 pTrxSize = &TrxHdrBuf[12]; 577 TrxSize = SWAP_LONG(*pTrxSize); 578 //_dprintf("trx size %x\n",TrxSize); 579 truncate("/tmp/linux.trx",TrxSize + 64); 580 // 64 is trx header size 581 return 1; 582} 583 584#define ADSL_FW_IP_PREFIX "194.255.255." 585 586 587void do_upgrade_adsldrv(void) 588{ 589 int ret; 590 char UpdateFwBuf[256]; 591 char PingBuf[256]; 592 char OneLine[80]; 593 char ipaddr[80]; 594 FILE* fp; 595 int WaitCnt; 596 int chk_image_err = 0; 597 598 if (update_tc_fw == 0) return; 599 600 fp = fopen("/tmp/adsl/tc_ip_addr.txt","r"); 601 if (fp == NULL) chk_image_err = 1; 602 fgets(ipaddr,sizeof(ipaddr),fp); 603 fclose(fp); 604 605 // if adsl fw IP address is different, user should update to a new router fw first 606 if (strncmp(ipaddr,ADSL_FW_IP_PREFIX,sizeof(ADSL_FW_IP_PREFIX)-1)!=0) chk_image_err = 1; 607 608 strcpy(UpdateFwBuf,"cd /tmp; tftp -p -l ras.bin "); 609 strcat(UpdateFwBuf,ipaddr); 610 611 _dprintf("## upgrade tc fw\n"); 612 613 if (chk_image_err == 0) 614 { 615 _dprintf("IP alias for ADSL firmware update\n"); 616 // this command will stop tp_init 617 system("adslate waitadsl;adslate quitdrv"); 618 system("ifconfig eth2.1:0 194.255.255.1 netmask 255.255.255.0;ifconfig eth2.1:0 up"); 619 // wait if up 620 strcpy(PingBuf,"ping "); 621 strcat(PingBuf,ipaddr); 622 strcat(PingBuf," -c 1"); 623 for (WaitCnt=0; WaitCnt<3; WaitCnt++) 624 { 625 system(PingBuf); 626 } 627 _dprintf("Start to update\n"); 628 _dprintf(UpdateFwBuf); 629 system(UpdateFwBuf); 630 _dprintf("tftp done\n"); 631 //usleep(1000*1000*5); 632 // wait a miniute and send set to default setting 633 for (WaitCnt=0; WaitCnt<20; WaitCnt++) 634 { 635 system(PingBuf); 636 } 637 // ifconfig down also remove IP alias 638 system("tp_init clear_modem_var"); 639 // wait tc flash write completed 640 usleep(1000*1000*2); 641 _dprintf("\nupgrade done\n"); 642 } 643} 644 645 646 647// -1: different or no origial header, upgrade 648// 0: same or no upgrade file, skip upgrade 649int compare_linux_image(void) 650{ 651 IMAGE_HEADER_TRX* TrxHdr; 652 FILE* FpHdr; 653 char TrxHdrBuf[512]; 654 unsigned int OrigTime; 655 unsigned int NewTime; 656 657 memset(TrxHdrBuf,0,sizeof(TrxHdrBuf)); 658 FpHdr = fopen("/tmp/trx_hdr.bin","rb"); 659 if (FpHdr == NULL) return -1; 660 fread(TrxHdrBuf,1,sizeof(TrxHdrBuf),FpHdr); 661 fclose(FpHdr); 662 TrxHdr = (IMAGE_HEADER_TRX*)TrxHdrBuf; 663 664 OrigTime = SWAP_LONG(TrxHdr->ih_time); 665 666 memset(TrxHdrBuf,0,sizeof(TrxHdrBuf)); 667 FpHdr = fopen("/tmp/linux.trx","rb"); 668 if (FpHdr == NULL) return 0; 669 fread(TrxHdrBuf,1,sizeof(TrxHdrBuf),FpHdr); 670 fclose(FpHdr); 671 TrxHdr = (IMAGE_HEADER_TRX*)TrxHdrBuf; 672 673 NewTime = SWAP_LONG(TrxHdr->ih_time); 674 675 fprintf(stderr, "Trx %x %x\n", NewTime, OrigTime); 676 677 if (NewTime == OrigTime) 678 { 679 fprintf(stderr, "trx same\n"); 680 return 0; 681 } 682 fprintf(stderr, "trx different\n"); 683 return -1; 684} 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699