upg.c 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677
  1. #include <errno.h>
  2. #include <stdio.h>
  3. #include <sys/ipc.h>
  4. #include <sys/msg.h>
  5. #include "elog.h"
  6. #include "upg.h"
  7. #include "sys.h"
  8. #include "file.h"
  9. #include "thread.h"
  10. #include "modbus_handle.h"
  11. #if 1
  12. #define LOGD log_d
  13. #define LOGE log_e
  14. #else
  15. #define LOGD printf
  16. #define LOGE printf
  17. #endif
  18. #define RETRY_MAX 3
  19. #define REG_UPG_READ 1501
  20. #define REG_UPG_WRITE 1550
  21. #define REG_UPG_JUMP_3 6330
  22. #define REG_BOARD_INFO_3 6331
  23. #define REG_UPG_JUMP_S 5260
  24. #define REG_BOARD_INFO_S 4360
  25. enum {
  26. OFFLINE=0,
  27. ONLINE,
  28. UPGRADING,
  29. UPGRADE_OK,
  30. UPGRADE_FAIL,
  31. };
  32. #pragma pack (1)
  33. typedef struct {
  34. int16_t pid;
  35. uint16_t dlen;
  36. uint8_t data[0];
  37. }upg_pkt_t;
  38. #pragma pack ()
  39. typedef struct {
  40. uint32_t id[3];
  41. uint32_t channels;
  42. char ver[12];
  43. char date[32];
  44. }switch_info_t;
  45. typedef struct {
  46. int upging;
  47. char path[200];
  48. }upg_arg_t;
  49. typedef struct {
  50. key_t key;
  51. upg_arg_t arg;
  52. handle_t upg;
  53. handle_t all;
  54. GlobalDeviceManager *dm;
  55. int init;
  56. }upg_handle_t;
  57. static upg_handle_t uHandle={0};
  58. static int upg_board_scan(void);
  59. static void* board_thread(void *arg);
  60. static void mem_swap(void *buf, int len)
  61. {
  62. int i;
  63. uint8_t tmp,*pbuf=(uint8_t*)buf;
  64. for(i=0; i<len; i+=2) {
  65. tmp = pbuf[i];
  66. pbuf[i] = pbuf[i+1];
  67. pbuf[i+1] = tmp;
  68. }
  69. }
  70. static int mb_read(Modbus_Manger *mm, uint16_t addr, uint16_t reg, void *data, int len, int timeout)
  71. {
  72. int to,r,cnt=(len+len%2)/2;
  73. g_modbus_get_timeout(mm, &to);
  74. g_modbus_set_timeout(mm, timeout);
  75. r = g_modbus_read_x_reg(mm, addr, reg, cnt, data);
  76. g_modbus_set_timeout(mm, to);
  77. //if(r>0) mem_swap(data, r*2);
  78. return (r==cnt)?0:-1;
  79. }
  80. static int mb_write(Modbus_Manger *mm, uint16_t addr, uint16_t reg, void *data, int len, int timeout)
  81. {
  82. int to,r,cnt=(len+len%2)/2;
  83. g_modbus_get_timeout(mm, &to);
  84. g_modbus_set_timeout(mm, timeout);
  85. r = g_modbus_write_x_reg(mm, addr, reg, cnt, data);
  86. g_modbus_set_timeout(mm, to);
  87. return (r==cnt)?0:-1;
  88. }
  89. //////////////////////////////////////////////////////////////////////
  90. #define UPG_RW_TIMEOUT 200
  91. static void sw_to_info(int addr, board_info_t *info, switch_info_t *swinfo, int status)
  92. {
  93. info->addr = addr;
  94. info->brd_id = swinfo->id[2];
  95. info->channels = swinfo->channels;
  96. info->status = status;
  97. strcpy(info->name, "Board");
  98. strcpy(info->ver, swinfo->ver);
  99. get_bldtime2(info->date, swinfo->date);
  100. }
  101. static int board_is_upgrading(Modbus_Manger* mm, int addr)
  102. {
  103. int r;
  104. uint16_t tmp;
  105. r = mb_read(mm, addr, REG_UPG_READ, &tmp, sizeof(tmp), UPG_RW_TIMEOUT);
  106. return (r==0)?1:0;
  107. }
  108. static int board_upgrade_jump(Modbus_Manger* mm, int addr)
  109. {
  110. int r;
  111. uint16_t tmp=1;
  112. upg_handle_t *h=&uHandle;
  113. if(h->dm->_globalDevInfo.product.pwr_type == SmartPDU_DC
  114. || h->dm->_globalDevInfo.product.pwr_type == SmartPDU_Tree_AC_Tree)
  115. {
  116. r = mb_write(mm, addr, REG_UPG_JUMP_3, &tmp, sizeof(tmp), UPG_RW_TIMEOUT);
  117. }else
  118. {
  119. r = mb_write(mm, addr, REG_UPG_JUMP_S, &tmp, sizeof(tmp), UPG_RW_TIMEOUT);
  120. }
  121. return r;
  122. }
  123. static int board_get_info(Modbus_Manger* mm, int addr, switch_info_t *info)
  124. {
  125. int r;
  126. upg_handle_t *h=&uHandle;
  127. if(h->dm->_globalDevInfo.product.pwr_type == SmartPDU_DC
  128. || h->dm->_globalDevInfo.product.pwr_type == SmartPDU_Tree_AC_Tree)
  129. {
  130. r = mb_read(mm, addr, REG_BOARD_INFO_3, info, sizeof(switch_info_t), UPG_RW_TIMEOUT);
  131. LOGD("___board %d ver: %s\n", addr, info->ver);
  132. LOGD("___board %d date: %s\n", addr, info->date);
  133. }else
  134. {
  135. r = mb_read(mm, addr, REG_BOARD_INFO_S, info, sizeof(switch_info_t), UPG_RW_TIMEOUT);
  136. LOGD("___board %d ver: %s\n", addr, info->ver);
  137. LOGD("___board %d date: %s\n", addr, info->date);
  138. }
  139. return r;
  140. }
  141. static int set_info(handle_t l, node_t *nd, node_t *xd, void *arg, int *act)
  142. {
  143. board_info_t *info1=(board_info_t*)nd->buf;
  144. board_info_t *info2=(board_info_t*)xd->buf;
  145. if(info1->addr<=0) {
  146. info2->status = info1->status;
  147. return 0;
  148. }
  149. else {
  150. if(info1->addr==info2->addr) {
  151. *act = LIST_ACT_STOP;
  152. *info2 = *info1;
  153. return 0;
  154. }
  155. else {
  156. return -1;
  157. }
  158. }
  159. }
  160. static int set_info2(handle_t l, node_t *nd, node_t *xd, void *arg, int *act)
  161. {
  162. board_info_t *info1=(board_info_t*)nd->buf;
  163. board_info_t *info2=(board_info_t*)xd->buf;
  164. if(info1->addr==info2->addr) {
  165. *act = LIST_ACT_STOP;
  166. info2->status = info1->status;
  167. return 0;
  168. }
  169. return -1;
  170. }
  171. static int board_info_set(board_info_t *info)
  172. {
  173. int r=-1;
  174. node_t node;
  175. handle_t l=uHandle.all;
  176. node.buf = info;
  177. node.dlen = sizeof(board_info_t);
  178. node.blen = sizeof(board_info_t);
  179. r = xlist_iterator(l, &node, set_info, NULL);
  180. return r;
  181. }
  182. static int board_info_set2(board_info_t *info)
  183. {
  184. int r=-1;
  185. node_t node;
  186. handle_t l=uHandle.all;
  187. node.buf = info;
  188. node.dlen = sizeof(board_info_t);
  189. node.blen = sizeof(board_info_t);
  190. r = xlist_iterator(l, &node, set_info2, NULL);
  191. return r;
  192. }
  193. static int board_send(Modbus_Manger *mm, uint16_t addr, char *data, int dlen)
  194. {
  195. int r,pid=0;
  196. char temp[400];
  197. int slen=0,onelen=0,onemax=128;
  198. upg_pkt_t *pkt=(upg_pkt_t*)temp;
  199. board_upgrade_jump(mm, addr);
  200. sleep(1);
  201. r = board_is_upgrading(mm,addr);
  202. if(r == 0){
  203. sleep(3);
  204. r = board_upgrade_jump(mm, addr);
  205. sleep(3);
  206. r = board_is_upgrading(mm,addr);
  207. }
  208. LOGD("r = %d addr = %d\n",r,addr);
  209. if(r == 0)
  210. {
  211. return -1;
  212. }
  213. sleep(2);
  214. while(1) {
  215. if((slen+onemax)>=dlen) {
  216. //onelen = dlen-(slen+onemax);
  217. onelen = onemax;
  218. pid = -1;
  219. }
  220. else {
  221. onelen = onemax;
  222. }
  223. memcpy(pkt->data, data+slen, onelen);
  224. pkt->pid = pid;
  225. pkt->dlen = onelen;
  226. r = mb_write(mm, addr, REG_UPG_WRITE, pkt, onelen+sizeof(upg_pkt_t), 80);
  227. slen += onelen;
  228. if(pid==0) {
  229. //file_save("/tmp/xxx.bin", pkt, onelen+sizeof(upg_pkt_t));
  230. sleep(1);
  231. }
  232. else usleep(20000);
  233. if(pid<0) break;
  234. pid++;
  235. }
  236. sleep(2);
  237. return 0;
  238. }
  239. static int board_proc(upg_handle_t *h, int quit)
  240. {
  241. int ok=0,err=0;
  242. buf_t fbuf;
  243. int i,r,timeout;
  244. switch_info_t swinfo;
  245. handle_t l=h->upg;
  246. list_node_t *ln=NULL;
  247. board_info_t info,*tmp;
  248. Modbus_Manger *mm=&h->dm->_globalRelaySampManger;
  249. r = file_load(h->arg.path, &fbuf);
  250. if(r) {
  251. return -1;
  252. }
  253. // info.addr = -1;
  254. // info.status = UPGRADING;
  255. // board_info_set(&info);
  256. //broadcase upgrade file
  257. sleep(1);
  258. while(1) {
  259. r = xlist_get_node(l, &ln, 0);
  260. if(r) {
  261. break;
  262. }
  263. tmp = (board_info_t*)ln->data.buf;
  264. info.addr = tmp->addr;
  265. info.status = UPGRADING;
  266. board_info_set2(&info);
  267. r = board_send(mm, tmp->addr, fbuf.buf, fbuf.dlen);
  268. if(r == 0)
  269. {
  270. for(i=0; i<20; i++) {
  271. r = board_get_info(mm, tmp->addr, &swinfo);
  272. if(r==0) {
  273. break;
  274. }
  275. LOGE("___ board upgrade failed, retry %d\n", i+1);
  276. sleep(1);
  277. // board_send(mm, i, fbuf.buf, fbuf.dlen);
  278. }
  279. }
  280. if(r) {
  281. tmp->status = UPGRADE_FAIL;
  282. err++;
  283. }
  284. else {
  285. sw_to_info(tmp->addr, tmp, &swinfo, UPGRADE_OK);
  286. ok++;
  287. }
  288. board_info_set(tmp);
  289. xlist_remove(l, 0);
  290. }
  291. free(fbuf.buf);
  292. // sys_exit(); //restart app
  293. return 0;
  294. }
  295. static int board_scan(void)
  296. {
  297. int i,r;
  298. board_info_t info={0};
  299. upg_handle_t *h=&uHandle;
  300. handle_t l=h->upg;
  301. Modbus_Manger *mm=&h->dm->_globalRelaySampManger;
  302. for(i=1; i<=h->dm->brdMax; i++) {
  303. r = board_is_upgrading(mm, i);
  304. if(r) {
  305. info.addr = i;
  306. info.status = UPGRADE_FAIL;
  307. xlist_append(l, 0, &info, sizeof(info));
  308. }
  309. }
  310. return 0;
  311. }
  312. static void start_threads(int flag)
  313. {
  314. if(flag) {
  315. // thread_start2(THREAD_ID_SNMP);
  316. // thread_start2(THREAD_ID_POWER);
  317. //thread_start2(THREAD_ID_CASCADE);
  318. //thread_start2(THREAD_ID_CASCADE_SCAN);
  319. //thread_start2(THREAD_ID_BREAKER);
  320. //thread_start2(THREAD_ID_BREAKER_SCANNER);
  321. }
  322. else {
  323. // thread_stop(THREAD_ID_SNMP);
  324. // thread_stop(THREAD_ID_POWER);
  325. //thread_stop(THREAD_ID_CASCADE);
  326. //thread_stop(THREAD_ID_CASCADE_SCAN);
  327. //thread_stop(THREAD_ID_BREAKER);
  328. //thread_stop(THREAD_ID_BREAKER_SCANNER);
  329. }
  330. }
  331. static void* board_thread(void *arg)
  332. {
  333. int r;
  334. thread_handle_t *th=(thread_handle_t*)arg;
  335. upg_handle_t *h=(upg_handle_t*)th->arg;
  336. Modbus_Manger *mm=&h->dm->_globalRelaySampManger;
  337. board_scan();
  338. upg_board_all_update();
  339. while(th->quit==0) {
  340. if(h->arg.upging) {
  341. // start_threads(0);
  342. h->dm->upgread_flag = 1;
  343. sleep(2);
  344. r = board_proc(h, th->quit);
  345. //start_threads(1);
  346. file_remove(h->arg.path);
  347. h->dm->upgread_flag = 0;
  348. h->arg.upging = 0;
  349. }
  350. else {
  351. sleep(2);
  352. }
  353. }
  354. pthread_exit(NULL);
  355. }
  356. /////////////////////////////////////////////////////
  357. int upg_init(void)
  358. {
  359. int r,msgid;
  360. list_cfg_t lc={0,LIST_FULL_FIFO,-1};
  361. upg_handle_t *h=&uHandle;
  362. memset(h, 0, sizeof(upg_handle_t));
  363. h->dm = &__globalDeviceManage;
  364. h->key = ftok(UPG_KEY_PATH, UPG_KEY_SN);
  365. if(h->key<0) {
  366. LOGE("ftok %s failed, errno: %d\n", UPG_KEY_PATH, errno);
  367. return -1;
  368. }
  369. h->upg = xlist_init(&lc);
  370. h->all = xlist_init(&lc);
  371. h->init = 1;
  372. thread_start(THREAD_ID_BOARD, board_thread, h);
  373. upg_host_send(UPGRADE_EVT_APP_RUNNING);
  374. return 0;
  375. }
  376. int upg_host_send(int evt)
  377. {
  378. int r,msgid;
  379. msgbuf_t mb;
  380. upg_handle_t *h=&uHandle;
  381. msgid = msgget(h->key, 0666|IPC_CREAT);
  382. //LOGD("+++++++++++ key: %d, msgid: %d\n", ukey, msgid);
  383. mb.evt = evt;
  384. r = msgsnd(msgid, &mb, sizeof(mb.evt), IPC_NOWAIT);
  385. if(r<0) {
  386. LOGE("msgsnd failed, %d, errno: %d\n", r, errno);
  387. }
  388. else {
  389. LOGD("msgsnd evt 0x%02x ok\n", evt);
  390. }
  391. return r;
  392. }
  393. /////////////////////////////////////////////////////////
  394. handle_t upg_board_list_get(void)
  395. {
  396. upg_handle_t *h=&uHandle;
  397. return h->upg;
  398. }
  399. int upg_board_list_set(char *s)
  400. {
  401. int i=0,n=0,max=0;
  402. char tmp[10],*p=s;
  403. char *tok="productId=";
  404. board_info_t info={0};
  405. handle_t l=uHandle.upg;
  406. if(!s) {
  407. return -1;
  408. }
  409. p = strstr(p, tok);
  410. if(!p) {
  411. return -1;
  412. }
  413. p += strlen(tok);
  414. while(1) {
  415. if((*p)==',' || (*p)=='&') {
  416. tmp[i] = 0;
  417. info.addr = atoi(tmp);
  418. xlist_append(l, 0, &info, sizeof(info));
  419. i = 0; n++;
  420. if((*p)=='&') {
  421. break;
  422. }
  423. }
  424. else {
  425. tmp[i++] = *p;
  426. }
  427. p++;
  428. }
  429. return (n>0)?0:-1;
  430. }
  431. handle_t upg_board_all_get(void)
  432. {
  433. int r;
  434. upg_handle_t *h=&uHandle;
  435. return h->all;
  436. }
  437. int upg_board_all_update(void)
  438. {
  439. int i,r,addr,addr2=-1;
  440. list_node_t *ln=NULL;
  441. upg_handle_t *h=&uHandle;
  442. handle_t l=h->all;
  443. Modbus_Manger *mm=&h->dm->_globalRelaySampManger;
  444. GlobalPowerManger *tmp,*hd=&h->dm->_globalPowerManger;
  445. switch_info_t swinfo;
  446. board_info_t info;
  447. if(!h->init) {
  448. return -1;
  449. }
  450. xlist_clear(l);
  451. list_for_each_entry(tmp,&hd->list,list) {
  452. if(tmp->product_saddr>0) {
  453. addr = tmp->product_saddr;
  454. if(addr==addr2) continue;
  455. for(i=0; i<RETRY_MAX; i++) {
  456. r = board_get_info(mm, addr, &swinfo);
  457. if(r==0) {
  458. sw_to_info(addr, &info, &swinfo, ONLINE);
  459. xlist_append(l, 0, &info, sizeof(info));
  460. addr2 = addr;
  461. break;
  462. }
  463. }
  464. }
  465. }
  466. while(1) {
  467. r = xlist_take_node(h->upg, &ln, 0);
  468. if(r) {
  469. break;
  470. }
  471. xlist_append_node(h->all, ln);
  472. }
  473. return 0;
  474. }
  475. static int fw_check(char *path);
  476. int upg_board_start(char *path)
  477. {
  478. upg_handle_t *h=&uHandle;
  479. if(h->arg.upging==1) {
  480. return -1;
  481. }
  482. strcpy(h->arg.path,path);
  483. h->arg.upging = 1;
  484. return 0;
  485. }
  486. #include "md5.h"
  487. #include "file.h"
  488. #define FW_HEAD_MAGIC "GOWONE_UPGRADE"
  489. #pragma pack (1)
  490. typedef union {
  491. struct {
  492. uint8_t magic[14];
  493. uint16_t size;
  494. uint32_t partition;
  495. uint32_t version;
  496. char md5[32];
  497. }hdr;
  498. uint8_t padd[128];
  499. }fw_hdr_t;
  500. #pragma pack ()
  501. #define CHAR(b) (((b)<=9)?((b)+0x30):((b)-10+0x61));
  502. static void byte2char(char *chr, uint8_t b)
  503. {
  504. chr[0] = CHAR(b>>4);
  505. chr[1] = CHAR(b&0x0f);
  506. }
  507. static void print_md5(char *s, char *m)
  508. {
  509. int i;
  510. printf("__%s", s);
  511. for(i=0; i<32; i++) {
  512. printf("%c", m[i]);
  513. }
  514. printf("\n");
  515. }
  516. //md5相同返回0,否则返回1
  517. static int md5_check(buf_t *fb)
  518. {
  519. char *m1,m2[32];
  520. md5_ctx_t ctx;
  521. uint8_t i,tmp[16];
  522. fw_hdr_t *hdr=(fw_hdr_t*)fb->buf;
  523. md5_init(&ctx);
  524. md5_update(&ctx, (uint8_t*)fb->buf+sizeof(fw_hdr_t), hdr->hdr.size);
  525. md5_final(&ctx, tmp);
  526. for (i=0; i<16; i++) {
  527. byte2char(&m2[i*2], tmp[i]);
  528. }
  529. m1 = hdr->hdr.md5;
  530. print_md5("ori md5: ", m1);
  531. print_md5("cal md5: ", m2);
  532. if(memcmp(m1, m2, sizeof(m2))) {
  533. return -1;
  534. }
  535. return 0;
  536. }
  537. static void print_hdr(fw_hdr_t *h)
  538. {
  539. char magic[20]={0};
  540. memcpy(magic, h->hdr.magic, sizeof(h->hdr.magic));
  541. LOGD("hdr.magic: %s\n", magic);
  542. LOGD("hdr.size: %d\n", h->hdr.size);
  543. LOGD("hdr.version: %x\n", h->hdr.version);
  544. LOGD("hdr.partition: %d\n", h->hdr.partition);
  545. }
  546. int upg_board_file_check(char *path)
  547. {
  548. int r=UPG_OK;
  549. buf_t fb;
  550. upg_handle_t *h=&uHandle;
  551. if(h->arg.upging==1) {
  552. return UPG_BUSYING;
  553. }
  554. r = file_load(path, &fb);
  555. if(r) {
  556. return -1;
  557. }
  558. fw_hdr_t *fh=(fw_hdr_t*)fb.buf;
  559. if(memcmp(fh->hdr.magic,FW_HEAD_MAGIC,strlen(FW_HEAD_MAGIC))) {
  560. LOGE("not found %s, invalid board firmware\n", FW_HEAD_MAGIC);
  561. print_hdr(fh);
  562. r = UPG_HDR_FAIL;
  563. }
  564. else {
  565. if(md5_check(&fb)) {
  566. LOGE("md5 check failed, invalid board firmware\n");
  567. r = UPG_MD5_FAIL;
  568. }
  569. }
  570. free(fb.buf);
  571. return r;
  572. }
  573. int upg_host_file_check(char *path)
  574. {
  575. return 0;
  576. }