httpserver.c 53 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615
  1. #include "httpserver.h"
  2. #include "lwip/def.h"
  3. #include "lwip/tcp.h"
  4. #include "fsdata.c"
  5. #include "main.h"
  6. #include "flash_if.h"
  7. #include "common_config.h"
  8. #include "conf.h"
  9. #include "settings_api.h"
  10. #include "crc.h"
  11. #include "board.h"
  12. #include "netconf.h"
  13. #ifdef SLAVEBRD_ENABLE
  14. #include "stm32sprog.h"
  15. #endif
  16. #ifdef LCD_ENABLE
  17. #include "lcd.h"
  18. #endif
  19. #include "led.h"
  20. #include "systick.h"
  21. #include <string.h>
  22. #include "tinystdio.h"
  23. #undef DBG
  24. #define DBG if(0)
  25. /* Uncomment this macro to compleately skip any flash read/write operations/
  26. USE THIS ONLY FOR DEBUG AND TESTING PURPOSES!
  27. NEVER UNKOMMENT FOR RELEASE BUILDS! */
  28. // #define DUMMY_PROG
  29. #ifdef DUMMY_PROG
  30. /* Disable main fw flash read/write operations */
  31. #define FLASH_If_Write(X, ...)
  32. #define FLASH_If_Erase(X, ...)
  33. #define CRC_Read() 0x00
  34. #define CRC_Calculate(X, ...) 0x00
  35. /* Disable daughter fw flash read/write operations */
  36. #define stmProg(X, ...)
  37. #define stmRebootForFlash(X, ...)
  38. #define stmConnect(X, ...) ok
  39. #define stmGetDevParams(X, ...) ok
  40. #define stmEraseFW(X, ...) ok
  41. #define stmReadFlashCrc() 0x00
  42. #define stmCalcFlashCrc(X, ...) 0x00
  43. #endif /* DUMMY_PROG*/
  44. #define FILENAME_MAX_LEN 30
  45. #define BOUNDARY_MAX_LEN 70
  46. #define BLOCK_PROG_TIMEOUT 20000
  47. #define COOKIES_MAX_LEN 64
  48. #define COOKIES_SET_ATTEMPTS 2
  49. #define BD_CONNECT_RETRY 3
  50. /* Max HTTP file name length including "/" */
  51. #define HTTP_FNAME_LEN 32
  52. /* Max HTTP Etag field length */
  53. #define MAX_ETAG_LEN 48
  54. #define MAIN_FW_SIZE USER_FLASH_END_ADDRESS - USER_FLASH_FIRST_PAGE_ADDRESS + 1
  55. #define DB_FW_SIZE DB_CPU_FLASH_END_ADDRESS - DB_CPU_FLASH_FIRST_PAGE_ADDRESS + 1
  56. #define HTTP_RET_UPLOAD_ERROR() do {\
  57. memset(sendBuf, 0, 32);\
  58. strcpy(sendBuf, HTTP_200_OK);\
  59. strcat(sendBuf, "0");\
  60. hs->file = sendBuf;\
  61. hs->left = strlen(sendBuf);\
  62. send_data(pcb, hs);\
  63. tcp_sent(pcb, http_sent);\
  64. htmlpage = UploadErrorPage;\
  65. SET_FWINVALID_FLAG();\
  66. } while(0)
  67. #define HTTP_RET_UPLOAD_ERROR_NO_FLASH_ERASE() do {\
  68. memset(sendBuf, 0, 32);\
  69. strcpy(sendBuf, HTTP_200_OK);\
  70. strcat(sendBuf, "0");\
  71. hs->file = sendBuf;\
  72. hs->left = strlen(sendBuf);\
  73. send_data(pcb, hs);\
  74. tcp_sent(pcb, http_sent);\
  75. htmlpage = UploadErrorPage;\
  76. } while(0)
  77. static char sendBuf[512];
  78. static char tempBuf[HW_REV_OFFSET + HW_REV_LEN];
  79. extern bool fDoneReset;
  80. extern bool fUpload;
  81. extern bool fInvalidFw;
  82. char lcdbuf[32] = {0};
  83. static vu32 DataFlag = 0;
  84. static vu32 BoundaryFlag = 0;
  85. static vu32 size = 0;
  86. static __IO uint32_t FlashWriteAddress;
  87. static u32 TotalReceived = 0;
  88. static char LeftBytesTab[4];
  89. static u8 LeftBytes = 0;
  90. static uint32_t BrowserFlag = 0;
  91. static uint32_t ContentOffset = 0;
  92. static __IO uint32_t TotalData = 0;
  93. static uint32_t FwDestSize = 0;
  94. static bool fEraseFlash = true;
  95. uint8_t update_timeout = UPDATE_TIMEOUT;
  96. struct http_state
  97. {
  98. char *file;
  99. u32_t left;
  100. };
  101. typedef enum {
  102. fw_unknown,
  103. fw_main_board,
  104. fw_daughter_board
  105. } fw_type_t;
  106. static fw_type_t fw_type = fw_unknown;
  107. htmlpageState htmlpage;
  108. /* Content Length */
  109. static const char Content_Length[17] = {
  110. 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x2d, 0x4c, 0x65, 0x6e, 0x67, 0x74, 0x68, 0x3a, 0x20,
  111. };
  112. static const char If_None_Match[] = "If-None-Match: ";
  113. static const char Etag[] = "ETag: ";
  114. const char HTTP_200_OK[] = "HTTP/1.1 200 OK\r\n\r\n";
  115. const char HTTP_304_NOT_MODIFIED[] = "HTTP/1.1 304 Not Modified\r\n\r\n";
  116. const char HTTP_200_OK_TEXT_HTML[] = "HTTP/1.1 200 OK\r\nContent-Type:text/html";
  117. const char Redirect_Head[] = "<!DOCTYPE html><html lang=""><head><meta charset=\"UTF-8\"><meta http-equiv=\"refresh\" ";
  118. const char Msg_Body[] = "<body style=\"background-color:#E8EBF1;\">\
  119. <p style=\"height:300px;line-height:300px;font-family:Arial,Helvetica,sans-serif;text-align:center;color:#333;\">";
  120. uint16_t printLen = 0;
  121. char printBuf[1500];
  122. uint32_t oldAdd = USER_FLASH_FIRST_PAGE_ADDRESS;
  123. uint32_t deltaAdd = 0;
  124. #ifdef SLAVEBRD_ENABLE
  125. uint32_t stm32addr = DB_CPU_FLASH_FIRST_PAGE_ADDRESS;
  126. static void IAP_HTTP_stmProg(char *data, uint32_t len);
  127. bool IAP_HTTP_stmConnect(void);
  128. #endif
  129. static uint32_t Parse_Content_Length(char *data, uint32_t len);
  130. void Parse_IfNonMatch(char *data, uint32_t len, char *value);
  131. static uint32_t Parse_Header(char *data, uint32_t len, const char *field, uint32_t flen, char *value);
  132. static bool Parse_Filename(const char *data, uint32_t len, fw_type_t *fw_type, uint32_t *fw_size);
  133. char *Parce_Boundary(const char *data, uint32_t len, char *dst, uint8_t dstlen);
  134. static void IAP_HTTP_writedata(char *data, uint32_t len);
  135. void ProgTimeout_Handler();
  136. /* file must be allocated by caller and will be filled in by the function. */
  137. static int fs_open(char *name, struct fs_file *file);
  138. bool send_file(char *filename, char *pnonmatch, struct tcp_pcb *pcb, struct http_state *hs, struct fs_file *file);
  139. void send_index_page(struct tcp_pcb *pcb, struct http_state *hs, struct pbuf *p, bool upload);
  140. static void PeriodicHandle(uint8_t progress);
  141. /* Get Cookie parameter value */
  142. bool GetCookieValue(char *inStr, char *paramName, char *paramValue, uint8_t *paramLen);
  143. /* Check if Cookie is set or not */
  144. bool CookieIsSet(char *inStr, uint16_t inLen, char *paramName);
  145. // Implements the GNU function memmem much faster (2x) than the standard memmem
  146. char *memmemory(char *haystack, int hlen, char *needle, int nlen)
  147. {
  148. if (nlen > hlen) return 0;
  149. int i = 0, j = 0;
  150. switch (nlen) { // we have a few specialized compares for certain needle sizes
  151. case 0: // no needle? just give the haystack
  152. return haystack;
  153. case 1: // just use memchr for 1-byte needle
  154. return memchr(haystack, needle[0], hlen);
  155. case 2: // use 16-bit compares for 2-byte needles
  156. for (i = 0; i < hlen - nlen + 1; i++) {
  157. if (*(uint16_t *)(haystack + i) == *(uint16_t *)needle) {
  158. return haystack + i;
  159. }
  160. }
  161. break;
  162. case 4: // use 32-bit compares for 4-byte needles
  163. for (i = 0; i < hlen - nlen + 1; i++) {
  164. if (*(uint32_t *)(haystack + i) == *(uint32_t *)needle) {
  165. return haystack + i;
  166. }
  167. }
  168. break;
  169. /* actually slower on my 32-bit machine
  170. case 8: // use 64-bit compares for 8-byte needles
  171. for (i=0; i<hlen-nlen+1; i++) {
  172. if (*(uint64_t*)(haystack+i)==*(uint64_t*)needle) {
  173. return haystack+i;
  174. }
  175. }
  176. break;
  177. */
  178. default: // generic compare for any other needle size
  179. // walk i through the haystack, matching j as long as needle[j] matches haystack[i]
  180. for (i = 0; i < hlen; i++) {
  181. if (haystack[i] == needle[j]) {
  182. if (j == nlen - 1) { // end of needle and it all matched? win.
  183. return haystack + i - j;
  184. } else { // keep advancing j (and i, implicitly)
  185. j++;
  186. }
  187. } else { // no match, rewind i the length of the failed match (j), and reset j
  188. i -= j;
  189. j = 0;
  190. }
  191. }
  192. }
  193. return NULL;
  194. }
  195. /**
  196. * @brief callback function for handling connection errors
  197. * @param arg: pointer to an argument to be passed to callback function
  198. * @param err: LwIP error code
  199. * @retval none
  200. */
  201. static void conn_err(void *arg, err_t err)
  202. {
  203. struct http_state *hs;
  204. (void)err;
  205. hs = arg;
  206. mem_free(hs);
  207. }
  208. /**
  209. * @brief closes tcp connection
  210. * @param pcb: pointer to a tcp_pcb struct
  211. * @param hs: pointer to a http_state struct
  212. * @retval
  213. */
  214. static void close_conn(struct tcp_pcb *pcb, struct http_state *hs)
  215. {
  216. tcp_arg(pcb, NULL);
  217. tcp_sent(pcb, NULL);
  218. tcp_recv(pcb, NULL);
  219. mem_free(hs);
  220. tcp_close(pcb);
  221. }
  222. /**
  223. * @brief sends data found in member "file" of a http_state struct
  224. * @param pcb: pointer to a tcp_pcb struct
  225. * @param hs: pointer to a http_state struct
  226. * @retval none
  227. */
  228. static void send_data(struct tcp_pcb *pcb, struct http_state *hs)
  229. {
  230. err_t err;
  231. u16_t len;
  232. /* We cannot send more data than space available in the send
  233. buffer */
  234. if (tcp_sndbuf(pcb) < hs->left) {
  235. len = tcp_sndbuf(pcb);
  236. } else {
  237. len = hs->left;
  238. }
  239. err = tcp_write(pcb, hs->file, len, 0);
  240. if (err == ERR_OK) {
  241. hs->file += len;
  242. hs->left -= len;
  243. }
  244. }
  245. /**
  246. * @brief tcp poll callback function
  247. * @param arg: pointer to an argument to be passed to callback function
  248. * @param pcb: pointer on tcp_pcb structure
  249. * @retval err_t
  250. */
  251. static err_t http_poll(void *arg, struct tcp_pcb *pcb)
  252. {
  253. if (arg == NULL) {
  254. tcp_close(pcb);
  255. } else {
  256. send_data(pcb, (struct http_state *)arg);
  257. }
  258. return ERR_OK;
  259. }
  260. /**
  261. * @brief callback function called after a successfull TCP data packet transmission
  262. * @param arg: pointer to an argument to be passed to callback function
  263. * @param pcb: pointer on tcp_pcb structure
  264. * @param len
  265. * @retval err : LwIP error code
  266. */
  267. static err_t http_sent(void *arg, struct tcp_pcb *pcb, u16_t len)
  268. {
  269. struct http_state *hs;
  270. hs = arg;
  271. (void)len;
  272. if (hs->left > 0) {
  273. send_data(pcb, hs);
  274. } else {
  275. close_conn(pcb, hs);
  276. if (htmlpage == UploadDonePage) {
  277. #ifndef DUMMY_PROG
  278. fDoneReset = true;
  279. fUpload = false;
  280. #endif
  281. } else if (htmlpage == UploadErrorPage) {
  282. /* Don't reboot if update was failed, just reload main page */
  283. fUpload = false;
  284. }
  285. }
  286. return ERR_OK;
  287. }
  288. /**
  289. * @brief callback function for handling TCP HTTP traffic
  290. * @param arg: pointer to an argument structure to be passed to callback function
  291. * @param pcb: pointer to a tcp_pcb structure
  292. * @param p: pointer to a packet buffer
  293. * @param err: LwIP error code
  294. * @retval err
  295. */
  296. /* goback.cgi - возврат в основную прошивку */
  297. /* upload.cgi - загрузка новой прошивки */
  298. static err_t http_recv(void *arg, struct tcp_pcb *pcb, struct pbuf *p, err_t err)
  299. {
  300. int32_t i, len = 0;
  301. static uint32_t temp_len = 0;
  302. uint32_t DataOffset, CrcRead = 0, CrcCalc = 0;
  303. char *data, *ptr;
  304. struct fs_file file = {0, 0};
  305. struct http_state *hs;
  306. static bool hw_validated = false;
  307. char fname[HTTP_FNAME_LEN];
  308. uint8_t fname_len;
  309. static struct tcp_pcb *upload_pcb = NULL;
  310. static cookie_attempt = 0;
  311. hs = arg;
  312. if (err == ERR_OK && p != NULL) {
  313. /* Inform TCP that we have taken the data */
  314. tcp_recved(pcb, p->tot_len);
  315. if (hs->file == NULL) {
  316. data = p->payload;
  317. len = p->tot_len;
  318. printLen = p->tot_len > 500 ? 500 : p->tot_len;
  319. memcpy(printBuf, p->payload, printLen);
  320. // DBG printf("\r\n[%d] %s...\r\n", p->tot_len, printBuf);
  321. // DBG printf("pcb: %p (%p)\r\n", pcb, upload_pcb);
  322. /* process HTTP GET requests */
  323. if (strncmp(data, "GET /", 5) == 0 && pcb != upload_pcb) {
  324. /* Возврат в основную прошивку. Сбрасываем флаг loadmode,
  325. * сохраняем настройки и перезагружаемся */
  326. if (strncmp(data, "GET /goback.cgi", 15) == 0) {
  327. /* Check if we realy can go back. Return to IAP if fw update was failed */
  328. if (!fInvalidFw) {
  329. /* Set loadMode = 0 */
  330. RTC_WriteBackupRegister(RTC_BKP_DR1, 0);
  331. } else {
  332. /* Set loadMode = 1 */
  333. RTC_WriteBackupRegister(RTC_BKP_DR1, 1);
  334. }
  335. #ifdef SLAVEBRD_ENABLE
  336. /* Reboot daughter board */
  337. stmReboot();
  338. #endif
  339. /* Self reboot */
  340. NVIC_SystemReset();
  341. }
  342. /* Статус обновления и таймаут до перезагрузки */
  343. else if (strncmp(data, "GET /status.cgi", 15) == 0) {
  344. memset(sendBuf, 0, sizeof(sendBuf));
  345. /* Headers для поддержки saffari */
  346. sprintf(sendBuf, "HTTP/1.1 200 OK\r\nContent-Type:text/json\r\n\r\n");
  347. char buf[32];
  348. uint8_t update_state = 0;
  349. if (upload_pcb != NULL && fw_type == fw_unknown) {
  350. update_state = 1;
  351. } else if (upload_pcb != NULL && fw_type == fw_daughter_board) {
  352. update_state = 2;
  353. } else if (upload_pcb != NULL && fw_type == fw_main_board) {
  354. update_state = 3;
  355. } else {
  356. update_state = 0;
  357. }
  358. strcat(sendBuf, "{");
  359. sprintf(buf, "\"upload\":\"%u\",", (unsigned int)update_state);
  360. strcat(sendBuf, buf);
  361. sprintf(buf, "\"progress\":\"%u\",", (unsigned int)(TotalReceived * 100 / size));
  362. strcat(sendBuf, buf);
  363. sprintf(buf, "\"wrtmr\":\"%u\",", timer_GetCountdown(&ProgTimeout_Handler) / 1000);
  364. strcat(sendBuf, buf);
  365. sprintf(buf, "\"updtmr\":\"%u\",", update_timeout);
  366. strcat(sendBuf, buf);
  367. #ifdef SLAVEBRD_ENABLE
  368. sprintf(buf, "\"file1\":\"%s\",", DAUGHTER_FW_NAME);
  369. strcat(sendBuf, buf);
  370. #endif
  371. sprintf(buf, "\"file2\":\"%s\",", MAIN_FW_NAME);
  372. strcat(sendBuf, buf);
  373. /* sprintf(buf, "\"rev\":\"%s\",", REVISION);
  374. strcat(sendBuf, buf); */
  375. sprintf(buf, "\"invalidfw\":%s", fInvalidFw ? "true" : "false");
  376. strcat(sendBuf, buf);
  377. strcat(sendBuf, "}");
  378. hs->file = sendBuf;
  379. hs->left = strlen(sendBuf);
  380. pbuf_free(p);
  381. send_data(pcb, hs);
  382. tcp_sent(pcb, http_sent);
  383. }
  384. else if ((strncmp(data, "GET /upload.html", 16) == 0) &&
  385. (!CookieIsSet(p->payload, p->tot_len, "file1=") ||
  386. !CookieIsSet(p->payload, p->tot_len, "file2="))) {
  387. if (cookie_attempt < COOKIES_SET_ATTEMPTS) {
  388. /* Cookies not found. Try to set. */
  389. send_index_page(pcb, hs, p, upload_pcb != NULL);
  390. cookie_attempt++;
  391. } else {
  392. cookie_attempt = 0;
  393. /* Send Cookie set error message */
  394. strcpy(sendBuf, HTTP_200_OK_TEXT_HTML);
  395. strcat(sendBuf, "\r\n\r\n");
  396. strcat(sendBuf, Redirect_Head);
  397. strcat(sendBuf, "</head>");
  398. strcat(sendBuf, Msg_Body);
  399. strcat(sendBuf, "Включите файлы cookie в браузере и попробуйте <a href=\"index.html\">еще раз.</a></p></body></html>\r\n\r\n");
  400. hs->file = sendBuf;
  401. hs->left = strlen(sendBuf);
  402. pbuf_free(p);
  403. send_data(pcb, hs);
  404. tcp_sent(pcb, http_sent);
  405. }
  406. }
  407. /* Check common GET request */
  408. else if (GetFileName(data, fname, &fname_len)) {
  409. char nonmatch[MAX_ETAG_LEN];
  410. char *pnonmatch = NULL;
  411. /* Parce If-Non_Match value */
  412. uint8_t nonmatch_len = Parse_Header(data, p->tot_len, If_None_Match, 15, nonmatch);
  413. if (nonmatch_len < MAX_ETAG_LEN && nonmatch_len > 0) {
  414. printf("If_None_Match: %s\r\n", nonmatch);
  415. pnonmatch = nonmatch;
  416. }
  417. if (send_file(fname, pnonmatch, pcb, hs, &file)) {
  418. pbuf_free(p);
  419. } else {
  420. send_index_page(pcb, hs, p, upload_pcb != NULL);
  421. }
  422. }
  423. /* Send default index page */
  424. else {
  425. send_index_page(pcb, hs, p, upload_pcb != NULL);
  426. }
  427. }
  428. /* Process POST request for file upload and incoming data packets after POST request */
  429. /* Tested MTU sizes: 400 - 1500. Sizes < 400 not supported currently. */
  430. else if ((strncmp(data, "POST /upload.cgi", 16) == 0 && upload_pcb == NULL) ||
  431. (DataFlag >= 1 && pcb == upload_pcb)) {
  432. static char boundary[BOUNDARY_MAX_LEN];
  433. static char boundary_part[BOUNDARY_MAX_LEN];
  434. static char *pbound = NULL;
  435. fUpload = true;
  436. DataOffset = 0;
  437. #ifndef DUMMY_PROG
  438. DBG printf("\r\n[%u] ______\r\n", (unsigned int)len);
  439. #endif
  440. /* POST Packet received */
  441. if (DataFlag == 0) {
  442. BrowserFlag = 0;
  443. TotalReceived = 0;
  444. BoundaryFlag = 0;
  445. temp_len = 0;
  446. upload_pcb = pcb;
  447. hw_validated = false;
  448. fw_type = fw_unknown;
  449. /* Reset block receive and prog timeout */
  450. timer_Restart(&ProgTimeout_Handler);
  451. /* Parse packet for Content-length field */
  452. size = Parse_Content_Length(data, p->tot_len);
  453. DBG printf("Content_Length: %u\r\n", (unsigned int)size);
  454. /* Parse packet for the boundary field */
  455. pbound = Parce_Boundary(data, p->tot_len, boundary, sizeof(boundary));
  456. DBG printf("boundary: %s\r\n", pbound ? boundary : "header not found");
  457. /* Find the boundary */
  458. if (pbound != NULL) {
  459. for (i = 0; i < len; i++) {
  460. if (strncmp((char *)(data + i), boundary, strlen(boundary)) == 0) {
  461. ContentOffset = i;
  462. BoundaryFlag = 1;
  463. DBG printf("boundary found\r\n");
  464. /* Parse packet for "\r\n\r\n" field */
  465. for (int32_t j = 0; j < len; j++) {
  466. if (strncmp((char *)(data + i + j), "\r\n\r\n", 4) == 0) {
  467. DataOffset = i + j + 4;
  468. break;
  469. }
  470. }
  471. }
  472. }
  473. }
  474. /* TODO Handle partially received boundary */
  475. if (BoundaryFlag) {
  476. TotalReceived = len - ContentOffset;
  477. }
  478. DBG {
  479. printf("Boundary: %s\r\n", BoundaryFlag ? "yes" : "no");
  480. printf("ContentOffset: %u\r\n", (unsigned int)ContentOffset);
  481. printf("DataOffset: %u\r\n", (unsigned int)DataOffset);
  482. printf("TotalReceived: %u/%u\r\n", (unsigned int)TotalReceived, (unsigned int)size);
  483. }
  484. if (fw_type == fw_unknown) {
  485. Parse_Filename(data, len, &fw_type, &FwDestSize);
  486. }
  487. /* No data in the first POST packet */
  488. if (DataOffset == 0) {
  489. DataFlag++;
  490. BrowserFlag = 1;
  491. pbuf_free(p);
  492. return ERR_OK;
  493. }
  494. }
  495. if (((DataFlag == 1) && (BrowserFlag == 1)) || ((DataFlag == 0) && (BrowserFlag == 0))) {
  496. if ((DataFlag == 0) && (BrowserFlag == 0)) {
  497. DataFlag++;
  498. } else if ((DataFlag == 1) && (BrowserFlag == 1)) {
  499. /* Find the boundary */
  500. for (i = 0; i < len; i++) {
  501. if (pbound != NULL) {
  502. if (strncmp((char *)(data + i), boundary, strlen(boundary)) == 0 || BoundaryFlag == 1) {
  503. /* Parse packet for "\r\n\r\n" field */
  504. for (int32_t j = 0; j < len; j++) {
  505. if (strncmp((char *)(data + i + j), "\r\n\r\n", 4) == 0) {
  506. DataOffset = i + j + 4;
  507. break;
  508. }
  509. }
  510. break;
  511. }
  512. }
  513. }
  514. /* TODO Handle partially received boundary */
  515. TotalReceived += len;
  516. DataFlag++;
  517. }
  518. if (fw_type == fw_unknown) {
  519. Parse_Filename(data, len, &fw_type, &FwDestSize);
  520. }
  521. DBG {
  522. printf("ContentOffset: %u\r\n", (unsigned int)ContentOffset);
  523. printf("DataOffset: %u\r\n", (unsigned int)DataOffset);
  524. printf("TotalReceived: %u/%u\r\n", (unsigned int)TotalReceived, (unsigned int)size);
  525. }
  526. /* Get next packet */
  527. if (!DataOffset) {
  528. DataFlag--;
  529. pbuf_free(p);
  530. return ERR_OK;
  531. }
  532. if (fw_type == fw_unknown) {
  533. htmlpage = FileUploadPage;
  534. /* No filename, in this case reload upload page */
  535. fs_open("/index.html", &file);
  536. hs->file = file.data;
  537. hs->left = file.len;
  538. pbuf_free(p);
  539. send_data(pcb, hs);
  540. tcp_sent(pcb, http_sent);
  541. DataFlag = 0;
  542. upload_pcb = NULL;
  543. printf("Error: Unknown firmware\r\n");
  544. #ifdef LCD_ENABLE
  545. LCD_PrintAligned(7, alignCENTER, "Ошибка!");
  546. #endif
  547. return ERR_OK;
  548. }
  549. TotalData = 0;
  550. }
  551. /* DataFlag >1 => the packet is data only */
  552. else {
  553. TotalReceived += len;
  554. }
  555. ptr = (char *)(data + DataOffset);
  556. len -= DataOffset;
  557. /* Update total data received counter */
  558. TotalData += len;
  559. #ifndef DUMMY_PROG
  560. DBG printf("TotalData: +%u %u/%u\r\n", (unsigned int)len,
  561. (unsigned int)TotalData, (unsigned int)FwDestSize);
  562. DBG printf("%u/%u\r\n", (unsigned int)TotalReceived, (unsigned int)size);
  563. #endif
  564. /* Check if last data packet */
  565. if (TotalReceived == size) {
  566. /* Check if boundary was splited into two packets. Get second part. */
  567. /* Data transfer sequence should end with "\r\n" + boundary + "--\rn" (6 extra bytes) */
  568. if ((pbound) && (p->tot_len <= strlen(boundary) + 6)) {
  569. /* No data in packet */
  570. TotalData = TotalData - len;
  571. len = 0;
  572. } else {
  573. char *bptr = memmemory(data, p->tot_len, boundary, strlen(boundary));
  574. // DBG printf("boundary: %s\r\n", boundary);
  575. if (bptr != NULL) {
  576. /* Substruct length of "\r\n" - 2 bytes */
  577. uint32_t last_len = bptr - data - 2;
  578. TotalData = TotalData - len + last_len;
  579. len = last_len;
  580. } else {
  581. printf("Boundary not found\r\n");
  582. }
  583. }
  584. }
  585. /* Not the last data packet */
  586. else if (TotalReceived < size) {
  587. /* Check if boundary was splited into two packets. Get first part. */
  588. /* Data transfer sequence should end with "\r\n" + boundary + "--\rn" (6 extra bytes) */
  589. if ((pbound) && (size - TotalReceived < strlen(boundary) + 6)) {
  590. uint16_t tail_len = size - TotalReceived;
  591. uint16_t boundary_len = strlen(boundary) + 6;
  592. /* Find "\r\n" or "\r" depending on a current packet length */
  593. uint8_t marker_len = (tail_len - boundary_len >= 2) ? 2 : 1;
  594. char *ptr = memmemory(data + p->tot_len - boundary_len, boundary_len,
  595. marker_len == 2 ? "\r\n" : "\r", marker_len);
  596. if (ptr != NULL) {
  597. DBG {
  598. /* Boundary first part is not actually used, just for debug output */
  599. uint32_t buflen = len - (uint32_t)(ptr + marker_len - data);
  600. printf("buflen: %u\r\n", (unsigned int)buflen);
  601. if (buflen > BOUNDARY_MAX_LEN) buflen = BOUNDARY_MAX_LEN;
  602. memcpy(boundary_part, ptr + marker_len, buflen);
  603. printf("boundary part: %s\r\n", boundary_part);
  604. }
  605. uint32_t last_len = ptr - data;
  606. TotalData = TotalData - len + last_len;
  607. len = last_len;
  608. } else {
  609. DBG printf("Boundary part not found!\r\n");
  610. }
  611. }
  612. /* Validate uploaded binary */
  613. if ((TotalData >= HW_REV_OFFSET + HW_REV_LEN) && (!hw_validated)) {
  614. char rev[HW_REV_LEN];
  615. if (fw_type == fw_main_board) {
  616. strncpy(rev, HW_REV, HW_REV_LEN);
  617. }
  618. #ifdef SLAVEBRD_ENABLE
  619. else if (fw_type == fw_daughter_board) {
  620. strncpy(rev, HW_REV_UPPER, HW_REV_LEN);
  621. }
  622. #endif
  623. else {
  624. strncpy(rev, "-", HW_REV_LEN);
  625. }
  626. char bin_rev[HW_REV_LEN];
  627. memset(bin_rev, 0, sizeof(bin_rev));
  628. uint32_t first_len = temp_len > HW_REV_OFFSET ? temp_len - HW_REV_OFFSET : 0;
  629. /* Copy 1st part (if not empty) */
  630. memcpy(bin_rev, tempBuf + HW_REV_OFFSET, first_len);
  631. /* Copy 2nd part */
  632. memcpy(bin_rev + first_len, ptr + HW_REV_OFFSET - (temp_len - first_len), HW_REV_LEN - first_len);
  633. if (strncmp(bin_rev, rev, HW_REV_LEN) != 0) {
  634. printf("HW version (%s) mismatch: found %s\r\n", rev, bin_rev);
  635. printf("Update aborted!\r\n");
  636. #ifdef LCD_ENABLE
  637. LCD_PrintAligned(7, alignCENTER, "Ошибка!");
  638. #endif
  639. DataFlag = 0;
  640. upload_pcb = NULL;
  641. HTTP_RET_UPLOAD_ERROR_NO_FLASH_ERASE();
  642. pbuf_free(p);
  643. return ERR_OK;
  644. } else {
  645. printf("HW version (%s) validated\r\n", bin_rev);
  646. hw_validated = true;
  647. printf("State: Erasing...\r\n");
  648. SET_FWINVALID_FLAG();
  649. #ifdef LCD_ENABLE
  650. LCD_ClearRow(7);
  651. #ifdef SLAVEBRD_ENABLE
  652. sprintf(lcdbuf, "Очистка %d/2 ", fw_type == fw_main_board ? 2 : 1);
  653. LCD_PrintAligned(5, alignCENTER, lcdbuf);
  654. #else
  655. LCD_PrintAligned(5, alignCENTER, "Очистка...");
  656. #endif
  657. #endif
  658. switch (fw_type) {
  659. case fw_main_board:
  660. /* Erase flash */
  661. if (fEraseFlash) {
  662. FLASH_If_Erase(USER_FLASH_FIRST_PAGE_ADDRESS);
  663. fEraseFlash = false;
  664. }
  665. /* Init flash */
  666. FLASH_If_Init();
  667. FlashWriteAddress = USER_FLASH_FIRST_PAGE_ADDRESS;
  668. break;
  669. #ifdef SLAVEBRD_ENABLE
  670. case fw_daughter_board:
  671. stm32addr = DB_CPU_FLASH_FIRST_PAGE_ADDRESS;
  672. uint8_t retries = 0;
  673. /* Try to connect to stm32 */
  674. while ((!IAP_HTTP_stmConnect()) && (retries++ < (BD_CONNECT_RETRY - 1))) {
  675. ;
  676. }
  677. /* Error if no device found */
  678. if (retries >= BD_CONNECT_RETRY) {
  679. #ifdef LCD_ENABLE
  680. LCD_PrintAligned(7, alignCENTER, "Ошибка!");
  681. #endif
  682. DataFlag = 0;
  683. upload_pcb = NULL;
  684. HTTP_RET_UPLOAD_ERROR();
  685. pbuf_free(p);
  686. return ERR_OK;
  687. }
  688. break;
  689. #endif
  690. default:
  691. break;
  692. }
  693. #ifdef LCD_ENABLE
  694. LCD_ClearRow(7);
  695. #ifdef SLAVEBRD_ENABLE
  696. sprintf(lcdbuf, "Запись %d/2", fw_type == fw_main_board ? 2 : 1);
  697. LCD_PrintAligned(5, alignCENTER, lcdbuf);
  698. #else
  699. LCD_PrintAligned(5, alignCENTER, "Запись...");
  700. #endif
  701. #endif
  702. /*indicate start of flash programming */
  703. printf("\r\nState: Programming..\r\n");
  704. }
  705. }
  706. }
  707. if (hw_validated) {
  708. /* Check fw data size overflow */
  709. if (TotalData > FwDestSize) {
  710. printf("FW binary size mismatch. Aborting update..\r\n");
  711. printf("FW dest size %u was %u\r\n", (unsigned int)FwDestSize, (unsigned int)TotalData);
  712. HTTP_RET_UPLOAD_ERROR_NO_FLASH_ERASE();
  713. } else {
  714. static uint8_t progress = 0;
  715. if (progress != TotalReceived * 100 / size) {
  716. progress = TotalReceived * 100 / size;
  717. #ifndef DUMMY_PROG
  718. printf("Writing: %u%%\r\n", (unsigned int)progress);
  719. #ifdef LCD_ENABLE
  720. LCD_PrintBar(7, (unsigned int)(100 * TotalReceived / size));
  721. #endif
  722. #endif
  723. }
  724. /* Reset block prog timeout */
  725. timer_Restart(&ProgTimeout_Handler);
  726. /* Write data in flash */
  727. if (len) {
  728. switch (fw_type) {
  729. case fw_main_board:
  730. if (temp_len) {
  731. IAP_HTTP_writedata(tempBuf, temp_len);
  732. temp_len = 0;
  733. }
  734. IAP_HTTP_writedata(ptr, len);
  735. break;
  736. #ifdef SLAVEBRD_ENABLE
  737. case fw_daughter_board:
  738. if (temp_len) {
  739. IAP_HTTP_stmProg(tempBuf, temp_len);
  740. temp_len = 0;
  741. }
  742. IAP_HTTP_stmProg(ptr, len);
  743. break;
  744. #endif
  745. default:
  746. break;
  747. }
  748. }
  749. }
  750. } else {
  751. /* Save first part */
  752. memcpy(tempBuf + temp_len, ptr, len);
  753. temp_len += len;
  754. DBG printf("Stashed: %u\r\n", (unsigned int)temp_len);
  755. }
  756. if (TotalReceived == size) {
  757. /* Stop block receive timer */
  758. timer_Stop(&ProgTimeout_Handler);
  759. DataFlag = 0;
  760. upload_pcb = NULL;
  761. printf("State: Verifying..\r\n");
  762. #ifdef LCD_ENABLE
  763. LCD_ClearRow(7);
  764. #ifdef SLAVEBRD_ENABLE
  765. sprintf(lcdbuf, "Проверка CRC %d/2", fw_type == fw_main_board ? 2 : 1);
  766. LCD_PrintAligned(5, alignCENTER, lcdbuf);
  767. #else
  768. LCD_PrintAligned(5, alignCENTER, "Проверка CRC...");
  769. #endif
  770. #endif
  771. switch (fw_type) {
  772. case fw_main_board:
  773. CrcRead = CRC_Read();
  774. CrcCalc = CRC_Calculate(&PeriodicHandle);
  775. break;
  776. #ifdef SLAVEBRD_ENABLE
  777. case fw_daughter_board:
  778. CrcRead = stmReadFlashCrc();
  779. CrcCalc = stmCalcFlashCrc(&PeriodicHandle);
  780. break;
  781. #endif
  782. default:
  783. break;
  784. }
  785. printf("State: Prog Finished\r\n\r\n");
  786. printf("Tot bytes received: %u bytes\r\n", (unsigned int)TotalData);
  787. printf("CRC read: 0x%X\r\n", (unsigned int)CrcRead);
  788. printf("CRC calcucated: 0x%X\r\n", (unsigned int)CrcCalc);
  789. /* Check CRC */
  790. if (CrcRead == CrcCalc) {
  791. printf("CRC check: Pass\r\n");
  792. /* Reset block receive and prog timeout */
  793. timer_Restart(&ProgTimeout_Handler);
  794. memset(sendBuf, 0, 32);
  795. strcpy(sendBuf, HTTP_200_OK);
  796. strcat(sendBuf, "1");
  797. hs->file = sendBuf;
  798. hs->left = strlen(sendBuf);
  799. send_data(pcb, hs);
  800. tcp_sent(pcb, http_sent);
  801. #ifdef LCD_ENABLE
  802. LCD_PrintAligned(7, alignCENTER, "Успешно!");
  803. #endif
  804. switch (fw_type) {
  805. case fw_main_board:
  806. /* Run main FW */
  807. htmlpage = UploadDonePage;
  808. break;
  809. #ifdef SLAVEBRD_ENABLE
  810. case fw_daughter_board:
  811. timer_ChangeFrequency(&LED_Blinky_Green, 250);
  812. /* Nothing to do */
  813. break;
  814. #endif
  815. default:
  816. break;
  817. }
  818. } else {
  819. #ifdef LCD_ENABLE
  820. LCD_PrintAligned(7, alignCENTER, "Ошибка!");
  821. #endif
  822. switch (fw_type) {
  823. case fw_main_board:
  824. /* Erase flash */
  825. /* That's a way not to boot wrong FW next time if update was failed */
  826. FLASH_If_Erase(USER_FLASH_FIRST_PAGE_ADDRESS);
  827. fEraseFlash = false;
  828. break;
  829. #ifdef SLAVEBRD_ENABLE
  830. case fw_daughter_board:
  831. /* We can boot device if upper board update was failed. */
  832. break;
  833. #endif
  834. default:
  835. break;
  836. }
  837. printf("CRC check: Fail\r\n");
  838. HTTP_RET_UPLOAD_ERROR();
  839. }
  840. }
  841. pbuf_free(p);
  842. } else {
  843. /* Bad HTTP requests */
  844. printf("Bad HTTP request\r\n");
  845. pbuf_free(p);
  846. close_conn(pcb, hs);
  847. }
  848. } else {
  849. pbuf_free(p);
  850. close_conn(pcb, hs);
  851. }
  852. } else if (err == ERR_OK && p == NULL) {
  853. /* Received empty frame */
  854. printf("Received empty frame\r\n");
  855. close_conn(pcb, hs);
  856. }
  857. return ERR_OK;
  858. }
  859. /**
  860. * @brief callback function on TCP connection setup ( on port 80)
  861. * @param arg: pointer to an argument structure to be passed to callback function
  862. * @param pcb: pointer to a tcp_pcb structure
  863. * &param err: Lwip stack error code
  864. * @retval err
  865. */
  866. static err_t http_accept(void *arg, struct tcp_pcb *pcb, err_t err)
  867. {
  868. struct http_state *hs;
  869. (void)err;
  870. (void)arg;
  871. /* Allocate memory for the structure that holds the state of the connection */
  872. hs = mem_malloc(sizeof(struct http_state));
  873. if (hs == NULL) {
  874. return ERR_MEM;
  875. }
  876. /* Initialize the structure. */
  877. hs->file = NULL;
  878. hs->left = 0;
  879. /* Tell TCP that this is the structure we wish to be passed for our
  880. callbacks. */
  881. tcp_arg(pcb, hs);
  882. /* Tell TCP that we wish to be informed of incoming data by a call
  883. to the http_recv() function. */
  884. tcp_recv(pcb, http_recv);
  885. tcp_err(pcb, conn_err);
  886. tcp_poll(pcb, http_poll, 10);
  887. return ERR_OK;
  888. }
  889. /**
  890. * @brief intialize HTTP webserver
  891. * @param none
  892. * @retval none
  893. */
  894. void IAP_httpd_init(void)
  895. {
  896. struct tcp_pcb *pcb;
  897. /*create new pcb*/
  898. pcb = tcp_new();
  899. /* bind HTTP traffic to pcb */
  900. tcp_bind(pcb, IP_ADDR_ANY, 80);
  901. /* start listening on port 80 */
  902. pcb = tcp_listen(pcb);
  903. /* define callback function for TCP connection setup */
  904. tcp_accept(pcb, http_accept);
  905. /* Set block receive and prog timeout */
  906. timer_AddFunction(BLOCK_PROG_TIMEOUT, &ProgTimeout_Handler);
  907. timer_Stop(&ProgTimeout_Handler);
  908. }
  909. /**
  910. * @brief Opens a file defined in fsdata.c ROM filesystem
  911. * @param name : pointer to a file name
  912. * @param file : pointer to a fs_file structure
  913. * @retval 1 if success, 0 if fail
  914. */
  915. static int fs_open(char *name, struct fs_file *file)
  916. {
  917. struct fsdata_file_noconst *f;
  918. for (f = (struct fsdata_file_noconst *)FS_ROOT; f != NULL; f = (struct fsdata_file_noconst *)f->next) {
  919. if (!strcmp(name, f->name)) {
  920. file->data = f->data;
  921. file->len = f->len;
  922. return 1;
  923. }
  924. }
  925. return 0;
  926. }
  927. /**
  928. * @brief sends file from flash FS
  929. * @param filename: pointer to the file name to send
  930. * @param pnonmatch: pointer to the If-Non_Match value
  931. * @param pcb: pointer to a tcp_pcb struct
  932. * @param hs: pointer to a http_state struct
  933. * @param file: pointer to a fs_file struct
  934. * @retval
  935. */
  936. bool send_file(char *filename, char *pnonmatch, struct tcp_pcb *pcb, struct http_state *hs, struct fs_file *file)
  937. {
  938. int res = 0;
  939. char etag[MAX_ETAG_LEN];
  940. char *petag = NULL;
  941. res = fs_open(filename, file);
  942. if (res == 0) {
  943. return false;
  944. }
  945. /* Find Etag value */
  946. uint8_t etag_len = Parse_Header(file->data, file->len, Etag, 6, etag);
  947. if (etag_len < MAX_ETAG_LEN && etag_len > 0) {
  948. printf("Etag: %s\r\n", etag);
  949. petag = etag;
  950. }
  951. /* Compare Etag and If-Non-Match fields */
  952. if (pnonmatch && petag && (strcmp(pnonmatch, petag) == 0)) {
  953. /* Send 304 code */
  954. sprintf(sendBuf, HTTP_304_NOT_MODIFIED);
  955. printf(sendBuf);
  956. hs->file = sendBuf;
  957. hs->left = strlen(sendBuf);
  958. } else {
  959. /* Send file */
  960. printf("%s\r\n\r\n", filename);
  961. hs->file = file->data;
  962. hs->left = file->len;
  963. }
  964. send_data(pcb, hs);
  965. tcp_sent(pcb, http_sent);
  966. return true;
  967. }
  968. /**
  969. * @brief
  970. * @retval None
  971. */
  972. void send_index_page(struct tcp_pcb *pcb, struct http_state *hs, struct pbuf *p, bool upload)
  973. {
  974. char buf[32];
  975. /* Send cookie */
  976. strcpy(sendBuf, "HTTP/1.1 200 OK\r\nContent-Type:text/html\r\n");
  977. strcat(sendBuf, "Set-Cookie: upload=");
  978. sprintf(buf, "%d", (unsigned char)upload);
  979. strcat(sendBuf, buf);
  980. strcat(sendBuf, "\r\nSet-Cookie: wrtmr=");
  981. sprintf(buf, "%d", timer_GetCountdown(&ProgTimeout_Handler) / 1000);
  982. strcat(sendBuf, buf);
  983. strcat(sendBuf, "\r\nSet-Cookie: updtmr=");
  984. sprintf(buf, "%d", update_timeout);
  985. strcat(sendBuf, buf);
  986. strcat(sendBuf, "\r\nSet-Cookie: file1=");
  987. #ifdef SLAVEBRD_ENABLE
  988. strcat(sendBuf, DAUGHTER_FW_NAME);
  989. #else
  990. strcat(sendBuf, "NONE");
  991. #endif
  992. strcat(sendBuf, "\r\nSet-Cookie: file2=");
  993. char file_name_buf[40];
  994. memset(file_name_buf, 0, sizeof(file_name_buf));
  995. strcpy(file_name_buf, MAIN_FW_NAME);
  996. if(strcmp(file_name_buf, "NONE") != 0){
  997. strcat(sendBuf, MAIN_FW_NAME);
  998. } else {
  999. strcat(sendBuf, " ");
  1000. }
  1001. strcat(sendBuf,
  1002. "\r\n\r\n<!DOCTYPE html><html lang="
  1003. "><head><meta \
  1004. http-equiv=\"refresh\" content=\"0;url=/upload.html\"/></head></html>\r\n\r\n");
  1005. htmlpage = LoginPage;
  1006. hs->file = sendBuf;
  1007. hs->left = strlen(sendBuf);
  1008. pbuf_free(p);
  1009. send_data(pcb, hs);
  1010. tcp_sent(pcb, http_sent);
  1011. }
  1012. /**
  1013. * @brief Extract the Content_Length data from HTML data
  1014. * @param data : pointer on receive packet buffer
  1015. * @param len : buffer length
  1016. * @retval size : Content_length in numeric format
  1017. */
  1018. static uint32_t Parse_Content_Length(char *data, uint32_t len)
  1019. {
  1020. uint32_t i = 0, size = 0, S = 1;
  1021. int32_t j = 0;
  1022. char sizestring[6], *ptr;
  1023. uint32_t ContentLengthOffset = 0;
  1024. /* find Content-Length data in packet buffer */
  1025. for (i = 0; i < len; i++) {
  1026. if (strncmp((char *)(data + i), Content_Length, 16) == 0) {
  1027. ContentLengthOffset = i + 16;
  1028. break;
  1029. }
  1030. }
  1031. /* read Content-Length value */
  1032. if (ContentLengthOffset) {
  1033. i = 0;
  1034. ptr = (char *)(data + ContentLengthOffset);
  1035. while (*(ptr + i) != 0x0d && (i < len - ContentLengthOffset)) {
  1036. sizestring[i] = *(ptr + i);
  1037. i++;
  1038. ContentLengthOffset++;
  1039. }
  1040. if (i > 0) {
  1041. /* transform string data into numeric format */
  1042. for (j = i - 1; j >= 0; j--) {
  1043. size += (sizestring[j] - 0x30) * S;
  1044. S = S * 10;
  1045. }
  1046. }
  1047. }
  1048. return size;
  1049. }
  1050. /**
  1051. * @brief Extract the custom field data from HTML data
  1052. * @param data : pointer on receive packet buffer
  1053. * @param len : buffer length
  1054. * @param field : field name
  1055. * @param flen : field name length
  1056. * @retval value : pointer for field data
  1057. */
  1058. static uint32_t Parse_Header(char *data, uint32_t len, const char *field, uint32_t flen, char *value)
  1059. {
  1060. uint32_t i = 0, size = 0;
  1061. char *ptr;
  1062. uint32_t Offset = 0;
  1063. /* Find field name in data buffer */
  1064. for (i = 0; i < len; i++) {
  1065. if (strncmp((char *)(data + i), field, flen) == 0) {
  1066. Offset = i + flen;
  1067. break;
  1068. }
  1069. }
  1070. /* Copy Field value */
  1071. if (Offset) {
  1072. i = 0;
  1073. ptr = (char *)(data + Offset);
  1074. while (*(ptr + i) != 0x0d && (i < len - Offset)) {
  1075. value[i] = *(ptr + i);
  1076. i++;
  1077. }
  1078. value[i] = '\0';
  1079. size = i;
  1080. }
  1081. return size;
  1082. }
  1083. /**
  1084. * @brief
  1085. * @retval None
  1086. */
  1087. char *Parce_Boundary(const char *data, uint32_t len, char *dst, uint8_t dstlen)
  1088. {
  1089. char *ptr = NULL;
  1090. char *boundary = NULL;
  1091. uint8_t i = 0;
  1092. for (uint32_t j = 0; j < len; j++) {
  1093. if (strncmp((char *)(data + j), "boundary=", 9) == 0) {
  1094. boundary = (char *)data + j + 9;
  1095. break;
  1096. }
  1097. }
  1098. if (!boundary) return NULL;
  1099. *dst++ = '-';
  1100. *dst++ = '-';
  1101. ptr = boundary;
  1102. while ((*ptr != 0x0d) && (i < dstlen - 4)) {
  1103. *dst++ = *ptr++;
  1104. i++;
  1105. }
  1106. //*dst++ = '-';
  1107. //*dst++ = '-';
  1108. *dst = '\0';
  1109. if (i > 0)
  1110. return boundary;
  1111. else
  1112. return NULL;
  1113. }
  1114. static bool Parse_Filename(const char *data, uint32_t len, fw_type_t *fw_type, uint32_t *fw_size)
  1115. {
  1116. /* Parse packet for the filename field */
  1117. uint32_t FilenameOffset = 0;
  1118. char filename[FILENAME_MAX_LEN];
  1119. char file_name_buf[40];
  1120. memset(file_name_buf, 0, sizeof(file_name_buf));
  1121. strcpy(file_name_buf, MAIN_FW_NAME);
  1122. if(strcmp(file_name_buf, "NONE") == 0){
  1123. *fw_type = fw_main_board;
  1124. *fw_size = MAIN_FW_SIZE;
  1125. return true;
  1126. }
  1127. for (uint32_t i = 0; i < len; i++) {
  1128. if (strncmp((char *)(data + i), "filename=", 9) == 0) {
  1129. FilenameOffset = i + 10;
  1130. break;
  1131. }
  1132. }
  1133. if (FilenameOffset) {
  1134. uint32_t i = 0;
  1135. while ((*(data + FilenameOffset + i) != 0x22) &&
  1136. (i < FILENAME_MAX_LEN) &&
  1137. (FilenameOffset + i <= len)) {
  1138. filename[i] = *(data + FilenameOffset + i);
  1139. i++;
  1140. }
  1141. filename[i] = 0x0;
  1142. printf("File: %s\r\n", filename);
  1143. /* Decide which FW is uploaded */
  1144. if (strncmp(filename, MAIN_FW_NAME, 16) == 0) {
  1145. *fw_type = fw_main_board;
  1146. *fw_size = MAIN_FW_SIZE;
  1147. printf("Updating main board FW..\r\n");
  1148. }
  1149. #ifdef SLAVEBRD_ENABLE
  1150. else if (strncmp(filename, DAUGHTER_FW_NAME, 16) == 0) {
  1151. *fw_type = fw_daughter_board;
  1152. *fw_size = DB_FW_SIZE;
  1153. printf("Updating daughter FW..\r\n");
  1154. }
  1155. #endif
  1156. else {
  1157. *fw_type = fw_unknown;
  1158. }
  1159. return true;
  1160. }
  1161. return false;
  1162. }
  1163. /**
  1164. * @brief
  1165. * @retval None
  1166. */
  1167. bool GetFileName(char *inStr, char *fileName, uint8_t *fileNameLen)
  1168. {
  1169. char *beginValue = NULL;
  1170. char *endValue = NULL;
  1171. int len = 0;
  1172. char *strPtr = NULL;
  1173. strPtr = strstr(inStr, "GET");
  1174. if (strPtr == NULL) {
  1175. strPtr = strstr(inStr, "POST");
  1176. }
  1177. if (strPtr == NULL) {
  1178. *fileNameLen = 0;
  1179. return false;
  1180. } else {
  1181. beginValue = strpbrk(strPtr, "/");
  1182. endValue = strpbrk(beginValue, " ");
  1183. if (endValue == NULL) {
  1184. *fileNameLen = 0;
  1185. return false;
  1186. }
  1187. len = endValue - beginValue;
  1188. if (len < HTTP_FNAME_LEN) {
  1189. strncpy(fileName, beginValue, len);
  1190. *fileNameLen = len;
  1191. fileName[len] = '\0';
  1192. return true;
  1193. } else {
  1194. return false;
  1195. }
  1196. }
  1197. }
  1198. /**
  1199. * @brief writes received data in flash
  1200. * @param ptr: data pointer
  1201. * @param len: data length
  1202. * @retval none
  1203. */
  1204. void IAP_HTTP_writedata(char *ptr, uint32_t len)
  1205. {
  1206. uint32_t count, i = 0, j = 0;
  1207. /* check if any left bytes from previous packet transfer*/
  1208. /* if it is the case do a concat with new data to create a 32-bit word */
  1209. if (LeftBytes) {
  1210. while (LeftBytes <= 3) {
  1211. if (len > (j + 1)) {
  1212. LeftBytesTab[LeftBytes++] = *(ptr + j);
  1213. } else {
  1214. LeftBytesTab[LeftBytes++] = 0xFF;
  1215. }
  1216. j++;
  1217. }
  1218. FLASH_If_Write(&FlashWriteAddress, (u32 *)(LeftBytesTab), 1);
  1219. LeftBytes = 0;
  1220. /* update data pointer */
  1221. ptr = (char *)(ptr + j);
  1222. len = len - j;
  1223. }
  1224. /* write received bytes into flash */
  1225. count = len / 4;
  1226. /* check if remaining bytes < 4 */
  1227. i = len % 4;
  1228. if (i > 0) {
  1229. if (TotalReceived != size) {
  1230. /* store bytes in LeftBytesTab */
  1231. LeftBytes = 0;
  1232. for (; i > 0; i--)
  1233. LeftBytesTab[LeftBytes++] = *(char *)(ptr + len - i);
  1234. } else
  1235. count++;
  1236. }
  1237. FLASH_If_Write(&FlashWriteAddress, (u32 *)ptr, count);
  1238. }
  1239. uint32_t ReturnFlashWriteAddress(void)
  1240. {
  1241. return FlashWriteAddress;
  1242. }
  1243. #ifdef SLAVEBRD_ENABLE
  1244. /**
  1245. * @brief Connect stm32
  1246. */
  1247. bool IAP_HTTP_stmConnect(void)
  1248. {
  1249. bool ok = true;
  1250. stmRebootForFlash();
  1251. /* Connect */
  1252. ok = stmConnect();
  1253. if (!ok) {
  1254. printf("Error: device not detected.\n");
  1255. return false;
  1256. } else
  1257. printf("Device connected\n");
  1258. /* Get params */
  1259. ok = stmGetDevParams();
  1260. if (!ok) {
  1261. printf("Error: Device not supported.\n");
  1262. return false;
  1263. }
  1264. /* Erase */
  1265. printf("Erasing.. ");
  1266. ok = stmEraseFW();
  1267. if (ok)
  1268. printf("OK\n");
  1269. else {
  1270. printf("Erase error!\n");
  1271. return false;
  1272. }
  1273. stm32addr = DB_CPU_FLASH_FIRST_PAGE_ADDRESS;
  1274. return true;
  1275. }
  1276. /**
  1277. * @brief Prog received data to connected stm32 on uart
  1278. * @param ptr: data pointer
  1279. * @param len: data length
  1280. * @retval none
  1281. */
  1282. void IAP_HTTP_stmProg(char *ptr, uint32_t len)
  1283. {
  1284. uint32_t count, i, j = 0;
  1285. /* check if any left bytes from previous packet transfer*/
  1286. /* if it is the case do a concat with new data to create a 32-bit word */
  1287. if (LeftBytes) {
  1288. while (LeftBytes <= 3) {
  1289. if (len > (j + 1)) {
  1290. LeftBytesTab[LeftBytes++] = *(ptr + j);
  1291. } else {
  1292. LeftBytesTab[LeftBytes++] = 0xFF;
  1293. }
  1294. j++;
  1295. }
  1296. stmProg(&stm32addr, (uint8_t *)(LeftBytesTab), 4);
  1297. LeftBytes = 0;
  1298. /* update data pointer */
  1299. ptr = (char *)(ptr + j);
  1300. len = len - j;
  1301. }
  1302. /* write received bytes into flash */
  1303. count = len / 4;
  1304. /* check if remaining bytes < 4 */
  1305. i = len % 4;
  1306. if (i > 0) {
  1307. if (TotalReceived != size) {
  1308. /* store bytes in LeftBytesTab */
  1309. LeftBytes = 0;
  1310. for (; i > 0; i--) {
  1311. LeftBytesTab[LeftBytes++] = *(char *)(ptr + len - i);
  1312. }
  1313. } else {
  1314. count++;
  1315. }
  1316. }
  1317. stmProg(&stm32addr, (uint8_t *)ptr, count * 4);
  1318. }
  1319. #endif
  1320. void ProgTimeout_Handler()
  1321. {
  1322. /* If connection was broken during update,
  1323. * abort process, erase main board flash and restart IAP */
  1324. printf("Program timeout. Seems that connection was broken. Reboot...\r\n");
  1325. SET_FWINVALID_FLAG();
  1326. #ifdef LCD_ENABLE
  1327. LCD_PrintAligned(5, alignCENTER, "Таймаут обновления");
  1328. LCD_PrintAligned(7, alignCENTER, "Перезагрузка..");
  1329. #endif
  1330. switch (fw_type) {
  1331. case fw_main_board:
  1332. /* Erase flash */
  1333. FLASH_If_Erase(USER_FLASH_FIRST_PAGE_ADDRESS);
  1334. break;
  1335. #ifdef SLAVEBRD_ENABLE
  1336. case fw_daughter_board:
  1337. /*TODO Should we erase upper board here? */
  1338. break;
  1339. #endif
  1340. default:
  1341. break;
  1342. }
  1343. #ifdef SLAVEBRD_ENABLE
  1344. /* Reboot daughter board */
  1345. stmReboot();
  1346. #endif
  1347. /* Self reboot */
  1348. NVIC_SystemReset();
  1349. }
  1350. static void PeriodicHandle(uint8_t progress)
  1351. {
  1352. (void)progress;
  1353. #ifdef LCD_ENABLE
  1354. LCD_PrintBar(7, progress);
  1355. #endif
  1356. /* Handle periodic timers for LwIP */
  1357. LwIP_Periodic_Handle(0);
  1358. }
  1359. /* Get Cookie parameter value */
  1360. bool GetCookieValue(char *inStr, char *paramName, char *paramValue, uint8_t *paramLen)
  1361. {
  1362. char *beginValue = 0;
  1363. char *endValue = 0;
  1364. char *endValueTemp = 0;
  1365. int len = 0;
  1366. char *strPtr = strstr(inStr, paramName);
  1367. if (strPtr != NULL) {
  1368. beginValue = strpbrk(strPtr, "=");
  1369. endValue = strpbrk(strPtr, ";");
  1370. endValueTemp = strpbrk(strPtr, "\r");
  1371. if (endValueTemp != 0 && endValueTemp < endValue) {
  1372. endValue = endValueTemp;
  1373. }
  1374. if (endValue == 0) {
  1375. endValue = strpbrk(strPtr, "\n");
  1376. }
  1377. len = endValue - beginValue - 1;
  1378. *endValue = '0';
  1379. *beginValue = '0';
  1380. if (paramValue && paramLen) {
  1381. strncpy(paramValue, beginValue + 1, len);
  1382. *paramLen = len;
  1383. }
  1384. return true;
  1385. } else {
  1386. return false;
  1387. }
  1388. }
  1389. /* Check if Cookie is set or not */
  1390. bool CookieIsSet(char *inStr, uint16_t inLen, char *paramName)
  1391. {
  1392. static char CookieBuf[COOKIES_MAX_LEN];
  1393. if (!inStr) return false;
  1394. char *CookiePtr = lwip_strnstr(inStr, "Cookie:", inLen);
  1395. if (CookiePtr) {
  1396. char *paramPtr = lwip_strnstr(CookiePtr, paramName, inLen - (inStr - CookiePtr));
  1397. if (paramPtr) {
  1398. strncpy(CookieBuf, paramPtr, sizeof(CookieBuf));
  1399. if (GetCookieValue(CookieBuf, paramName, NULL, NULL)) {
  1400. return true;
  1401. }
  1402. }
  1403. }
  1404. return false;
  1405. }
  1406. /******************* (C) COPYRIGHT 2011 STMicroelectronics *****END OF FILE****/