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