mrdump_zip.c 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690
  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 char zero_page[PAGE_SIZE] __attribute__((aligned(PAGE_SIZE))) = {0};
  55. static void putvalue(void* dest, uint64_t x, int nbByte)
  56. {
  57. uint8_t *buf = (uint8_t *)dest;
  58. int n;
  59. for (n = 0; n < nbByte; n++) {
  60. buf[n] = (unsigned char)(x & 0xff);
  61. x >>= 8;
  62. }
  63. #if 0
  64. if (x != 0) {
  65. /* data overflow - hack for ZIP64 */
  66. for (n = 0; n < nbByte; n++) {
  67. buf[n] = 0xff;
  68. }
  69. }
  70. #endif
  71. }
  72. static int put_zip64_eoc_directory_record(uint8_t *buf, int record_num, uint64_t zip_centralheader_offset, int zip_centralheader_size)
  73. {
  74. uint8_t *oldbuf = buf;
  75. putvalue(buf, ZIP64ENDOFCENTRALDIRMAGIC, 4);
  76. buf += 4;
  77. putvalue(buf, 44, 8); /* zip64 eoc size */
  78. buf += 8;
  79. putvalue(buf, ZIPVERSION_NEEDED, 2); /* version made by */
  80. buf += 2;
  81. putvalue(buf, ZIPVERSION_NEEDED, 2); /* version needed to extract */
  82. buf += 2;
  83. putvalue(buf, 0, 4); /* number of this disk */
  84. buf += 4;
  85. putvalue(buf, 0, 4); /* number of the disk with the start of the central directory */
  86. buf += 4;
  87. putvalue(buf, record_num, 8); /* total number of entries in the central directory on this disk */
  88. buf += 8;
  89. putvalue(buf, record_num, 8); /* total number of entries in the central directory */
  90. buf += 8;
  91. putvalue(buf, zip_centralheader_size, 8); /* size of the central directory */
  92. buf += 8;
  93. putvalue(buf, zip_centralheader_offset, 8); /* offset of start of central directory with respect to the starting disk number */
  94. buf += 8;
  95. return buf - oldbuf;
  96. }
  97. static int put_zip64_eoc_directory_locator(uint8_t *buf, uint64_t zip64_eoc_offset)
  98. {
  99. uint8_t *oldbuf = buf;
  100. putvalue(buf, ZIP64ENDOFCENTRALDIRLOCATORMAGIC, 4);
  101. buf += 4;
  102. putvalue(buf, 0, 4); /* number of the disk with the start of the zip64 end of central directory */
  103. buf += 4;
  104. putvalue(buf, zip64_eoc_offset, 8); /* relative offset of the zip64 end of central directory record */
  105. buf += 8;
  106. putvalue(buf, 1, 4); /* total number of disks */
  107. buf += 4;
  108. return buf - oldbuf;
  109. }
  110. static int put_eoc_directory_record(uint8_t *buf, int record_num, uint64_t zip_centralheader_offset, int zip_centralheader_size)
  111. {
  112. uint8_t *oldbuf = buf;
  113. putvalue(buf, ENDOFCENTRALDIRMAGIC, 4);
  114. buf += 4;
  115. putvalue(buf, 0, 2); /* Number of this disk */
  116. buf += 2;
  117. putvalue(buf, 0, 2); /* Disk where central directory starts */
  118. buf += 2;
  119. putvalue(buf, record_num, 2); /* Number of central directory records on this disk */
  120. buf += 2;
  121. putvalue(buf, record_num, 2); /* Total number of central directory records */
  122. buf += 2;
  123. putvalue(buf, zip_centralheader_size, 4);
  124. buf += 4;
  125. putvalue(buf, 0xffffffff, 4);
  126. buf += 4;
  127. putvalue(buf, 0, 2); /* Comment length (n) */
  128. buf += 2;
  129. return buf - oldbuf;
  130. }
  131. static int put_localheader(uint8_t *buf, const char *filename, int level)
  132. {
  133. uint8_t *oldbuf = buf;
  134. putvalue(buf, LOCALHEADERMAGIC, 4);
  135. buf += 4;
  136. putvalue(buf, ZIPVERSION_NEEDED, 2);
  137. buf += 2;
  138. uint16_t flag = 0;
  139. if ((level==8) || (level == 9))
  140. flag |= 2;
  141. if ((level == 2))
  142. flag |= 4;
  143. if ((level == 1))
  144. flag |= 6;
  145. #if 0
  146. if (password != NULL)
  147. flag |= 1;
  148. #endif
  149. putvalue(buf, flag | 0x8, 2);
  150. buf += 2;
  151. putvalue(buf, Z_DEFLATED, 2);
  152. buf += 2;
  153. putvalue(buf,0UL, 4);
  154. buf += 4;
  155. // CRC / Compressed size / Uncompressed size will be filled in later and rewritten later
  156. putvalue(buf, 0UL, 4); /* crc 32, unknown */
  157. buf += 4;
  158. putvalue(buf, 0xFFFFFFFFUL, 4); /* compressed size, unknown */
  159. buf += 4;
  160. putvalue(buf, 0xFFFFFFFFUL, 4); /* uncompressed size, unknown */
  161. buf += 4;
  162. putvalue(buf, strlen(filename), 2); /* size of filename */
  163. buf += 2;
  164. putvalue(buf, 4 + 8 + 8, 2); /* size of extra field */
  165. buf += 2;
  166. memcpy(buf, filename, strlen(filename));
  167. buf += strlen(filename);
  168. /* ZIP64 extension */
  169. putvalue(buf, 0x0001, 2); /* ZIP64_EXTENSION */
  170. buf += 2;
  171. putvalue(buf, 8 + 8, 2);
  172. buf += 2;
  173. putvalue(buf, 0UL, 8);
  174. buf += 8;
  175. putvalue(buf, 0UL, 8);
  176. buf += 8;
  177. return buf - oldbuf;
  178. }
  179. 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)
  180. {
  181. uint8_t *oldbuf = buf;
  182. putvalue(buf, CENTRALHEADERMAGIC, 4);
  183. buf += 4;
  184. putvalue(buf, ZIPVERSION_NEEDED, 2);
  185. buf += 2;
  186. putvalue(buf, ZIPVERSION_NEEDED, 2);
  187. buf += 2;
  188. uint16_t flag = 0;
  189. if ((level==8) || (level == 9))
  190. flag |= 2;
  191. if ((level == 2))
  192. flag |= 4;
  193. if ((level == 1))
  194. flag |= 6;
  195. #if 0
  196. if (password != NULL)
  197. flag |= 1;
  198. #endif
  199. putvalue(buf, flag | 0x8, 2);
  200. buf += 2;
  201. putvalue(buf, Z_DEFLATED, 2);
  202. buf += 2;
  203. putvalue(buf,0UL, 4);
  204. buf += 4;
  205. // CRC / Compressed size / Uncompressed size will be filled in later and rewritten later
  206. putvalue(buf, crc32_value, 4); /* crc 32 */
  207. buf += 4;
  208. putvalue(buf, 0xffffffffUL, 4); /* compressed size */
  209. buf += 4;
  210. putvalue(buf, 0xffffffffUL, 4); /* uncompressed size */
  211. buf += 4;
  212. putvalue(buf, strlen(filename), 2);
  213. buf += 2;
  214. putvalue(buf, 4 + 8 + 8 + 8, 2); /* size of extra field */
  215. buf += 2;
  216. putvalue(buf, 0UL, 2); /* size of comment field */
  217. buf += 2;
  218. putvalue(buf, 0UL, 2); /* disk number */
  219. buf += 2;
  220. putvalue(buf, 0UL, 2); /* internal attributes */
  221. buf += 2;
  222. putvalue(buf, 0UL, 4); /* external file attributes */
  223. buf += 4;
  224. putvalue(buf, 0xffffffffUL, 4); /* Relative offset */
  225. buf += 4;
  226. memcpy(buf, filename, strlen(filename));
  227. buf += strlen(filename);
  228. /* ZIP64 extension */
  229. putvalue(buf, 0x0001, 2); /* ZIP64_EXTENSION */
  230. buf += 2;
  231. putvalue(buf, 8 + 8 + 8, 2);
  232. buf += 2;
  233. putvalue(buf, uncomp_size, 8);
  234. buf += 8;
  235. putvalue(buf, size, 8);
  236. buf += 8;
  237. putvalue(buf, zip_localheader_offset, 8);
  238. buf += 8;
  239. return buf - oldbuf;
  240. }
  241. static int kzip_write_current(struct kzip_file *zfile, void *buf, int len)
  242. {
  243. KZIP_DEBUG("%s: write_cb %p len %d\n", __func__, zfile->write_cb, len);
  244. int retval = zfile->write_cb(zfile->handle, buf, len);
  245. if (retval > 0) {
  246. zfile->current_size += retval;
  247. }
  248. if ((zfile->current_size - zfile->reported_size) >= KDUMP_SIZE_REPORT) {
  249. vo_show_progress(zfile->current_size / 0x100000);
  250. zfile->reported_size = zfile->current_size;
  251. }
  252. if ((zfile->current_size - zfile->wdk_kick_size) >= KDUMP_TICK_WDT) {
  253. mtk_wdt_restart();
  254. zfile->wdk_kick_size = zfile->current_size;
  255. }
  256. return retval;
  257. }
  258. struct kzip_file *kzip_open(void *handle, int (*write_cb)(void *handle, void *p, int size))
  259. {
  260. struct kzip_file *zf = malloc(sizeof(struct kzip_file));
  261. if (zf == NULL) {
  262. KZIP_DEBUG("%s: No enough memory\n", __func__);
  263. return NULL;
  264. }
  265. memset(zf, 0, sizeof(struct kzip_file));
  266. zf->handle = handle;
  267. zf->write_cb = write_cb;
  268. KZIP_DEBUG("%s: handle zf %p %p write_cb %p\n", __func__, zf, zf->handle, zf->write_cb);
  269. vo_show_progress(0);
  270. return zf;
  271. }
  272. bool kzip_close(struct kzip_file *zf)
  273. {
  274. uint64_t central_header_offset = zf->current_size, zip64_eoc_offset;
  275. struct kzip_entry *zentries = zf->zentries;
  276. int num = zf->entries_num;
  277. int i, hsize = 0, local_hsize;
  278. uint8_t databuf[128];
  279. for (i = 0; i < num; i++) {
  280. local_hsize = put_centralheader(databuf, zentries[i].filename, zentries[i].level,
  281. zentries[i].localheader_offset,
  282. zentries[i].comp_size,
  283. zentries[i].uncomp_size,
  284. zentries[i].crc32);
  285. if (kzip_write_current(zf, databuf, local_hsize) != local_hsize) {
  286. goto error;
  287. }
  288. hsize += local_hsize;
  289. }
  290. voprintf_debug("%s: current_size %lld hoffset %lld\n", __func__, zf->current_size, central_header_offset);
  291. zip64_eoc_offset = zf->current_size;
  292. local_hsize = put_zip64_eoc_directory_record(databuf, num, central_header_offset, hsize);
  293. if ((local_hsize > 0) && (kzip_write_current(zf, databuf, local_hsize) != local_hsize)) {
  294. goto error;
  295. }
  296. local_hsize = put_zip64_eoc_directory_locator(databuf, zip64_eoc_offset);
  297. if ((local_hsize > 0) && (kzip_write_current(zf, databuf, local_hsize) != local_hsize)) {
  298. goto error;
  299. }
  300. local_hsize = put_eoc_directory_record(databuf, num, central_header_offset, hsize);
  301. if (kzip_write_current(zf, databuf, local_hsize) != local_hsize) {
  302. goto error;
  303. }
  304. free(zf);
  305. return true;
  306. error:
  307. free(zf);
  308. return false;
  309. }
  310. #define CHUNK 65536
  311. /* Compress from file source to file dest until EOF on source.
  312. def() returns Z_OK on success, Z_MEM_ERROR if memory could not be
  313. allocated for processing, Z_STREAM_ERROR if an invalid compression
  314. level is supplied, Z_VERSION_ERROR if the version of zlib.h and the
  315. version of the library linked do not match, or Z_ERRNO if there is
  316. an error reading or writing the files. */
  317. static bool kzip_add_file_no_mapped(struct kzip_file *zfile, const struct kzip_addlist *memlist,
  318. int *flush, int *ret, uint8_t *in, uint8_t *out,
  319. struct kzip_entry *zentry, z_stream *strm, struct aee_timer *zip_time)
  320. {
  321. uint64_t mem_size = memlist->size;
  322. uint8_t *memsrc = (uint8_t *)(uintptr_t)memlist->address;
  323. *flush = (memlist->size == 0) ? Z_FINISH : Z_NO_FLUSH;
  324. voprintf_debug("-- Compress memory %llx, size %llu\n",
  325. memlist->address, memlist->size);
  326. do {
  327. int in_size = mem_size > CHUNK ? CHUNK : mem_size;
  328. memcpy(in, memsrc, in_size);
  329. zentry->crc32 = crc32_no_comp(zentry->crc32, in, in_size);
  330. memsrc += in_size;
  331. mem_size -= in_size;
  332. strm->avail_in = in_size;
  333. strm->next_in = in;
  334. /* run deflate() on input until output buffer not full, finish
  335. compression if all of source has been read in */
  336. do {
  337. strm->avail_out = CHUNK;
  338. strm->next_out = out;
  339. *ret = deflate(strm, *flush); /* no bad return value */
  340. assert(*ret != Z_STREAM_ERROR); /* state not clobbered */
  341. int have = CHUNK - strm->avail_out;
  342. if (have > 0) {
  343. aee_timer_stop(zip_time);
  344. if (kzip_write_current(zfile, out, have) != have) {
  345. voprintf_debug("-- Compress memory %llx, error. surplus size: %u\n",
  346. memlist->address, mem_size);
  347. return false;
  348. }
  349. aee_timer_start(zip_time);
  350. }
  351. } while (strm->avail_out == 0);
  352. assert(strm->avail_in == 0); /* all input will be used */
  353. } while (mem_size > 0);
  354. voprintf_debug("-- Compress memory %llx, done. surplus size: %u\n",
  355. memlist->address, mem_size);
  356. return true;
  357. }
  358. #ifndef MTK_3LEVEL_PAGETABLE
  359. /* full mapping at LK, only one function is needed. kzip_add_file_no_mapped() */
  360. #define kzip_add_file_do_mapped kzip_add_file_no_mapped
  361. #else
  362. /* LPAE, map before accessing the address of memory */
  363. #define MAX_MAP_CNT (SECTION_SIZE/CHUNK)
  364. #define mapflags (MMU_MEMORY_TYPE_NORMAL_WRITE_BACK | MMU_MEMORY_AP_P_RW_U_NA)
  365. extern uint64_t v2p_64(uint64_t vptr);
  366. long mrdump_mem_map(const struct kzip_addlist *memlist,
  367. uint64_t paddr, vaddr_t vaddr, unsigned long sz, uint64_t zero_pa)
  368. {
  369. uint64_t memmap = memlist->memmap;
  370. uint64_t pageflags = memlist->pageflags;
  371. uint32_t struct_page_size = memlist->struct_page_size;
  372. long i, memmap_sz = sz / PAGE_SIZE * struct_page_size, invalid_cnt = 0, offset;
  373. vaddr_t page_start;
  374. uint64_t pa;
  375. /* map memmap */
  376. memmap += paddr / PAGE_SIZE * struct_page_size;
  377. offset = (long)memmap&(PAGE_SIZE - 1);
  378. page_start = vaddr + sz + offset; /* page struct map to vaddr + sz!!! */
  379. for (i = -offset; i < memmap_sz; i += PAGE_SIZE) {
  380. pa = v2p_64(memmap + i);
  381. if (pa < DRAM_PHY_ADDR
  382. || arch_mmu_map(pa, page_start + i, mapflags, PAGE_SIZE) != NO_ERROR) {
  383. paddr = pa;
  384. vaddr = page_start - offset + i;
  385. goto fail;
  386. }
  387. }
  388. /* map DDR according memmap flag */
  389. for (i = 0; i < memmap_sz; i += struct_page_size, vaddr += PAGE_SIZE, paddr += PAGE_SIZE) {
  390. if (*(uint64_t *)(page_start + i)&pageflags) {
  391. if (arch_mmu_map(zero_pa, vaddr, mapflags, PAGE_SIZE) == NO_ERROR) {
  392. invalid_cnt++;
  393. continue;
  394. }
  395. }
  396. if (arch_mmu_map(paddr, vaddr, mapflags, PAGE_SIZE) != NO_ERROR)
  397. goto fail;
  398. }
  399. return invalid_cnt;
  400. fail:
  401. voprintf_debug("map error: paddr=0x%016llx, vaddr=0x%08x, zero_pa=0x%016llx\n", paddr, vaddr, zero_pa);
  402. return -1;
  403. }
  404. static bool is_linux_kernel_memory_dump(const struct kzip_addlist *addlist)
  405. {
  406. uint64_t memmap = addlist->memmap;
  407. uint64_t pageflags = addlist->pageflags;
  408. uint32_t struct_page_size = addlist->struct_page_size;
  409. char dump_type[32] = {0};
  410. if (mrdump_get_env(MRDUMP_DUMP_TYPE, dump_type, sizeof(dump_type))) {
  411. return false;
  412. }
  413. if (strcmp(dump_type, MRDUMP_LINUX_KERNEL_MEMORY) == 0) {
  414. if ((memmap > 0) && (pageflags > 0) && (struct_page_size > 0)) {
  415. voprintf_debug("dump_linux_kernel_memory = 1, memmap(0x%llx), pageflags(0x%llx), struct_page_size(0x%x)\n",
  416. memmap, pageflags, struct_page_size);
  417. return true;
  418. }
  419. }
  420. voprintf_debug("dump_linux_kernel_memory = 0, memmap(0x%llx), pageflags(0x%llx), struct_page_size(0x%x)\n",
  421. memmap, pageflags, struct_page_size);
  422. return false;
  423. }
  424. static bool kzip_add_file_do_mapped(struct kzip_file *zfile, const struct kzip_addlist *memlist,
  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. /* multiple physical address mapped onto static 2MB address space. (scratch_addr) */
  429. int cnt = 0;
  430. uint64_t paddr = memlist->address;
  431. long invalid_cnt = -1, tot_invalid_cnt = 0;
  432. vaddr_t vaddr = ROUNDUP(scratch_addr(), SECTION_SIZE);
  433. voprintf_debug("-- map: paddr=0x%016llx, vaddr=0x%08x, zero_page=%p\n", paddr, vaddr, zero_page);
  434. uint64_t mem_size = memlist->size;
  435. uint8_t *memsrc;
  436. *flush = (memlist->size == 0) ? Z_FINISH : Z_NO_FLUSH;
  437. voprintf_debug("-- Compress memory %llx, size %llu\n", memlist->address, memlist->size);
  438. bool dump_linux_kernel_memory = is_linux_kernel_memory_dump(memlist);
  439. do {
  440. /* arch_mmu_map by each 2MB size */
  441. if (cnt == 0) {
  442. if (dump_linux_kernel_memory)
  443. invalid_cnt = mrdump_mem_map(memlist, paddr, vaddr, SECTION_SIZE, v2p_64((uint64_t)(uintptr_t)zero_page));
  444. if (invalid_cnt >= 0) {
  445. tot_invalid_cnt += invalid_cnt;
  446. } else {
  447. int map_ok = arch_mmu_map(paddr, vaddr, mapflags, SECTION_SIZE);
  448. if (map_ok != NO_ERROR) {
  449. voprintf_debug("-- arch_mmu_map map error: map_ok=%d, paddr=0x%016llx, vaddr=0x%08x\n",
  450. map_ok, paddr, vaddr);
  451. return false;
  452. }
  453. }
  454. memsrc = (uint8_t *)vaddr;
  455. }
  456. int in_size = mem_size > CHUNK ? CHUNK : mem_size;
  457. memcpy(in, memsrc, in_size);
  458. zentry->crc32 = crc32_no_comp(zentry->crc32, in, in_size);
  459. memsrc += in_size;
  460. mem_size -= in_size;
  461. strm->avail_in = in_size;
  462. strm->next_in = in;
  463. /* run deflate() on input until output buffer not full, finish
  464. compression if all of source has been read in */
  465. do {
  466. strm->avail_out = CHUNK;
  467. strm->next_out = out;
  468. *ret = deflate(strm, *flush); /* no bad return value */
  469. assert(*ret != Z_STREAM_ERROR); /* state not clobbered */
  470. int have = CHUNK - strm->avail_out;
  471. if (have > 0) {
  472. aee_timer_stop(zip_time);
  473. if (kzip_write_current(zfile, out, have) != have) {
  474. voprintf_debug("-- Compress memory %llx, error. surplus size: %u\n",
  475. memlist->address, mem_size);
  476. return false;
  477. }
  478. aee_timer_start(zip_time);
  479. }
  480. } while (strm->avail_out == 0);
  481. assert(strm->avail_in == 0); /* all input will be used */
  482. /* mod by 2MB (SECTION_SIZE) */
  483. cnt++;
  484. cnt %= MAX_MAP_CNT;
  485. if (cnt == 0)
  486. paddr += SECTION_SIZE;
  487. } while (mem_size > 0);
  488. voprintf_debug("-- Compress memory %llx, done. surplus size: %lld, ignore: %dMB\n", memlist->address, mem_size, tot_invalid_cnt * 4 / 1024);
  489. return true;
  490. }
  491. #endif
  492. static bool kzip_add_file_from_expdb(struct kzip_file *zfile, const struct kzip_addlist *addlist,
  493. int *flush, int *ret, uint8_t *in, uint8_t *out,
  494. struct kzip_entry *zentry, z_stream *strm, struct aee_timer *zip_time)
  495. {
  496. uint64_t offset_src = addlist->address;
  497. int64_t mem_size = addlist->size;
  498. *flush = (addlist->size == 0) ? Z_FINISH : Z_NO_FLUSH;
  499. voprintf_debug("-- Compress expdb offset %llx, size %llu\n", offset_src, mem_size);
  500. do {
  501. /* read from expdb to memsrc */
  502. if (mem_size > CHUNK) {
  503. mrdump_read_expdb(in, CHUNK, offset_src);
  504. } else {
  505. mrdump_read_expdb(in, (int)mem_size, offset_src);
  506. }
  507. int in_size = mem_size > CHUNK ? CHUNK : mem_size;
  508. zentry->crc32 = crc32_no_comp(zentry->crc32, in, in_size);
  509. mem_size -= in_size;
  510. strm->avail_in = in_size;
  511. strm->next_in = in;
  512. /* run deflate() on input until output buffer not full, finish
  513. compression if all of source has been read in */
  514. do {
  515. strm->avail_out = CHUNK;
  516. strm->next_out = out;
  517. *ret = deflate(strm, *flush); /* no bad return value */
  518. assert(*ret != Z_STREAM_ERROR); /* state not clobbered */
  519. int have = CHUNK - strm->avail_out;
  520. if (have > 0) {
  521. aee_timer_stop(zip_time);
  522. if (kzip_write_current(zfile, out, have) != have) {
  523. voprintf_debug("-- Compress expdb offset %llx, error. surplus size: %u\n",
  524. offset_src, mem_size);
  525. return false;
  526. }
  527. aee_timer_start(zip_time);
  528. }
  529. } while (strm->avail_out == 0);
  530. assert(strm->avail_in == 0); /* all input will be used */
  531. offset_src += in_size;
  532. } while (mem_size > 0);
  533. voprintf_debug("-- Compress expdb offset %llx, done. surplus size: %u\n", offset_src, mem_size);
  534. return true;
  535. }
  536. bool kzip_add_file(struct kzip_file *zfile, const struct kzip_addlist *addlist, const char *zfilename)
  537. {
  538. int ret, flush;
  539. z_stream strm;
  540. struct aee_timer zip_time;
  541. if (zfile->entries_num >= KZIP_ENTRY_MAX) {
  542. voprintf_error("Too many zip entry %d\n", zfile->entries_num);
  543. return false;
  544. }
  545. voprintf_debug("%s: zf %p(%p) %s\n", __func__, zfile, zfile->write_cb, zfilename);
  546. struct kzip_entry *zentry = &zfile->zentries[zfile->entries_num++];
  547. zentry->filename = strdup(zfilename);
  548. zentry->localheader_offset = zfile->current_size;
  549. zentry->level = KDUMP_ZLIB_LEVEL;
  550. zentry->crc32 = 0xffffffffUL;
  551. KZIP_DEBUG("%s: write local header\n", __func__);
  552. uint8_t zip_localheader[128];
  553. int hsize = put_localheader(zip_localheader, zfilename, zentry->level);
  554. if (kzip_write_current(zfile, zip_localheader, hsize) != hsize) {
  555. return false;
  556. }
  557. KZIP_DEBUG("%s: init compressor\n", __func__);
  558. /* allocate deflate state */
  559. memset(&strm, 0, sizeof(z_stream));
  560. ret = deflateInit2(&strm, zentry->level, Z_DEFLATED, -MAX_WBITS, DEF_MEM_LEVEL, Z_DEFAULT_STRATEGY);
  561. if (ret != Z_OK) {
  562. voprintf_error("zlib compress init failed\n");
  563. return false;
  564. }
  565. uint64_t start = zfile->current_size, uncomp_size = 0;
  566. uint8_t *out = malloc(CHUNK);
  567. uint8_t *in = malloc(CHUNK);
  568. if ((out == NULL) || (in == NULL)) {
  569. voprintf_error("%s: malloc failed in %p out %p.\n", __func__, in, out);
  570. goto error;
  571. }
  572. aee_timer_init(&zip_time);
  573. aee_timer_start(&zip_time);
  574. do {
  575. switch (addlist->type) {
  576. case MEM_NO_MAP:
  577. if (kzip_add_file_no_mapped(zfile, addlist, &flush, &ret, in, out, zentry, &strm, &zip_time) == false)
  578. goto error;
  579. break;
  580. case MEM_DO_MAP:
  581. if (kzip_add_file_do_mapped(zfile, addlist, &flush, &ret, in, out, zentry, &strm, &zip_time) == false)
  582. goto error;
  583. break;
  584. case EXPDB_FILE:
  585. if (kzip_add_file_from_expdb(zfile, addlist, &flush, &ret, in, out, zentry, &strm, &zip_time) == false)
  586. goto error;
  587. break;
  588. default:
  589. goto error;
  590. break;
  591. }
  592. uncomp_size += addlist->size;
  593. addlist++;
  594. /* done when last data in file processed */
  595. } while (flush != Z_FINISH);
  596. assert(ret == Z_STREAM_END); /* stream will be complete */
  597. aee_timer_stop(&zip_time);
  598. voprintf_info("Zip time: %d sec\n", zip_time.acc_ms / 1000);
  599. zentry->comp_size = zfile->current_size - start;
  600. zentry->uncomp_size = uncomp_size;
  601. zentry->crc32 = zentry->crc32 ^ 0xffffffffUL;
  602. deflateEnd(&strm);
  603. free(out);
  604. free(in);
  605. return true;
  606. error:
  607. free(out);
  608. free(in);
  609. deflateEnd(&strm);
  610. return false;
  611. }