[Feature]add MT2731_MP2_MR2_SVN388 baseline version

Change-Id: Ief04314834b31e27effab435d3ca8ba33b499059
diff --git a/src/bsp/lk/lib/aee/kdump_zip.c b/src/bsp/lk/lib/aee/kdump_zip.c
new file mode 100644
index 0000000..70ffdbe
--- /dev/null
+++ b/src/bsp/lk/lib/aee/kdump_zip.c
@@ -0,0 +1,604 @@
+/*
+ * Copyright (c) 2018 MediaTek Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files
+ * (the "Software"), to deal in the Software without restriction,
+ * including without limitation the rights to use, copy, modify, merge,
+ * publish, distribute, sublicense, and/or sell copies of the Software,
+ * and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#include <aee.h>
+#include <assert.h>
+#include <kdump.h>
+#include <lib/mempool.h>
+#include <lib/zlib.h>
+#include <lib/zutil.h>
+#include <malloc.h>
+#include <platform.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <string.h>
+#include "lib/cksum.h"
+
+#ifdef MTK_3LEVEL_PAGETABLE
+#include <stdlib.h>
+#include <err.h>
+#endif
+
+#define KZIP_DEBUG(x...)
+
+#define KDUMP_SIZE_REPORT 0x1000000
+#define KDUMP_TICK_WDT 0x10000
+
+#ifdef MRDUMP_USB_DUMP_NO_COMPRESSION
+#define KDUMP_ZLIB_LEVEL Z_NO_COMPRESSION
+#else
+#define KDUMP_ZLIB_LEVEL Z_BEST_SPEED
+#endif
+
+#define ZIPVERSION_NEEDED 45UL
+
+static void putvalue(void *dest, uint64_t x, int nbByte)
+{
+    uint8_t *buf = (uint8_t *)dest;
+    int n;
+    for (n = 0; n < nbByte; n++) {
+        buf[n] = (unsigned char)(x & 0xff);
+        x >>= 8;
+    }
+#if 0
+    if (x != 0) {
+        /* data overflow - hack for ZIP64 */
+        for (n = 0; n < nbByte; n++) {
+            buf[n] = 0xff;
+        }
+    }
+#endif
+}
+
+static int put_zip64_eoc_directory_record(uint8_t *buf, int record_num, uint64_t zip_centralheader_offset, int zip_centralheader_size)
+{
+    uint8_t *oldbuf = buf;
+    putvalue(buf, ZIP64ENDOFCENTRALDIRMAGIC, 4);
+    buf += 4;
+    putvalue(buf, 44, 8); /* zip64 eoc size */
+    buf += 8;
+    putvalue(buf, ZIPVERSION_NEEDED, 2); /* version made by */
+    buf += 2;
+    putvalue(buf, ZIPVERSION_NEEDED, 2); /* version needed to extract */
+    buf += 2;
+    putvalue(buf, 0, 4); /* number of this disk */
+    buf += 4;
+    putvalue(buf, 0, 4); /* number of the disk with the start of the central directory */
+    buf += 4;
+    putvalue(buf, record_num, 8); /* total number of entries in the central directory on this disk */
+    buf += 8;
+    putvalue(buf, record_num, 8); /* total number of entries in the central directory */
+    buf += 8;
+    putvalue(buf, zip_centralheader_size, 8); /* size of the central directory */
+    buf += 8;
+    putvalue(buf, zip_centralheader_offset, 8); /* offset of start of central directory with respect to the starting disk number */
+    buf += 8;
+    return buf - oldbuf;
+}
+
+static int put_zip64_eoc_directory_locator(uint8_t *buf, uint64_t zip64_eoc_offset)
+{
+    uint8_t *oldbuf = buf;
+    putvalue(buf, ZIP64ENDOFCENTRALDIRLOCATORMAGIC, 4);
+    buf += 4;
+    putvalue(buf, 0, 4); /* number of the disk with the start of the zip64 end of central directory */
+    buf += 4;
+    putvalue(buf, zip64_eoc_offset, 8); /* relative offset of the zip64 end of central directory record */
+    buf += 8;
+    putvalue(buf, 1, 4); /* total number of disks */
+    buf += 4;
+    return buf - oldbuf;
+}
+
+static int put_eoc_directory_record(uint8_t *buf, int record_num, uint64_t zip_centralheader_offset, int zip_centralheader_size)
+{
+    uint8_t *oldbuf = buf;
+    putvalue(buf, ENDOFCENTRALDIRMAGIC, 4);
+    buf += 4;
+    putvalue(buf, 0, 2); /* Number of this disk */
+    buf += 2;
+    putvalue(buf, 0, 2); /* Disk where central directory starts */
+    buf += 2;
+    putvalue(buf, record_num, 2); /* Number of central directory records on this disk */
+    buf += 2;
+    putvalue(buf, record_num, 2); /* Total number of central directory records */
+    buf += 2;
+    putvalue(buf, zip_centralheader_size, 4);
+    buf += 4;
+    putvalue(buf, 0xffffffff, 4);
+    buf += 4;
+    putvalue(buf, 0, 2); /* Comment length (n) */
+    buf += 2;
+    return buf - oldbuf;
+}
+
+static int put_localheader(uint8_t *buf, const char *filename, int level)
+{
+    uint8_t *oldbuf = buf;
+    putvalue(buf, LOCALHEADERMAGIC, 4);
+    buf += 4;
+    putvalue(buf, ZIPVERSION_NEEDED, 2);
+    buf += 2;
+
+    uint16_t flag = 0;
+    if ((level==8) || (level == 9))
+        flag |= 2;
+    if (level == 2)
+        flag |= 4;
+    if (level == 1)
+        flag |= 6;
+#if 0
+    if (password != NULL)
+        flag |= 1;
+#endif
+
+    putvalue(buf, flag | 0x8, 2);
+    buf += 2;
+
+    putvalue(buf, Z_DEFLATED, 2);
+    buf += 2;
+
+    putvalue(buf,0UL, 4);
+    buf += 4;
+
+    // CRC / Compressed size / Uncompressed size will be filled in later and rewritten later
+    putvalue(buf, 0UL, 4); /* crc 32, unknown */
+    buf += 4;
+    putvalue(buf, 0xFFFFFFFFUL, 4); /* compressed size, unknown */
+    buf += 4;
+    putvalue(buf, 0xFFFFFFFFUL, 4); /* uncompressed size, unknown */
+    buf += 4;
+    putvalue(buf, strlen(filename), 2); /* size of filename */
+    buf += 2;
+    putvalue(buf, 4 + 8 + 8, 2); /* size of extra field */
+    buf += 2;
+
+    memcpy(buf, filename, strlen(filename));
+    buf += strlen(filename);
+
+    /* ZIP64 extension */
+    putvalue(buf, 0x0001, 2); /* ZIP64_EXTENSION */
+    buf += 2;
+    putvalue(buf, 8 + 8, 2);
+    buf += 2;
+    putvalue(buf, 0UL, 8);
+    buf += 8;
+    putvalue(buf, 0UL, 8);
+    buf += 8;
+
+    return buf - oldbuf;
+}
+
+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)
+{
+    uint8_t *oldbuf = buf;
+
+    putvalue(buf, CENTRALHEADERMAGIC, 4);
+    buf += 4;
+    putvalue(buf, ZIPVERSION_NEEDED, 2);
+    buf += 2;
+    putvalue(buf, ZIPVERSION_NEEDED, 2);
+    buf += 2;
+
+    uint16_t flag = 0;
+    if ((level==8) || (level == 9))
+        flag |= 2;
+    if (level == 2)
+        flag |= 4;
+    if (level == 1)
+        flag |= 6;
+#if 0
+    if (password != NULL)
+        flag |= 1;
+#endif
+
+    putvalue(buf, flag | 0x8, 2);
+    buf += 2;
+
+    putvalue(buf, Z_DEFLATED, 2);
+    buf += 2;
+
+    putvalue(buf,0UL, 4);
+    buf += 4;
+
+    // CRC / Compressed size / Uncompressed size will be filled in later and rewritten later
+    putvalue(buf, crc32_value, 4); /* crc 32 */
+    buf += 4;
+    putvalue(buf, 0xffffffffUL, 4); /* compressed size */
+    buf += 4;
+    putvalue(buf, 0xffffffffUL, 4); /* uncompressed size */
+    buf += 4;
+    putvalue(buf, strlen(filename), 2);
+    buf += 2;
+    putvalue(buf, 4 + 8 + 8 + 8, 2); /* size of extra field */
+    buf += 2;
+    putvalue(buf, 0UL, 2); /* size of comment field */
+    buf += 2;
+    putvalue(buf, 0UL, 2); /* disk number */
+    buf += 2;
+    putvalue(buf, 0UL, 2); /* internal attributes */
+    buf += 2;
+    putvalue(buf, 0UL, 4); /* external file attributes */
+    buf += 4;
+    putvalue(buf, 0xffffffffUL, 4); /* Relative offset */
+    buf += 4;
+    memcpy(buf, filename, strlen(filename));
+    buf += strlen(filename);
+
+    /* ZIP64 extension */
+    putvalue(buf, 0x0001, 2); /* ZIP64_EXTENSION */
+    buf += 2;
+    putvalue(buf, 8 + 8 + 8, 2);
+    buf += 2;
+    putvalue(buf, uncomp_size, 8);
+    buf += 8;
+    putvalue(buf, size, 8);
+    buf += 8;
+    putvalue(buf, zip_localheader_offset, 8);
+    buf += 8;
+
+    return buf - oldbuf;
+}
+
+static int kzip_write_current(struct kzip_file *zfile, void *buf, int len)
+{
+    KZIP_DEBUG("%s: write_cb %p len %d\n", __func__, zfile->write_cb, len);
+    int retval = zfile->write_cb(zfile->handle, buf, len);
+    if (retval > 0) {
+        zfile->current_size += retval;
+    }
+    if ((zfile->current_size - zfile->reported_size) >= KDUMP_SIZE_REPORT) {
+        vo_show_progress(zfile->current_size / 0x100000);
+        zfile->reported_size = zfile->current_size;
+    }
+    if ((zfile->current_size - zfile->wdk_kick_size) >= KDUMP_TICK_WDT) {
+        mtk_wdt_restart();
+        zfile->wdk_kick_size = zfile->current_size;
+    }
+    return retval;
+}
+
+struct kzip_file *kzip_open(void *handle, int (*write_cb)(void *handle, void *p, int size))
+{
+    struct kzip_file *zf = mempool_alloc(sizeof(struct kzip_file), MEMPOOL_ANY);
+    memset(zf, 0, sizeof(struct kzip_file));
+    zf->handle = handle;
+    zf->write_cb = write_cb;
+    KZIP_DEBUG("%s: handle zf %p %p write_cb %p\n", __func__, zf, zf->handle, zf->write_cb);
+
+    vo_show_progress(0);
+    return zf;
+}
+
+bool kzip_close(struct kzip_file *zf)
+{
+    uint64_t central_header_offset = zf->current_size;
+    struct kzip_entry *zentries = zf->zentries;
+    int num = zf->entries_num;
+
+    int i, hsize = 0, local_hsize;
+    uint8_t databuf[128];
+    for (i = 0; i < num; i++) {
+        local_hsize = put_centralheader(databuf, zentries[i].filename, zentries[i].level,
+                                        zentries[i].localheader_offset,
+                                        zentries[i].comp_size,
+                                        zentries[i].uncomp_size,
+                                        zentries[i].crc32);
+        if (kzip_write_current(zf, databuf, local_hsize) != local_hsize) {
+            return false;
+        }
+        hsize += local_hsize;
+    }
+    voprintf_debug("%s: current_size %lld hoffset %lld\n", __func__, zf->current_size, central_header_offset);
+
+    uint64_t zip64_eoc_offset = zf->current_size;
+    local_hsize = put_zip64_eoc_directory_record(databuf, num, central_header_offset, hsize);
+    if ((local_hsize > 0) && (kzip_write_current(zf, databuf, local_hsize) != local_hsize)) {
+        return false;
+    }
+
+    local_hsize = put_zip64_eoc_directory_locator(databuf, zip64_eoc_offset);
+    if ((local_hsize > 0) && (kzip_write_current(zf, databuf, local_hsize) != local_hsize)) {
+        return false;
+    }
+
+    local_hsize = put_eoc_directory_record(databuf, num, central_header_offset, hsize);
+    if (kzip_write_current(zf, databuf, local_hsize) != local_hsize) {
+        return false;
+    }
+    mempool_free(zf);
+    return true;
+}
+
+#define CHUNK 65536
+
+/* Compress from file source to file dest until EOF on source.
+   def() returns Z_OK on success, Z_MEM_ERROR if memory could not be
+   allocated for processing, Z_STREAM_ERROR if an invalid compression
+   level is supplied, Z_VERSION_ERROR if the version of zlib.h and the
+   version of the library linked do not match, or Z_ERRNO if there is
+   an error reading or writing the files. */
+
+static bool kzip_add_file_no_mapped(struct kzip_file *zfile, const struct kzip_addlist *memlist,
+                                    int *flush, int *ret, uint8_t *in, uint8_t *out,
+                                    struct kzip_entry *zentry, z_stream *strm, struct aee_timer *zip_time)
+{
+    lk_time_t t = current_time();
+    uint64_t mem_size = memlist->size;
+    uint8_t *memsrc = (uint8_t *)(uintptr_t)memlist->address;
+    *flush = (memlist->size == 0) ? Z_FINISH : Z_NO_FLUSH;
+    voprintf_debug("-- Compress memory %llx, size %llu\n",
+                   memlist->address, memlist->size);
+
+    do {
+        int in_size = mem_size > CHUNK ? CHUNK : mem_size;
+        if ((current_time() - t)/1000 > 10) {
+            voprintf_debug("-- I am working(interval to 10s) --\n");
+            t = current_time();
+        }
+        memcpy(in, memsrc, in_size);
+        zentry->crc32 = crc32_no_comp(zentry->crc32, in, in_size);
+        memsrc += in_size;
+        mem_size -= in_size;
+        strm->avail_in = in_size;
+        strm->next_in = in;
+
+        /* run deflate() on input until output buffer not full, finish
+           compression if all of source has been read in */
+        do {
+            strm->avail_out = CHUNK;
+            strm->next_out = out;
+            *ret = deflate(strm, *flush);    /* no bad return value */
+            assert(*ret != Z_STREAM_ERROR);  /* state not clobbered */
+            int have = CHUNK - strm->avail_out;
+            if (have > 0) {
+                aee_timer_stop(zip_time);
+                if (kzip_write_current(zfile, out, have) != have) {
+                    voprintf_debug("-- Compress memory %llx, error. surplus size: %u\n",
+                                   memlist->address, mem_size);
+                    return false;
+                }
+                aee_timer_start(zip_time);
+            }
+        } while (strm->avail_out == 0);
+        assert(strm->avail_in == 0);     /* all input will be used */
+    } while (mem_size > 0);
+
+    voprintf_debug("-- Compress memory %llx, done. surplus size: %u\n",
+                   memlist->address, mem_size);
+    return true;
+}
+
+#ifndef MTK_3LEVEL_PAGETABLE
+/* full mapping at LK, only one function is needed. kzip_add_file_no_mapped() */
+#define kzip_add_file_do_mapped kzip_add_file_no_mapped
+#else
+/* LPAE, map before accessing the address of memory */
+#define MAX_MAP_CNT (SECTION_SIZE/CHUNK)
+#define mapflags (MMU_MEMORY_TYPE_NORMAL_WRITE_BACK | MMU_MEMORY_AP_P_RW_U_NA)
+static bool kzip_add_file_do_mapped(struct kzip_file *zfile, const struct kzip_addlist *memlist,
+                                    int *flush, int *ret, uint8_t *in, uint8_t *out,
+                                    struct kzip_entry *zentry, z_stream *strm, struct aee_timer *zip_time)
+{
+    /* multiple physical address mapped onto static 2MB address space. (scratch_addr) */
+    int cnt = 0;
+    uint64_t paddr = memlist->address;
+    vaddr_t vaddr = ROUNDUP(scratch_addr(), SECTION_SIZE);
+    voprintf_debug("-- map: paddr=0x%016llx, vaddr=0x%08x\n", paddr, vaddr);
+
+    uint64_t mem_size = memlist->size;
+    uint8_t *memsrc;
+    *flush = (memlist->size == 0) ? Z_FINISH : Z_NO_FLUSH;
+    voprintf_debug("-- Compress memory %llx, size %llu\n", memlist->address, memlist->size);
+
+    do {
+        /* arch_mmu_map by each 2MB size */
+        if (cnt == 0) {
+            int map_ok = arch_mmu_map(paddr, vaddr, mapflags, SECTION_SIZE);
+            if (map_ok != NO_ERROR) {
+                voprintf_debug("-- arch_mmu_map map error: map_ok=%d, paddr=0x%016llx, vaddr=0x%08x\n",
+                               map_ok, paddr, vaddr);
+                return false;
+            }
+            memsrc = (uint8_t *)vaddr;
+        }
+
+        int in_size = mem_size > CHUNK ? CHUNK : mem_size;
+        memcpy(in, memsrc, in_size);
+        zentry->crc32 = crc32_no_comp(zentry->crc32, in, in_size);
+        memsrc += in_size;
+        mem_size -= in_size;
+        strm->avail_in = in_size;
+        strm->next_in = in;
+
+        /* run deflate() on input until output buffer not full, finish
+           compression if all of source has been read in */
+        do {
+            strm->avail_out = CHUNK;
+            strm->next_out = out;
+            *ret = deflate(strm, *flush);    /* no bad return value */
+            assert(*ret != Z_STREAM_ERROR);  /* state not clobbered */
+            int have = CHUNK - strm->avail_out;
+            if (have > 0) {
+                aee_timer_stop(zip_time);
+                if (kzip_write_current(zfile, out, have) != have) {
+                    voprintf_debug("-- Compress memory %llx, error. surplus size: %u\n",
+                                   memlist->address, mem_size);
+                    return false;
+                }
+                aee_timer_start(zip_time);
+            }
+        } while (strm->avail_out == 0);
+        assert(strm->avail_in == 0);     /* all input will be used */
+
+        /* mod by 2MB (SECTION_SIZE) */
+        cnt++;
+        cnt %= MAX_MAP_CNT;
+        if (cnt == 0)
+            paddr += SECTION_SIZE;
+
+    } while (mem_size > 0);
+
+    voprintf_debug("-- Compress memory %llx, done. surplus size: %u\n", memlist->address, mem_size);
+    return true;
+}
+#endif
+
+static bool kzip_add_file_from_expdb(struct kzip_file *zfile, const struct kzip_addlist *addlist,
+                                     int *flush, int *ret, uint8_t *in, uint8_t *out,
+                                     struct kzip_entry *zentry, z_stream *strm, struct aee_timer *zip_time)
+{
+    uint64_t offset_src = addlist->address;
+    int64_t mem_size = addlist->size;
+
+    *flush = (addlist->size == 0) ? Z_FINISH : Z_NO_FLUSH;
+    voprintf_debug("-- Compress expdb offset %llx, size %llu\n", offset_src, mem_size);
+
+    do {
+        /* read from expdb to memsrc */
+        if (mem_size > CHUNK) {
+            //mrdump_read_expdb(in, CHUNK, offset_src);
+        } else {
+            //mrdump_read_expdb(in, (int)mem_size, offset_src);
+        }
+
+        int in_size = mem_size > CHUNK ? CHUNK : mem_size;
+        zentry->crc32 = crc32_no_comp(zentry->crc32, in, in_size);
+        mem_size -= in_size;
+        strm->avail_in = in_size;
+        strm->next_in = in;
+
+        /* run deflate() on input until output buffer not full, finish
+           compression if all of source has been read in */
+        do {
+            strm->avail_out = CHUNK;
+            strm->next_out = out;
+            *ret = deflate(strm, *flush);    /* no bad return value */
+            assert(*ret != Z_STREAM_ERROR);  /* state not clobbered */
+            int have = CHUNK - strm->avail_out;
+            if (have > 0) {
+                aee_timer_stop(zip_time);
+                if (kzip_write_current(zfile, out, have) != have) {
+                    voprintf_debug("-- Compress expdb offset %llx, error. surplus size: %u\n",
+                                   offset_src, mem_size);
+                    return false;
+                }
+                aee_timer_start(zip_time);
+            }
+        } while (strm->avail_out == 0);
+        assert(strm->avail_in == 0);     /* all input will be used */
+
+        offset_src += in_size;
+
+    } while (mem_size > 0);
+
+    voprintf_debug("-- Compress expdb offset %llx, done. surplus size: %u\n", offset_src, mem_size);
+    return true;
+}
+
+bool kzip_add_file(struct kzip_file *zfile, const struct kzip_addlist *addlist, const char *zfilename)
+{
+    int ret, flush;
+    z_stream strm;
+    struct aee_timer zip_time;
+
+    if (zfile->entries_num >= KZIP_ENTRY_MAX) {
+        voprintf_error("Too many zip entry %d\n", zfile->entries_num);
+        return false;
+    }
+
+    voprintf_debug("%s: zf %p(%p) %s\n", __func__, zfile, zfile->write_cb, zfilename);
+    struct kzip_entry *zentry = &zfile->zentries[zfile->entries_num++];
+    zentry->filename = strdup(zfilename);
+    zentry->localheader_offset = zfile->current_size;
+    zentry->level = KDUMP_ZLIB_LEVEL;
+    zentry->crc32 = 0xffffffffUL;
+
+    KZIP_DEBUG("%s: write local header\n", __func__);
+    uint8_t zip_localheader[128];
+    int hsize = put_localheader(zip_localheader, zfilename, zentry->level);
+    if (kzip_write_current(zfile, zip_localheader, hsize) != hsize) {
+        return false;
+    }
+
+    /* allocate deflate state */
+    memset(&strm, 0, sizeof(z_stream));
+    ret = deflateInit2(&strm, zentry->level, Z_DEFLATED, -MAX_WBITS, DEF_MEM_LEVEL, Z_DEFAULT_STRATEGY);
+    if (ret != Z_OK) {
+        voprintf_error("zlib compress init failed\n");
+        return false;
+    }
+
+    uint8_t *out = mempool_alloc(CHUNK, MEMPOOL_ANY);
+    uint8_t *in = mempool_alloc(CHUNK, MEMPOOL_ANY);
+    if ((out == NULL) || (in == NULL)) {
+        voprintf_error("%s: malloc failed.\n", __func__);
+        goto error;
+    }
+
+    aee_timer_init(&zip_time);
+    aee_timer_start(&zip_time);
+
+    uint64_t start = zfile->current_size, uncomp_size = 0;
+    do {
+        switch (addlist->type) {
+            case MEM_NO_MAP:
+                if (kzip_add_file_no_mapped(zfile, addlist, &flush, &ret, in, out, zentry, &strm, &zip_time) == false)
+                    goto error;
+                break;
+            case MEM_DO_MAP:
+                if (kzip_add_file_do_mapped(zfile, addlist, &flush, &ret, in, out, zentry, &strm, &zip_time) == false)
+                    goto error;
+                break;
+            case EXPDB_FILE:
+                if (kzip_add_file_from_expdb(zfile, addlist, &flush, &ret, in, out, zentry, &strm, &zip_time) == false)
+                    goto error;
+                break;
+            default:
+                goto error;
+                break;
+        }
+        uncomp_size += addlist->size;
+        addlist++;
+        /* done when last data in file processed */
+    } while (flush != Z_FINISH);
+    assert(ret == Z_STREAM_END);        /* stream will be complete */
+
+    deflateEnd(&strm);
+    mempool_free(out);
+    mempool_free(in);
+    aee_timer_stop(&zip_time);
+    voprintf_info("Zip time: %d sec\n", zip_time.acc_ms / 1000);
+
+    zentry->comp_size = zfile->current_size - start;
+    zentry->uncomp_size = uncomp_size;
+    zentry->crc32 = zentry->crc32 ^ 0xffffffffUL;
+
+    return true;
+
+error:
+    mempool_free(out);
+    mempool_free(in);
+    deflateEnd(&strm);
+    return false;
+}