188d52c6aSLei Wen /*
288d52c6aSLei Wen * (C) Copyright 2012
388d52c6aSLei Wen * Lei Wen <leiwen@marvell.com>, Marvell Inc.
488d52c6aSLei Wen *
51a459660SWolfgang Denk * SPDX-License-Identifier: GPL-2.0+
688d52c6aSLei Wen */
788d52c6aSLei Wen
888d52c6aSLei Wen #include <common.h>
988d52c6aSLei Wen #include <watchdog.h>
1088d52c6aSLei Wen #include <command.h>
1188d52c6aSLei Wen #include <image.h>
1288d52c6aSLei Wen #include <malloc.h>
13*6e295186SSimon Glass #include <memalign.h>
1488d52c6aSLei Wen #include <u-boot/zlib.h>
1588d52c6aSLei Wen #include "zlib/zutil.h"
1688d52c6aSLei Wen
1788d52c6aSLei Wen #ifndef CONFIG_GZIP_COMPRESS_DEF_SZ
1888d52c6aSLei Wen #define CONFIG_GZIP_COMPRESS_DEF_SZ 0x200
1988d52c6aSLei Wen #endif
2088d52c6aSLei Wen #define ZALLOC_ALIGNMENT 16
2188d52c6aSLei Wen
zalloc(void * x,unsigned items,unsigned size)2288d52c6aSLei Wen static void *zalloc(void *x, unsigned items, unsigned size)
2388d52c6aSLei Wen {
2488d52c6aSLei Wen void *p;
2588d52c6aSLei Wen
2688d52c6aSLei Wen size *= items;
2788d52c6aSLei Wen size = (size + ZALLOC_ALIGNMENT - 1) & ~(ZALLOC_ALIGNMENT - 1);
2888d52c6aSLei Wen
294519668bSMarcel Ziswiler p = malloc_cache_aligned(size);
3088d52c6aSLei Wen
3188d52c6aSLei Wen return (p);
3288d52c6aSLei Wen }
3388d52c6aSLei Wen
zfree(void * x,void * addr,unsigned nb)3488d52c6aSLei Wen static void zfree(void *x, void *addr, unsigned nb)
3588d52c6aSLei Wen {
3688d52c6aSLei Wen free (addr);
3788d52c6aSLei Wen }
3888d52c6aSLei Wen
gzip(void * dst,unsigned long * lenp,unsigned char * src,unsigned long srclen)3988d52c6aSLei Wen int gzip(void *dst, unsigned long *lenp,
4088d52c6aSLei Wen unsigned char *src, unsigned long srclen)
4188d52c6aSLei Wen {
4288d52c6aSLei Wen return zzip(dst, lenp, src, srclen, 1, NULL);
4388d52c6aSLei Wen }
4488d52c6aSLei Wen
4588d52c6aSLei Wen /*
4688d52c6aSLei Wen * Compress blocks with zlib
4788d52c6aSLei Wen */
zzip(void * dst,unsigned long * lenp,unsigned char * src,unsigned long srclen,int stoponerr,int (* func)(unsigned long,unsigned long))4888d52c6aSLei Wen int zzip(void *dst, unsigned long *lenp, unsigned char *src,
4988d52c6aSLei Wen unsigned long srclen, int stoponerr,
5088d52c6aSLei Wen int (*func)(unsigned long, unsigned long))
5188d52c6aSLei Wen {
5288d52c6aSLei Wen z_stream s;
5388d52c6aSLei Wen int r, flush, orig, window;
5488d52c6aSLei Wen unsigned long comp_len, left_len;
5588d52c6aSLei Wen
5688d52c6aSLei Wen if (!srclen)
5788d52c6aSLei Wen return 0;
5888d52c6aSLei Wen
5988d52c6aSLei Wen #ifndef CONFIG_GZIP
6088d52c6aSLei Wen window = MAX_WBITS;
6188d52c6aSLei Wen #else
6288d52c6aSLei Wen window = 2 * MAX_WBITS;
6388d52c6aSLei Wen #endif
6488d52c6aSLei Wen orig = *lenp;
6588d52c6aSLei Wen s.zalloc = zalloc;
6688d52c6aSLei Wen s.zfree = zfree;
6788d52c6aSLei Wen s.opaque = Z_NULL;
6888d52c6aSLei Wen
6988d52c6aSLei Wen r = deflateInit2_(&s, Z_BEST_SPEED, Z_DEFLATED, window,
7088d52c6aSLei Wen DEF_MEM_LEVEL, Z_DEFAULT_STRATEGY,
7188d52c6aSLei Wen ZLIB_VERSION, sizeof(z_stream));
7288d52c6aSLei Wen if (r != Z_OK) {
7388d52c6aSLei Wen printf ("Error: deflateInit2_() returned %d\n", r);
7488d52c6aSLei Wen return -1;
7588d52c6aSLei Wen }
7688d52c6aSLei Wen
7788d52c6aSLei Wen while (srclen > 0) {
7888d52c6aSLei Wen comp_len = (srclen > CONFIG_GZIP_COMPRESS_DEF_SZ) ?
7988d52c6aSLei Wen CONFIG_GZIP_COMPRESS_DEF_SZ : srclen;
8088d52c6aSLei Wen
8188d52c6aSLei Wen s.next_in = src;
8288d52c6aSLei Wen s.avail_in = comp_len;
8388d52c6aSLei Wen flush = (srclen > CONFIG_GZIP_COMPRESS_DEF_SZ)?
8488d52c6aSLei Wen Z_NO_FLUSH : Z_FINISH;
8588d52c6aSLei Wen
8688d52c6aSLei Wen do {
8788d52c6aSLei Wen left_len = (*lenp > CONFIG_GZIP_COMPRESS_DEF_SZ) ?
8888d52c6aSLei Wen CONFIG_GZIP_COMPRESS_DEF_SZ : *lenp;
8988d52c6aSLei Wen s.next_out = dst;
9088d52c6aSLei Wen s.avail_out = left_len;
9188d52c6aSLei Wen r = deflate(&s, flush);
9288d52c6aSLei Wen if (r == Z_STREAM_ERROR && stoponerr == 1) {
9388d52c6aSLei Wen printf("Error: deflate() returned %d\n", r);
9488d52c6aSLei Wen r = -1;
9588d52c6aSLei Wen goto bail;
9688d52c6aSLei Wen }
9788d52c6aSLei Wen if (!func) {
9888d52c6aSLei Wen dst += (left_len - s.avail_out);
9988d52c6aSLei Wen *lenp -= (left_len - s.avail_out);
10088d52c6aSLei Wen } else if (left_len - s.avail_out > 0) {
10188d52c6aSLei Wen r = func((unsigned long)dst,
10288d52c6aSLei Wen left_len - s.avail_out);
10388d52c6aSLei Wen if (r < 0)
10488d52c6aSLei Wen goto bail;
10588d52c6aSLei Wen }
10688d52c6aSLei Wen } while (s.avail_out == 0 && (*lenp > 0));
10788d52c6aSLei Wen if (s.avail_in) {
10888d52c6aSLei Wen printf("Deflate failed to consume %u bytes", s.avail_in);
10988d52c6aSLei Wen r = -1;
11088d52c6aSLei Wen goto bail;
11188d52c6aSLei Wen }
11288d52c6aSLei Wen if (*lenp == 0) {
11388d52c6aSLei Wen printf("Deflate need more space to compress "
11488d52c6aSLei Wen "left %lu bytes\n", srclen);
11588d52c6aSLei Wen r = -1;
11688d52c6aSLei Wen goto bail;
11788d52c6aSLei Wen }
11888d52c6aSLei Wen srclen -= comp_len;
11988d52c6aSLei Wen src += comp_len;
12088d52c6aSLei Wen }
12188d52c6aSLei Wen
12288d52c6aSLei Wen r = 0;
12388d52c6aSLei Wen bail:
12488d52c6aSLei Wen deflateEnd(&s);
12588d52c6aSLei Wen *lenp = orig - *lenp;
12688d52c6aSLei Wen return r;
12788d52c6aSLei Wen }
128