upg.c 12 KB

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