openwrt/tools/firmware-utils/src/dgn3500sum.c

154 lines
4.3 KiB
C

// SPDX-License-Identifier: GPL-2.0-or-later
/* **************************************************************************
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.
************************************************************************* */
#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 = 0, sum1 = 0;
char sumbuf[8 + 8 + 1];
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;
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;
}