1#include <stdio.h>
2#include <stdlib.h>
3#include <string.h>
4#include <unistd.h>
5#include <signal.h>
6#include "shutils.h"
7#include "shared.h"
8
9static int crc_table_empty = 1;
10static unsigned long crc_table[256];
11
12#define SWAP_LONG(x) \
13	((u_int32_t)( \
14		(((u_int32_t)(x) & (u_int32_t)0x000000ffUL) << 24) | \
15		(((u_int32_t)(x) & (u_int32_t)0x0000ff00UL) <<  8) | \
16		(((u_int32_t)(x) & (u_int32_t)0x00ff0000UL) >>  8) | \
17		(((u_int32_t)(x) & (u_int32_t)0xff000000UL) >> 24) ))
18
19#define DO1(buf) crc = crc_table[((int)crc ^ (*buf++)) & 0xff] ^ (crc >> 8);
20#define DO2(buf)  DO1(buf); DO1(buf);
21#define DO4(buf)  DO2(buf); DO2(buf);
22#define DO8(buf)  DO4(buf); DO4(buf);
23
24#define TC_HDR_LEN	0x100
25
26static void make_crc_table()
27{
28	unsigned long c;
29	int n, k;
30	unsigned long poly;	    /* polynomial exclusive-or pattern */
31	/* terms of polynomial defining this crc (except x^32): */
32	static const unsigned char p[] = {0,1,2,4,5,7,8,10,11,12,16,22,23,26};
33
34	/* make exclusive-or pattern from polynomial (0xedb88320L) */
35	poly = 0L;
36	for (n = 0; n < sizeof(p)/sizeof(unsigned char); n++)
37		poly |= 1L << (31 - p[n]);
38
39	for (n = 0; n < 256; n++)
40	{
41		c = (unsigned long)n;
42		for (k = 0; k < 8; k++)
43			c = c & 1 ? poly ^ (c >> 1) : c >> 1;
44		crc_table[n] = c;
45	}
46	crc_table_empty = 0;
47}
48
49unsigned long crc32_no_comp(unsigned long crc,const unsigned char* buf, int len)
50{
51	if (crc_table_empty)
52		make_crc_table();
53
54	while (len >= 8)
55	{
56		DO8(buf);
57		len -= 8;
58	}
59	if (len) do {
60		DO1(buf);
61	} while (--len);
62
63	return crc;
64}
65
66int separate_tc_fw_from_trx(char* trxpath)
67{
68	FILE* FpTrx;
69	char TrxHdrBuf[512];
70	char buf[4096];
71	unsigned int *pTrxSize;
72	unsigned int TrxSize = 0;
73	unsigned int filelen;
74	unsigned int TcFwSize;
75	int RetVal = 0;
76
77	FILE* fpSrc = NULL;
78	FILE* fpDst = NULL;
79
80	FpTrx = fopen(trxpath, "rb");
81	if (FpTrx == NULL) goto err;
82	fread(TrxHdrBuf,1,sizeof(TrxHdrBuf),FpTrx);
83	fseek( FpTrx, 0, SEEK_END);
84	filelen = ftell( FpTrx );
85	fclose(FpTrx);
86
87	pTrxSize = (unsigned int*)(TrxHdrBuf+4);	//bcm
88	TrxSize = *pTrxSize;
89	cprintf("trx size %u, file size %u\n", TrxSize, filelen);
90	if (filelen > TrxSize)
91	{
92		TcFwSize = filelen - TrxSize;
93		cprintf("tcfw size %u\n",TcFwSize);
94
95		if (TcFwSize > TC_HDR_LEN)
96		{
97			fpSrc = fopen(trxpath, "rb");
98			if (fpSrc==NULL) goto err;
99			fpDst = fopen("/tmp/tcfw.bin", "wb");
100			if (fpDst==NULL) goto err;
101
102			fseek(fpSrc, TrxSize, SEEK_SET);
103
104			fread(buf, 1, TC_HDR_LEN, fpSrc);
105			fwrite(buf, 1, TC_HDR_LEN, fpDst);
106			TcFwSize -= TC_HDR_LEN;
107
108			cprintf("tcfw magic : %c%c%c%c\n",buf[0],buf[1],buf[2],buf[3]);
109			if (strncmp(&buf[0], "2RDH", 4))
110				goto err;
111
112			while (TcFwSize > 0)
113			{
114				if (TcFwSize > sizeof(buf))
115				{
116					fread(buf, 1, sizeof(buf), fpSrc);
117					fwrite(buf, 1, sizeof(buf), fpDst);
118					TcFwSize -= sizeof(buf);
119				}
120				else
121				{
122					fread(buf, 1, TcFwSize, fpSrc);
123					fwrite(buf, 1, TcFwSize, fpDst);
124					TcFwSize = 0;
125				}
126			}
127		}
128		else {
129			cprintf("not tc fw\n");
130			goto err;
131		}
132	}
133	else if (TrxSize == filelen)
134	{
135		// only trx, no tc fw
136		printf("no tc fw\n");
137		goto err;
138	}
139
140	RetVal = 1;
141
142err:
143	if(TrxSize)
144		truncate(trxpath, TrxSize);
145
146	if (fpSrc)
147		fclose(fpSrc);
148
149	if (fpDst)
150		fclose(fpDst);
151
152	return RetVal;
153}
154
155int check_tc_firmware_crc()
156{
157	FILE* fpSrc = NULL;
158	FILE* fpDst = NULL;
159	unsigned long* crc_value_ptr = NULL;
160	unsigned long ulfw_crc = 0, calc_crc = 0;
161	unsigned long trxlen, *trxlenptr;
162	int skip_flag = 0;
163	int RetVal = 0;
164	char buf[4096] = {0};
165
166	fpSrc = fopen("/tmp/tcfw.bin", "rb");
167	if (fpSrc==NULL)
168	{
169		skip_flag = 1;
170		goto exit;
171	}
172	fpDst = fopen("/tmp/tclinux.bin", "wb");
173	if (fpDst==NULL)
174	{
175		skip_flag = 1;
176		goto exit;
177	}
178
179	fread(buf, 1, 0x100, fpSrc);
180
181	trxlenptr=(unsigned long*)(buf+8);
182	trxlen=*trxlenptr;
183	trxlen=SWAP_LONG(trxlen);
184	cprintf("tcfw len: %lu\n", trxlen);
185
186	fwrite(buf, 1, 0x100, fpDst);
187	trxlen -= 0x100;
188
189	crc_value_ptr=(unsigned long*)(buf+12);
190	ulfw_crc=*crc_value_ptr;
191	ulfw_crc=SWAP_LONG(ulfw_crc);
192	cprintf("ulfw crc: %lx\n", ulfw_crc);
193
194	calc_crc = 0xffffffff;
195
196	while(trxlen>0)
197	{
198		if (trxlen > sizeof(buf))
199		{
200			fread(buf, 1, sizeof(buf), fpSrc);
201			fwrite(buf, 1, sizeof(buf), fpDst);
202			calc_crc = crc32_no_comp(calc_crc, (unsigned char*)buf, sizeof(buf));
203			trxlen-=sizeof(buf);
204		}
205		else
206		{
207			fread(buf, 1, trxlen, fpSrc);
208			fwrite(buf, 1, trxlen, fpDst);
209			calc_crc = crc32_no_comp(calc_crc, (unsigned char*)buf, trxlen);
210			trxlen=0;
211		}
212	}
213
214	cprintf("calc crc: %lx\n", calc_crc);
215
216	if (ulfw_crc != calc_crc)
217			skip_flag = 1;
218#ifdef RTCONFIG_BRCM_NAND_JFFS2
219	else {
220		cprintf("backup tclinux\n");
221		eval("cp", "-f", "/tmp/tclinux.bin", "/jffs/tclinux.bin");
222	}
223#endif
224
225	unlink("/tmp/tcfw.bin");
226
227
228	cprintf("check tcfw done\n");
229
230exit:
231
232	if(skip_flag)
233		RetVal = -1;
234
235	if (fpSrc)
236		fclose(fpSrc);
237
238	if (fpDst)
239		fclose(fpDst);
240
241	return RetVal;
242}
243
244void do_upgrade_adsldrv(void)
245{
246	char UpdateFwBuf[256];
247	char ipaddr[80];
248	FILE* fp;
249	int ret;
250	int skip_flag = 0, force_flag = 0;
251	unsigned long old_crc = 0, new_crc = 0;
252
253	cprintf("%s\n", __FUNCTION__);
254
255	if(!check_if_file_exist("/tmp/tclinux.bin"))
256		return;
257
258	fp = fopen("/tmp/adsl/tc_ip_addr.txt","r");
259	if (fp) {
260		fgets(ipaddr,sizeof(ipaddr),fp);
261		fclose(fp);
262	}
263	else {
264		snprintf(ipaddr, sizeof(ipaddr), "169.254.0.1");
265		force_flag = 1;
266	}
267
268	strcpy(UpdateFwBuf,"cd /tmp; tftp -p -l tclinux.bin ");
269	strcat(UpdateFwBuf,ipaddr);
270
271	fp = fopen("/tmp/adsl/tc_hdr.bin", "rb");
272	if (fp)
273	{
274		fseek(fp, 12L, SEEK_SET);
275		fread(&old_crc, 1, sizeof(unsigned long), fp);
276		old_crc = SWAP_LONG(old_crc);
277		cprintf("old crc: %lx\n", old_crc);
278		fclose(fp);
279	}
280	fp = fopen("/tmp/tclinux.bin", "rb");
281	if (fp)
282	{
283		fseek(fp, 12L, SEEK_SET);
284		fread(&new_crc, 1, sizeof(unsigned long), fp);
285		new_crc = SWAP_LONG(new_crc);
286		cprintf("new crc: %lx\n", new_crc);
287		fclose(fp);
288	}
289
290	if (old_crc && new_crc && new_crc == old_crc)
291		skip_flag = 1;
292
293	if (!skip_flag)
294	{
295		if(force_flag) {
296			killall("tp_init", SIGKILL);
297		}
298		else {
299			eval("adslate", "waitadsl");
300			eval("adslate", "quitdrv");
301		}
302		eval("iptables", "-I", "INPUT", "-p", "udp", "-j", "ACCEPT");
303		eval("ifconfig", "vlan2", "169.254.10.10");	//tmp
304		eval("route", "add", "-host", ipaddr, "vlan2");
305
306		cprintf("Start to upgrade tc fw\n");
307		printf(UpdateFwBuf);
308		ret = system(UpdateFwBuf);
309		if(ret)
310			cprintf("tftp failed\n");
311		else
312			cprintf("tftp done\n");
313
314		eval("iptables", "-D", "INPUT", "-p", "udp", "-j", "ACCEPT");
315	}
316	else
317		cprintf("Skip upgrade tc firmware\n");
318}
319