fwupdate.c 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573
  1. #define MODULE "fwupdate"
  2. #define DEBUG 1
  3. #include "common.h"
  4. #include "jtag.h"
  5. #include "spiflash.h"
  6. #include "fpga.h"
  7. #include "ota.h"
  8. #include "spz.h"
  9. #include "httpd.h"
  10. #include "fw.h"
  11. #include "boardinfo_esp.h"
  12. #include "matchver.h"
  13. #include <unzipLIB.h>
  14. #include <zlib.h>
  15. /* Needed for struct inflate_state, due to unziplib hacks */
  16. #include <zutil.h>
  17. #include <inftrees.h>
  18. #include <inflate.h>
  19. #ifndef local
  20. # define local static
  21. #endif
  22. #define BUFFER_SIZE SPIFLASH_SECTOR_SIZE
  23. #define FWUPDATE_STACK 8192
  24. #define FWUPDATE_PRIORITY 3
  25. static inline void spz_heap_info(bool always)
  26. {
  27. if (DEBUG || always)
  28. heap_info();
  29. }
  30. static void *spz_malloc(void *opaque, unsigned int size)
  31. {
  32. spz_stream *spz = opaque;
  33. MSG("spz_malloc(%u) = ", size);
  34. void *p = malloc(size);
  35. CMSG("%p\n", p);
  36. spz_heap_info(!p);
  37. if (!p) {
  38. spz->err = Z_MEM_ERROR;
  39. printf("[FWUP] Out of memory error!\n");
  40. }
  41. return p;
  42. }
  43. static void *spz_calloc(void *opaque, unsigned int items, unsigned int size)
  44. {
  45. size_t bytes = items*size;
  46. void *p = spz_malloc(opaque, bytes);
  47. if (likely(p))
  48. memset(p, 0, bytes);
  49. return p;
  50. }
  51. static void spz_free(void *opaque, void *ptr)
  52. {
  53. MSG("spz_free(%p)\n", ptr);
  54. (void)opaque;
  55. free(ptr);
  56. spz_heap_info(false);
  57. }
  58. int spz_read_data(spz_stream *spz, void *buf, size_t len)
  59. {
  60. uint8_t *p = buf;
  61. while (len) {
  62. unsigned int avail = spz->zs.next_out - spz->optr;
  63. if (spz->err)
  64. break;
  65. if (avail) {
  66. if (avail > len)
  67. avail = len;
  68. memcpy(p, spz->optr, avail);
  69. p += avail;
  70. spz->optr += avail;
  71. len -= avail;
  72. } else {
  73. spz->optr = spz->zs.next_out = spz->obuf;
  74. spz->zs.avail_out = BUFFER_SIZE;
  75. while (spz->zs.avail_out) {
  76. if (!spz->zs.avail_in && !spz->eoi) {
  77. int rlen;
  78. spz->zs.next_in = spz->ibuf;
  79. rlen = spz->read_data(spz->token, spz->ibuf, BUFFER_SIZE);
  80. if (rlen < 0) {
  81. if (!spz->err)
  82. spz->err = rlen;
  83. rlen = 0;
  84. }
  85. spz->eoi = !rlen;
  86. spz->zs.avail_in = rlen;
  87. }
  88. int rv = inflate(&spz->zs, Z_SYNC_FLUSH);
  89. if (rv == Z_OK || (rv == Z_BUF_ERROR && !spz->eoi))
  90. continue;
  91. spz->eoi = true;
  92. if (rv != Z_STREAM_END && !spz->err)
  93. spz->err = rv;
  94. break;
  95. }
  96. }
  97. }
  98. return p - (uint8_t *)buf;
  99. }
  100. /*
  101. * spz needs to be initialized to zero except the read_data and cookie
  102. * fields.
  103. */
  104. static int fwupdate_data_init(spz_stream *spz)
  105. {
  106. spz->zs.zalloc = spz_calloc;
  107. spz->zs.zfree = spz_free;
  108. spz->zs.opaque = spz; /* For error reporting */
  109. spz->err = Z_OK;
  110. /* This is necessary due to unziplib damage */
  111. spz->zs.state = spz_calloc(spz, 1, sizeof(struct inflate_state));
  112. if (!spz->zs.state)
  113. goto err;
  114. for (int i = 0; i < SPZ_NBUF; i++) {
  115. spz->bufs[i] = spz_malloc(spz, BUFFER_SIZE);
  116. if (!spz->bufs[i])
  117. goto err;
  118. }
  119. /* gzip, max window size */
  120. int rv = inflateInit2(&spz->zs, 16 + 15);
  121. printf("[FWUP] fwupdate_data_init: inflateInit2 returned %d\n", rv);
  122. if (rv != Z_OK && rv != Z_STREAM_END) {
  123. spz->err = rv;
  124. goto err;
  125. }
  126. spz->cleanup = true;
  127. err:
  128. return spz->err;
  129. }
  130. static int fwupdate_data_cleanup(spz_stream *spz)
  131. {
  132. int err = 0;
  133. if (!spz)
  134. return 0;
  135. err = spz->err;
  136. if (spz->cleanup)
  137. inflateEnd(&spz->zs);
  138. /* Don't reload the FPGA on error; it wedges the JTAG bus */
  139. if (spz->fpga_updated && !err)
  140. fpga_reset();
  141. for (int i = 0; i < SPZ_NBUF; i++) {
  142. if (spz->bufs[i])
  143. free(spz->bufs[i]);
  144. }
  145. if (spz->zs.state)
  146. free(spz->zs.state);
  147. return err;
  148. }
  149. /*
  150. * Blash a full chunk of data as a JTAG SHIFT_DR transaction
  151. */
  152. int jtag_shift_spz(spz_stream *spz, enum jtag_io_flags flags)
  153. {
  154. unsigned int data_left = spz->header.len;
  155. int err = 0;
  156. if (!data_left)
  157. return 0;
  158. while (data_left) {
  159. unsigned int bytes = data_left;
  160. int rv;
  161. if (bytes > BUFFER_SIZE)
  162. bytes = BUFFER_SIZE;
  163. rv = spz_read_data(spz, spz->dbuf, bytes);
  164. if (rv < 1) {
  165. err = Z_DATA_ERROR;
  166. break;
  167. }
  168. data_left -= rv;
  169. jtag_io(rv << 3, data_left ? 0 : flags, spz->dbuf, NULL);
  170. }
  171. return err;
  172. }
  173. static void *fwupdate_read_chunk_str(spz_stream *spz)
  174. {
  175. int rv;
  176. if (spz->header.len >= BUFFER_SIZE) {
  177. spz->err = Z_DATA_ERROR;
  178. return NULL;
  179. }
  180. rv = spz_read_data(spz, spz->dbuf, spz->header.len);
  181. if (spz->err) {
  182. return NULL;
  183. }
  184. if (rv != (int)spz->header.len) {
  185. spz->err = Z_DATA_ERROR;
  186. return NULL;
  187. }
  188. spz->dbuf[spz->header.len] = '\0';
  189. return spz->dbuf;
  190. }
  191. /* Skip a data chunk */
  192. static int fwupdate_skip_chunk(spz_stream *spz)
  193. {
  194. unsigned int skip = spz->header.len;
  195. while (skip) {
  196. unsigned int block = skip;
  197. if (block > BUFFER_SIZE)
  198. block = BUFFER_SIZE;
  199. int rv = spz_read_data(spz, spz->dbuf, block);
  200. if (spz->err)
  201. return spz->err;
  202. if (rv != (int)block) {
  203. return spz->err = Z_DATA_ERROR;
  204. }
  205. skip -= block;
  206. }
  207. return 0;
  208. }
  209. static int fwupdate_boardinfo(spz_stream *spz)
  210. {
  211. uint8_t *board_info_data = spz_malloc(spz, BOARDINFO_SIZE);
  212. int rv = Z_OK;
  213. MSG("updating FPGA board_info\n");
  214. if (!board_info_data)
  215. return spz->err;
  216. if (board_info.len >= 16 &&
  217. board_info.len <= sizeof board_info &&
  218. board_info.len <= BOARDINFO_SIZE) {
  219. memcpy(board_info_data, &board_info, board_info.len);
  220. memset(board_info_data + board_info.len, 0xff,
  221. BOARDINFO_SIZE - board_info.len);
  222. rv = spiflash_write_spz(spz, board_info_data, BOARDINFO_SIZE);
  223. }
  224. free(board_info_data);
  225. fwupdate_skip_chunk(spz);
  226. if (rv)
  227. spz->err = rv;
  228. return spz->err;
  229. }
  230. /* Get a piece of the chunk header */
  231. static int fwupdate_get_header_data(spz_stream *spz, void *buf, size_t len)
  232. {
  233. int rv;
  234. rv = spz_read_data(spz, buf, len);
  235. if (spz->err)
  236. return spz->err;
  237. else if (!rv)
  238. return Z_STREAM_END;
  239. else if (rv != len)
  240. return spz->err = Z_STREAM_ERROR;
  241. else
  242. return Z_OK;
  243. }
  244. /* Get and validate a chunk header */
  245. static int fwupdate_get_header(spz_stream *spz)
  246. {
  247. struct fw_header * const hdr = &spz->header;
  248. uint8_t *hptr = (uint8_t *)hdr;
  249. int rv;
  250. unsigned int hlen;
  251. memset(hdr, 0, sizeof *hdr);
  252. hdr->vmax = -1;
  253. rv = fwupdate_get_header_data(spz, hptr, FW_HDR_LEN_V1);
  254. if (rv)
  255. return rv;
  256. switch (hdr->magic) {
  257. case FW_MAGIC_V1:
  258. hlen = FW_HDR_LEN_V1;
  259. break;
  260. case FW_MAGIC_V2:
  261. hlen = FW_HDR_LEN_V2;
  262. break;
  263. default:
  264. MSG("bad chunk header magic 0x%08x\n", hdr->magic);
  265. hlen = 0;
  266. rv = Z_DATA_ERROR;
  267. break;
  268. }
  269. if (hlen > FW_HDR_LEN_V1) {
  270. rv = fwupdate_get_header_data(spz, hptr + FW_HDR_LEN_V1,
  271. hlen - FW_HDR_LEN_V1);
  272. if (rv == Z_STREAM_END) /* Only valid for the first chunk */
  273. rv = Z_STREAM_ERROR;
  274. }
  275. return spz->err = rv;
  276. }
  277. /* Process a data chunk; return a nonzero value if done */
  278. static int fwupdate_process_chunk(spz_stream *spz)
  279. {
  280. int rv;
  281. char *str;
  282. rv = fwupdate_get_header(spz);
  283. if (rv)
  284. return rv;
  285. if (spz->header.type != FDT_NOTE &&
  286. spz->header.type != FDT_TARGET &&
  287. spz->header.type != FDT_END &&
  288. !(spz->header.flags & FDF_PRETARGET)) {
  289. if (!spz->vmatch.magic) {
  290. /* No matching firmware target support */
  291. return spz->err = FWUPDATE_ERR_NOT_MINE;
  292. }
  293. if (spz->header.vmin > spz->vmatch.vmax ||
  294. spz->header.vmax < spz->vmatch.vmin ||
  295. ((spz->header.vmatch ^ spz->vmatch.vmatch) & spz->header.vmask)) {
  296. /* Chunk not applicable to this target */
  297. return fwupdate_skip_chunk(spz);
  298. }
  299. }
  300. switch (spz->header.type) {
  301. case FDT_END:
  302. return Z_STREAM_END; /* End of data - not an error */
  303. case FDT_DATA:
  304. MSG("updating FPGA flash\n");
  305. return spiflash_write_spz(spz, NULL, 0);
  306. case FDT_BOARDINFO:
  307. return fwupdate_boardinfo(spz);
  308. case FDT_TARGET:
  309. {
  310. bool match;
  311. str = fwupdate_read_chunk_str(spz);
  312. match = match_version(board_info.version_str, str);
  313. if (match || spz->header.magic == FW_MAGIC_V1)
  314. spz->vmatch = spz->header;
  315. MSG("firmware file supports: %s%s\n",
  316. str, match ? " (match)" : "");
  317. return Z_OK;
  318. }
  319. case FDT_NOTE:
  320. str = fwupdate_read_chunk_str(spz);
  321. MSG("%s\n", str);
  322. return Z_OK;
  323. case FDT_ESP_OTA:
  324. MSG("updating ESP32... ");
  325. spz->esp_updated = true;
  326. rv = esp_update((read_func_t)spz_read_data, (token_t)spz,
  327. spz->header.len);
  328. CMSG("done.\n");
  329. return rv;
  330. case FDT_FPGA_INIT:
  331. MSG("initializing FPGA for flash programming... ");
  332. spz->fpga_updated = true;
  333. rv = fpga_program_spz(spz);
  334. CMSG("done\n");
  335. return rv;
  336. case FDT_ESP_PART:
  337. case FDT_ESP_SYS:
  338. case FDT_ESP_TOOL:
  339. /* Not applicable to this update method */
  340. return fwupdate_skip_chunk(spz);
  341. default:
  342. if (spz->header.flags & FDF_OPTIONAL) {
  343. return fwupdate_skip_chunk(spz);
  344. } else {
  345. MSG("unknown chunk type: %u\n", spz->header.type);
  346. return spz->err = Z_DATA_ERROR;
  347. }
  348. }
  349. }
  350. const char *firmware_errstr(int err)
  351. {
  352. static char unknown_err[32];
  353. static const char * const errstr[] = {
  354. [-Z_STREAM_ERROR] = "Decompression error",
  355. [-Z_DATA_ERROR] = "Invalid data stream",
  356. [-Z_MEM_ERROR] = "Out of memory",
  357. [-Z_BUF_ERROR] = "Decompression error",
  358. [-FWUPDATE_ERR_IN_PROGRESS] =
  359. "Firmware update already in progress",
  360. [-FWUPDATE_ERR_BAD_CHUNK] = "Invalid firmware chunk header",
  361. [-FWUPDATE_ERR_ERASE_FAILED] = "FPGA flash erase failed",
  362. [-FWUPDATE_ERR_PROGRAM_FAILED] = "FGPA flash program failed",
  363. [-FWUPDATE_ERR_WRITE_PROTECT] = "FPGA flash write protected",
  364. [-FWUPDATE_ERR_NOT_READY] = "FPGA flash stuck at not ready",
  365. [-FWUPDATE_ERR_FPGA_JTAG] =
  366. "FPGA JTAG bus stuck, check for JTAG adapter or power cycle board",
  367. [-FWUPDATE_ERR_FPGA_MISMATCH] =
  368. "Bad FPGA IDCODE, check for JTAG adapter or power cycle board",
  369. [-FWUPDATE_ERR_FPGA_FAILED] = "FPGA reboot failed",
  370. [-FWUPDATE_ERR_UNKNOWN] = "Unidentified error",
  371. [-FWUPDATE_ERR_ESP_NO_PARTITION] = "No available ESP partition",
  372. [-FWUPDATE_ERR_ESP_BAD_OTA] = "ESP OTA information corrupt",
  373. [-FWUPDATE_ERR_ESP_FLASH_FAILED] = "ESP flash program failed",
  374. [-FWUPDATE_ERR_ESP_BAD_DATA] = "ESP firmware image corrupt",
  375. [-FWUPDATE_ERR_CONFIG_READ] = "Configuration upload failure",
  376. [-FWUPDATE_ERR_CONFIG_SAVE] = "Error saving configuration",
  377. [-FWUPDATE_ERR_NOT_MINE] = "Firmware file is not compatible"
  378. };
  379. switch (err) {
  380. case Z_OK:
  381. return errstr[-FWUPDATE_ERR_UNKNOWN];
  382. case Z_ERRNO:
  383. return strerror(errno);
  384. case -ARRAY_SIZE(errstr)+1 ... Z_STREAM_ERROR:
  385. if (errstr[-err])
  386. return errstr[-err];
  387. /* fall through */
  388. default:
  389. snprintf(unknown_err, sizeof unknown_err, "error %d", -err);
  390. return unknown_err;
  391. }
  392. }
  393. static TaskHandle_t fwupdate_task;
  394. static spz_stream *fwupdate_spz;
  395. static SemaphoreHandle_t fwupdate_done;
  396. static bool do_reboot;
  397. static void firmware_update_task(void *pvt)
  398. {
  399. spz_stream *spz = pvt;
  400. fpga_service_enable(false);
  401. printf("[FWUP] fwupdate_data_init()\n");
  402. spz->err = fwupdate_data_init(spz);
  403. if (spz->err)
  404. goto fail;
  405. printf("[FWUP] fwupdate_process_chunk loop\n");
  406. int err;
  407. while (!(err = fwupdate_process_chunk(spz))) {
  408. /* Process data chunks until end */
  409. }
  410. if (!spz->err && err != Z_STREAM_END)
  411. spz->err = err;
  412. printf("[FWUP] fwupdate_data_cleanup\n");
  413. err = fwupdate_data_cleanup(spz);
  414. if (err)
  415. spz->err = err;
  416. fail:
  417. if (spz->err)
  418. MSG("failed (err %d)\n", spz->err);
  419. xSemaphoreGive(fwupdate_done);
  420. if (do_reboot) {
  421. printf("[FWUP] rebooting in %d seconds\n", reboot_delayed());
  422. while (1)
  423. vTaskSuspend(NULL);
  424. } else {
  425. exit_task();
  426. }
  427. }
  428. static int firmware_update_cleanup(void)
  429. {
  430. int err = Z_OK;
  431. fwupdate_task = NULL;
  432. if (fwupdate_done) {
  433. SemaphoreHandle_t done = fwupdate_done;
  434. fwupdate_done = NULL;
  435. vSemaphoreDelete(done);
  436. } else {
  437. err = Z_MEM_ERROR;
  438. }
  439. if (fwupdate_spz) {
  440. struct spz_stream *spz = fwupdate_spz;
  441. if (spz->err)
  442. err = spz->err;
  443. fwupdate_spz = NULL;
  444. free(spz);
  445. } else {
  446. err = Z_MEM_ERROR;
  447. }
  448. return err;
  449. }
  450. int firmware_update_start(read_func_t read_data, token_t token, bool autoreboot)
  451. {
  452. do_reboot = autoreboot;
  453. if (fwupdate_spz)
  454. return FWUPDATE_ERR_IN_PROGRESS;
  455. fwupdate_spz = calloc(1, sizeof *fwupdate_spz);
  456. if (!fwupdate_spz)
  457. goto err;
  458. fwupdate_spz->read_data = read_data;
  459. fwupdate_spz->token = token;
  460. fwupdate_done = xSemaphoreCreateBinary();
  461. if (!fwupdate_done)
  462. goto err;
  463. if (xTaskCreate(firmware_update_task, "fwupdate",
  464. FWUPDATE_STACK, fwupdate_spz,
  465. FWUPDATE_PRIORITY, &fwupdate_task) != pdPASS) {
  466. xSemaphoreGive(fwupdate_done);
  467. }
  468. return Z_OK;
  469. err:
  470. return firmware_update_cleanup();
  471. }
  472. int firmware_update_wait(TickType_t delay)
  473. {
  474. if (!fwupdate_done)
  475. return Z_MEM_ERROR;
  476. if (!xSemaphoreTake(fwupdate_done, delay))
  477. return FWUPDATE_ERR_IN_PROGRESS;
  478. return firmware_update_cleanup();
  479. }