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