upg.c 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645
  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 board_info_set(board_info_t *info)
  161. {
  162. int r=-1;
  163. node_t node;
  164. handle_t l=uHandle.all;
  165. node.buf = info;
  166. node.dlen = sizeof(board_info_t);
  167. node.blen = sizeof(board_info_t);
  168. r = xlist_iterator(l, &node, set_info, NULL);
  169. return r;
  170. }
  171. static int board_send(Modbus_Manger *mm, uint16_t addr, char *data, int dlen)
  172. {
  173. int r,pid=0;
  174. char temp[400];
  175. int slen=0,onelen=0,onemax=128;
  176. upg_pkt_t *pkt=(upg_pkt_t*)temp;
  177. board_upgrade_jump(mm, addr);
  178. sleep(1);
  179. r = board_is_upgrading(mm,addr);
  180. if(r == 0){
  181. sleep(3);
  182. r = board_upgrade_jump(mm, addr);
  183. sleep(3);
  184. r = board_is_upgrading(mm,addr);
  185. }
  186. LOGD("r = %d addr = %d\n",r,addr);
  187. if(r == 0)
  188. {
  189. return -1;
  190. }
  191. sleep(2);
  192. while(1) {
  193. if((slen+onemax)>=dlen) {
  194. //onelen = dlen-(slen+onemax);
  195. onelen = onemax;
  196. pid = -1;
  197. }
  198. else {
  199. onelen = onemax;
  200. }
  201. memcpy(pkt->data, data+slen, onelen);
  202. pkt->pid = pid;
  203. pkt->dlen = onelen;
  204. r = mb_write(mm, addr, REG_UPG_WRITE, pkt, onelen+sizeof(upg_pkt_t), 40);
  205. slen += onelen;
  206. if(pid==0) {
  207. //file_save("/tmp/xxx.bin", pkt, onelen+sizeof(upg_pkt_t));
  208. sleep(1);
  209. }
  210. else usleep(10000);
  211. if(pid<0) break;
  212. pid++;
  213. }
  214. sleep(2);
  215. return 0;
  216. }
  217. static int board_proc(upg_handle_t *h, int quit)
  218. {
  219. int ok=0,err=0;
  220. buf_t fbuf;
  221. int i,r,timeout;
  222. switch_info_t swinfo;
  223. handle_t l=h->upg;
  224. list_node_t *ln=NULL;
  225. board_info_t info,*tmp;
  226. Modbus_Manger *mm=&h->dm->_globalRelaySampManger;
  227. r = file_load(h->arg.path, &fbuf);
  228. if(r) {
  229. return -1;
  230. }
  231. info.addr = -1;
  232. info.status = UPGRADING;
  233. board_info_set(&info);
  234. //broadcase upgrade file
  235. sleep(1);
  236. while(1) {
  237. r = xlist_get_node(l, &ln, 0);
  238. if(r) {
  239. break;
  240. }
  241. tmp = (board_info_t*)ln->data.buf;
  242. r = board_send(mm, tmp->addr, fbuf.buf, fbuf.dlen);
  243. if(r == 0)
  244. {
  245. for(i=0; i<20; i++) {
  246. r = board_get_info(mm, tmp->addr, &swinfo);
  247. if(r==0) {
  248. break;
  249. }
  250. LOGE("___ board upgrade failed, retry %d\n", i+1);
  251. sleep(1);
  252. // board_send(mm, i, fbuf.buf, fbuf.dlen);
  253. }
  254. }
  255. if(r) {
  256. tmp->status = UPGRADE_FAIL;
  257. err++;
  258. }
  259. else {
  260. sw_to_info(tmp->addr, tmp, &swinfo, UPGRADE_OK);
  261. ok++;
  262. }
  263. board_info_set(tmp);
  264. xlist_remove(l, 0);
  265. }
  266. free(fbuf.buf);
  267. // sys_exit(); //restart app
  268. return 0;
  269. }
  270. static int board_scan(void)
  271. {
  272. int i,r;
  273. board_info_t info={0};
  274. upg_handle_t *h=&uHandle;
  275. handle_t l=h->upg;
  276. Modbus_Manger *mm=&h->dm->_globalRelaySampManger;
  277. for(i=1; i<=h->dm->brdMax; i++) {
  278. r = board_is_upgrading(mm, i);
  279. if(r) {
  280. info.addr = i;
  281. info.status = UPGRADE_FAIL;
  282. xlist_append(l, 0, &info, sizeof(info));
  283. }
  284. }
  285. return 0;
  286. }
  287. static void start_threads(int flag)
  288. {
  289. if(flag) {
  290. // thread_start2(THREAD_ID_SNMP);
  291. // thread_start2(THREAD_ID_POWER);
  292. //thread_start2(THREAD_ID_CASCADE);
  293. //thread_start2(THREAD_ID_CASCADE_SCAN);
  294. //thread_start2(THREAD_ID_BREAKER);
  295. //thread_start2(THREAD_ID_BREAKER_SCANNER);
  296. }
  297. else {
  298. // thread_stop(THREAD_ID_SNMP);
  299. // thread_stop(THREAD_ID_POWER);
  300. //thread_stop(THREAD_ID_CASCADE);
  301. //thread_stop(THREAD_ID_CASCADE_SCAN);
  302. //thread_stop(THREAD_ID_BREAKER);
  303. //thread_stop(THREAD_ID_BREAKER_SCANNER);
  304. }
  305. }
  306. static void* board_thread(void *arg)
  307. {
  308. int r;
  309. thread_handle_t *th=(thread_handle_t*)arg;
  310. upg_handle_t *h=(upg_handle_t*)th->arg;
  311. Modbus_Manger *mm=&h->dm->_globalRelaySampManger;
  312. board_scan();
  313. upg_board_all_update();
  314. while(th->quit==0) {
  315. if(h->arg.upging) {
  316. // start_threads(0);
  317. h->dm->upgread_flag = 1;
  318. sleep(2);
  319. r = board_proc(h, th->quit);
  320. //start_threads(1);
  321. file_remove(h->arg.path);
  322. h->dm->upgread_flag = 0;
  323. h->arg.upging = 0;
  324. }
  325. else {
  326. sleep(2);
  327. }
  328. }
  329. pthread_exit(NULL);
  330. }
  331. /////////////////////////////////////////////////////
  332. int upg_init(void)
  333. {
  334. int r,msgid;
  335. list_cfg_t lc={0,LIST_FULL_FIFO,-1};
  336. upg_handle_t *h=&uHandle;
  337. memset(h, 0, sizeof(upg_handle_t));
  338. h->dm = &__globalDeviceManage;
  339. h->key = ftok(UPG_KEY_PATH, UPG_KEY_SN);
  340. if(h->key<0) {
  341. LOGE("ftok %s failed, errno: %d\n", UPG_KEY_PATH, errno);
  342. return -1;
  343. }
  344. h->upg = xlist_init(&lc);
  345. h->all = xlist_init(&lc);
  346. h->init = 1;
  347. thread_start(THREAD_ID_BOARD, board_thread, h);
  348. upg_host_send(UPGRADE_EVT_APP_RUNNING);
  349. return 0;
  350. }
  351. int upg_host_send(int evt)
  352. {
  353. int r,msgid;
  354. msgbuf_t mb;
  355. upg_handle_t *h=&uHandle;
  356. msgid = msgget(h->key, 0666|IPC_CREAT);
  357. //LOGD("+++++++++++ key: %d, msgid: %d\n", ukey, msgid);
  358. mb.evt = evt;
  359. r = msgsnd(msgid, &mb, sizeof(mb.evt), IPC_NOWAIT);
  360. if(r<0) {
  361. LOGE("msgsnd failed, %d, errno: %d\n", r, errno);
  362. }
  363. else {
  364. LOGD("msgsnd evt 0x%02x ok\n", evt);
  365. }
  366. return r;
  367. }
  368. /////////////////////////////////////////////////////////
  369. handle_t upg_board_list_get(void)
  370. {
  371. upg_handle_t *h=&uHandle;
  372. return h->upg;
  373. }
  374. int upg_board_list_set(char *s)
  375. {
  376. int i=0,n=0,max=0;
  377. char tmp[10],*p=s;
  378. char *tok="productId=";
  379. board_info_t info={0};
  380. handle_t l=uHandle.upg;
  381. if(!s) {
  382. return -1;
  383. }
  384. p = strstr(p, tok);
  385. if(!p) {
  386. return -1;
  387. }
  388. p += strlen(tok);
  389. while(1) {
  390. if((*p)==',' || (*p)=='&') {
  391. tmp[i] = 0;
  392. info.addr = atoi(tmp);
  393. xlist_append(l, 0, &info, sizeof(info));
  394. i = 0; n++;
  395. if((*p)=='&') {
  396. break;
  397. }
  398. }
  399. else {
  400. tmp[i++] = *p;
  401. }
  402. p++;
  403. }
  404. return (n>0)?0:-1;
  405. }
  406. handle_t upg_board_all_get(void)
  407. {
  408. int r;
  409. upg_handle_t *h=&uHandle;
  410. return h->all;
  411. }
  412. int upg_board_all_update(void)
  413. {
  414. int i,r,addr,addr2=-1;
  415. list_node_t *ln=NULL;
  416. upg_handle_t *h=&uHandle;
  417. handle_t l=h->all;
  418. Modbus_Manger *mm=&h->dm->_globalRelaySampManger;
  419. GlobalPowerManger *tmp,*hd=&h->dm->_globalPowerManger;
  420. switch_info_t swinfo;
  421. board_info_t info;
  422. if(!h->init) {
  423. return -1;
  424. }
  425. xlist_clear(l);
  426. list_for_each_entry(tmp,&hd->list,list) {
  427. if(tmp->product_saddr>0) {
  428. addr = tmp->product_saddr;
  429. if(addr==addr2) continue;
  430. for(i=0; i<RETRY_MAX; i++) {
  431. r = board_get_info(mm, addr, &swinfo);
  432. if(r==0) {
  433. sw_to_info(addr, &info, &swinfo, ONLINE);
  434. xlist_append(l, 0, &info, sizeof(info));
  435. addr2 = addr;
  436. break;
  437. }
  438. }
  439. }
  440. }
  441. while(1) {
  442. r = xlist_take_node(h->upg, &ln, 0);
  443. if(r) {
  444. break;
  445. }
  446. xlist_append_node(h->all, ln);
  447. }
  448. return 0;
  449. }
  450. static int fw_check(char *path);
  451. int upg_board_start(char *path)
  452. {
  453. upg_handle_t *h=&uHandle;
  454. if(h->arg.upging==1) {
  455. return -1;
  456. }
  457. strcpy(h->arg.path,path);
  458. h->arg.upging = 1;
  459. return 0;
  460. }
  461. #include "md5.h"
  462. #include "file.h"
  463. #define FW_HEAD_MAGIC "GOWONE_UPGRADE"
  464. #pragma pack (1)
  465. typedef union {
  466. struct {
  467. uint8_t magic[14];
  468. uint16_t size;
  469. uint32_t partition;
  470. uint32_t version;
  471. char md5[32];
  472. }hdr;
  473. uint8_t padd[128];
  474. }fw_hdr_t;
  475. #pragma pack ()
  476. #define CHAR(b) (((b)<=9)?((b)+0x30):((b)-10+0x61));
  477. static void byte2char(char *chr, uint8_t b)
  478. {
  479. chr[0] = CHAR(b>>4);
  480. chr[1] = CHAR(b&0x0f);
  481. }
  482. static void print_md5(char *s, char *m)
  483. {
  484. int i;
  485. printf("__%s", s);
  486. for(i=0; i<32; i++) {
  487. printf("%c", m[i]);
  488. }
  489. printf("\n");
  490. }
  491. //md5相同返回0,否则返回1
  492. static int md5_check(buf_t *fb)
  493. {
  494. char *m1,m2[32];
  495. md5_ctx_t ctx;
  496. uint8_t i,tmp[16];
  497. fw_hdr_t *hdr=(fw_hdr_t*)fb->buf;
  498. md5_init(&ctx);
  499. md5_update(&ctx, (uint8_t*)fb->buf+sizeof(fw_hdr_t), hdr->hdr.size);
  500. md5_final(&ctx, tmp);
  501. for (i=0; i<16; i++) {
  502. byte2char(&m2[i*2], tmp[i]);
  503. }
  504. m1 = hdr->hdr.md5;
  505. print_md5("ori md5: ", m1);
  506. print_md5("cal md5: ", m2);
  507. if(memcmp(m1, m2, sizeof(m2))) {
  508. return -1;
  509. }
  510. return 0;
  511. }
  512. static void print_hdr(fw_hdr_t *h)
  513. {
  514. char magic[20]={0};
  515. memcpy(magic, h->hdr.magic, sizeof(h->hdr.magic));
  516. LOGD("hdr.magic: %s\n", magic);
  517. LOGD("hdr.size: %d\n", h->hdr.size);
  518. LOGD("hdr.version: %x\n", h->hdr.version);
  519. LOGD("hdr.partition: %d\n", h->hdr.partition);
  520. }
  521. int upg_board_file_check(char *path)
  522. {
  523. int r=UPG_OK;
  524. buf_t fb;
  525. upg_handle_t *h=&uHandle;
  526. if(h->arg.upging==1) {
  527. return UPG_BUSYING;
  528. }
  529. r = file_load(path, &fb);
  530. if(r) {
  531. return -1;
  532. }
  533. fw_hdr_t *fh=(fw_hdr_t*)fb.buf;
  534. if(memcmp(fh->hdr.magic,FW_HEAD_MAGIC,strlen(FW_HEAD_MAGIC))) {
  535. LOGE("not found %s, invalid board firmware\n", FW_HEAD_MAGIC);
  536. print_hdr(fh);
  537. r = UPG_HDR_FAIL;
  538. }
  539. else {
  540. if(md5_check(&fb)) {
  541. LOGE("md5 check failed, invalid board firmware\n");
  542. r = UPG_MD5_FAIL;
  543. }
  544. }
  545. free(fb.buf);
  546. return r;
  547. }
  548. int upg_host_file_check(char *path)
  549. {
  550. return 0;
  551. }