1
0
Files
2016-11-30 09:03:17 +08:00

1568 lines
44 KiB
C
Executable File

#include "skbuff.h"
#include "eth.h"
#include "ip.h"
#include "udp.h"
#include "arp.h"
#include "icmp.h"
#include "ipv4/lwip/ip_addr.h"
#include "lwip/err.h"
#include "lwip/pbuf.h"
#include "lwip/tcp.h"
#include "lwip/opt.h"
#include "linux/stddef.h"
#include "osdep.h"
#include "common.h"
#ifdef TCSUPPORT_NAND_RT63368
extern int nand_logic_size;
#endif
#if defined(TCSUPPORT_MULTI_UPGRADE) || defined(TCSUPPORT_MULTI_BOOT)
#include "../../../tools/trx/trx.h"
#include <asm/tc3162.h>
#include <spiflash.h>
#include <nandflash.h>
#include "../include/flashhal.h"
#include "tftp.h"
#include "mac.h"
#if !defined(TCSUPPORT_CT_WAN_PTM)
#define DBG_PRINT
#endif
#define MULTI_BUF_BASE 0x80020000
#define MICONF_OFFSET 0xff00
#define MICONF_SIZE 0x100
#define DSL_GPIO_DEFAULT 6
#define INTERNET_GPIO_DEFAULT 7
struct mtd_info {
unsigned long offset; /* Offset within the memory */
unsigned long size; /* Total size of the MTD */
unsigned long erasesize;
};
extern struct mtd_info mtd;
#ifdef TCSUPPORT_BB_NAND
extern struct ra_nand_chip ra;
#endif
#endif
#if defined(TCSUPPORT_MULTI_UPGRADE)
#if !defined(TCSUPPORT_C1_TRUE)
#define BACKUPRF_TO_BOTTOM_2 0x20000
#define BACKUPRF_TO_BOTTOM_3 0x30000
#define BACKUPRF_TO_BOTTOM_4 0x40000
#define BACKUPRF_TO_BOTTOM_7 0x70000
#endif
#endif
#define RESERVEAREA_BLOCK_BASE 0
/*backupromfile*/
#define BACKUPROMFILE_RA_SIZE 0x10000
#define BACKUPROMFILE_RA_OFFSET RESERVEAREA_BLOCK_BASE
/*defaultromfile*/
#define DEFAULTROMFILE_RA_SIZE 0x10000
#define DEFAULTROMFILE_RA_OFFSET (BACKUPROMFILE_RA_OFFSET+BACKUPROMFILE_RA_SIZE)
/*syslog*/
#define SYSLOG_RA_SIZE 0x10000
#define SYSLOG_RA_OFFSET (DEFAULTROMFILE_RA_OFFSET+DEFAULTROMFILE_RA_SIZE)
/*product para*/
#define PROLINE_CWMPPARA_RA_SIZE 0x10000
#define PROLINE_CWMPPARA_RA_OFFSET (SYSLOG_RA_OFFSET+SYSLOG_RA_SIZE)
/*temp data*/
#define TEMP_RA_SIZE 0x10000
#define TEMP_RA_OFFSET (PROLINE_CWMPPARA_RA_OFFSET+PROLINE_CWMPPARA_RA_SIZE)
#if defined(TCSUPPORT_MULTI_BOOT)
#define MULTIBOOT_SIG_OFFSET 8
#define MULTIBOOT_SIG "zyx"
#define MULTIBOOT_PACKET_SIZE 1024
#define TRX_LEN 256
#define ROMD_TO_BOTTOM 0x50000
#define CLEAR_ROMFILE 0x2
#define CLEAR_ROMD 0x4
#define CUR_FILE_MASK 0xFF00
#define CURR_FILE_FLAG_BOOT 0x100
#define CURR_FILE_FLAG_ROMFILE 0x200
#define CURR_FILE_FLAG_TCLINUX 0x400
#define CURR_FILE_FLAG_ROMD 0x800
#define ROMFILE_SIZE 0x10000
struct MULTI_BOOT_T{
unsigned char signature[4];
unsigned short checkSum;
unsigned int ID;
unsigned int dataLen;
unsigned int fileLen;
unsigned int fileFlag;
unsigned short countryCode;
unsigned char debugFlag;
unsigned char reserve1;
unsigned int reserve2;
unsigned char data[MULTIBOOT_PACKET_SIZE];
} __attribute__ ((packed));
unsigned int rcv_len = 0;
volatile char finishMultiBoot = 0;
unsigned int cur_file_type = 0;
volatile char startMultiBoot= 0;
#endif
#if defined(TCSUPPORT_MULTI_UPGRADE)
/*
pkt format is shown as below:
byte 0~1 pkt type
byte 2~3 pkt sequence
byte 4~11 pkt tag
byte 12~15 total length
byte 16~19 CRC of firmware fragment
byte 20~23 CRC of whole firmware
1024bytes data
*/
#define MULTI_UPGRADE_PKT_TAG "TCBulkFW"
#define MULTIPKT_TAG_OFFSET 12
#define LAST_MULTIPKT 0x40
#define NOT_LAST_MULTIPKT 0x20
#define IMG_LEN_OFFSET 20
#define LT_OFFSET 8
#define CRC_OFFSET 28
#define MULTI_UPGRADE_PKT_HEADLEN 32
#define MULTI_UPGRADE_DATA_LEN 1024
unsigned long receive_len = 0;
char startMultiUpgrade = 0;
#define FLASH_ERASE_SIZE 0x10000
extern int nand_logic_size;
extern int nand_flash_avalable_size;
extern u32 reservearea_size;
#ifdef TCSUPPORT_BB_NAND
#ifdef TCSUPPORT_MTD_PARTITIONS_CMDLINE
#define ROMFILE_SIZE ecnt_get_romfile_size()
#else
#ifdef TCSUPPORT_NAND_BMT
#define ROMFILE_SIZE 0x40000
#else
#if defined(TCSUPPORT_CT_PON)
#define ROMFILE_SIZE 0x40000
#else
#define ROMFILE_SIZE 0x10000
#endif
#endif
#endif
#if (TCSUPPORT_RESERVEAREA_BLOCK==7)
#if defined(TCSUPPORT_CT_PON)
#define RESERVEAREA_BLOCK_BASE 0
/*backupromfile*/
#define BACKUPROMFILE_RA_SIZE 0x40000
#define BACKUPROMFILE_RA_OFFSET RESERVEAREA_BLOCK_BASE
/*defaultromfile*/
#define DEFAULTROMFILE_RA_SIZE 0x40000
#define DEFAULTROMFILE_RA_OFFSET (BACKUPROMFILE_RA_OFFSET+BACKUPROMFILE_RA_SIZE)
/*syslog*/
#define SYSLOG_RA_SIZE 0x40000
#define SYSLOG_RA_OFFSET (DEFAULTROMFILE_RA_OFFSET+DEFAULTROMFILE_RA_SIZE)
/*product para*/
#define PROLINE_CWMPPARA_RA_SIZE 0x40000
#define PROLINE_CWMPPARA_RA_OFFSET (SYSLOG_RA_OFFSET+SYSLOG_RA_SIZE)
/*temp data*/
#define TEMP_RA_SIZE 0x40000
#define TEMP_RA_OFFSET (PROLINE_CWMPPARA_RA_OFFSET+PROLINE_CWMPPARA_RA_SIZE)
#endif
#endif
#else
#ifdef TCSUPPORT_MTD_PARTITIONS_CMDLINE
#define ROMFILE_SIZE ecnt_get_romfile_size()
#else
#define ROMFILE_SIZE 0x10000
#endif
#if (TCSUPPORT_RESERVEAREA_BLOCK==7)
#if defined(TCSUPPORT_CT_PON)
#define RESERVEAREA_BLOCK_BASE 0
/*backupromfile*/
#define BACKUPROMFILE_RA_SIZE 0x10000
#define BACKUPROMFILE_RA_OFFSET RESERVEAREA_BLOCK_BASE
/*defaultromfile*/
#define DEFAULTROMFILE_RA_SIZE 0x10000
#define DEFAULTROMFILE_RA_OFFSET (BACKUPROMFILE_RA_OFFSET+BACKUPROMFILE_RA_SIZE)
/*syslog*/
#define SYSLOG_RA_SIZE 0x10000
#define SYSLOG_RA_OFFSET (DEFAULTROMFILE_RA_OFFSET+DEFAULTROMFILE_RA_SIZE)
/*product para*/
#define PROLINE_CWMPPARA_RA_SIZE 0x10000
#define PROLINE_CWMPPARA_RA_OFFSET (SYSLOG_RA_OFFSET+SYSLOG_RA_SIZE)
/*temp data*/
#define TEMP_RA_SIZE 0x10000
#define TEMP_RA_OFFSET (PROLINE_CWMPPARA_RA_OFFSET+PROLINE_CWMPPARA_RA_SIZE)
#endif
#endif
#endif
#if !defined(TCSUPPORT_C1_TRUE)
volatile char finishMultiUpgrade = 0;
int maxMultiLedNum = 16;
#endif
extern unsigned long Jiffies;
#if defined(TCSUPPORT_MULTI_UPGRADE_LIONS)
/*according to the structure of map defined in mic.c*/
typedef struct _mrdInfoLinux_s{
unsigned char SDRAM_CONF_array[4];
unsigned char VENDOR_NAME[32];
unsigned char PRODUCT_NAME[32];
unsigned char FUNC_BYTE[4];
unsigned char ETHER_ADDR[6];
unsigned char SNMP_SYSOBJID_array[22];
unsigned char COUNTRY_array;
unsigned char ether_gpio;
unsigned char power_gpio[2];
}mrdInfoLinux_t;
#define LIONS_ETHER_ADDR_OFFSET 0x5ff8
#define TC_FLASH_READ_CMD "/userfs/bin/mtd readflash %s %lu %lu %s"
#define LINOSALLINONE_SIG_OFFSET 38
#define LINOSALLINONE_LEN_OFFSET 42
#define LINOSALLINONE_CHKSUM_OFFSET 52
#define LINOSALLINONE_HEADER 51
#define SIG_LINOSALLINONE "LOA"
#define SIG_LEN 3
#define LINOSALLINONE_FIRST_PKT_HEADLEN 83
#define LINOSALLINONE_FIRST_DATA_LEN 973
static uint8 odd_flag = 0;
static uint8 isLinosAllinone = 0;
static unsigned short mutAllinoneChksum = 0;
static unsigned long mutAllinoneSize = 0;
static uint32 ChkSum = 0;
void linosAllinoneChkSumCalc(uint8 *start_p, uint32 len)
{
uint32 i;
uint16 word;
for( i=0; i<len; i++ )
{
word = start_p[i];
if( (i&0x01) == odd_flag )
ChkSum += (word << 8)&0xff00 ;
else
ChkSum += word&0x00ff;
if (ChkSum > 0xFFFF)
ChkSum = (ChkSum + 1) & 0xFFFF;
}
if( (receive_len&0x01) == 1 )
odd_flag = 1;
else
odd_flag = 0;
}
void restore_linux_info(char *buf)
{
mrdInfoLinux_t mrd_u;
unsigned char mic_buf[256] = {0};
unsigned long retlen;
memset(&mrd_u,0,sizeof(mrd_u));
flash_read(TCBOOT_BASE+MICONF_OFFSET, MICONF_SIZE, &retlen, mic_buf);
mrd_u = *(mrdInfoLinux_t *)mic_buf;
/*only restore Linux mac addr. Other parameters in Linux mrd can be update as below. */
memcpy(buf+LIONS_ETHER_ADDR_OFFSET, mrd_u.ETHER_ADDR, 6);
return;
}
#endif
void MultiWriteImage(char *ptr, unsigned long datalen)
{
struct trx_header *trx = (struct trx_header *)ptr;
unsigned long retlen;
int cal_check_sum = 0;
unsigned int romfile_offset = 0;
unsigned int tclinux_size = 0;
#if !defined(TCSUPPORT_C1_TRUE)
unsigned int backuprf_offset = 0;
#endif
/*Get the Internet GPIO Number*/
// uint8 internet_gpio = *(uint8 *)(INTERNET_GPIO);
uint8 internet_gpio = READ_FLASH_BYTE(INTERNET_GPIO);
/*Get the DSL GPIO Number*/
// uint8 dsl_gpio = *(uint8 *)(ADSL_GPIO);
uint8 dsl_gpio = READ_FLASH_BYTE(ADSL_GPIO);
if(dsl_gpio == 0)
dsl_gpio = DSL_GPIO_DEFAULT;
if(internet_gpio == 0){
if(isEN7526D || isEN7526G || isEN7513 || isEN7513G || isEN7521G || isEN7586)
internet_gpio = 28;
else if(isEN7526F || isEN7521F || isEN7521S || isEN7512)
internet_gpio = 4;
else
internet_gpio = INTERNET_GPIO_DEFAULT;
}
#if !defined(TCSUPPORT_C1_TRUE)
if (IS_SPIFLASH) {
#if (TCSUPPORT_RESERVEAREA_BLOCK==2)
backuprf_offset = mtd.size - BACKUPRF_TO_BOTTOM_2;
#elif (TCSUPPORT_RESERVEAREA_BLOCK==3)
backuprf_offset = mtd.size - BACKUPRF_TO_BOTTOM_3;
#elif (TCSUPPORT_RESERVEAREA_BLOCK==4)
backuprf_offset = mtd.size - BACKUPRF_TO_BOTTOM_4;
#elif (TCSUPPORT_RESERVEAREA_BLOCK==7)
backuprf_offset = mtd.size - BACKUPRF_TO_BOTTOM_7;
#else
#endif
} else if (IS_NANDFLASH) {
#ifdef TCSUPPORT_BB_NAND
#if (TCSUPPORT_RESERVEAREA_BLOCK==2)
#ifdef TCSUPPORT_NAND_RT63368
backuprf_offset = nand_logic_size - 2 * (1<<ra.flash->erase_shift);
#else
backuprf_offset = (1<<ra.flash->chip_shift) - 2 * (1<<ra.flash->erase_shift);
#endif
#elif (TCSUPPORT_RESERVEAREA_BLOCK==3)
#ifdef TCSUPPORT_NAND_RT63368
backuprf_offset = nand_logic_size - 3 * (1<<ra.flash->erase_shift);
#else
backuprf_offset = (1<<ra.flash->chip_shift) - 3 * (1<<ra.flash->erase_shift);
#endif
#elif (TCSUPPORT_RESERVEAREA_BLOCK==4)
#ifdef TCSUPPORT_NAND_RT63368
backuprf_offset = nand_logic_size - 4 * (1<<ra.flash->erase_shift);
#else
backuprf_offset = (1<<ra.flash->chip_shift) - 4 * (1<<ra.flash->erase_shift);
//backuprf_offset = nand_logic_size - 4 * reservearea_size;
#endif
#elif (TCSUPPORT_RESERVEAREA_BLOCK==5)
#ifdef TCSUPPORT_NAND_RT63368
backuprf_offset = nand_logic_size - 5 * (1<<ra.flash->erase_shift);
#else
backuprf_offset = (1<<ra.flash->chip_shift) - 5 * (1<<ra.flash->erase_shift);
//backuprf_offset = nand_logic_size - 5 * reservearea_size;
#endif
#elif (TCSUPPORT_RESERVEAREA_BLOCK==7)
#ifdef TCSUPPORT_NAND_RT63368
backuprf_offset = nand_logic_size - 7 * (1<<ra.flash->erase_shift);
#else
//backuprf_offset = nand_logic_size - 7 * reservearea_size;
backuprf_offset = nand_flash_avalable_size - 7 * reservearea_size;
#endif
#else
#endif
#ifdef TCSUPPORT_NAND_BADBLOCK_CHECK
backuprf_offset = TCBKROMFILE_START << ra.flash->erase_shift;
#endif
#endif
}
#endif
/*
turn off ADSL LED and turn on Internet LED
*/
LED_ON(dsl_gpio);
LED_ON(internet_gpio);
#if defined(TCSUPPORT_MULTI_UPGRADE_LIONS)
if(isLinosAllinone == 1){
prom_printf("Linos allinone file\n");
prom_printf("Write to flash from %X to %X with %X bytes\n", MULTI_BUF_BASE, TCBOOT_BASE, datalen);
prom_printf(" write bootbase \n");
flash_erase(TCBOOT_BASE, TCBOOT_SIZE);
prom_printf("\n");
flash_write(TCBOOT_BASE, TCBOOT_SIZE, &retlen, (const unsigned char *) (MULTI_BUF_BASE));
prom_printf(" write ras \n");
flash_erase(0x10000,datalen-TCBOOT_SIZE);
prom_printf("\n");
flash_write(0x10000, datalen-TCBOOT_SIZE, &retlen, (const unsigned char *) (MULTI_BUF_BASE+TCBOOT_SIZE));
}
else{
#endif
if(trx->magic == TRX_MAGIC2){
prom_printf("bin file\n");
#ifdef DBG_PRINT
prom_printf("Write to flash from %X to %X with %X bytes\n", MULTI_BUF_BASE, flash_tclinux_start, datalen);
#endif
#if !defined(TCSUPPORT_C1_TRUE)
if (IS_SPIFLASH){
flash_erase((TCBOOT_BASE+TCBOOT_SIZE), ROMFILE_SIZE);//erase current romfile for reset with default setting
} else if (IS_NANDFLASH){
#ifdef TCSUPPORT_BB_NAND
if (ra_inl(CR_AHB_HWCONF) & (0x00080000)) {
#ifdef TCSUPPORT_NAND_BADBLOCK_CHECK
flash_erase(TCBOOT_BASE + 7 * (1<<ra.flash->erase_shift), ROMFILE_SIZE);
#elif defined(TCSUPPORT_NAND_RT63368)
flash_erase(TCBOOT_BASE + (1<<ra.flash->erase_shift), ROMFILE_SIZE);
#else
#ifdef TCSUPPORT_BB_NAND
#ifdef TCSUPPORT_NAND_BMT
flash_erase((TCBOOT_BASE+TCBOOT_SIZE), ROMFILE_SIZE);//erase current romfile for reset with default setting
#else
#if defined(TCSUPPORT_CT_PON)
flash_erase((TCBOOT_BASE+TCBOOT_SIZE), ROMFILE_SIZE);//erase current romfile for reset with default setting
#else
flash_erase((1<<ra.flash->chip_shift) - 6 * (1<<ra.flash->erase_shift), ROMFILE_SIZE);
#endif
#endif
#else
flash_erase((1<<ra.flash->chip_shift) - 6 * (1<<ra.flash->erase_shift), ROMFILE_SIZE);
#endif
#endif
} else {
flash_erase((TCBOOT_BASE+TCBOOT_SIZE), ROMFILE_SIZE);
}
#endif
}
#if !defined(TCSUPPORT_CT_PON_CN)
#if (TCSUPPORT_RESERVEAREA_BLOCK==2 || TCSUPPORT_RESERVEAREA_BLOCK==3 || TCSUPPORT_RESERVEAREA_BLOCK==4 || TCSUPPORT_RESERVEAREA_BLOCK==5 || TCSUPPORT_RESERVEAREA_BLOCK==7)
flash_erase(backuprf_offset, ROMFILE_SIZE);//erase backup romfile for reset with default setting
#if defined(TCSUPPORT_C7)
flash_erase(backuprf_offset+ROMFILE_SIZE, ROMFILE_SIZE);//erase default romfile for reset with default setting
#endif
#endif
#if (TCSUPPORT_RESERVEAREA_BLOCK==7)
#if defined(TCSUPPORT_CT_PON)
flash_erase(backuprf_offset+TEMP_RA_OFFSET, TEMP_RA_SIZE);//erase temp area data.
#endif
#endif
#endif
#endif
#ifdef TCSUPPORT_NAND_BADBLOCK_CHECK
flash_erase(TCBOOT_BASE + 20 * (1<<ra.flash->erase_shift), datalen);
prom_printf("\n");
flash_write(TCBOOT_BASE + 20 * (1<<ra.flash->erase_shift), datalen, &retlen, (const unsigned char *) (MULTI_BUF_BASE));
#elif defined(TCSUPPORT_NAND_RT63368)
flash_erase(TCBOOT_BASE + 2 * (1<<ra.flash->erase_shift), datalen);
prom_printf("\n");
flash_write(TCBOOT_BASE + 2 * (1<<ra.flash->erase_shift), datalen, &retlen, (const unsigned char *) (MULTI_BUF_BASE));
#else
flash_erase(flash_tclinux_start, datalen);
prom_printf("\n");
flash_write(flash_tclinux_start, datalen, &retlen, (const unsigned char *) (MULTI_BUF_BASE));
#endif
//flash_write();
}else{
prom_printf("all_in_one file\n");
#ifdef DBG_PRINT
prom_printf("bin file\n");
prom_printf("Write to flash from 0x%X to 0x%X with 0x%X bytes\n", MULTI_BUF_BASE, TCBOOT_BASE, datalen);
//flash_erase(TCBOOT_BASE, datalen);
//flash_write(TCBOOT_BASE, datalen, &retlen, (const unsigned char *) (MULTI_BUF_BASE));
prom_printf(" write tcboot.bin \n");
#endif
flash_erase(TCBOOT_BASE, TCBOOT_SIZE);
prom_printf("\n");
flash_write(TCBOOT_BASE, TCBOOT_SIZE, &retlen, (const unsigned char *) (MULTI_BUF_BASE));
#ifdef DBG_PRINT
prom_printf(" write romfile.cfg \n");
#endif
if (IS_SPIFLASH){
romfile_offset = TCBOOT_BASE+TCBOOT_SIZE;
} else if (IS_NANDFLASH){
#ifdef TCSUPPORT_BB_NAND
if (ra_inl(CR_AHB_HWCONF) & (0x00080000)) {
#ifdef TCSUPPORT_NAND_BADBLOCK_CHECK
romfile_offset = TCBOOT_BASE + 7 * (1<<ra.flash->erase_shift);
#elif defined(TCSUPPORT_NAND_RT63368)
romfile_offset = TCBOOT_BASE + (1<<ra.flash->erase_shift);
#else
#ifdef TCSUPPORT_BB_NAND
#ifdef TCSUPPORT_NAND_BMT
romfile_offset = TCBOOT_BASE+TCBOOT_SIZE;
#else
#if defined(TCSUPPORT_CT_PON)
romfile_offset = TCBOOT_BASE+TCBOOT_SIZE;
#else
romfile_offset = (1<<ra.flash->chip_shift) - 6 * (1<<ra.flash->erase_shift);
#endif
#endif
#else
romfile_offset = (1<<ra.flash->chip_shift) - 6 * (1<<ra.flash->erase_shift);
#endif
#endif
} else {
romfile_offset = TCBOOT_BASE+TCBOOT_SIZE;
}
#endif
}
flash_erase(romfile_offset, ROMFILE_SIZE);
prom_printf("\n");
#if defined(TCSUPPORT_CT)
#if defined(TCSUPPORT_CY)
#if (TCSUPPORT_RESERVEAREA_BLOCK==2 || TCSUPPORT_RESERVEAREA_BLOCK==3 || TCSUPPORT_RESERVEAREA_BLOCK==4 || TCSUPPORT_RESERVEAREA_BLOCK==7)
flash_erase(backuprf_offset, ROMFILE_SIZE);//erase backup romfile for reset with default setting
prom_printf("\n");
#endif
#endif
#if defined(TCSUPPORT_C7)
flash_write(romfile_offset, ROMFILE_SIZE, &retlen, (const unsigned char *) (MULTI_BUF_BASE+TCBOOT_SIZE));
#endif
#if (TCSUPPORT_RESERVEAREA_BLOCK==7)
#if defined(TCSUPPORT_CT_PON)
flash_erase(backuprf_offset+BACKUPROMFILE_RA_OFFSET, BACKUPROMFILE_RA_SIZE);//erase backup romfile.
flash_erase(backuprf_offset+TEMP_RA_OFFSET, TEMP_RA_SIZE);//erase temp area data.
#endif
#endif
#else
flash_write(romfile_offset, ROMFILE_SIZE, &retlen, (const unsigned char *) (MULTI_BUF_BASE+TCBOOT_SIZE));
#endif
#ifdef DBG_PRINT
prom_printf(" write tclinux.bin \n");
#endif
#ifdef TCSUPPORT_NAND_BADBLOCK_CHECK
flash_erase(TCBOOT_BASE + 20 * (1<<ra.flash->erase_shift), datalen-0x20000);
prom_printf("\n");
flash_write(TCBOOT_BASE + 20 * (1<<ra.flash->erase_shift), datalen-0x20000, &retlen, (const unsigned char *) (MULTI_BUF_BASE+flash_tclinux_start));
#elif defined(TCSUPPORT_NAND_RT63368)
flash_erase(TCBOOT_BASE + 2 * (1<<ra.flash->erase_shift), datalen-0x20000);
prom_printf("\n");
flash_write(TCBOOT_BASE + 2 * (1<<ra.flash->erase_shift), datalen-0x20000, &retlen, (const unsigned char *) (MULTI_BUF_BASE+flash_tclinux_start));
#else
/* should modify for general sun.zhu_20140503 */
flash_erase(TCBOOT_BASE+TCBOOT_SIZE+ROMFILE_SIZE, datalen-TCBOOT_SIZE-ROMFILE_SIZE);
prom_printf("\n");
flash_write(TCBOOT_BASE+TCBOOT_SIZE+ROMFILE_SIZE, datalen-TCBOOT_SIZE-ROMFILE_SIZE, &retlen, (const unsigned char *) (MULTI_BUF_BASE+flash_tclinux_start));
#endif
}
#if defined(TCSUPPORT_MULTI_UPGRADE_LIONS)
}
#endif
/*
turn on ADSL and Internet LED
*/
#ifdef DBG_PRINT
LED_ON(dsl_gpio);
LED_OFF(internet_gpio);
#endif
}
void
MultiUpgradeHandle(sk_buff *skb)
{
unsigned long LenAndType = swap32(*(unsigned long *)(skb->data + LT_OFFSET));
unsigned long pktseq = ((LenAndType & 0xffff0000)>>16);
unsigned long imagelen = swap32(*(unsigned long *)(skb->data + IMG_LEN_OFFSET));
unsigned char ret, pkt_type, last_packet = 0;
static unsigned long prevImgLen = 0;
static unsigned long Jiffiestmp;
static char tag = 0;
static int oldSeq=-1;
static int startSeq = -1;
static int maxSeq = 0;
int cal_check_sum = 0;
int raw_check_sum = 0;
unsigned char *crc_ptr = NULL;
struct trx_header *trx = (struct trx_header *)MULTI_BUF_BASE;
struct trx_header *aio_trx = NULL;
unsigned long retlen = 0;
static char badimg = 0;
/*Get the Internet GPIO Number*/
// uint8 internet_gpio = *(uint8 *)(INTERNET_GPIO);
uint8 internet_gpio = READ_FLASH_BYTE(INTERNET_GPIO);
/*Get the DSL GPIO Number*/
// uint8 dsl_gpio = *(uint8 *)(ADSL_GPIO);
uint8 dsl_gpio = READ_FLASH_BYTE(ADSL_GPIO);
if(dsl_gpio == 0)
dsl_gpio = DSL_GPIO_DEFAULT;
if(internet_gpio == 0){
if(isEN7526D || isEN7526G || isEN7513 || isEN7513G || isEN7521G || isEN7586)
internet_gpio = 28;
else if(isEN7526F || isEN7521F || isEN7521S || isEN7512)
internet_gpio = 4;
else
internet_gpio = INTERNET_GPIO_DEFAULT;
}
if(finishMultiUpgrade == 1){
return; //upgrade success
}
/* may modify for general sun.zhu_20140503 */
if (startSeq == -1)
{
startSeq = pktseq;
oldSeq = pktseq - 1;
receive_len = 0;
maxSeq = imagelen / MULTI_UPGRADE_DATA_LEN;
if (imagelen % MULTI_UPGRADE_DATA_LEN)
maxSeq++;
}
/*
check seq
*/
if (pktseq!=(oldSeq+1))
{
if ((pktseq != 1) || (oldSeq != maxSeq)) // on only one condition it would be fine: pktseq == 1 && oldSeq == macSeq
{
goto error;
}
}
oldSeq = pktseq; // always assign current packet seq to old seq, or the (oldSeq != maxSeq) would be false after the loop meets the end
if ((startSeq != -1) && ((startSeq != 1) && (pktseq == (startSeq - 1)) || (startSeq == 1 && pktseq == maxSeq)))
{
last_packet = 1;
}
else
{
last_packet = 0;
}
#if defined(TCSUPPORT_MULTI_UPGRADE_LIONS)
if(isLinosAllinone && (pktseq > 1)){
memcpy(MULTI_BUF_BASE + ((pktseq-1)*MULTI_UPGRADE_DATA_LEN)-LINOSALLINONE_HEADER, skb->data + MULTI_UPGRADE_PKT_HEADLEN, MULTI_UPGRADE_DATA_LEN);
receive_len += MULTI_UPGRADE_DATA_LEN;
linosAllinoneChkSumCalc(skb->data + MULTI_UPGRADE_PKT_HEADLEN,MULTI_UPGRADE_DATA_LEN);
}
else if(!isLinosAllinone){
#endif
memcpy(MULTI_BUF_BASE + ((pktseq-1)*MULTI_UPGRADE_DATA_LEN), skb->data + MULTI_UPGRADE_PKT_HEADLEN, MULTI_UPGRADE_DATA_LEN);
receive_len += MULTI_UPGRADE_DATA_LEN;
#if defined(TCSUPPORT_MULTI_UPGRADE_LIONS)
}
#endif
if((Jiffies - Jiffiestmp) > 20){
Jiffiestmp = Jiffies;
if(tag == 0){
#ifdef DBG_PRINT
LED_OFF(internet_gpio);
#endif
tag = 1;
}else{
#ifdef DBG_PRINT
LED_ON(internet_gpio);
#endif
tag = 0;
}
}
if(last_packet == 1){
#if defined(TCSUPPORT_MULTI_UPGRADE_LIONS)
if(isLinosAllinone){
if(receive_len < mutAllinoneSize){
#ifdef DBG_PRINT
prom_printf("linos allinone receive_len < imagelen\n");
#endif
receive_len = 0;
isLinosAllinone = 0;
goto error;
}
/*Check the image size, Linos has two block reserved area*/
if(IS_SPIFLASH){
if(mutAllinoneSize>(mtd.size-FLASH_ERASE_SIZE*2)){
#ifdef DBG_PRINT
prom_printf("Image too big for partition: %s\n", mtd);
LED_OFF(dsl_gpio);
LED_ON(internet_gpio);
#endif
receive_len = 0;
isLinosAllinone = 0;
goto error;
}
}
//prom_printf("calculate checksum = %x\n",(uint16)ChkSum);
/*crc check*/
if(mutAllinoneChksum != (uint16)ChkSum){
#ifdef DBG_PRINT
prom_printf("Linos Allinone checksum error!!calculate checksum = %x\n",(uint16)ChkSum);
LED_OFF(dsl_gpio);
LED_ON(internet_gpio);
#endif
receive_len = 0;
isLinosAllinone = 0;
goto error;
}
/*backup Linux mac address to Linos allinone*/
restore_linux_info((char *)MULTI_BUF_BASE);
#ifdef DBG_PRINT
prom_printf("Linos allinone receive ok, goto erase and write image to flash\n");
#endif
MultiWriteImage(MULTI_BUF_BASE, mutAllinoneSize);
finishMultiUpgrade = 1;
return;
}
#endif
if(receive_len >= imagelen){
/*
decide the type of image
*/
if(trx->magic == TRX_MAGIC2){
cal_check_sum = crc32buf((MULTI_BUF_BASE+sizeof(struct trx_header)), (imagelen-sizeof(struct trx_header)), 1);
if (cal_check_sum != trx->crc32){
#ifdef DBG_PRINT
prom_printf("checksum error!!! \r\n");
/*
turn off ADSL and Internet LED
*/
LED_OFF(dsl_gpio);
LED_ON(internet_gpio);
#endif
goto error;
}
if (IS_SPIFLASH) {
/*Check the image size*/
#if (TCSUPPORT_RESERVEAREA_BLOCK==1)
if(imagelen > (mtd.size-TCBOOT_SIZE-ROMFILE_SIZE-FLASH_ERASE_SIZE*1)) {
#elif (TCSUPPORT_RESERVEAREA_BLOCK==2)
if(imagelen > (mtd.size-TCBOOT_SIZE-ROMFILE_SIZE-FLASH_ERASE_SIZE*2)) {
#elif (TCSUPPORT_RESERVEAREA_BLOCK==3)
if(imagelen > (mtd.size-TCBOOT_SIZE-ROMFILE_SIZE-FLASH_ERASE_SIZE*3)) {
#elif (TCSUPPORT_RESERVEAREA_BLOCK==4)
if(imagelen > (mtd.size-TCBOOT_SIZE-ROMFILE_SIZE-FLASH_ERASE_SIZE*4)) {
#else
if(imagelen > (mtd.size-TCBOOT_SIZE-ROMFILE_SIZE-FLASH_ERASE_SIZE*7)) {
#endif
badimg = 1;
}
} else if (IS_NANDFLASH) {
#ifdef TCSUPPORT_BB_NAND
if (ra_inl(CR_AHB_HWCONF) & (0x00080000)) {
if(imagelen > ((1<<ra.flash->chip_shift) - 7*(1<<ra.flash->erase_shift))) {
badimg = 1;
}
} else {
/*Check the image size*/
#if (TCSUPPORT_RESERVEAREA_BLOCK==1)
if(imagelen > ((1<<ra.flash->chip_shift)-TCBOOT_SIZE-ROMFILE_SIZE-FLASH_ERASE_SIZE*1)) {
#elif (TCSUPPORT_RESERVEAREA_BLOCK==2)
if(imagelen > ((1<<ra.flash->chip_shift)-TCBOOT_SIZE-ROMFILE_SIZE-FLASH_ERASE_SIZE*2)) {
#elif (TCSUPPORT_RESERVEAREA_BLOCK==3)
if(imagelen > ((1<<ra.flash->chip_shift)-TCBOOT_SIZE-ROMFILE_SIZE-FLASH_ERASE_SIZE*3)) {
#elif (TCSUPPORT_RESERVEAREA_BLOCK==4)
if(imagelen > ((1<<ra.flash->chip_shift)-TCBOOT_SIZE-ROMFILE_SIZE-FLASH_ERASE_SIZE*4)) {
#elif (TCSUPPORT_RESERVEAREA_BLOCK==5)
if(imagelen > ((1<<ra.flash->chip_shift)-TCBOOT_SIZE-ROMFILE_SIZE-FLASH_ERASE_SIZE*5)) {
#else
if(imagelen > ((1<<ra.flash->chip_shift)-TCBOOT_SIZE-ROMFILE_SIZE-FLASH_ERASE_SIZE*7)) {
#endif
badimg = 1;
}
}
#endif
}
if (badimg){
#ifdef DBG_PRINT
prom_printf("Image too big for partition: %s\n", mtd);
LED_OFF(dsl_gpio);
LED_ON(internet_gpio);
#endif
goto error;
}
}
else{
/*
check if image is tclinux_allinone
*/
/* may modify for general sun.zhu_20140503 */
aio_trx = (struct trx_header *)(MULTI_BUF_BASE+TCBOOT_SIZE+ROMFILE_SIZE);
if(aio_trx->magic == TRX_MAGIC2){
#ifdef DBG_PRINT
prom_printf(" it is tclinux_allineone!!! \r\n");
#endif
}
else{
#ifdef DBG_PRINT
prom_printf(" it is not tclinux_allineone!!! \r\n");
#endif
goto error;
}
cal_check_sum = crc32buf((char*)MULTI_BUF_BASE, (imagelen-4), 1);
crc_ptr = (unsigned char *)(MULTI_BUF_BASE+imagelen-4);
raw_check_sum |= *crc_ptr;
raw_check_sum |= *(crc_ptr+1)<<8;
raw_check_sum |= *(crc_ptr+2)<<16;
raw_check_sum |= *(crc_ptr+3)<<24;
if (cal_check_sum != raw_check_sum){
#ifdef DBG_PRINT
prom_printf("tclinux_allinone checksum error!!! \r\n");
/*
turn off ADSL and Internet LED
*/
LED_OFF(dsl_gpio);
LED_ON(internet_gpio);
#endif
goto error;
}
/*
backup mi.conf
*/
flash_read(TCBOOT_BASE+MICONF_OFFSET, MICONF_SIZE, &retlen, MULTI_BUF_BASE+MICONF_OFFSET);
}
#ifdef DBG_PRINT
prom_printf("receive ok\n");
#endif
MultiWriteImage(MULTI_BUF_BASE, imagelen);
finishMultiUpgrade = 1;
}else{
#ifdef DBG_PRINT
prom_printf("receive_len < imagelen\n");
#endif
receive_len = 0;
prevImgLen = 0;
goto error;
}
}
/* may modify for general sun.zhu_20140503 */
return;
error:
startSeq = -1;
maxSeq = 0;
return;
}
#endif
#if defined(TCSUPPORT_MULTI_BOOT)
unsigned short calculate_check_sum(unsigned char *base, int len)
{
int check_sum = 0;
unsigned char *start = NULL;
unsigned char *end = NULL;
unsigned short result;
if (base == NULL)
return -1;
start = base;
end = start+len;
while(start < end){
check_sum += *start;
start++;
}
result = (check_sum & 0xffff) + (check_sum >>16 );
return result;
}
void MultiBootHandle(sk_buff *skb)
{
static int oldSeq=-1;
int cal_check_sum = 0;
int raw_check_sum = 0;
unsigned short pkt_check_sum = 0;
unsigned char *crc_ptr = NULL;
// unsigned int addr;
struct trx_header *trx = (struct trx_header *)MULTI_BUF_BASE;
struct MULTI_BOOT_T *rcv_ptr = (struct MULTI_BOOT_T *)(skb->data + MULTIBOOT_SIG_OFFSET);
unsigned long pktseq = rcv_ptr->ID+1;
unsigned long imagelen = rcv_ptr->fileLen;
#ifdef CONFIG_DUAL_IMAGE
#ifdef TCSUPPORT_DUAL_IMAGE_ENHANCE
// unsigned int *header_slave = (unsigned int *)(0xb0020000+offset);
unsigned int *header_slave = (unsigned int *)(flash_base+flash_tclinux_start+offset);
unsigned int slave_tclinux_offset = offset+flash_tclinux_start;
#else
// unsigned int *header_slave = (unsigned int *)(0xb0020000+0x500000);
unsigned int *header_slave = (unsigned int *)(flash_base+flash_tclinux_start+TCLINUX_SLAVE_FLASH_START);
unsigned int slave_tclinux_offset = flash_tclinux_start+TCLINUX_SLAVE_FLASH_START;
#endif
// unsigned int slave_kernel_size = header_slave[20]+TRX_LEN;
// unsigned int slave_rootfs_size = header_slave[21];
char boot_flag = 0;
unsigned int slave_kernel_size = READ_FLASH_DWORD((unsigned long long)((unsigned int)header_slave + 20 * sizeof(unsigned int)))+TRX_LEN;
unsigned int slave_rootfs_size = READ_FLASH_DWORD((unsigned long long)((unsigned int)header_slave + 21 * sizeof(unsigned int)));;
unsigned int slave_tclinux_size = slave_kernel_size + slave_rootfs_size;
#endif
unsigned int romd_offset;
unsigned int nand2K_rom_offset;
// unsigned int *header = (unsigned int *)(0xb0020000);
unsigned int *header = (unsigned int *)(flash_base+flash_tclinux_start);
// unsigned int kernel_size = header[20]+TRX_LEN;
// unsigned int rootfs_size = header[21];
unsigned int kernel_size = READ_FLASH_DWORD((unsigned long long)((unsigned int)header + 20 * sizeof(unsigned int)))+TRX_LEN;
unsigned int rootfs_size = READ_FLASH_DWORD((unsigned long long)((unsigned int)header + 21 * sizeof(unsigned int)));;
unsigned int tclinux_size = kernel_size + rootfs_size;
unsigned long retlen = 0;
unsigned long romfile_offset;
if (IS_SPIFLASH) {
romd_offset = mtd.size - ROMD_TO_BOTTOM;
} else if (IS_NANDFLASH) {
#ifdef TCSUPPORT_BB_NAND
/* 128 K block NAND Flash */
if (ra_inl(CR_AHB_HWCONF) & (0x00080000)) {
romd_offset = (1<<ra.flash->chip_shift) - 5 * (1<<ra.flash->erase_shift);
nand2K_rom_offset = (1<<ra.flash->chip_shift) - 6 * (1<<ra.flash->erase_shift);
} else {
romd_offset = (1<<ra.flash->chip_shift) - ROMD_TO_BOTTOM;
}
#endif
}
if(finishMultiBoot == 1){
return; //upgrade success
}
if (pktseq == 1){
/*
check if need to clear romfile or romd
*/
if (rcv_ptr->debugFlag == CLEAR_ROMFILE){
#ifdef DBG_PRINT
prom_printf("erase running romfile... \n");
#endif
if (IS_SPIFLASH) {
flash_erase((TCBOOT_BASE+TCBOOT_SIZE), ROMFILE_SIZE);
} else if (IS_NANDFLASH) {
#ifdef TCSUPPORT_BB_NAND
if (ra_inl(CR_AHB_HWCONF) & (0x00080000)) {
flash_erase(nand2K_rom_offset, (1<<ra.flash->erase_shift));
} else {
flash_erase((TCBOOT_BASE+TCBOOT_SIZE), ROMFILE_SIZE);
}
#endif
}
finishMultiBoot = 1;
return;
}
else if (rcv_ptr->debugFlag == CLEAR_ROMD){
#ifdef DBG_PRINT
prom_printf("erase rom-d... \n");
#endif
if (IS_SPIFLASH) {
flash_erase(romd_offset, ROMFILE_SIZE);
} else {
#ifdef TCSUPPORT_BB_NAND
if (ra_inl(CR_AHB_HWCONF) & (0x00080000)) {
flash_erase(romd_offset, (1<<ra.flash->erase_shift));
} else {
flash_erase(romd_offset, ROMFILE_SIZE);
}
#endif
}
finishMultiBoot = 1;
return;
}
oldSeq = 0;
rcv_len = 0;
}
/*
check seq
*/
if (pktseq!=(oldSeq+1)){
return;
}
else
oldSeq = pktseq;
/*
store data in buf and update rcv_len
*/
memcpy(MULTI_BUF_BASE+(rcv_ptr->ID)*MULTIBOOT_PACKET_SIZE, rcv_ptr->data, rcv_ptr->dataLen);
rcv_len += rcv_ptr->dataLen;
cur_file_type = rcv_ptr->fileFlag&CUR_FILE_MASK;
/*
check crc for romfile and rom-d
*/
if (cur_file_type == CURR_FILE_FLAG_ROMFILE || cur_file_type==CURR_FILE_FLAG_ROMD){
pkt_check_sum = calculate_check_sum(rcv_ptr->data, rcv_ptr->dataLen);
if (rcv_ptr->checkSum != pkt_check_sum){
#ifdef DBG_PRINT
prom_printf(" check sum is not correct!!!\r\n");
#endif
rcv_len = 0;
oldSeq = -1;
return;
}
}
/*
received the last pkt
*/
if (rcv_len >= imagelen){
/*
check the type of image
*/
switch (cur_file_type){
case CURR_FILE_FLAG_BOOT:
#ifdef DBG_PRINT
prom_printf(" it is tcboot.bin!!!\r\n");
#endif
/*
check CRC
*/
cal_check_sum = crc32buf((char*)MULTI_BUF_BASE, (imagelen-4), 1);
crc_ptr = (unsigned char *)(MULTI_BUF_BASE+imagelen-4);
raw_check_sum |= *crc_ptr<<24;
raw_check_sum |= *(crc_ptr+1)<<16;
raw_check_sum |= *(crc_ptr+2)<<8;
raw_check_sum |= *(crc_ptr+3);
if (cal_check_sum != raw_check_sum){
#ifdef DBG_PRINT
prom_printf("tclinux.bin checksum error!!! \r\n");
#endif
goto error;
}
/*
backup mi.conf
*/
flash_read(TCBOOT_BASE+MICONF_OFFSET, MICONF_SIZE, &retlen, MULTI_BUF_BASE+MICONF_OFFSET);
LED_ON(SYSTEM_GPIO);
prom_printf("Write to flash from %X to %X with %X bytes\n", MULTI_BUF_BASE, TCBOOT_BASE, imagelen);
flash_erase(TCBOOT_BASE, TCBOOT_SIZE);
prom_printf("\n");
flash_write(TCBOOT_BASE, imagelen, &retlen, (const unsigned char *) (MULTI_BUF_BASE));
break;
case CURR_FILE_FLAG_TCLINUX:
if(trx->magic == TRX_MAGIC2){
#ifdef DBG_PRINT
prom_printf(" it is tclinux.bin!!! \r\n");
#endif
cal_check_sum = crc32buf((MULTI_BUF_BASE+sizeof(struct trx_header)), (imagelen-sizeof(struct trx_header)), 1);
if (cal_check_sum != trx->crc32){
#ifdef DBG_PRINT
prom_printf("checksum error!!! \r\n");
#endif
goto error;
}
#ifdef CONFIG_DUAL_IMAGE
if (flash_tclinux_start+tclinux_size > slave_tclinux_offset){
#ifdef DBG_PRINT
prom_printf("tclinux can not be upgraded because of dual image!!!\r\n");
#endif
goto error;
}
#else
if (flash_tclinux_start+tclinux_size > romd_offset){
#ifdef DBG_PRINT
prom_printf("romd can not be upgraded because tclinux.bin is too large!!!\r\n");
#endif
goto error;
}
#endif
LED_ON(SYSTEM_GPIO);
prom_printf("Write to flash from %X to %X with %X bytes\n", MULTI_BUF_BASE, flash_tclinux_start, imagelen);
flash_erase(flash_tclinux_start, imagelen);
prom_printf("\n");
flash_write(flash_tclinux_start, imagelen, &retlen, (const unsigned char *) (MULTI_BUF_BASE));
}
else{
/*
check if image is tclinux_allinone
*/
if (memcmp(MULTI_BUF_BASE+TCBOOT_SIZE, "<ROMFILE>", strlen("<ROMFILE>")) == 0){
#ifdef DBG_PRINT
prom_printf(" it is tclinux_allineone!!! \r\n");
#endif
}
else{
#ifdef DBG_PRINT
prom_printf(" it is not tclinux_allineone!!! \r\n");
#endif
goto error;
}
cal_check_sum = crc32buf((char*)MULTI_BUF_BASE, (imagelen-4), 1);
crc_ptr = (unsigned char *)(MULTI_BUF_BASE+imagelen-4);
raw_check_sum |= *crc_ptr;
raw_check_sum |= *(crc_ptr+1)<<8;
raw_check_sum |= *(crc_ptr+2)<<16;
raw_check_sum |= *(crc_ptr+3)<<24;
if (cal_check_sum != raw_check_sum){
#ifdef DBG_PRINT
prom_printf("tclinux_allinone checksum error!!! \r\n");
#endif
goto error;
}
/*
check if image is too large
*/
#ifdef CONFIG_DUAL_IMAGE
if (TCBOOT_BASE+imagelen > slave_tclinux_offset){
prom_printf("tclinux_allinone can not be upgraded because of dual image!!!\r\n");
goto error;
}
#else
if (TCBOOT_BASE+imagelen > romd_offset){
prom_printf("tclinux_allinone can not be upgraded because it is too large!!!\r\n");
goto error;
}
#endif
/*
backup mi.conf
*/
flash_read(TCBOOT_BASE+MICONF_OFFSET, MICONF_SIZE, &retlen, MULTI_BUF_BASE+MICONF_OFFSET);
LED_ON(SYSTEM_GPIO);
prom_printf("Write to flash from %X to %X with %X bytes\n", MULTI_BUF_BASE, TCBOOT_BASE, imagelen);
flash_erase(TCBOOT_BASE, imagelen);
prom_printf("\n");
flash_write(TCBOOT_BASE, imagelen, &retlen, (const unsigned char *) (MULTI_BUF_BASE));
if (IS_NANDFLASH){
#ifdef TCSUPPORT_BB_NAND
prom_printf(" write romfile.cfg \n");
/* page size 2K bytes nand flash */
if (ra_inl(CR_AHB_HWCONF) & (0x00080000)){
romfile_offset = (1<<ra.flash->chip_shift) - 6 * (1<<ra.flash->erase_shift);
flash_erase(romfile_offset, ROMFILE_SIZE);
prom_printf("\n");
flash_write(romfile_offset, ROMFILE_SIZE, &retlen, (const unsigned char *) (MULTI_BUF_BASE+TCBOOT_SIZE));
}
#endif
}
}
break;
case CURR_FILE_FLAG_ROMD:
#ifdef DBG_PRINT
prom_printf(" it is rom-d!!!\r\n");
#endif
#ifdef CONFIG_DUAL_IMAGE
if (slave_tclinux_offset+slave_tclinux_size > romd_offset){
#ifdef DBG_PRINT
prom_printf("romd can not be upgraded because of dual image!!!\r\n");
#endif
goto error;
}
#else
if (flash_tclinux_start+tclinux_size > romd_offset){
#ifdef DBG_PRINT
prom_printf("romd can not be upgraded because tclinux.bin is too large!!!\r\n");
#endif
goto error;
}
#endif
LED_ON(SYSTEM_GPIO);
prom_printf("Write to flash from %X to %X with %X bytes\n", MULTI_BUF_BASE, romd_offset, imagelen);
flash_erase(romd_offset, ROMFILE_SIZE);
prom_printf("\n");
flash_write(romd_offset, imagelen, &retlen, (const unsigned char *) (MULTI_BUF_BASE));
break;
case CURR_FILE_FLAG_ROMFILE:
#ifdef DBG_PRINT
prom_printf(" it is romfile!!!\r\n");
#endif
LED_ON(SYSTEM_GPIO);
prom_printf("Write to flash from %X to %X with %X bytes\n", MULTI_BUF_BASE, (TCBOOT_BASE+TCBOOT_SIZE), imagelen);
/* page size 2K bytes nand flash */
if (IS_NANDFLASH && (ra_inl(CR_AHB_HWCONF) & (0x00080000))){
#ifdef TCSUPPORT_BB_NAND
romfile_offset = (1<<ra.flash->chip_shift) - 6 * (1<<ra.flash->erase_shift);
#endif
} else{
romfile_offset = TCBOOT_BASE+TCBOOT_SIZE;
}
flash_erase(romfile_offset, ROMFILE_SIZE);
prom_printf("\n");
flash_write(romfile_offset, imagelen, &retlen, (const unsigned char *) (MULTI_BUF_BASE));
break;
default:
#ifdef DBG_PRINT
prom_printf(" unknown file type!!!\r\n");
#endif
goto error;
}
#ifdef DBG_PRINT
prom_printf("receive ok\n");
#endif
finishMultiBoot = 1;
}
return;
error:
LED_OFF(SYSTEM_GPIO);
startMultiBoot = 0;
return;
}
#endif
#ifdef BOOT_LZMA_SUPPORT
struct web_connection {
/* the client tcp connection */
struct tcp_pcb *current_connection;
/* Detect idle connection using the last seq number */
unsigned long last_rx_seqno;
/* the rx state */
int rx_state;
/* save the GET http path here */
char get_path[200];
/* use this buffer for processing received data */
char rx_buffer[200];
} the_web_connection;
#endif
unsigned long local_ip = 0;
/* Extract a short from a long */
#define hiword(x) ((unsigned short)((x) >> 16))
#define loword(x) ((unsigned short)(x))
unsigned short in_csum(/* pseudohdr_t *pseudohdr, */ unsigned short *ptr, int nbytes)
{
register int sum; /* assumes long == 32 bits */
unsigned short oddbyte;
register unsigned short answer; /* assumes u_short == 16 bits */
/*
* Our algorithm is simple, using a 32-bit accumulator (sum),
* we add sequential 16-bit words to it, and at the end, fold back
* all the carry bits from the top 16 bits into the lower 16 bits.
*/
sum = 0;
/* Sum pseudo-header, if present */
#if 0
if(pseudohdr != NULL){
sum = hiword(pseudohdr->source);
sum += loword(pseudohdr->source);
sum += hiword(pseudohdr->dest);
sum += loword(pseudohdr->dest);
sum += pseudohdr->protocol;
sum += pseudohdr->length;
}
#endif
while (nbytes > 1) {
sum += *ptr++;
nbytes -= 2;
}
/* mop up an odd byte, if necessary */
if (nbytes == 1) {
oddbyte = 0; /* make sure top half is zero */
*((unsigned char *) &oddbyte) = *(unsigned char *)ptr; /* one byte only */
sum += oddbyte;
}
/*
* Add back carry outs from top 16 bits to low 16 bits.
*/
sum = (sum >> 16) + (sum & 0xffff); /* add high-16 to low-16 */
sum += (sum >> 16); /* add carry */
answer = ~sum; /* ones-complement, then truncate to 16 bits */
return(answer);
}
int ip_init(unsigned long ip)
{
local_ip = ip;
return 0;
}
int ip_rcv_packet(sk_buff *skb)
{
struct iphdr *ip_hdr = (struct iphdr *)(skb->data);
#if defined(TCSUPPORT_MULTI_UPGRADE) || defined(TCSUPPORT_MULTI_BOOT)
char *mac = (char *)(ip_hdr) - sizeof(struct ethhdr);
static int drop_multi = 0;
#endif
#if defined(TCSUPPORT_MULTI_UPGRADE)
/*Get the Internet GPIO Number*/
// uint8 internet_gpio = *(uint8 *)(INTERNET_GPIO);
uint8 internet_gpio = READ_FLASH_BYTE(INTERNET_GPIO);
/*Get the DSL GPIO Number*/
// uint8 dsl_gpio = *(uint8 *)(ADSL_GPIO);
uint8 dsl_gpio = READ_FLASH_BYTE(ADSL_GPIO);
#if !defined(TCSUPPORT_C1_TRUE)
int i = 0;
/*Get the Multi upgrade*/
uint8 *multi_upgrade_gpio = (uint8 *)(MULTI_UPGRADE_GPIO);
uint8 multi_led;
#endif
if(dsl_gpio == 0)
dsl_gpio = DSL_GPIO_DEFAULT;
if(internet_gpio == 0){
if(isEN7526D || isEN7526G || isEN7513 || isEN7513G || isEN7521G || isEN7586)
internet_gpio = 28;
else if(isEN7526F || isEN7521F || isEN7521S || isEN7512)
internet_gpio = 4;
else
internet_gpio = INTERNET_GPIO_DEFAULT;
}
#endif
/* record ip header pointer */
skb->ip_hdr = ip_hdr;
#if !defined(TCSUPPORT_MULTI_UPGRADE) && !defined(TCSUPPORT_MULTI_BOOT)
if (ntohl(ip_hdr->daddr) == local_ip)
{
#endif
if (ip_hdr->protocol == UDP){
skb->len = ntohs(ip_hdr->tot_len);
skb_pull(skb, sizeof(struct iphdr));
#if defined(TCSUPPORT_MULTI_UPGRADE) || defined(TCSUPPORT_MULTI_BOOT)
#if !defined(TCSUPPORT_C1_OBM)
if(mac[0] & 0x1)
#endif
{
if (0){
;
}
#if defined(TCSUPPORT_MULTI_UPGRADE)
else if(memcmp((skb->data + MULTIPKT_TAG_OFFSET), MULTI_UPGRADE_PKT_TAG, (sizeof(MULTI_UPGRADE_PKT_TAG)-1)) == 0){
if (skb->len < 1048) {
#ifdef DBG_PRINT
prom_printf("skb->len < 1048 \r\n");
#endif
return 0;
}
if(startMultiUpgrade == 0){
prom_printf("\nStartMultiUpgrade\n");
startMultiUpgrade = 1;
LED_OEN(internet_gpio);
LED_OEN(dsl_gpio);
#if !defined(TCSUPPORT_C1_TRUE)
for(i=0; i<maxMultiLedNum; i++){
multi_led = READ_FLASH_BYTE(multi_upgrade_gpio + i);
// if(multi_upgrade_gpio[i] != 0)
// LED_OEN(multi_upgrade_gpio[i]);
if(multi_led != 0)
#if defined(TCSUPPORT_CT_WAN_PTM)
{
if(multi_led > 31){
if(multi_led > 47){
regWrite32(CR_GPIO_CTRL3,regRead32(CR_GPIO_CTRL3)|(1<<((multi_led-48)*2)));
}else{
regWrite32(CR_GPIO_CTRL2,regRead32(CR_GPIO_CTRL2)|(1<<((multi_led-32)*2)));
}
regWrite32(CR_GPIO_ODRAIN1,regRead32(CR_GPIO_ODRAIN1)|(1<<(multi_led-32)));
}else{
if(multi_led > 15){
regWrite32(CR_GPIO_CTRL1,regRead32(CR_GPIO_CTRL1)|(1<<((multi_led-16)*2)));
}else{
regWrite32(CR_GPIO_CTRL,regRead32(CR_GPIO_CTRL)|(1<<(multi_led*2)));
}
regWrite32(CR_GPIO_ODRAIN,regRead32(CR_GPIO_ODRAIN)|(1<<multi_led));
}
}
#else
LED_OEN(multi_led);
#endif
}
#endif
LED_OFF(internet_gpio);
}
MultiUpgradeHandle(skb);
}
#endif
#if defined(TCSUPPORT_MULTI_BOOT)
else if(memcmp((skb->data + MULTIBOOT_SIG_OFFSET), MULTIBOOT_SIG, (sizeof(MULTIBOOT_SIG)-1)) == 0){
if (skb->len < 1054) {
#ifdef DBG_PRINT
prom_printf("skb->len < 1054 \r\n");
#endif
return 0;
}
if(startMultiBoot == 0){
#ifdef DBG_PRINT
prom_printf("\nStartMultiBoot\n");
#endif
startMultiBoot = 1;
LED_OEN(SYSTEM_GPIO);
}
MultiBootHandle(skb);
}
#endif
}
#if defined(TCSUPPORT_MULTI_UPGRADE)
if(startMultiUpgrade == 1){
return 0;
}
#endif
#if defined(TCSUPPORT_MULTI_BOOT)
if(startMultiBoot == 1){
return 0;
}
#endif
#endif
udp_rcv_packet(skb);
}
else if(ip_hdr->protocol == ICMP){
skb->len = ntohs(ip_hdr->tot_len);
skb_pull(skb, sizeof(struct iphdr));
icmp_rcv_packet(skb);
}
#ifdef BOOT_LZMA_SUPPORT
else if(ip_hdr->protocol == TCP){
struct pbuf *tcp_pkt;
struct pbuf *q;
int i;
#ifdef HTTP_DBG
prom_printf("Here comes TCP: skb->len = %d\r\n", skb->len);
#endif
tcp_pkt = pbuf_alloc(PBUF_TRANSPORT, skb->len, PBUF_POOL);
if(!tcp_pkt){
#ifdef HTTP_DBG
prom_printf("failed to allocate pbuf\r\n");
#endif
return -1;
}
//pbuf is a link list queue, so need copy p->next. shnwind 20110721.
for(q=tcp_pkt,i=0; q!=NULL; q=q->next){
memcpy(q->payload, (skb->data)+i, q->len);
i+=q->len;
}
//memcpy(tcp_pkt->payload, skb->data, tcp_pkt->len); //treyy
tcp_input(tcp_pkt);
}
#endif
#if !defined(TCSUPPORT_MULTI_UPGRADE) && !defined(TCSUPPORT_MULTI_BOOT)
}
#endif
return 0;
}
#ifdef BOOT_LZMA_SUPPORT
int tc_tcpout(struct pbuf *p, struct ip_addr *src, struct ip_addr *dest, u8_t ttl, u8_t tos)
{
sk_buff *skb;
#ifdef HTTP_DBG
prom_printf("tc_tcpout\r\n");
#endif
skb = alloc_skb(ETH_FRAME_LEN);
ip_skb_reserve(skb);
skb->len += p->len;
memcpy(skb->data, p->payload, p->len);
#ifdef HTTP_DBG
prom_printf("tc_tcpout: p->len = %d\r\n", p->len);
#endif
ip_send(skb, dest->addr, TCP);
}
#endif
int ip_send(sk_buff *skb, unsigned long ip, unsigned char proto)
{
struct iphdr *ip_hdr;
static unsigned short ip_id = 32;
unsigned char dest_eth_addr[ETH_ALEN];
if (arp_get_eth_addr(ip, dest_eth_addr)) {
free_skb(skb);
return -1;
}
ip_hdr = (struct iphdr *)skb_push(skb, sizeof(struct iphdr));
ip_hdr->ihl = 5;
ip_hdr->version = 4;
ip_hdr->tos = 0;
ip_hdr->tot_len = htons(skb->len);
ip_hdr->id = htons(ip_id++);
ip_hdr->frag_off = 0;
ip_hdr->ttl = 20;
ip_hdr->protocol = proto;
ip_hdr->check = 0;
ip_hdr->saddr = htonl(local_ip);
ip_hdr->daddr = htonl(ip);
ip_hdr->check = in_csum((unsigned short *)ip_hdr, sizeof(struct iphdr));
eth_send(skb, dest_eth_addr, ETH_P_IP);
return 0;
}
void ip_skb_reserve(sk_buff *skb)
{
eth_skb_reserve(skb);
skb_reserve(skb, sizeof(struct iphdr));
}
unsigned long ip_get_source_ip(sk_buff *skb)
{
struct iphdr *ip_hdr;
ip_hdr = (struct iphdr *)(skb->ip_hdr);
return ntohl(ip_hdr->saddr);
}