ota_backend_temp_part.c 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425
  1. /*
  2. * Copyright (c) 2019 Actions Semiconductor Co., Ltd
  3. *
  4. * SPDX-License-Identifier: Apache-2.0
  5. */
  6. /**
  7. * @file
  8. * @brief OTA SDCARD backend interface
  9. */
  10. #include <kernel.h>
  11. #include <string.h>
  12. #include <drivers/flash.h>
  13. #include <partition/partition.h>
  14. #include <mem_manager.h>
  15. #include <ota_backend.h>
  16. #include <ota_backend_temp_part.h>
  17. #include <os_common_api.h>
  18. #include <drivers/mmc/sd.h>
  19. #ifdef CONFIG_OTA_LZMA
  20. #include <minlzma.h>
  21. #endif
  22. #ifdef CONFIG_WATCHDOG
  23. #include <watchdog_hal.h>
  24. #endif
  25. enum ota_backend_temp_type {
  26. OTA_BACKEND_SPINOR,
  27. OTA_BACKEND_SD,
  28. OTA_BACKEND_NAND,
  29. };
  30. #define OTA_BACKEND_SD_SECTOR_SIZE (512)
  31. #define CONFIG_MMC_SDCARD_DEV_NAME "sd"
  32. #define CONFIG_SPINAND_DEV_NAME "spinand"
  33. struct ota_backend_temp_part {
  34. struct ota_backend backend;
  35. const struct device *dev;
  36. const char *dev_name;
  37. uint32_t offset;
  38. int size;
  39. int type; // refer to enum ota_backend_temp_type
  40. int lzma; // lzma compress flag
  41. };
  42. #define IMAGE_MAGIC0 0x48544341
  43. #define IMAGE_MAGIC1 0x41435448
  44. typedef struct image_head {
  45. uint32_t ih_magic0;
  46. uint32_t ih_magic1; //
  47. uint32_t ih_load_addr; /*load addr, include header*/
  48. uint8_t ih_name[8]; //
  49. uint32_t ih_entry;
  50. uint32_t ih_img_size;
  51. uint32_t ih_img_chksum; /*if not sign, use check sum??ih_img_size not include header */
  52. uint32_t ih_hdr_chksum; /* include header. */
  53. uint16_t ih_hdr_size; /* Size of image header (bytes). */
  54. uint16_t ih_ptlv_size; /* Size of protected TLV area (bytes). */
  55. uint16_t ih_tlv_size; /*tlv size*/
  56. uint16_t ih_version;
  57. uint32_t ih_flags;
  58. uint8_t ih_ext_ictype[7];
  59. uint8_t ih_storage_type; // mbrec
  60. }image_head_t;
  61. #if CONFIG_PSRAM_SIZE >= 4096
  62. #define LZMA_IN_MAX (1536*1024)
  63. #define LZMA_OUT_MAX (2048*1024)
  64. #elif CONFIG_PSRAM_SIZE >= 1024
  65. #define LZMA_IN_MAX (256*1024)
  66. #define LZMA_OUT_MAX (256*1024)
  67. #else
  68. #define LZMA_IN_MAX (32*1024)
  69. #define LZMA_OUT_MAX (32*1024)
  70. #endif
  71. static uint8_t __in_section_unique(noinit) lzma_inbuf[LZMA_IN_MAX];
  72. static uint8_t __in_section_unique(noinit) lzma_outbuf[LZMA_OUT_MAX];
  73. static uint32_t lzma_inoff = 0;
  74. static uint32_t lzma_outoff = 0xffffffff;
  75. static int temp_part_read_flash(struct ota_backend_temp_part *ob_tp, int offset, uint8_t *buf, int size)
  76. {
  77. int err = 0;
  78. uint32_t offs = ob_tp->offset + offset;
  79. uint32_t head, count, left;
  80. uint8_t *buffer = NULL;
  81. SYS_LOG_DBG("dev %s: offset 0x%x, size 0x%x, buf %p",
  82. ob_tp->dev_name, offset, size, buf);
  83. if ((offset + size) > ob_tp->size) {
  84. SYS_LOG_ERR("offs 0x%x size 0x%x is too big, max size 0x%x",
  85. offset, size, ob_tp->size);
  86. return -EINVAL;
  87. }
  88. if (ob_tp->type == OTA_BACKEND_SD || ob_tp->type == OTA_BACKEND_NAND) {
  89. head = ROUND_UP(offs, OTA_BACKEND_SD_SECTOR_SIZE) - offs;
  90. size = (size > head) ? (size - head): 0;
  91. count = size / OTA_BACKEND_SD_SECTOR_SIZE;
  92. left = size % OTA_BACKEND_SD_SECTOR_SIZE;
  93. offs /= OTA_BACKEND_SD_SECTOR_SIZE;
  94. if (head || left) {
  95. buffer = (uint8_t *)mem_malloc(OTA_BACKEND_SD_SECTOR_SIZE);
  96. if (!buffer) {
  97. SYS_LOG_ERR("can not malloc %d size", OTA_BACKEND_SD_SECTOR_SIZE);
  98. return -ENOMEM;
  99. }
  100. }
  101. if (head && !err) {
  102. err = flash_read(ob_tp->dev, offs<<9, buffer, 1<<9);
  103. if (err) {
  104. SYS_LOG_ERR("read error %d, offs 0x%x, count %d",
  105. err, offs, count);
  106. err = -EIO;
  107. }
  108. memcpy(buf, buffer + OTA_BACKEND_SD_SECTOR_SIZE - head, head);
  109. buf += head;
  110. offs += 1;
  111. }
  112. if (count && !err) {
  113. err = flash_read(ob_tp->dev, offs<<9, buf, count<<9);
  114. if (err) {
  115. SYS_LOG_ERR("read error %d, offs 0x%x, count %d",
  116. err, offs, count);
  117. err = -EIO;
  118. }
  119. buf += (count * OTA_BACKEND_SD_SECTOR_SIZE);
  120. offs += count;
  121. }
  122. if (left && !err) {
  123. err = flash_read(ob_tp->dev, offs<<9, buffer, 1<<9);
  124. if (err) {
  125. SYS_LOG_ERR("read error %d, offs 0x%x, count %d",
  126. err, offs, count);
  127. err = -EIO;
  128. }
  129. memcpy(buf, buffer, left);
  130. }
  131. if (buffer) {
  132. mem_free(buffer);
  133. }
  134. } else {
  135. err = flash_read(ob_tp->dev, offs, buf, size);
  136. if (err) {
  137. SYS_LOG_ERR("read error %d, offs 0x%x, buf %p, size 0x%x",
  138. err, offset, buf, size);
  139. return -EIO;
  140. }
  141. }
  142. return err;
  143. }
  144. static int temp_part_read_lzma(struct ota_backend_temp_part *ob_tp, int offset, uint8_t *buf, int size)
  145. {
  146. int err, ret;
  147. uint32_t out_off, out_size;
  148. lzma_head_t *plzma_h = (lzma_head_t *)lzma_inbuf;
  149. // read first part from lzma buffer
  150. if ((offset >= lzma_outoff) && (offset < (lzma_outoff + LZMA_OUT_MAX))) {
  151. if ((offset + size) > (lzma_outoff + LZMA_OUT_MAX)) {
  152. out_size = lzma_outoff + LZMA_OUT_MAX - offset;
  153. memcpy(buf, lzma_outbuf+offset-lzma_outoff, out_size);
  154. buf += out_size;
  155. offset += out_size;
  156. size -= out_size;
  157. }
  158. }
  159. // check size
  160. if (size <= 0) {
  161. return 0;
  162. }
  163. // check offset
  164. if ((offset < lzma_outoff) || (offset >= (lzma_outoff + LZMA_OUT_MAX))) {
  165. // init lzma block
  166. if (offset < lzma_outoff) {
  167. lzma_inoff = 0;
  168. out_off = 0;
  169. } else {
  170. out_off = lzma_outoff;
  171. }
  172. // search lzma block
  173. while (1) {
  174. // read lzma header
  175. err = temp_part_read_flash(ob_tp, lzma_inoff, (uint8_t*)plzma_h, sizeof(lzma_head_t));
  176. if (err) {
  177. return -1;
  178. }
  179. // check lzma magic
  180. if (plzma_h->ih_magic != LZMA_MAGIC) {
  181. SYS_LOG_ERR("lzma error magic: 0x%x", plzma_h->ih_magic);
  182. return -1;
  183. }
  184. // check out offset
  185. if ((offset >= out_off) && (offset < (out_off + LZMA_OUT_MAX))) {
  186. break;
  187. }
  188. // next lzma block
  189. lzma_inoff += plzma_h->ih_hdr_size + plzma_h->ih_img_size;
  190. out_off += plzma_h->ih_org_size;
  191. }
  192. // check lzma buffer size
  193. if (plzma_h->ih_org_size > LZMA_OUT_MAX) {
  194. SYS_LOG_ERR("lzma buffer too small! size 0x%x", LZMA_OUT_MAX);
  195. return -1;
  196. }
  197. // read lzma img
  198. err = temp_part_read_flash(ob_tp, lzma_inoff, lzma_inbuf, plzma_h->ih_hdr_size+plzma_h->ih_img_size);
  199. if (err) {
  200. return -1;
  201. }
  202. #ifdef CONFIG_WATCHDOG
  203. watchdog_clear();
  204. #endif
  205. // lzma decompress
  206. out_size = LZMA_OUT_MAX;
  207. #ifdef CONFIG_OTA_LZMA
  208. ret = XzDecode(lzma_inbuf+plzma_h->ih_hdr_size, plzma_h->ih_img_size, lzma_outbuf, &out_size);
  209. #else
  210. ret = 0;
  211. #endif
  212. if (ret == 0) {
  213. SYS_LOG_ERR("XzDecode error! size 0x%x", out_size);
  214. return -2;
  215. }
  216. // check origin size
  217. if (out_size != plzma_h->ih_org_size) {
  218. SYS_LOG_ERR("XzDecode out_size mismatch! 0x%x", out_size);
  219. return -3;
  220. }
  221. lzma_outoff = out_off;
  222. SYS_LOG_INF("XzDecode 0x%x ok! 0x%x -> 0x%x", out_off, plzma_h->ih_img_size, plzma_h->ih_org_size);
  223. }
  224. // read last part from lzma buffer
  225. memcpy(buf, lzma_outbuf+offset-lzma_outoff, size);
  226. return 0;
  227. }
  228. static int ota_backend_temp_part_prepare(struct ota_backend_temp_part *ob_tp)
  229. {
  230. int err;
  231. uint32_t inner_offset = 0;
  232. image_head_t *pimg_h = (image_head_t *)lzma_inbuf;
  233. lzma_head_t *plzma_h = (lzma_head_t *)lzma_inbuf;
  234. // init lzma flag
  235. ob_tp->lzma = 0;
  236. // read image header
  237. err = temp_part_read_flash(ob_tp, 0, (uint8_t*)pimg_h, sizeof(image_head_t));
  238. if (err) {
  239. return -1;
  240. }
  241. // check ota_app
  242. if ((pimg_h->ih_magic0 == IMAGE_MAGIC0) && (pimg_h->ih_magic1 == IMAGE_MAGIC1)) {
  243. inner_offset = pimg_h->ih_hdr_size + pimg_h->ih_img_size;
  244. inner_offset = (inner_offset + OTA_BACKEND_SD_SECTOR_SIZE - 1) & ~(OTA_BACKEND_SD_SECTOR_SIZE - 1);
  245. SYS_LOG_INF("found app! temp inner offset: 0x%x", inner_offset);
  246. }
  247. // update temp offset and size
  248. if (inner_offset > 0) {
  249. ob_tp->offset += inner_offset;
  250. ob_tp->size -= inner_offset;
  251. }
  252. // read lzma header
  253. err = temp_part_read_flash(ob_tp, 0, (uint8_t*)plzma_h, sizeof(lzma_head_t));
  254. if (err) {
  255. return -1;
  256. }
  257. // check lzma header
  258. if (plzma_h->ih_magic == LZMA_MAGIC) {
  259. // set lzma flag
  260. ob_tp->lzma = 1;
  261. SYS_LOG_INF("found lzma!");
  262. }
  263. return 0;
  264. }
  265. int ota_backend_temp_part_read(struct ota_backend *backend, int offset, uint8_t *buf, int size)
  266. {
  267. struct ota_backend_temp_part *ob_tp = CONTAINER_OF(backend,
  268. struct ota_backend_temp_part, backend);
  269. int err = 0;
  270. // check lzma flag
  271. if (ob_tp->lzma) {
  272. err = temp_part_read_lzma(ob_tp, offset, buf, size);
  273. } else {
  274. err = temp_part_read_flash(ob_tp, offset, buf, size);
  275. }
  276. return err;
  277. }
  278. int ota_backend_temp_part_open(struct ota_backend *backend)
  279. {
  280. #if CONFIG_LOG
  281. struct ota_backend_temp_part *backend_temp_part = CONTAINER_OF(backend,
  282. struct ota_backend_temp_part, backend);
  283. SYS_LOG_INF("dev %s: open: type %d", backend_temp_part->dev_name, backend->type);
  284. #endif
  285. return 0;
  286. }
  287. int ota_backend_temp_part_close(struct ota_backend *backend)
  288. {
  289. #if CONFIG_LOG
  290. struct ota_backend_temp_part *backend_temp_part = CONTAINER_OF(backend,
  291. struct ota_backend_temp_part, backend);
  292. SYS_LOG_INF("dev %s: close: type %d", backend_temp_part->dev_name, backend->type);
  293. #endif
  294. return 0;
  295. }
  296. void ota_backend_temp_part_exit(struct ota_backend *backend)
  297. {
  298. struct ota_backend_temp_part *backend_temp_part = CONTAINER_OF(backend,
  299. struct ota_backend_temp_part, backend);
  300. SYS_LOG_INF("dev %s: exit: type %d", backend_temp_part->dev_name, backend->type);
  301. mem_free(backend_temp_part);
  302. }
  303. const struct ota_backend_api ota_backend_api_temp_part = {
  304. .init = (void *)ota_backend_temp_part_init,
  305. .exit = ota_backend_temp_part_exit,
  306. .open = ota_backend_temp_part_open,
  307. .close = ota_backend_temp_part_close,
  308. .read = ota_backend_temp_part_read,
  309. };
  310. struct ota_backend *ota_backend_temp_part_init(ota_backend_notify_cb_t cb,
  311. struct ota_backend_temp_part_init_param *param)
  312. {
  313. struct ota_backend_temp_part *backend_temp_part;
  314. const struct partition_entry *temp_part;
  315. const struct device *temp_part_dev;
  316. SYS_LOG_INF("init backend %s\n", param->dev_name);
  317. temp_part_dev = device_get_binding(param->dev_name);
  318. if (!temp_part_dev) {
  319. SYS_LOG_ERR("cannot found temp part device %s", param->dev_name);
  320. return NULL;
  321. }
  322. temp_part = partition_get_temp_part();
  323. if (temp_part == NULL) {
  324. SYS_LOG_ERR("cannot found temp partition to store ota fw");
  325. return NULL;
  326. }
  327. SYS_LOG_INF("temp partition offset 0x%x, size 0x%x\n",
  328. temp_part->offset, temp_part->size);
  329. backend_temp_part = mem_malloc(sizeof(struct ota_backend_temp_part));
  330. if (!backend_temp_part) {
  331. SYS_LOG_ERR("malloc failed");
  332. return NULL;
  333. }
  334. memset(backend_temp_part, 0x0, sizeof(struct ota_backend_temp_part));
  335. backend_temp_part->dev = temp_part_dev;
  336. backend_temp_part->dev_name = param->dev_name;
  337. backend_temp_part->offset = temp_part->offset;
  338. backend_temp_part->size = temp_part->size;
  339. if (!strcmp(param->dev_name, CONFIG_MMC_SDCARD_DEV_NAME)) {
  340. backend_temp_part->type = OTA_BACKEND_SD;
  341. #ifdef CONFIG_MMC
  342. if (sd_card_storage_init(backend_temp_part->dev)) {
  343. SYS_LOG_ERR("init sd device error");
  344. return NULL;
  345. }
  346. #endif
  347. } else if (!strcmp(param->dev_name, CONFIG_SPINAND_DEV_NAME)) {
  348. backend_temp_part->type = OTA_BACKEND_NAND;
  349. } else {
  350. backend_temp_part->type = OTA_BACKEND_SPINOR;
  351. }
  352. ota_backend_temp_part_prepare(backend_temp_part);
  353. ota_backend_init(&backend_temp_part->backend, OTA_BACKEND_TYPE_TEMP_PART,
  354. (struct ota_backend_api *)&ota_backend_api_temp_part, cb);
  355. /* spinor backend detected, notify app */
  356. cb(&backend_temp_part->backend, OTA_BACKEND_UPGRADE_STATE, 1);
  357. return &backend_temp_part->backend;
  358. }