1// SPDX-License-Identifier: GPL-2.0+
2/*
3 * (C) Copyright 2012
4 * Lei Wen <leiwen@marvell.com>, Marvell Inc.
5 */
6
7#include <watchdog.h>
8#include <command.h>
9#include <gzip.h>
10#include <image.h>
11#include <malloc.h>
12#include <memalign.h>
13#include <u-boot/zlib.h>
14#include "zlib/zutil.h"
15
16#ifndef CFG_GZIP_COMPRESS_DEF_SZ
17#define CFG_GZIP_COMPRESS_DEF_SZ	0x200
18#endif
19#define ZALLOC_ALIGNMENT		16
20
21static void *zalloc(void *x, unsigned items, unsigned size)
22{
23	void *p;
24
25	size *= items;
26	size = (size + ZALLOC_ALIGNMENT - 1) & ~(ZALLOC_ALIGNMENT - 1);
27
28	p = malloc_cache_aligned(size);
29
30	return (p);
31}
32
33static void zfree(void *x, void *addr, unsigned nb)
34{
35	free (addr);
36}
37
38int gzip(void *dst, unsigned long *lenp,
39		unsigned char *src, unsigned long srclen)
40{
41	return zzip(dst, lenp, src, srclen, 1, NULL);
42}
43
44/*
45 * Compress blocks with zlib
46 */
47int zzip(void *dst, unsigned long *lenp, unsigned char *src,
48		unsigned long srclen, int stoponerr,
49		int (*func)(unsigned long, unsigned long))
50{
51	z_stream s;
52	int r, flush, orig, window;
53	unsigned long comp_len, left_len;
54
55	if (!srclen)
56		return 0;
57
58#ifndef CONFIG_GZIP
59	window = MAX_WBITS;
60#else
61	window = 2 * MAX_WBITS;
62#endif
63	orig = *lenp;
64	s.zalloc = zalloc;
65	s.zfree = zfree;
66	s.opaque = Z_NULL;
67
68	r = deflateInit2_(&s, Z_BEST_SPEED, Z_DEFLATED,	window,
69			DEF_MEM_LEVEL, Z_DEFAULT_STRATEGY,
70			sizeof(z_stream));
71	if (r != Z_OK) {
72		printf ("Error: deflateInit2_() returned %d\n", r);
73		return -1;
74	}
75
76	while (srclen > 0) {
77		comp_len = (srclen > CFG_GZIP_COMPRESS_DEF_SZ) ?
78				CFG_GZIP_COMPRESS_DEF_SZ : srclen;
79
80		s.next_in = src;
81		s.avail_in = comp_len;
82		flush = (srclen > CFG_GZIP_COMPRESS_DEF_SZ)?
83			Z_NO_FLUSH : Z_FINISH;
84
85		do {
86			left_len = (*lenp > CFG_GZIP_COMPRESS_DEF_SZ) ?
87					CFG_GZIP_COMPRESS_DEF_SZ : *lenp;
88			s.next_out = dst;
89			s.avail_out = left_len;
90			r = deflate(&s, flush);
91			if (r == Z_STREAM_ERROR && stoponerr == 1) {
92				printf("Error: deflate() returned %d\n", r);
93				r = -1;
94				goto bail;
95			}
96			if (!func) {
97				dst += (left_len - s.avail_out);
98				*lenp -= (left_len - s.avail_out);
99			} else if (left_len - s.avail_out > 0) {
100				r = func((unsigned long)dst,
101					left_len - s.avail_out);
102				if (r < 0)
103					goto bail;
104			}
105		} while (s.avail_out == 0 && (*lenp > 0));
106		if (s.avail_in) {
107			printf("Deflate failed to consume %u bytes", s.avail_in);
108			r = -1;
109			goto bail;
110		}
111		if (*lenp == 0) {
112			printf("Deflate need more space to compress "
113				"left %lu bytes\n", srclen);
114			r = -1;
115			goto bail;
116		}
117		srclen -= comp_len;
118		src += comp_len;
119	}
120
121	r = 0;
122bail:
123	deflateEnd(&s);
124	*lenp = orig - *lenp;
125	return r;
126}
127