summaryrefslogtreecommitdiffstats
path: root/package/librtk-inband/src/inband_cmd.c
diff options
context:
space:
mode:
Diffstat (limited to 'package/librtk-inband/src/inband_cmd.c')
-rw-r--r--package/librtk-inband/src/inband_cmd.c465
1 files changed, 465 insertions, 0 deletions
diff --git a/package/librtk-inband/src/inband_cmd.c b/package/librtk-inband/src/inband_cmd.c
new file mode 100644
index 000000000..a85a04f8a
--- /dev/null
+++ b/package/librtk-inband/src/inband_cmd.c
@@ -0,0 +1,465 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <signal.h>
+#include <unistd.h>
+#include <sys/ioctl.h>
+#include <errno.h>
+
+#include <fcntl.h>
+#include <sys/types.h>
+#include <sys/uio.h>
+
+#include <sys/stat.h> //mark_file
+
+#include "inband_if.h"
+
+#define HOST_NETIF ("wlan0")
+#define SLAVE_MAC ("001234567899")
+#define ETH_P_RTK 0x8899 // Realtek Remote Control Protocol (RRCP)
+int hcd_inband_chan=0;
+
+// command ID
+#define id_ioctl 0x01
+#define id_systemcall 0x02
+#define id_firm_upgrade 0x03
+#define id_hostcmd_only 0xff //only for new hostcmd implement ,if the cmd is not real "inband cmd"
+
+// Command Table
+struct inband_cmd_table_t {
+ char cmd_id;
+ const char *cmd; // Input command string
+ int (*func)(int index,int argc, char *argv[]);
+ void (*print_func)(char *para,char *data,int len);
+ const char *msg; // Help message
+};
+
+/*firmware define*/
+#define __PACK__ __attribute__ ((packed))
+
+#define SIGNATURE_LEN 4
+#define FW_HEADER_WITH_ROOT ((char *)"cr6c")
+#define FW_HEADER ((char *)"cs6c")
+#define ROOT_HEADER ((char *)"r6cr")
+#define WEB_HEADER ((char *)"w6cg") //no ap sign now //mark_issue
+
+typedef struct img_header {
+ unsigned char signature[SIGNATURE_LEN] __PACK__;
+ unsigned int startAddr __PACK__;
+ unsigned int burnAddr __PACK__;
+ unsigned int len __PACK__;
+} IMG_HEADER_T, *IMG_HEADER_Tp;
+
+
+unsigned int host_inband_seq=0; //use to do requset <-> response check
+
+int cmd_systemcall(int index,int argc, char *argv[]);
+int cmd_firmware_upgrade(int index,int argc, char *argv[]);
+void print_systemcall(char *para,char *data,int len);
+
+
+struct inband_cmd_table_t inband_cmd_table[]=
+{
+ //
+ {id_systemcall,"systemcall", cmd_systemcall, print_systemcall, "inband systemcall \'cmd_string\'"},
+ {id_firm_upgrade,"firm_upgrade", cmd_firmware_upgrade, NULL,"inband firm_upgrade /var/linux.bin"},
+ //{id_hostcmd_only,"send_conf", cmd_sendconf, NULL,"inband send_conf /etc/xxx.conf"},
+ {NULL, NULL, NULL},
+};
+
+
+unsigned int get_random(int max)
+{
+ struct timeval tod;
+
+ gettimeofday(&tod , NULL);
+ srand(tod.tv_usec);
+ return rand()%max;
+}
+
+void print_command_list(void)
+{
+ int i;
+
+ printf("\n==========commands for debugging============\n");
+ i = 0;
+ while (inband_cmd_table[i].cmd != NULL) {
+ printf("%s\n", inband_cmd_table[i].msg);
+ i++;
+ }
+}
+
+void print_systemcall(char *para,char *data,int len)
+{
+ int i=0;
+ unsigned char *value;
+
+ data[len] = '\0';
+ printf("cmd_cfgread \n");
+ printf("%s",data);
+}
+
+static int host_inband_write(char cmd_id,char *data,int data_len)
+{
+ int ret;
+
+ host_inband_seq = get_random(65536);
+
+ ret = inband_write(hcd_inband_chan,host_inband_seq,cmd_id,data,data_len,0); //send request
+ return ret;
+}
+
+static inline int CHECKSUM_OK(unsigned char *data, int len)
+{
+ int i;
+ unsigned char sum=0;
+
+ for (i=0; i<len; i++)
+ sum += data[i];
+
+ if (sum == 0)
+ return 1;
+ else
+ return 0;
+}
+
+static int fwChecksumOk(char *data, int len)
+{
+ unsigned short sum=0;
+ int i;
+
+ for (i=0; i<len; i+=2) {
+#ifdef _LITTLE_ENDIAN_
+ sum += WORD_SWAP( *((unsigned short *)&data[i]) );
+#else
+ sum += *((unsigned short *)&data[i]);
+#endif
+
+ }
+ return( (sum==0) ? 1 : 0);
+}
+static int host_firmware_write(char *data,int len)
+{
+ unsigned int tx_seq,rx_seq;
+ int ret=0,count;
+ char rx_cmd_type;
+ char *buf_p;
+
+ ret = host_inband_write(id_firm_upgrade,data,len); //send request
+
+ tx_seq = host_inband_seq;
+
+ if(ret < 0)
+ return -1;
+
+ ret = inband_rcv_data_and_seq(hcd_inband_chan,&rx_seq,&rx_cmd_type,&buf_p,20000); //return data length
+
+ if(ret < 0)
+ {
+ ret=-1;
+ goto out;
+ }
+
+ if( (rx_cmd_type == id_firm_upgrade) && (tx_seq == rx_seq))
+ printf("host_firmware_write ok!\n");
+ else
+ {
+ ret=-1;
+ printf("host_firmware_write fail!\n");
+ }
+
+out:
+ inband_free_buf(buf_p, count);
+ return ret;
+
+}
+
+static int rtk_firmware_update(char *upload_data, int upload_len)
+{
+int head_offset=0 ;
+int isIncludeRoot=0;
+int len;
+ int numLeft;
+int numWrite;
+IMG_HEADER_Tp pHeader;
+int fh;
+int fwSizeLimit = 0x200000;
+char buffer[100];
+int flag=0;
+
+while(head_offset < upload_len) {
+
+ pHeader = (IMG_HEADER_Tp) &upload_data[head_offset];
+ len = pHeader->len;
+#ifdef _LITTLE_ENDIAN_
+ len = DWORD_SWAP(len);
+#endif
+
+ numLeft = len + sizeof(IMG_HEADER_T) ;
+
+ // check header and checksum
+ if (!memcmp(&upload_data[head_offset], FW_HEADER, SIGNATURE_LEN) ||
+ !memcmp(&upload_data[head_offset], FW_HEADER_WITH_ROOT, SIGNATURE_LEN))
+ flag = 1;
+ else if (!memcmp(&upload_data[head_offset], WEB_HEADER, SIGNATURE_LEN))
+ flag = 2;
+ else if (!memcmp(&upload_data[head_offset], ROOT_HEADER, SIGNATURE_LEN)){
+ flag = 3;
+ isIncludeRoot = 1;
+ }
+ else {
+ strcpy(buffer, "Invalid file format!");
+ goto ret_upload;
+ }
+
+ if(len > fwSizeLimit){ //len check by sc_yang
+ sprintf(buffer, "Image len exceed max size 0x%x ! len=0x%x",fwSizeLimit, len);
+ goto ret_upload;
+ }
+ if ( (flag == 1) || (flag == 3)) {
+ if ( !fwChecksumOk(&upload_data[sizeof(IMG_HEADER_T)+head_offset], len)) {
+ sprintf(buffer, "Image checksum mismatched! len=0x%x, checksum=0x%x", len,
+ *((unsigned short *)&upload_data[len-2]) );
+ goto ret_upload;
+ }
+ }
+ else {
+ char *ptr = &upload_data[sizeof(IMG_HEADER_T)+head_offset];
+ if ( !CHECKSUM_OK(ptr, len) ) {
+ sprintf(buffer, "Image checksum mismatched! len=0x%x", len);
+ goto ret_upload;
+ }
+ }
+
+ //numWrite = write(fh, &(upload_data[locWrite+head_offset]), numLeft);
+ //inband write , and check ack
+ if(host_firmware_write(&(upload_data[head_offset]),numLeft) < 0 )
+ {
+ sprintf(buffer, "host_firmware_write! numLeft=0x%x", numLeft);
+ goto ret_upload;
+ }
+
+ head_offset += len + sizeof(IMG_HEADER_T) ;
+ }
+
+ return 0;
+
+ ret_upload:
+ fprintf(stderr, "%s\n", buffer);
+ return -1;
+} //while //sc_yang
+
+int cmd_firmware_upgrade(int index,int argc, char *argv[])
+{
+ int len,ret,count;
+ //char data[1480];
+ char filename[50];
+ char *data;
+ int fd,rc;
+ struct stat ffstat;
+ int flen=0;
+
+ //sprintf(data,"%s",argv[2]);
+ sprintf(filename,"%s",argv[2]);
+
+ fd = open(filename, O_RDONLY);
+
+ if (fd < 0) {
+ printf("Cannot Open file %s!\n", filename);
+ return -1;
+ }
+ fstat(fd, &ffstat);
+ flen = ffstat.st_size;
+ printf("flen = %d \n",flen);
+
+ if((data = (char *)malloc(flen)) == NULL)
+ {
+ printf("data buffer allocation failed!\n");
+ return -1;
+ }
+
+ // rc = read(fd, data, 1480);
+ rc = read(fd, data, flen);
+
+ //if (rc != 1480) {
+ if (rc != flen) {
+ printf("Reading error\n");
+ free(data); //need free before return!!!!!
+ return -1;
+ }
+
+ close(fd);
+
+ ret = rtk_firmware_update(data, flen);
+
+ if(ret < 0)
+ printf("rtk_firmware_update fail \n");
+ else
+ printf("rtk_firmware_update ok \n");
+
+ free(data); //need free before return!!!!!
+
+ return ret;
+}
+
+#if 0
+int cmd_sendconf(int index,int argc, char *argv[])
+{
+ int len,ret,count;
+ //char data[1480];
+ char cmd_id,rx_cmd_type;
+ char *buf_p;
+ unsigned int tx_seq,rx_seq;
+ char filename[50];
+ char *data;
+ int fd,rc;
+ struct stat ffstat;
+ int flen=0;
+
+ cmd_id = id_set_mib;
+
+ //sprintf(data,"%s",argv[2]);
+ sprintf(filename,"%s",argv[2]);
+
+ fd = open(filename, O_RDONLY);
+
+ if (fd < 0) {
+ printf("Cannot Open file %s!\n", filename);
+ return -1;
+ }
+ fstat(fd, &ffstat);
+ flen = ffstat.st_size;
+ printf("flen = %d \n",flen);
+
+ if((data = (char *)malloc(flen)) == NULL)
+ {
+ printf("data buffer allocation failed!\n");
+ return -1;
+ }
+
+ // rc = read(fd, data, 1480);
+ rc = read(fd, data, flen);
+
+ //if (rc != 1480) {
+ if (rc != flen) {
+ printf("Reading error\n");
+ free(data); //need free before return!!!!!
+ return -1;
+ }
+
+ close(fd);
+ //len = 1480;
+ len = flen;
+ tx_seq = host_inband_seq;
+ ret = host_inband_write(cmd_id,data,len); //send request
+
+ free(data); //need free before return!!!!!
+
+ if(ret < 0)
+ return -1;
+
+ //count = inband_rcv_data(&rx_cmd_type,&buf_p,1000); //return data length
+ count = inband_rcv_data_and_seq(hcd_inband_chan,&rx_seq,&rx_cmd_type,&buf_p,3000); //return data length
+ if(count < 0)
+ {
+ ret=-1;
+ goto out;
+ }
+
+ if( (rx_cmd_type == cmd_id) && (tx_seq == rx_seq))
+ printf("remote write ok!\n");
+ else
+ {
+ ret=-1;
+ printf("remote write fail!\n");
+ }
+
+ out:
+ inband_free_buf(buf_p, count);
+
+ return ret;
+}
+#endif
+int cmd_systemcall(int index,int argc, char *argv[])
+{
+ int len,ret,count;
+ char data[1480];
+ char cmd_id,rx_cmd_type;
+ char *buf_p;
+ unsigned int tx_seq,rx_seq;
+
+ cmd_id = inband_cmd_table[index].cmd_id;
+
+ if(argc > 3)
+ sprintf(data,"%s %s",argv[2],argv[3]);
+ else
+ sprintf(data,"%s",argv[2]);
+
+ len = strlen(data);
+
+
+ ret = host_inband_write(cmd_id,data,len); //send request
+
+ tx_seq = host_inband_seq;
+
+ if(ret < 0)
+ return -1;
+
+ //count = inband_rcv_data(&rx_cmd_type,&buf_p,1000); //return data length
+ count = inband_rcv_data_and_seq(hcd_inband_chan,&rx_seq,&rx_cmd_type,&buf_p,1000); //return data length
+
+ if(count < 0)
+ return -1;
+ //printf("count=%d rx_cmd_type=%x,cmd_id=%x,tx_seq=%d,rx_seq=%d",count,rx_cmd_type,cmd_id,tx_seq,rx_seq);
+
+ if((rx_cmd_type == cmd_id) && (tx_seq == rx_seq))
+ {
+ if(inband_cmd_table[index].print_func)
+ inband_cmd_table[index].print_func(data,buf_p,count);
+ }
+ else
+ return -1;
+
+ return 0;
+
+}
+
+int main(int argc, char *argv[])
+{
+ //int fdflags;
+ //unsigned int arg;
+ int i, ret;
+ int chan;
+
+ if (argc < 2) {
+ print_command_list();
+ return 0;
+ }
+
+ //open inband
+ chan = inband_open(HOST_NETIF,SLAVE_MAC,ETH_P_RTK,0);
+ if (chan < 0) {
+ printf("open inband failed!\n");
+ return -1;
+ }
+ hcd_inband_chan = chan;
+
+ i = 0;
+ while (inband_cmd_table[i].cmd != NULL) {
+ if (0 == strcmp(argv[1], inband_cmd_table[i].cmd)) {
+ if (inband_cmd_table[i].func) {
+ ret = inband_cmd_table[i].func(i,argc, argv);
+ if (ret > 0)
+ printf("OK\n");
+ else if (ret < 0)
+ printf("FAIL\n");
+ }
+ break;
+ }
+ i++;
+ }
+
+ inband_close(hcd_inband_chan);
+
+ return 0;
+}