bspatch.c 7.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295
  1. /*-
  2. * Copyright 2003-2005 Colin Percival
  3. * Copyright 2012 Matthew Endsley
  4. * All rights reserved
  5. *
  6. * Redistribution and use in source and binary forms, with or without
  7. * modification, are permitted providing that the following conditions
  8. * are met:
  9. * 1. Redistributions of source code must retain the above copyright
  10. * notice, this list of conditions and the following disclaimer.
  11. * 2. Redistributions in binary form must reproduce the above copyright
  12. * notice, this list of conditions and the following disclaimer in the
  13. * documentation and/or other materials provided with the distribution.
  14. *
  15. * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
  16. * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
  17. * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  18. * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
  19. * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  20. * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  21. * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  22. * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
  23. * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
  24. * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  25. * POSSIBILITY OF SUCH DAMAGE.
  26. */
  27. #include <limits.h>
  28. #include <stdlib.h>
  29. #include <string.h>
  30. #include "bspatch.h"
  31. #include "user_interface.h"
  32. #define WRITE_BLOCK_SIZE 1024
  33. int64_t offtin(uint8_t *buf)
  34. {
  35. int64_t y;
  36. y = buf[7] & 0x7F;
  37. y = y * 256;
  38. y += buf[6];
  39. y = y * 256;
  40. y += buf[5];
  41. y = y * 256;
  42. y += buf[4];
  43. y = y * 256;
  44. y += buf[3];
  45. y = y * 256;
  46. y += buf[2];
  47. y = y * 256;
  48. y += buf[1];
  49. y = y * 256;
  50. y += buf[0];
  51. if (buf[7] & 0x80) y = -y;
  52. return y;
  53. }
  54. int bspatch(const uint8_t *old, int64_t oldsize, int64_t newsize, struct bspatch_stream *stream)
  55. {
  56. uint8_t buf[8];
  57. uint8_t *buf_data;
  58. int64_t oldpos, newpos, len;
  59. int64_t ctrl[3];
  60. int64_t i;
  61. buf_data = (uint8_t *)bs_malloc(WRITE_BLOCK_SIZE + 1);
  62. if (buf_data == NULL)return -1;
  63. oldpos = 0;
  64. newpos = 0;
  65. while (newpos < newsize)
  66. {
  67. /* Read control data */
  68. for (i = 0; i <= 2; i++)
  69. {
  70. if (stream->read(stream, buf, 8))
  71. {
  72. bs_printf("err%d", __LINE__);
  73. return -1;
  74. }
  75. ctrl[i] = offtin(buf);
  76. };
  77. /* Sanity-check */
  78. if (ctrl[0] < 0 || ctrl[0] > INT_MAX ||
  79. ctrl[1] < 0 || ctrl[1] > INT_MAX ||
  80. newpos + ctrl[0] > newsize)
  81. {
  82. bs_printf("err%d", __LINE__);
  83. return -1;
  84. }
  85. /* Read diff string */
  86. while (ctrl[0] > 0)
  87. {
  88. if (ctrl[0] > WRITE_BLOCK_SIZE)len = WRITE_BLOCK_SIZE;
  89. else len = ctrl[0];
  90. if (stream->read(stream, buf_data, len))return -1;
  91. for (i = 0; i < len; i++)
  92. {
  93. if ((oldpos + i >= 0) && (oldpos + i < oldsize))
  94. {
  95. buf_data[i] += old[oldpos + i];
  96. }
  97. }
  98. stream->write(stream, buf_data, len);
  99. ctrl[0] -= len;
  100. oldpos += len;
  101. newpos += len;
  102. }
  103. /* Sanity-check */
  104. if (newpos + ctrl[1] > newsize)
  105. {
  106. bs_printf("err%d", __LINE__);
  107. return -1;
  108. }
  109. /* Read extra string */
  110. while (ctrl[1] > 0)
  111. {
  112. if (ctrl[1] > WRITE_BLOCK_SIZE)len = WRITE_BLOCK_SIZE;
  113. else len = ctrl[1];
  114. if (stream->read(stream, buf_data, len))return -1;
  115. stream->write(stream, buf_data, len);
  116. ctrl[1] -= len;
  117. newpos += len;
  118. }
  119. /* Adjust pointers */
  120. oldpos += ctrl[2];
  121. //printk("newpos = %d, ctrl[0] = %ld, ctrl[1] = %ld, ctrl[2] = %ld\n", newpos, ctrl[0], ctrl[1], ctrl[2]);
  122. };
  123. if (buf_data != NULL) bs_free(buf_data);
  124. return 0;
  125. }
  126. //===========================================================
  127. #include "lzma_decompress.h"
  128. #include "vFile.h"
  129. #include "user_interface.h"
  130. #ifndef TRUE
  131. #define TRUE 1
  132. #endif
  133. #ifndef FALSE
  134. #define FALSE 0
  135. #endif
  136. #define DCOMPRESS_BUFFER_SIZE 1024
  137. static uint8_t *diff_data_buff;
  138. static int diff_data_len, diff_data_fp;
  139. static int new_data_fp;
  140. static int patch_data_read(const struct bspatch_stream *stream, void *buffer, int length)
  141. {
  142. uint8_t *dp = (uint8_t *)buffer;
  143. vFile *pf;
  144. pf = (vFile *) stream->opaque_r;
  145. for (int i = 0; i < length; i++)
  146. {
  147. if (diff_data_len == 0)
  148. {
  149. diff_data_len = lzma_decompress_read(pf, diff_data_buff, DCOMPRESS_BUFFER_SIZE);
  150. if (diff_data_len > 0)
  151. {
  152. diff_data_fp = 0;
  153. }
  154. else
  155. {
  156. bs_printf("err%d", __LINE__);
  157. return -1;
  158. }
  159. }
  160. if (diff_data_len > 0)
  161. {
  162. *(dp++) = diff_data_buff[diff_data_fp++];
  163. diff_data_len--;
  164. }
  165. }
  166. return 0;
  167. }
  168. static int new_data_write(const struct bspatch_stream *stream, void *buffer, int length)
  169. {
  170. uint32_t file_addr;
  171. file_addr = *((uint32_t *)stream->opaque_w);
  172. if (0 != bs_flash_write(file_addr + new_data_fp, buffer, length))
  173. {
  174. bs_printf("err");
  175. }
  176. new_data_fp += length;
  177. return (TRUE);
  178. }
  179. static void patch_data_read_finish(void)
  180. {
  181. lzma_decompress_finish();
  182. }
  183. /**
  184. * @brief
  185. *
  186. * @param old 旧文件的地址
  187. * @param oldsize 旧文件的大小
  188. * @param patch 差分包的位置
  189. * @param patchsize 差分包的大小
  190. * @param newfile 还原的完整bin下载的位置
  191. * @return int 还原的文件大小
  192. */
  193. int iap_patch(const uint8_t *old, uint32_t oldsize, const uint8_t *patch, uint32_t patchsize, uint32_t newfile)
  194. {
  195. vFile *patch_fp;
  196. struct bspatch_stream stream;
  197. uint8_t header[24];
  198. int64_t newsize;
  199. //初始化全局变量
  200. diff_data_len = 0;
  201. diff_data_fp = 0;
  202. new_data_fp = 0;
  203. patch_fp = vfopen(patch, patchsize);
  204. if (patch_fp == NULL)
  205. {
  206. bs_printf("Line 224 bs_malloc err");
  207. return (0);
  208. }
  209. //读取差分文件头
  210. vfread(patch_fp, header, sizeof(header));
  211. bs_printf("patch_fp->offset:%d", patch_fp->offset);
  212. if (memcmp(header, "ENDSLEY/BSDIFF43", 16) != 0)
  213. {
  214. bs_printf("ENDSLEY/BSDIFF43 err: %s", header);
  215. for (uint32_t i = 0; i < sizeof(header); i++)
  216. {
  217. bs_printf("%02X ", header[i]);
  218. }
  219. return (0);
  220. }
  221. //计算新固件长度
  222. newsize = offtin(header + 16);
  223. if (newsize < 0)
  224. {
  225. bs_printf("newsize err");
  226. return (0);
  227. }
  228. //分配内存
  229. diff_data_buff = bs_malloc(DCOMPRESS_BUFFER_SIZE);
  230. if (diff_data_buff == NULL)
  231. {
  232. bs_printf("\r\nmalloc err");
  233. return (0);
  234. }
  235. //准备合并文件
  236. stream.read = patch_data_read;
  237. stream.opaque_r = (void *)patch_fp;
  238. stream.write = new_data_write;
  239. stream.opaque_w = &newfile;
  240. int res = bspatch(old, oldsize, newsize, &stream);
  241. bs_printf("bspatch res:%d", res);
  242. //释放内存
  243. patch_data_read_finish();
  244. bs_free(diff_data_buff);
  245. vfclose(patch_fp);
  246. return ((int)newsize);
  247. }