summaryrefslogtreecommitdiff
path: root/tools/firmware-utils/src/dgn3500sum.c
blob: 00a0c5f8377af0232be01d812820c4f465fda20e (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
/* **************************************************************************

   This program creates a modified 16bit checksum used for the Netgear
   DGN3500 series routers. The difference between this and a standard
   checksum is that every 0x100 bytes added 0x100 have to be subtracted
   from the sum.

   (C) 2013 Marco Antonio Mauro <marcus90 at gmail.com>

   Based on previous unattributed work.

   This program is free software; you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
   the Free Software Foundation; either version 2 of the License, or
   (at your option) any later version.

   This program is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
   General Public License for more details.

   You should have received a copy of the GNU General Public License
   along with this program; if not, write to the Free Software
   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA

 ************************************************************************* */


#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/stat.h>

unsigned char PidDataWW[70] =
{
    0x73, 0x45, 0x72, 0x43, 0x6F, 0x4D, 0x6D, 0x00, 0x00, 0x00, 0x00, 0x59, 0x50, 0x35, 0x37, 0x32,
    0x33, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41, 0x00, 0x37,
    0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x73,
    0x45, 0x72, 0x43, 0x6F, 0x4D, 0x6D,
} ;

unsigned char PidDataDE[70] =
{
    0x73, 0x45, 0x72, 0x43, 0x6F, 0x4D, 0x6D, 0x00, 0x00, 0x00, 0x00, 0x59, 0x50, 0x35, 0x37, 0x32,
    0x34, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x42, 0x00, 0x37,
    0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x73,
    0x45, 0x72, 0x43, 0x6F, 0x4D, 0x6D,
} ;

unsigned char PidDataNA[70] =
{
    0x73, 0x45, 0x72, 0x43, 0x6F, 0x4D, 0x6D, 0x00, 0x00, 0x00, 0x00, 0x59, 0x50, 0x35, 0x37, 0x32,
    0x36, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41, 0x00, 0x37,
    0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x73,
    0x45, 0x72, 0x43, 0x6F, 0x4D, 0x6D,
} ;

/* *******************************************************************
   Reads the file into memory and returns pointer to the buffer. */
static char *readfile(char *filename, int *size)
{
	FILE		*fp;
	char		*buffer;
	struct stat	info;

	if (stat(filename,&info)!=0)
		return NULL;

	if ((fp=fopen(filename,"r"))==NULL)
		return NULL;

	buffer=NULL;
	for (;;)
	{
		if ((buffer=(char *)malloc(info.st_size+1))==NULL)
			break;

		if (fread(buffer,1,info.st_size,fp)!=info.st_size)
		{
			free(buffer);
			buffer=NULL;
			break;
		}

		buffer[info.st_size]='\0';
		if(size) *size = info.st_size;

		break;
	}

	(void)fclose(fp);

	return buffer;
}


/* ******************************************************************* */
int main(int argc, char** argv)
{
  unsigned long start, i;
  char *endptr, *buffer, *p;
  int count;  // size of file in bytes
  unsigned short sum, sum1;
  char sumbuf[9];

  if(argc < 3) {
    printf("ERROR: Argument missing!\n\nUsage %s filename starting offset in hex [PID code]\n\n", argv[0]);
    return 1;
  }


  FILE *fp = fopen(argv[1], "a");
  if(!fp) {
    printf("ERROR: File not writeable!\n");
    return 1;
  }
  if(argc = 4)
  {
    printf("%s: PID type: %s\n", argv[0], argv[3]);
    if(strcmp(argv[3], "DE")==0)
      fwrite(PidDataDE, sizeof(PidDataDE), sizeof(char), fp);  /* write DE pid */
    else if(strcmp(argv[3], "NA")==0)
      fwrite(PidDataNA, sizeof(PidDataNA), sizeof(char), fp);  /* write NA pid */
    else /* if(strcmp(argv[3], "WW")) */
      fwrite(PidDataWW, sizeof(PidDataWW), sizeof(char), fp);  /* write WW pid */
  }
  else
    fwrite(PidDataWW, sizeof(PidDataWW), sizeof(char), fp);  /* write WW pid if unspecified */

  fclose(fp);

  /* Read the file to calculate the checksums */
  buffer = readfile(argv[1], &count);
  if(!buffer) {
    printf("ERROR: File %s not found!\n", argv[1]);
    return 1;
  }

  p = buffer;
  for(i = 0; i < count; i++)
  {
	sum += p[i];
  }

  start = strtol(argv[2], &endptr, 16);
  p = buffer+start;
  sum1 = 0;
  for(i = 0; i < count - start; i++)
  {
	sum1 += p[i];
  }

  sprintf(sumbuf,"%04X%04X",sum1,sum);
  /* Append the 2 checksums to end of file */
  fp = fopen(argv[1], "a");
  if(!fp) {
    printf("ERROR: File not writeable!\n");
    return 1;
  }
  fwrite(sumbuf, 8, sizeof(char), fp);
  fclose(fp);
  free(buffer);
  return 0;
}