mrdump_zip.c 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613
  1. /* Copyright Statement:
  2. *
  3. * This software/firmware and related documentation ("MediaTek Software") are
  4. * protected under relevant copyright laws. The information contained herein
  5. * is confidential and proprietary to MediaTek Inc. and/or its licensors.
  6. * Without the prior written permission of MediaTek inc. and/or its licensors,
  7. * any reproduction, modification, use or disclosure of MediaTek Software,
  8. * and information contained herein, in whole or in part, shall be strictly prohibited.
  9. */
  10. /* MediaTek Inc. (C) 2016. All rights reserved.
  11. *
  12. * BY OPENING THIS FILE, RECEIVER HEREBY UNEQUIVOCALLY ACKNOWLEDGES AND AGREES
  13. * THAT THE SOFTWARE/FIRMWARE AND ITS DOCUMENTATIONS ("MEDIATEK SOFTWARE")
  14. * RECEIVED FROM MEDIATEK AND/OR ITS REPRESENTATIVES ARE PROVIDED TO RECEIVER ON
  15. * AN "AS-IS" BASIS ONLY. MEDIATEK EXPRESSLY DISCLAIMS ANY AND ALL WARRANTIES,
  16. * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF
  17. * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR NONINFRINGEMENT.
  18. * NEITHER DOES MEDIATEK PROVIDE ANY WARRANTY WHATSOEVER WITH RESPECT TO THE
  19. * SOFTWARE OF ANY THIRD PARTY WHICH MAY BE USED BY, INCORPORATED IN, OR
  20. * SUPPLIED WITH THE MEDIATEK SOFTWARE, AND RECEIVER AGREES TO LOOK ONLY TO SUCH
  21. * THIRD PARTY FOR ANY WARRANTY CLAIM RELATING THERETO. RECEIVER EXPRESSLY ACKNOWLEDGES
  22. * THAT IT IS RECEIVER'S SOLE RESPONSIBILITY TO OBTAIN FROM ANY THIRD PARTY ALL PROPER LICENSES
  23. * CONTAINED IN MEDIATEK SOFTWARE. MEDIATEK SHALL ALSO NOT BE RESPONSIBLE FOR ANY MEDIATEK
  24. * SOFTWARE RELEASES MADE TO RECEIVER'S SPECIFICATION OR TO CONFORM TO A PARTICULAR
  25. * STANDARD OR OPEN FORUM. RECEIVER'S SOLE AND EXCLUSIVE REMEDY AND MEDIATEK'S ENTIRE AND
  26. * CUMULATIVE LIABILITY WITH RESPECT TO THE MEDIATEK SOFTWARE RELEASED HEREUNDER WILL BE,
  27. * AT MEDIATEK'S OPTION, TO REVISE OR REPLACE THE MEDIATEK SOFTWARE AT ISSUE,
  28. * OR REFUND ANY SOFTWARE LICENSE FEES OR SERVICE CHARGE PAID BY RECEIVER TO
  29. * MEDIATEK FOR SUCH MEDIATEK SOFTWARE AT ISSUE.
  30. */
  31. #include <malloc.h>
  32. #include <stdint.h>
  33. #include <stdio.h>
  34. #include <string.h>
  35. #include <assert.h>
  36. #include <lib/crc.h>
  37. #include <lib/zutil.h>
  38. #include <lib/zlib.h>
  39. #include "aee.h"
  40. #include "mrdump_private.h"
  41. #ifdef MTK_3LEVEL_PAGETABLE
  42. #include <stdlib.h>
  43. #include <err.h>
  44. #endif
  45. #define KZIP_DEBUG(x...)
  46. #define KDUMP_SIZE_REPORT 0x1000000
  47. #define KDUMP_TICK_WDT 0x10000
  48. #ifdef MRDUMP_ZIP_NO_COMPRESSION
  49. #define KDUMP_ZLIB_LEVEL Z_NO_COMPRESSION
  50. #else
  51. #define KDUMP_ZLIB_LEVEL Z_BEST_SPEED
  52. #endif
  53. #define ZIPVERSION_NEEDED 45UL
  54. static void putvalue(void* dest, uint64_t x, int nbByte)
  55. {
  56. uint8_t *buf = (uint8_t *)dest;
  57. int n;
  58. for (n = 0; n < nbByte; n++) {
  59. buf[n] = (unsigned char)(x & 0xff);
  60. x >>= 8;
  61. }
  62. #if 0
  63. if (x != 0) {
  64. /* data overflow - hack for ZIP64 */
  65. for (n = 0; n < nbByte; n++) {
  66. buf[n] = 0xff;
  67. }
  68. }
  69. #endif
  70. }
  71. static int put_zip64_eoc_directory_record(uint8_t *buf, int record_num, uint64_t zip_centralheader_offset, int zip_centralheader_size)
  72. {
  73. uint8_t *oldbuf = buf;
  74. putvalue(buf, ZIP64ENDOFCENTRALDIRMAGIC, 4);
  75. buf += 4;
  76. putvalue(buf, 44, 8); /* zip64 eoc size */
  77. buf += 8;
  78. putvalue(buf, ZIPVERSION_NEEDED, 2); /* version made by */
  79. buf += 2;
  80. putvalue(buf, ZIPVERSION_NEEDED, 2); /* version needed to extract */
  81. buf += 2;
  82. putvalue(buf, 0, 4); /* number of this disk */
  83. buf += 4;
  84. putvalue(buf, 0, 4); /* number of the disk with the start of the central directory */
  85. buf += 4;
  86. putvalue(buf, record_num, 8); /* total number of entries in the central directory on this disk */
  87. buf += 8;
  88. putvalue(buf, record_num, 8); /* total number of entries in the central directory */
  89. buf += 8;
  90. putvalue(buf, zip_centralheader_size, 8); /* size of the central directory */
  91. buf += 8;
  92. putvalue(buf, zip_centralheader_offset, 8); /* offset of start of central directory with respect to the starting disk number */
  93. buf += 8;
  94. return buf - oldbuf;
  95. }
  96. static int put_zip64_eoc_directory_locator(uint8_t *buf, uint64_t zip64_eoc_offset)
  97. {
  98. uint8_t *oldbuf = buf;
  99. putvalue(buf, ZIP64ENDOFCENTRALDIRLOCATORMAGIC, 4);
  100. buf += 4;
  101. putvalue(buf, 0, 4); /* number of the disk with the start of the zip64 end of central directory */
  102. buf += 4;
  103. putvalue(buf, zip64_eoc_offset, 8); /* relative offset of the zip64 end of central directory record */
  104. buf += 8;
  105. putvalue(buf, 1, 4); /* total number of disks */
  106. buf += 4;
  107. return buf - oldbuf;
  108. }
  109. static int put_eoc_directory_record(uint8_t *buf, int record_num, uint64_t zip_centralheader_offset, int zip_centralheader_size)
  110. {
  111. uint8_t *oldbuf = buf;
  112. putvalue(buf, ENDOFCENTRALDIRMAGIC, 4);
  113. buf += 4;
  114. putvalue(buf, 0, 2); /* Number of this disk */
  115. buf += 2;
  116. putvalue(buf, 0, 2); /* Disk where central directory starts */
  117. buf += 2;
  118. putvalue(buf, record_num, 2); /* Number of central directory records on this disk */
  119. buf += 2;
  120. putvalue(buf, record_num, 2); /* Total number of central directory records */
  121. buf += 2;
  122. putvalue(buf, zip_centralheader_size, 4);
  123. buf += 4;
  124. putvalue(buf, 0xffffffff, 4);
  125. buf += 4;
  126. putvalue(buf, 0, 2); /* Comment length (n) */
  127. buf += 2;
  128. return buf - oldbuf;
  129. }
  130. static int put_localheader(uint8_t *buf, const char *filename, int level)
  131. {
  132. uint8_t *oldbuf = buf;
  133. putvalue(buf, LOCALHEADERMAGIC, 4);
  134. buf += 4;
  135. putvalue(buf, ZIPVERSION_NEEDED, 2);
  136. buf += 2;
  137. uint16_t flag = 0;
  138. if ((level==8) || (level == 9))
  139. flag |= 2;
  140. if ((level == 2))
  141. flag |= 4;
  142. if ((level == 1))
  143. flag |= 6;
  144. #if 0
  145. if (password != NULL)
  146. flag |= 1;
  147. #endif
  148. putvalue(buf, flag | 0x8, 2);
  149. buf += 2;
  150. putvalue(buf, Z_DEFLATED, 2);
  151. buf += 2;
  152. putvalue(buf,0UL, 4);
  153. buf += 4;
  154. // CRC / Compressed size / Uncompressed size will be filled in later and rewritten later
  155. putvalue(buf, 0UL, 4); /* crc 32, unknown */
  156. buf += 4;
  157. putvalue(buf, 0xFFFFFFFFUL, 4); /* compressed size, unknown */
  158. buf += 4;
  159. putvalue(buf, 0xFFFFFFFFUL, 4); /* uncompressed size, unknown */
  160. buf += 4;
  161. putvalue(buf, strlen(filename), 2); /* size of filename */
  162. buf += 2;
  163. putvalue(buf, 4 + 8 + 8, 2); /* size of extra field */
  164. buf += 2;
  165. memcpy(buf, filename, strlen(filename));
  166. buf += strlen(filename);
  167. /* ZIP64 extension */
  168. putvalue(buf, 0x0001, 2); /* ZIP64_EXTENSION */
  169. buf += 2;
  170. putvalue(buf, 8 + 8, 2);
  171. buf += 2;
  172. putvalue(buf, 0UL, 8);
  173. buf += 8;
  174. putvalue(buf, 0UL, 8);
  175. buf += 8;
  176. return buf - oldbuf;
  177. }
  178. static int put_centralheader(uint8_t *buf, const char *filename, int level, uint64_t zip_localheader_offset, uint64_t size, uint64_t uncomp_size, uint32_t crc32_value)
  179. {
  180. uint8_t *oldbuf = buf;
  181. putvalue(buf, CENTRALHEADERMAGIC, 4);
  182. buf += 4;
  183. putvalue(buf, ZIPVERSION_NEEDED, 2);
  184. buf += 2;
  185. putvalue(buf, ZIPVERSION_NEEDED, 2);
  186. buf += 2;
  187. uint16_t flag = 0;
  188. if ((level==8) || (level == 9))
  189. flag |= 2;
  190. if ((level == 2))
  191. flag |= 4;
  192. if ((level == 1))
  193. flag |= 6;
  194. #if 0
  195. if (password != NULL)
  196. flag |= 1;
  197. #endif
  198. putvalue(buf, flag | 0x8, 2);
  199. buf += 2;
  200. putvalue(buf, Z_DEFLATED, 2);
  201. buf += 2;
  202. putvalue(buf,0UL, 4);
  203. buf += 4;
  204. // CRC / Compressed size / Uncompressed size will be filled in later and rewritten later
  205. putvalue(buf, crc32_value, 4); /* crc 32 */
  206. buf += 4;
  207. putvalue(buf, 0xffffffffUL, 4); /* compressed size */
  208. buf += 4;
  209. putvalue(buf, 0xffffffffUL, 4); /* uncompressed size */
  210. buf += 4;
  211. putvalue(buf, strlen(filename), 2);
  212. buf += 2;
  213. putvalue(buf, 4 + 8 + 8 + 8, 2); /* size of extra field */
  214. buf += 2;
  215. putvalue(buf, 0UL, 2); /* size of comment field */
  216. buf += 2;
  217. putvalue(buf, 0UL, 2); /* disk number */
  218. buf += 2;
  219. putvalue(buf, 0UL, 2); /* internal attributes */
  220. buf += 2;
  221. putvalue(buf, 0UL, 4); /* external file attributes */
  222. buf += 4;
  223. putvalue(buf, 0xffffffffUL, 4); /* Relative offset */
  224. buf += 4;
  225. memcpy(buf, filename, strlen(filename));
  226. buf += strlen(filename);
  227. /* ZIP64 extension */
  228. putvalue(buf, 0x0001, 2); /* ZIP64_EXTENSION */
  229. buf += 2;
  230. putvalue(buf, 8 + 8 + 8, 2);
  231. buf += 2;
  232. putvalue(buf, uncomp_size, 8);
  233. buf += 8;
  234. putvalue(buf, size, 8);
  235. buf += 8;
  236. putvalue(buf, zip_localheader_offset, 8);
  237. buf += 8;
  238. return buf - oldbuf;
  239. }
  240. static int kzip_write_current(struct kzip_file *zfile, void *buf, int len)
  241. {
  242. KZIP_DEBUG("%s: write_cb %p len %d\n", __func__, zfile->write_cb, len);
  243. int retval = zfile->write_cb(zfile->handle, buf, len);
  244. if (retval > 0) {
  245. zfile->current_size += retval;
  246. }
  247. if ((zfile->current_size - zfile->reported_size) >= KDUMP_SIZE_REPORT) {
  248. vo_show_progress(zfile->current_size / 0x100000);
  249. zfile->reported_size = zfile->current_size;
  250. }
  251. if ((zfile->current_size - zfile->wdk_kick_size) >= KDUMP_TICK_WDT) {
  252. mtk_wdt_restart();
  253. zfile->wdk_kick_size = zfile->current_size;
  254. }
  255. return retval;
  256. }
  257. struct kzip_file *kzip_open(void *handle, int (*write_cb)(void *handle, void *p, int size))
  258. {
  259. struct kzip_file *zf = malloc(sizeof(struct kzip_file));
  260. if (zf == NULL) {
  261. KZIP_DEBUG("%s: No enough memory\n", __func__);
  262. return NULL;
  263. }
  264. memset(zf, 0, sizeof(struct kzip_file));
  265. zf->handle = handle;
  266. zf->write_cb = write_cb;
  267. KZIP_DEBUG("%s: handle zf %p %p write_cb %p\n", __func__, zf, zf->handle, zf->write_cb);
  268. vo_show_progress(0);
  269. return zf;
  270. }
  271. bool kzip_close(struct kzip_file *zf)
  272. {
  273. uint64_t central_header_offset = zf->current_size, zip64_eoc_offset;
  274. struct kzip_entry *zentries = zf->zentries;
  275. int num = zf->entries_num;
  276. int i, hsize = 0, local_hsize;
  277. uint8_t databuf[128];
  278. for (i = 0; i < num; i++) {
  279. local_hsize = put_centralheader(databuf, zentries[i].filename, zentries[i].level,
  280. zentries[i].localheader_offset,
  281. zentries[i].comp_size,
  282. zentries[i].uncomp_size,
  283. zentries[i].crc32);
  284. if (kzip_write_current(zf, databuf, local_hsize) != local_hsize) {
  285. goto error;
  286. }
  287. hsize += local_hsize;
  288. }
  289. voprintf_debug("%s: current_size %lld hoffset %lld\n", __func__, zf->current_size, central_header_offset);
  290. zip64_eoc_offset = zf->current_size;
  291. local_hsize = put_zip64_eoc_directory_record(databuf, num, central_header_offset, hsize);
  292. if ((local_hsize > 0) && (kzip_write_current(zf, databuf, local_hsize) != local_hsize)) {
  293. goto error;
  294. }
  295. local_hsize = put_zip64_eoc_directory_locator(databuf, zip64_eoc_offset);
  296. if ((local_hsize > 0) && (kzip_write_current(zf, databuf, local_hsize) != local_hsize)) {
  297. goto error;
  298. }
  299. local_hsize = put_eoc_directory_record(databuf, num, central_header_offset, hsize);
  300. if (kzip_write_current(zf, databuf, local_hsize) != local_hsize) {
  301. goto error;
  302. }
  303. free(zf);
  304. return true;
  305. error:
  306. free(zf);
  307. return false;
  308. }
  309. #define CHUNK 65536
  310. /* Compress from file source to file dest until EOF on source.
  311. def() returns Z_OK on success, Z_MEM_ERROR if memory could not be
  312. allocated for processing, Z_STREAM_ERROR if an invalid compression
  313. level is supplied, Z_VERSION_ERROR if the version of zlib.h and the
  314. version of the library linked do not match, or Z_ERRNO if there is
  315. an error reading or writing the files. */
  316. static bool kzip_add_file_no_mapped(struct kzip_file *zfile, const struct kzip_addlist *memlist,
  317. int *flush, int *ret, uint8_t *in, uint8_t *out,
  318. struct kzip_entry *zentry, z_stream *strm, struct aee_timer *zip_time)
  319. {
  320. uint64_t mem_size = memlist->size;
  321. uint8_t *memsrc = (uint8_t *)(uintptr_t)memlist->address;
  322. *flush = (memlist->size == 0) ? Z_FINISH : Z_NO_FLUSH;
  323. voprintf_debug("-- Compress memory %llx, size %llu\n",
  324. memlist->address, memlist->size);
  325. do {
  326. int in_size = mem_size > CHUNK ? CHUNK : mem_size;
  327. memcpy(in, memsrc, in_size);
  328. zentry->crc32 = crc32_no_comp(zentry->crc32, in, in_size);
  329. memsrc += in_size;
  330. mem_size -= in_size;
  331. strm->avail_in = in_size;
  332. strm->next_in = in;
  333. /* run deflate() on input until output buffer not full, finish
  334. compression if all of source has been read in */
  335. do {
  336. strm->avail_out = CHUNK;
  337. strm->next_out = out;
  338. *ret = deflate(strm, *flush); /* no bad return value */
  339. assert(*ret != Z_STREAM_ERROR); /* state not clobbered */
  340. int have = CHUNK - strm->avail_out;
  341. if (have > 0) {
  342. aee_timer_stop(zip_time);
  343. if (kzip_write_current(zfile, out, have) != have) {
  344. voprintf_debug("-- Compress memory %llx, error. surplus size: %u\n",
  345. memlist->address, mem_size);
  346. return false;
  347. }
  348. aee_timer_start(zip_time);
  349. }
  350. } while (strm->avail_out == 0);
  351. assert(strm->avail_in == 0); /* all input will be used */
  352. } while (mem_size > 0);
  353. voprintf_debug("-- Compress memory %llx, done. surplus size: %u\n",
  354. memlist->address, mem_size);
  355. return true;
  356. }
  357. #ifndef MTK_3LEVEL_PAGETABLE
  358. /* full mapping at LK, only one function is needed. kzip_add_file_no_mapped() */
  359. #define kzip_add_file_do_mapped kzip_add_file_no_mapped
  360. #else
  361. /* LPAE, map before accessing the address of memory */
  362. #define MAX_MAP_CNT (SECTION_SIZE/CHUNK)
  363. #define mapflags (MMU_MEMORY_TYPE_NORMAL_WRITE_BACK | MMU_MEMORY_AP_P_RW_U_NA)
  364. static bool kzip_add_file_do_mapped(struct kzip_file *zfile, const struct kzip_addlist *memlist,
  365. int *flush, int *ret, uint8_t *in, uint8_t *out,
  366. struct kzip_entry *zentry, z_stream *strm, struct aee_timer *zip_time)
  367. {
  368. /* multiple physical address mapped onto static 2MB address space. (scratch_addr) */
  369. int cnt = 0;
  370. uint64_t paddr = memlist->address;
  371. vaddr_t vaddr = ROUNDUP(scratch_addr(), SECTION_SIZE);
  372. voprintf_debug("-- map: paddr=0x%016llx, vaddr=0x%08x\n", paddr, vaddr);
  373. uint64_t mem_size = memlist->size;
  374. uint8_t *memsrc;
  375. *flush = (memlist->size == 0) ? Z_FINISH : Z_NO_FLUSH;
  376. voprintf_debug("-- Compress memory %llx, size %llu\n", memlist->address, memlist->size);
  377. do {
  378. /* arch_mmu_map by each 2MB size */
  379. if (cnt == 0) {
  380. int map_ok = arch_mmu_map(paddr, vaddr, mapflags, SECTION_SIZE);
  381. if (map_ok != NO_ERROR) {
  382. voprintf_debug("-- arch_mmu_map map error: map_ok=%d, paddr=0x%016llx, vaddr=0x%08x\n",
  383. map_ok, paddr, vaddr);
  384. return false;
  385. }
  386. memsrc = (uint8_t *)vaddr;
  387. }
  388. int in_size = mem_size > CHUNK ? CHUNK : mem_size;
  389. memcpy(in, memsrc, in_size);
  390. zentry->crc32 = crc32_no_comp(zentry->crc32, in, in_size);
  391. memsrc += in_size;
  392. mem_size -= in_size;
  393. strm->avail_in = in_size;
  394. strm->next_in = in;
  395. /* run deflate() on input until output buffer not full, finish
  396. compression if all of source has been read in */
  397. do {
  398. strm->avail_out = CHUNK;
  399. strm->next_out = out;
  400. *ret = deflate(strm, *flush); /* no bad return value */
  401. assert(*ret != Z_STREAM_ERROR); /* state not clobbered */
  402. int have = CHUNK - strm->avail_out;
  403. if (have > 0) {
  404. aee_timer_stop(zip_time);
  405. if (kzip_write_current(zfile, out, have) != have) {
  406. voprintf_debug("-- Compress memory %llx, error. surplus size: %u\n",
  407. memlist->address, mem_size);
  408. return false;
  409. }
  410. aee_timer_start(zip_time);
  411. }
  412. } while (strm->avail_out == 0);
  413. assert(strm->avail_in == 0); /* all input will be used */
  414. /* mod by 2MB (SECTION_SIZE) */
  415. cnt++;
  416. cnt %= MAX_MAP_CNT;
  417. if (cnt == 0)
  418. paddr += SECTION_SIZE;
  419. } while (mem_size > 0);
  420. voprintf_debug("-- Compress memory %llx, done. surplus size: %u\n", memlist->address, mem_size);
  421. return true;
  422. }
  423. #endif
  424. static bool kzip_add_file_from_expdb(struct kzip_file *zfile, const struct kzip_addlist *addlist,
  425. int *flush, int *ret, uint8_t *in, uint8_t *out,
  426. struct kzip_entry *zentry, z_stream *strm, struct aee_timer *zip_time)
  427. {
  428. uint64_t offset_src = addlist->address;
  429. int64_t mem_size = addlist->size;
  430. *flush = (addlist->size == 0) ? Z_FINISH : Z_NO_FLUSH;
  431. voprintf_debug("-- Compress expdb offset %llx, size %llu\n", offset_src, mem_size);
  432. do {
  433. /* read from expdb to memsrc */
  434. if (mem_size > CHUNK) {
  435. mrdump_read_expdb(in, CHUNK, offset_src);
  436. } else {
  437. mrdump_read_expdb(in, (int)mem_size, offset_src);
  438. }
  439. int in_size = mem_size > CHUNK ? CHUNK : mem_size;
  440. zentry->crc32 = crc32_no_comp(zentry->crc32, in, in_size);
  441. mem_size -= in_size;
  442. strm->avail_in = in_size;
  443. strm->next_in = in;
  444. /* run deflate() on input until output buffer not full, finish
  445. compression if all of source has been read in */
  446. do {
  447. strm->avail_out = CHUNK;
  448. strm->next_out = out;
  449. *ret = deflate(strm, *flush); /* no bad return value */
  450. assert(*ret != Z_STREAM_ERROR); /* state not clobbered */
  451. int have = CHUNK - strm->avail_out;
  452. if (have > 0) {
  453. aee_timer_stop(zip_time);
  454. if (kzip_write_current(zfile, out, have) != have) {
  455. voprintf_debug("-- Compress expdb offset %llx, error. surplus size: %u\n",
  456. offset_src, mem_size);
  457. return false;
  458. }
  459. aee_timer_start(zip_time);
  460. }
  461. } while (strm->avail_out == 0);
  462. assert(strm->avail_in == 0); /* all input will be used */
  463. offset_src += in_size;
  464. } while (mem_size > 0);
  465. voprintf_debug("-- Compress expdb offset %llx, done. surplus size: %u\n", offset_src, mem_size);
  466. return true;
  467. }
  468. bool kzip_add_file(struct kzip_file *zfile, const struct kzip_addlist *addlist, const char *zfilename)
  469. {
  470. int ret, flush;
  471. z_stream strm;
  472. struct aee_timer zip_time;
  473. if (zfile->entries_num >= KZIP_ENTRY_MAX) {
  474. voprintf_error("Too many zip entry %d\n", zfile->entries_num);
  475. return false;
  476. }
  477. voprintf_debug("%s: zf %p(%p) %s\n", __func__, zfile, zfile->write_cb, zfilename);
  478. struct kzip_entry *zentry = &zfile->zentries[zfile->entries_num++];
  479. zentry->filename = strdup(zfilename);
  480. zentry->localheader_offset = zfile->current_size;
  481. zentry->level = KDUMP_ZLIB_LEVEL;
  482. zentry->crc32 = 0xffffffffUL;
  483. KZIP_DEBUG("%s: write local header\n", __func__);
  484. uint8_t zip_localheader[128];
  485. int hsize = put_localheader(zip_localheader, zfilename, zentry->level);
  486. if (kzip_write_current(zfile, zip_localheader, hsize) != hsize) {
  487. return false;
  488. }
  489. KZIP_DEBUG("%s: init compressor\n", __func__);
  490. /* allocate deflate state */
  491. memset(&strm, 0, sizeof(z_stream));
  492. ret = deflateInit2(&strm, zentry->level, Z_DEFLATED, -MAX_WBITS, DEF_MEM_LEVEL, Z_DEFAULT_STRATEGY);
  493. if (ret != Z_OK) {
  494. voprintf_error("zlib compress init failed\n");
  495. return false;
  496. }
  497. uint64_t start = zfile->current_size, uncomp_size = 0;
  498. uint8_t *out = malloc(CHUNK);
  499. uint8_t *in = malloc(CHUNK);
  500. if ((out == NULL) || (in == NULL)) {
  501. voprintf_error("%s: malloc failed in %p out %p.\n", __func__, in, out);
  502. goto error;
  503. }
  504. aee_timer_init(&zip_time);
  505. aee_timer_start(&zip_time);
  506. do {
  507. switch (addlist->type) {
  508. case MEM_NO_MAP:
  509. if (kzip_add_file_no_mapped(zfile, addlist, &flush, &ret, in, out, zentry, &strm, &zip_time) == false)
  510. goto error;
  511. break;
  512. case MEM_DO_MAP:
  513. if (kzip_add_file_do_mapped(zfile, addlist, &flush, &ret, in, out, zentry, &strm, &zip_time) == false)
  514. goto error;
  515. break;
  516. case EXPDB_FILE:
  517. if (kzip_add_file_from_expdb(zfile, addlist, &flush, &ret, in, out, zentry, &strm, &zip_time) == false)
  518. goto error;
  519. break;
  520. default:
  521. goto error;
  522. break;
  523. }
  524. uncomp_size += addlist->size;
  525. addlist++;
  526. /* done when last data in file processed */
  527. } while (flush != Z_FINISH);
  528. assert(ret == Z_STREAM_END); /* stream will be complete */
  529. aee_timer_stop(&zip_time);
  530. voprintf_info("Zip time: %d sec\n", zip_time.acc_ms / 1000);
  531. zentry->comp_size = zfile->current_size - start;
  532. zentry->uncomp_size = uncomp_size;
  533. zentry->crc32 = zentry->crc32 ^ 0xffffffffUL;
  534. deflateEnd(&strm);
  535. free(out);
  536. free(in);
  537. return true;
  538. error:
  539. free(out);
  540. free(in);
  541. deflateEnd(&strm);
  542. return false;
  543. }