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