#include #include #include #include #include "elog.h" #include "upg.h" #include "file.h" #include "thread.h" #include "modbus_handle.h" #if 1 #define LOGD log_d #define LOGE log_e #else #define LOGD printf #define LOGE printf #endif #define RETRY_MAX 3 #define REG_UPG_READ 1501 #define REG_UPG_WRITE 1550 #define REG_UPG_JUMP 6330 #define REG_BOARD_INFO 6331 enum { OFFLINE=0, ONLINE, UPGRADING, UPGRADE_OK, UPGRADE_FAIL, }; #pragma pack (1) typedef struct { int16_t pid; uint16_t dlen; uint8_t data[0]; }upg_pkt_t; #pragma pack () typedef struct { uint32_t id[3]; uint32_t channels; char ver[12]; char date[32]; }switch_info_t; typedef struct { int upging; char path[200]; }upg_arg_t; typedef struct { key_t key; upg_arg_t arg; handle_t upg; handle_t all; GlobalDeviceManager *dm; int init; }upg_handle_t; static upg_handle_t uHandle={0}; static int upg_board_scan(void); static void* board_thread(void *arg); static void mem_swap(void *buf, int len) { int i; uint8_t tmp,*pbuf=(uint8_t*)buf; for(i=0; i0) mem_swap(data, r*2); return (r==cnt)?0:-1; } static int mb_write(Modbus_Manger *mm, uint16_t addr, uint16_t reg, void *data, int len, int timeout) { int to,r,cnt=(len+len%2)/2; g_modbus_get_timeout(mm, &to); g_modbus_set_timeout(mm, timeout); r = g_modbus_write_x_reg(mm, addr, reg, cnt, data); g_modbus_set_timeout(mm, to); return (r==cnt)?0:-1; } ////////////////////////////////////////////////////////////////////// #define UPG_RW_TIMEOUT 200 static void sw_to_info(int addr, board_info_t *info, switch_info_t *swinfo, int status) { info->addr = addr; info->brd_id = swinfo->id[0]; info->channels = swinfo->channels; info->status = status; strcpy(info->name, "Board"); strcpy(info->ver, swinfo->ver); get_bldtime2(info->date, swinfo->date); } static int board_is_upgrading(Modbus_Manger* mm, int addr) { int r; uint16_t tmp; r = mb_read(mm, addr, REG_UPG_READ, &tmp, sizeof(tmp), UPG_RW_TIMEOUT); return (r==0)?1:0; } static int board_upgrade_jump(Modbus_Manger* mm, int addr) { int r; uint16_t tmp=1; r = mb_write(mm, addr, REG_UPG_JUMP, &tmp, sizeof(tmp), UPG_RW_TIMEOUT); return r; } static int board_get_info(Modbus_Manger* mm, int addr, switch_info_t *info) { int r; r = mb_read(mm, addr, REG_BOARD_INFO, info, sizeof(switch_info_t), UPG_RW_TIMEOUT); if(r==0) { LOGD("___board %d ver: %s\n", addr, info->ver); LOGD("___board %d date: %s\n", addr, info->date); } return r; } static int set_info(handle_t l, node_t *nd, node_t *xd, void *arg, int *act) { board_info_t *info1=(board_info_t*)nd->buf; board_info_t *info2=(board_info_t*)xd->buf; if(info1->addr<=0) { info2->status = info1->status; return 0; } else { if(info1->addr==info2->addr) { *act = LIST_ACT_STOP; *info2 = *info1; return 0; } else { return -1; } } } static int board_info_set(board_info_t *info) { int r=-1; node_t node; handle_t l=uHandle.all; node.buf = info; node.dlen = sizeof(board_info_t); node.blen = sizeof(board_info_t); r = xlist_iterator(l, &node, set_info, NULL); return r; } static int board_send(Modbus_Manger *mm, uint16_t addr, char *data, int dlen) { int r,pid=0; char temp[400]; int slen=0,onelen=0,onemax=128; upg_pkt_t *pkt=(upg_pkt_t*)temp; r = board_upgrade_jump(mm, addr); while(1) { if((slen+onemax)>=dlen) { //onelen = dlen-(slen+onemax); onelen = onemax; pid = -1; } else { onelen = onemax; } memcpy(pkt->data, data+slen, onelen); pkt->pid = pid; pkt->dlen = onelen; r = mb_write(mm, addr, REG_UPG_WRITE, pkt, onelen+sizeof(upg_pkt_t), 10); slen += onelen; if(pid==0) sleep(1); else usleep(10000); if(pid<0) break; pid++; } sleep(1); return 0; } static int board_proc(upg_handle_t *h, int quit) { int ok=0,err=0; buf_t fbuf; int i,r,timeout; switch_info_t swinfo; handle_t l=h->upg; list_node_t *ln=NULL; board_info_t info,*tmp; Modbus_Manger *mm=&h->dm->_globalRelaySampManger; r = file_load(h->arg.path, &fbuf); if(r) { return -1; } info.addr = -1; info.status = UPGRADING; board_info_set(&info); //broadcase upgrade file board_send(mm, 0, fbuf.buf, fbuf.dlen); while(1) { r = xlist_get_node(l, &ln, 0); if(r) { break; } tmp = (board_info_t*)ln->data.buf; for(i=0; iaddr, &swinfo); if(r==0) { break; } LOGE("___ board upgrade failed, retry %d\n", i+1); board_send(mm, i, fbuf.buf, fbuf.dlen); } if(r) { tmp->status = UPGRADE_FAIL; err++; } else { sw_to_info(tmp->addr, tmp, &swinfo, UPGRADE_OK); ok++; } board_info_set(tmp); xlist_remove(l, 0); } free(fbuf.buf); exit(0); //restart app return 0; } static int board_scan(void) { int i,r; board_info_t info={0}; upg_handle_t *h=&uHandle; handle_t l=h->upg; Modbus_Manger *mm=&h->dm->_globalRelaySampManger; for(i=1; i<=h->dm->brdMax; i++) { r = board_is_upgrading(mm, i); if(r) { info.addr = i; info.status = UPGRADE_FAIL; xlist_append(l, 0, &info, sizeof(info)); } } return 0; } static void start_threads(int flag) { if(flag) { thread_start2(THREAD_ID_SNMP); thread_start2(THREAD_ID_POWER); //thread_start2(THREAD_ID_CASCADE); //thread_start2(THREAD_ID_CASCADE_SCAN); //thread_start2(THREAD_ID_BREAKER); //thread_start2(THREAD_ID_BREAKER_SCANNER); } else { thread_stop(THREAD_ID_SNMP); thread_stop(THREAD_ID_POWER); //thread_stop(THREAD_ID_CASCADE); //thread_stop(THREAD_ID_CASCADE_SCAN); //thread_stop(THREAD_ID_BREAKER); //thread_stop(THREAD_ID_BREAKER_SCANNER); } } static void* board_thread(void *arg) { int r; thread_handle_t *th=(thread_handle_t*)arg; upg_handle_t *h=(upg_handle_t*)th->arg; Modbus_Manger *mm=&h->dm->_globalRelaySampManger; board_scan(); upg_board_all_update(); while(th->quit==0) { if(h->arg.upging) { start_threads(0); r = board_proc(h, th->quit); start_threads(1); file_remove(h->arg.path); h->arg.upging = 0; } else { sleep(2); } } pthread_exit(NULL); } ///////////////////////////////////////////////////// int upg_init(void) { int r,msgid; list_cfg_t lc={0,LIST_FULL_FIFO,-1}; upg_handle_t *h=&uHandle; memset(h, 0, sizeof(upg_handle_t)); h->dm = &__globalDeviceManage; h->key = ftok(UPG_KEY_PATH, UPG_KEY_SN); if(h->key<0) { LOGE("ftok %s failed, errno: %d\n", UPG_KEY_PATH, errno); return -1; } h->upg = xlist_init(&lc); h->all = xlist_init(&lc); h->init = 1; #ifdef USE_BOARD_UPGRADE thread_start(THREAD_ID_BOARD, board_thread, h); #endif upg_host_send(UPGRADE_EVT_APP_RUNNING); return 0; } int upg_host_send(int evt) { int r,msgid; msgbuf_t mb; upg_handle_t *h=&uHandle; msgid = msgget(h->key, 0666|IPC_CREAT); //LOGD("+++++++++++ key: %d, msgid: %d\n", ukey, msgid); mb.evt = evt; r = msgsnd(msgid, &mb, sizeof(mb.evt), IPC_NOWAIT); if(r<0) { LOGE("msgsnd failed, %d, errno: %d\n", r, errno); } else { LOGD("msgsnd evt 0x%02x ok\n", evt); } return r; } ///////////////////////////////////////////////////////// handle_t upg_board_list_get(void) { upg_handle_t *h=&uHandle; return h->upg; } int upg_board_list_set(char *s) { int i=0,n=0,max=0; char tmp[10],*p=s; char *tok="productId="; board_info_t info={0}; handle_t l=uHandle.upg; if(!s) { return -1; } p = strstr(p, tok); if(!p) { return -1; } p += strlen(tok); while(1) { if((*p)==',' || (*p)=='&') { tmp[i] = 0; info.addr = atoi(tmp); xlist_append(l, 0, &info, sizeof(info)); i = 0; n++; if((*p)=='&') { break; } } else { tmp[i++] = *p; } p++; } return (n>0)?0:-1; } handle_t upg_board_all_get(void) { int r; upg_handle_t *h=&uHandle; return h->all; } int upg_board_all_update(void) { int i,r,addr; list_node_t *ln=NULL; upg_handle_t *h=&uHandle; handle_t l=h->all; Modbus_Manger *mm=&h->dm->_globalRelaySampManger; GlobalPowerManger *tmp,*hd=&h->dm->_globalPowerManger; switch_info_t swinfo; board_info_t info; if(!h->init) { return -1; } xlist_clear(l); list_for_each_entry(tmp,&hd->list,list) { if(tmp->product_saddr>0) { addr = tmp->product_saddr; for(i=0; iupg, &ln, 0); if(r) { break; } xlist_append_node(h->all, ln); } return 0; } static int fw_check(char *path); int upg_board_start(char *path) { upg_handle_t *h=&uHandle; if(h->arg.upging==1) { return -1; } strcpy(h->arg.path,path); h->arg.upging = 1; return 0; } #include "md5.h" #include "file.h" #define FW_HEAD_MAGIC "GOWONE_UPGRADE" #pragma pack (1) typedef union { struct { uint8_t magic[14]; uint16_t size; uint32_t partition; uint32_t version; }hdr; uint8_t padd[128]; }fw_hdr_t; #pragma pack () #define CHAR(b) (((b)<=9)?((b)+0x30):((b)-10+0x61)); static void byte2char(char *chr, uint8_t b) { chr[0] = CHAR(b>>4); chr[1] = CHAR(b&0x0f); } static void print_md5(char *s, md5_t *m) { int i; printf("__%s", s); for(i=0; i<32; i++) { printf("%c", m->data[i]); } printf("\n"); } //md5相同返回0,否则返回1 static int md5_check(buf_t *fb) { md5_t m1,m2; md5_ctx_t ctx; uint8_t i,tmp[16]; md5_init(&ctx); md5_update(&ctx, (uint8_t*)fb->buf, fb->dlen-32); md5_final(&ctx, tmp); for (i=0; i<16; i++) { byte2char(&m2.data[i*2], tmp[i]); } memcpy(&m1, fb->buf+fb->dlen-32, sizeof(md5_t)); print_md5("ori md5: ", &m1); print_md5("cal md5: ", &m2); if(memcmp(&m1, &m2, sizeof(md5_t))) { return -1; } return 0; } int upg_board_file_check(char *path) { int r=UPG_OK; buf_t fb; upg_handle_t *h=&uHandle; if(h->arg.upging==1) { return UPG_BUSYING; } r = file_load(path, &fb); if(r) { return -1; } fw_hdr_t *fh=(fw_hdr_t*)fb.buf; if(memcmp(fh->hdr.magic,FW_HEAD_MAGIC,sizeof(FW_HEAD_MAGIC))) { LOGE("not found %s, invalid board firmware\n", FW_HEAD_MAGIC); r = UPG_HDR_FAIL; } if(md5_check(&fb)) { LOGE("md5 check failed, invalid board firmware\n"); r = UPG_MD5_FAIL; } free(fb.buf); return r; } int upg_host_file_check(char *path) { return 0; }