#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <fcntl.h>
#include <dirent.h>
typedef unsigned char U8;
typedef unsigned int U32;
#define DEBUG_THIS
#if defined(DEBUG_THIS)
#define DBGMODL "CHAGESTATE"
#define dbg_print(outflag,...) do{switch(outflag){case 1:printf("\n<INFO> " DBGMODL ": [%s],Line %d ",__FUNCTION__,__LINE__);printf(__VA_ARGS__);fflush(stdout);break;case 2: printf("\n<ERROR> " DBGMODL ": [%s],Line %d ",__FUNCTION__,__LINE__);printf(__VA_ARGS__);fflush(stdout);break;default:break;}}while(0)
#else
#define dbg_print
#endif
#define E2P_JWT_LOADER_SIZE_FDCA 20
typedef struct
{
U8 activation;
U8 pid[2];
U8 table_id;
U8 freq[4];
U8 symbol[4];
U8 modulation;
U8 block_index;
U8 version[2];
U8 crc[4];
}JWT_UPDATE_FDCA_t;
typedef struct{
U8 manufacturer_id;
U8 model_id;
U8 majorhardwrare_id;
U8 subhardwrare_id;
U8 ca_ident_number[4];
U8 release_number[4];
U8 broadcaster[4];
U8 signature[152];
U8 batch_id;
U8 MAC_address[6];
U8 build_year;
U8 build_week;
U8 STB_provider_id[2];
U8 manager_code[4];
U8 hardware_code[4];
U8 software_version[4];
U8 reserved[61];
U8 crc[4];
}JWT_UPDATE_BCA_t;
typedef struct{
U8 major_mrs_version;
U8 sub_mrs_version;
U8 reserved1[8];
U8 release_year;
U8 release_month;
U8 release_date;
U8 reserved2[11];
U8 fdca_image[E2P_JWT_LOADER_SIZE_FDCA];
U8 signature[152];
U8 crc[4];
}JWT_UPDATE_FLASH_HEADER_t;
extern char *optarg;
//global variable
char exe_filename[20]="\0";
U8 chgstate = 0,ori_chgstate = 0;
U8 sw_ver = 0,ori_sw_ver = 0;
U8 auto_reboot = 0;
U32 dumplen = 2048;
U32 fgda_offset = 512;
U32 bca_offset = 0;
U8 quit = 0;
char dumpfile[256]="/mnt/info/stbinfotmp";
#ifdef BCM7581B0
U8 mtdnum = 7;
char *filename="/mnt/usb/kv_7581b0_update/usb_update.cfg";
char *platform="bcm7581b0";
#endif
#ifdef BCM7019C0
U8 mtdnum = 11;
char *filename="/mnt/usb/kv_update/usb_update.cfg";
char *platform="bcm7019c0";
#endif
unsigned long ulTable_MPEG32_ota[256] =
{
0x00000000L, 0x04C11DB7L, 0x09823B6EL, 0x0D4326D9L,
0x130476DCL, 0x17C56B6BL, 0x1A864DB2L, 0x1E475005L,
0x2608EDB8L, 0x22C9F00FL, 0x2F8AD6D6L, 0x2B4BCB61L,
0x350C9B64L, 0x31CD86D3L, 0x3C8EA00AL, 0x384FBDBDL,
0x4C11DB70L, 0x48D0C6C7L, 0x4593E01EL, 0x4152FDA9L,
0x5F15ADACL, 0x5BD4B01BL, 0x569796C2L, 0x52568B75L,
0x6A1936C8L, 0x6ED82B7FL, 0x639B0DA6L, 0x675A1011L,
0x791D4014L, 0x7DDC5DA3L, 0x709F7B7AL, 0x745E66CDL,
0x9823B6E0L, 0x9CE2AB57L, 0x91A18D8EL, 0x95609039L,
0x8B27C03CL, 0x8FE6DD8BL, 0x82A5FB52L, 0x8664E6E5L,
0xBE2B5B58L, 0xBAEA46EFL, 0xB7A96036L, 0xB3687D81L,
0xAD2F2D84L, 0xA9EE3033L, 0xA4AD16EAL, 0xA06C0B5DL,
0xD4326D90L, 0xD0F37027L, 0xDDB056FEL, 0xD9714B49L,
0xC7361B4CL, 0xC3F706FBL, 0xCEB42022L, 0xCA753D95L,
0xF23A8028L, 0xF6FB9D9FL, 0xFBB8BB46L, 0xFF79A6F1L,
0xE13EF6F4L, 0xE5FFEB43L, 0xE8BCCD9AL, 0xEC7DD02DL,
0x34867077L, 0x30476DC0L, 0x3D044B19L, 0x39C556AEL,
0x278206ABL, 0x23431B1CL, 0x2E003DC5L, 0x2AC12072L,
0x128E9DCFL, 0x164F8078L, 0x1B0CA6A1L, 0x1FCDBB16L,
0x018AEB13L, 0x054BF6A4L, 0x0808D07DL, 0x0CC9CDCAL,
0x7897AB07L, 0x7C56B6B0L, 0x71159069L, 0x75D48DDEL,
0x6B93DDDBL, 0x6F52C06CL, 0x6211E6B5L, 0x66D0FB02L,
0x5E9F46BFL, 0x5A5E5B08L, 0x571D7DD1L, 0x53DC6066L,
0x4D9B3063L, 0x495A2DD4L, 0x44190B0DL, 0x40D816BAL,
0xACA5C697L, 0xA864DB20L, 0xA527FDF9L, 0xA1E6E04EL,
0xBFA1B04BL, 0xBB60ADFCL, 0xB6238B25L, 0xB2E29692L,
0x8AAD2B2FL, 0x8E6C3698L, 0x832F1041L, 0x87EE0DF6L,
0x99A95DF3L, 0x9D684044L, 0x902B669DL, 0x94EA7B2AL,
0xE0B41DE7L, 0xE4750050L, 0xE9362689L, 0xEDF73B3EL,
0xF3B06B3BL, 0xF771768CL, 0xFA325055L, 0xFEF34DE2L,
0xC6BCF05FL, 0xC27DEDE8L, 0xCF3ECB31L, 0xCBFFD686L,
0xD5B88683L, 0xD1799B34L, 0xDC3ABDEDL, 0xD8FBA05AL,
0x690CE0EEL, 0x6DCDFD59L, 0x608EDB80L, 0x644FC637L,
0x7A089632L, 0x7EC98B85L, 0x738AAD5CL, 0x774BB0EBL,
0x4F040D56L, 0x4BC510E1L, 0x46863638L, 0x42472B8FL,
0x5C007B8AL, 0x58C1663DL, 0x558240E4L, 0x51435D53L,
0x251D3B9EL, 0x21DC2629L, 0x2C9F00F0L, 0x285E1D47L,
0x36194D42L, 0x32D850F5L, 0x3F9B762CL, 0x3B5A6B9BL,
0x0315D626L, 0x07D4CB91L, 0x0A97ED48L, 0x0E56F0FFL,
0x1011A0FAL, 0x14D0BD4DL, 0x19939B94L, 0x1D528623L,
0xF12F560EL, 0xF5EE4BB9L, 0xF8AD6D60L, 0xFC6C70D7L,
0xE22B20D2L, 0xE6EA3D65L, 0xEBA91BBCL, 0xEF68060BL,
0xD727BBB6L, 0xD3E6A601L, 0xDEA580D8L, 0xDA649D6FL,
0xC423CD6AL, 0xC0E2D0DDL, 0xCDA1F604L, 0xC960EBB3L,
0xBD3E8D7EL, 0xB9FF90C9L, 0xB4BCB610L, 0xB07DABA7L,
0xAE3AFBA2L, 0xAAFBE615L, 0xA7B8C0CCL, 0xA379DD7BL,
0x9B3660C6L, 0x9FF77D71L, 0x92B45BA8L, 0x9675461FL,
0x8832161AL, 0x8CF30BADL, 0x81B02D74L, 0x857130C3L,
0x5D8A9099L, 0x594B8D2EL, 0x5408ABF7L, 0x50C9B640L,
0x4E8EE645L, 0x4A4FFBF2L, 0x470CDD2BL, 0x43CDC09CL,
0x7B827D21L, 0x7F436096L, 0x7200464FL, 0x76C15BF8L,
0x68860BFDL, 0x6C47164AL, 0x61043093L, 0x65C52D24L,
0x119B4BE9L, 0x155A565EL, 0x18197087L, 0x1CD86D30L,
0x029F3D35L, 0x065E2082L, 0x0B1D065BL, 0x0FDC1BECL,
0x3793A651L, 0x3352BBE6L, 0x3E119D3FL, 0x3AD08088L,
0x2497D08DL, 0x2056CD3AL, 0x2D15EBE3L, 0x29D4F654L,
0xC5A92679L, 0xC1683BCEL, 0xCC2B1D17L, 0xC8EA00A0L,
0xD6AD50A5L, 0xD26C4D12L, 0xDF2F6BCBL, 0xDBEE767CL,
0xE3A1CBC1L, 0xE760D676L, 0xEA23F0AFL, 0xEEE2ED18L,
0xF0A5BD1DL, 0xF464A0AAL, 0xF9278673L, 0xFDE69BC4L,
0x89B8FD09L, 0x8D79E0BEL, 0x803AC667L, 0x84FBDBD0L,
0x9ABC8BD5L, 0x9E7D9662L, 0x933EB0BBL, 0x97FFAD0CL,
0xAFB010B1L, 0xAB710D06L, 0xA6322BDFL, 0xA2F33668L,
0xBCB4666DL, 0xB8757BDAL, 0xB5365D03L, 0xB1F740B4L
};
U32 calculateCRC(U8 *pData, U8 len)
{
U32 section_len;
U32 calucate_crc;
U8 *tempData = pData;
section_len = len;
calucate_crc = 0xFFFFFFFF;
/* calculate CRC */
while (section_len--)
{
calucate_crc = ulTable_MPEG32_ota[((calucate_crc >> 24) ^ *tempData++) & 0xFFL] ^ (calucate_crc << 8);
}
return calucate_crc;
}
void print_help(char *name)
{
printf("此程序用作更改机顶盒的信息-n改变进入选项,-s改变软件版本号\n");
printf("用法:%s [选项] <[-n state] [-s sw_ver]>\n",name);
printf("选项有:-m 指定的mtd号(默认是7)\n");
printf(" :-f 指定要导出的文件名(默认为/mnt/info/stbinfotmp)\n");
printf(" :-l 指定要导出的数据长度(默认为2048)\n");
printf(" :-o 指定信息表的偏移(默认为512)\n");
printf(" :-a 指定修改完成后是否自动重新启动机顶盒(默认是不自动重启)\n");
printf("举例如:%s -n 0x1b -a\n\t\t将信息修改为0x1b后,自动重启\n",name);
printf(" :%s -n 0x1b -m 9 -f /mnt/tmp -l 1024 -o 256\n",name);
printf("This Program is for %s by KINGVON\n",platform);
printf("Any Problem You can contact me:lqrensn@163.com\n");
}
//parse input paramerter
void parse_input(int argc,char *argv[])
{
int opt;
U8 chgstate_flag = 0;
U8 tmpbuf[2];
if(argc <2)
{
print_help(exe_filename);
exit(-1);
}
//To compatible the version before
if(argc == 2)
{
if(!strncmp(argv[1],"-h",2))
{
print_help(exe_filename);
exit(0);
}
if((!strncmp(argv[1],"0x",2)) || (!strncmp(argv[1],"0X",2)))
{
chgstate = strtoul(argv[1],NULL,16);
}
else
{
chgstate = atoi(argv[1]);
}
dbg_print(1,"The change value is %d\n",chgstate);
return;
}
while((opt = getopt(argc,argv,"ahn:m:f:s:l:")) != -1)
{
switch(opt)
{
case 'n':
if((!strncmp(optarg,"0x",2)) || (!strncmp(optarg,"0X",2)))
{
chgstate = strtoul(optarg,NULL,16);
}
else
{
chgstate = atoi(optarg);
}
dbg_print(1,"The change value is %d\n",chgstate);
chgstate_flag = 1;
break;
case 'm':
mtdnum = atoi(optarg);
break;
case 's':
if((!strncmp(optarg,"0x",2)) || (!strncmp(optarg,"0X",2)))
{
sw_ver = strtoul(optarg,NULL,16);
}
else
{
sw_ver = atoi(optarg);
}
dbg_print(1,"The changed SW Version is %d\n",sw_ver);
chgstate_flag = 1;
break;
case 'f':
strcpy(dumpfile,optarg);
break;
case 'l':
dumplen = atoi(optarg);
break;
case 'o':
fgda_offset = atoi(optarg);
break;
case 'a':
auto_reboot = 1;
break;
default:
print_help(exe_filename);
exit(-1);
break;
}
}
if(chgstate_flag != 1)
{
printf("Your Must Set the State Vaule or changed SW version!\n");
print_help(exe_filename);
exit(-1);
}
}
//get dir from file name
void getdir(char *src,char **buf)
{
int l = strlen(src);
dbg_print(1,"src:%s,len:%d\n",src,l);
char *p = strrchr(src,'/');
int len = strlen(p);
dbg_print(1,"*p=%s,len:%d\n",p,len);
strncpy(*buf,src,(l-len));
(*buf)[l-len]='\0';
dbg_print(1,"buf:%s\n",*buf);
}
//check the dir if exist,dump the file to dir
int check_dump_file(void)
{
char *buf;
int status;
char cmd[64]="\0";
if(!access(dumpfile,R_OK))
{
dbg_print(1,"The file allready existed !\n");
return 0;
}
buf = malloc(50);
memset(buf,'\0',sizeof(buf));
//if file is not exist,then mkdir the path and dump the file
getdir(dumpfile,&buf);
dbg_print(1,"dir name is %s\n",buf);
if(opendir(buf) == NULL)
{
status = mkdir(buf,S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH);
if(status == -1)
{
printf("mkdir %s error\n",buf);
free(buf);
return -1;
}
}
free(buf);
sprintf(cmd,"nanddump -q -o -l %d -f %s /dev/mtd%d",dumplen,dumpfile,mtdnum);
system(cmd);
return 0;
}
int jwtdrv_flash_read(const char *filename,U32 offset, U32 len, U8 *buff)
{
int flag = 0;
FILE *fp = NULL;
int nflag=-1;
fp = fopen(filename,"r+");
if(NULL == fp)
{
fclose(fp);
return -1;
}
fseek(fp,offset,SEEK_SET);
nflag = fread(buff,1,len,fp);
fclose(fp);
if(0 > nflag)
{
return -1;
}
return nflag;
}
int jwtdrv_flash_write(const char *filename,U32 offset, U32 len, U8 *buff)
{
int fp;
int nflag = -1;
fp = open(filename,O_RDWR);
if(-1 == fp)
{
return -1;
}
lseek(fp,offset,SEEK_SET);
// fseek(fp,offset,SEEK_SET);
nflag = write(fp,buff,len);
// nflag=fwrite(buff,1,len,fp);
if(0 > nflag)
{
close(fp);
return -1;
}
fsync(fp);
close(fp);
return 0;
}
int parse_str(char *ssrc,char *src,char *dst)
{
char *ptr;
ptr = strstr(ssrc,src);
ptr = strchr(ssrc,'=');
ptr++;
strcpy(dst,ptr);
dbg_print(1,"buf:%s\n",dst);
return 0;
}
int buf_to_int(char *buf)
{
int conved = 0;
if((!strncmp(buf,"0x",2)) || (!strncmp(buf,"0X",2)))
{
conved = strtoul(buf,NULL,16);
}
else
{
conved = atoi(buf);
}
return conved;
}
int read_cfg_from_usb()
{
FILE *fp = NULL;
char chptr[256];
char *ptr;
char buf[256];
#if 0
fp = fopen("usb_update.cfg","rb");
#else
fp = fopen(filename,"rb");
#endif
if(fp == NULL)
{
printf("Open File from USB error\n");
return -1;
}
while(fgets(chptr,256,fp)!='\0')
{
if(strncasecmp(chptr,"[E_JWT_USB_UPDATE]",17) == 0)
{
printf("End of JWT Usb Update config!\n");
break;
}
if(strncasecmp(chptr,"[S_JWT_USB_UPDATE]",17) == 0)
{
fgets(chptr,256,fp);
parse_str(chptr,"state=",buf);
chgstate = buf_to_int(buf);
fgets(chptr,256,fp);
parse_str(chptr,"sw_ver=",buf);
sw_ver = buf_to_int(buf);
fgets(chptr,256,fp);
parse_str(chptr,"stbmtd=",buf);
mtdnum = buf_to_int(buf);
fgets(chptr,256,fp);
parse_str(chptr,"dumpfile=",buf);
strncpy(dumpfile,buf,strlen(dumpfile));
fgets(chptr,256,fp);
parse_str(chptr,"dumplen=",buf);
dumplen = buf_to_int(buf);
fgets(chptr,256,fp);
parse_str(chptr,"off_bca=",buf);
bca_offset = buf_to_int(buf);
fgets(chptr,256,fp);
parse_str(chptr,"off_fgda=",buf);
fgda_offset = buf_to_int(buf);
fgets(chptr,256,fp);
parse_str(chptr,"auto_reboot=",buf);
auto_reboot = buf_to_int(buf);
fgets(chptr,256,fp);
parse_str(chptr,"debug_print=",buf);
quit = buf_to_int(buf);
}
}
if(fp != NULL)
{
fclose(fp);
}
return 0;
}
void printf_usb_cfg()
{
printf("chgstate:0x%x\n",chgstate);
printf("sw_ver:0x%x\n",sw_ver);
printf("mtdnum:%d\n",mtdnum);
printf("dumpfile:%s\n",dumpfile);
printf("dumplen:%d\n",dumplen);
printf("bca_offset:%d\n",bca_offset);
printf("fgda_offset:%d\n",fgda_offset);
printf("auto_reboot:%d\n",auto_reboot);
}
int main(int argc,char *argv[])
{
int ret = 0;
char *buf;
U32 FDCACRCValue;
U32 BCACrc32Value;
JWT_UPDATE_FDCA_t fdca_t;
JWT_UPDATE_BCA_t bca_t;
char cmd[128]="\0";
//save the bin file name
strcpy(exe_filename,argv[0]);
buf = malloc(1024);
memset(buf,'\0',1024);
//parse parameter
if(argc<=1)
{
//read input from usbdisk
ret = read_cfg_from_usb();
if(-1 ==ret)
{
return -1;
}
}
else
{
//input paramater
parse_input(argc,argv);
}
//check the file
ret = check_dump_file();
if(ret !=0)
{
dbg_print(2,"check and dump file error\n");
return -1;
}
//get default stb infomation
ret = jwtdrv_flash_read(dumpfile,0,1024,buf);
if(ret < 0)
{
dbg_print(2,"flash read error\n");
return -1;
}
else
{
memcpy(&fdca_t,&buf[512],sizeof(fdca_t));
memcpy(&bca_t,buf,sizeof(bca_t));
ori_chgstate = fdca_t.activation;
ori_sw_ver = bca_t.software_version[1];
}
#if 0
memset(&buf[offset],chgstate,1);
#else
if((chgstate < 0x17) || (chgstate > 0x2a))
{
printf("Your input State error,use default\n");
chgstate = ori_chgstate;
}
else
{
fdca_t.activation = chgstate;
FDCACRCValue = calculateCRC((U8 *)&fdca_t, sizeof(fdca_t) - 4);
fdca_t.crc[0] = (FDCACRCValue >> 24) & 0xFF;
fdca_t.crc[1] = (FDCACRCValue >> 16) & 0xFF;
fdca_t.crc[2] = (FDCACRCValue >> 8) & 0xFF;
fdca_t.crc[3] = FDCACRCValue & 0xFF;
memcpy(&buf[512],&fdca_t,sizeof(fdca_t));
}
#endif
if((sw_ver <= 0) || (sw_ver > 255))
{
printf("Your input SW_VER:%d error(0,255],Use dafault\n");
sw_ver = ori_sw_ver;
}
else
{
bca_t.software_version[1] = (unsigned char)sw_ver;
BCACrc32Value = calculateCRC((U8 *)&bca_t,sizeof(bca_t)-4);
bca_t.crc[0] = (U8)((BCACrc32Value >> 24) & 0xff);
bca_t.crc[1] = (U8)((BCACrc32Value >> 16) & 0xff);
bca_t.crc[2] = (U8)((BCACrc32Value >> 8) & 0xff);
bca_t.crc[3] = (U8)(BCACrc32Value & 0xff);
memcpy(buf,&bca_t,sizeof(bca_t));
}
if(jwtdrv_flash_write(dumpfile,0,1024,buf) != 0)
{
dbg_print(2,"flash write error\n");
return -1;
}
if(!quit)
{
printf_usb_cfg();
}
//erase flash first
sprintf(cmd,"flash_erase -q /dev/mtd%d 0 0",mtdnum);
system(cmd);
//write to flash
sprintf(cmd,"nandwrite -q /dev/mtd%d %s",mtdnum,dumpfile);
system(cmd);
if(auto_reboot)system("reboot");
return 0;
}
Makefile
.PHONY: all clean help
CROSS?=mipsel-linux-
ifeq ($(CROSS),)
arch:=x86
endif
ifeq ($(findstring mips,$(CROSS)),mips)
arch=mipsel
else
arch=other
endif
ifeq ($(findstring 7581,${platform}),7581)
CFLAGS += -DBCM7581B0
endif
ifeq ($(findstring 7019,${platform}),7019)
CFLAGS += -DBCM7019C0
endif
target:=chgstate_$(platform)_$(arch)
all:
$(if ${platform},,$(error platform must be set!!!))
@echo "flag ${CFLAGS} over"
$(CROSS)gcc ${CFLAGS} -o ${target} chgstate.c
clean:
rm -fr *.o chgstate_*
help:
@echo -e "*********************************************\n*"
@echo -e "* This Program Used for \n* modify sw version and boot flag"
@echo -e "*\n*"
@echo -e "*Example:"
@echo -e "*\tmake platform=7581"
@echo -e "*\tmake platform=7019"
@echo -e "*\n*********************************************"