upg.c 13 KB

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