xref: /openbmc/u-boot/lib/gzip.c (revision 7e8702a00fe88590c2ece93061da4a40adf3c242)
1  /*
2   * (C) Copyright 2012
3   * Lei Wen <leiwen@marvell.com>, Marvell Inc.
4   *
5   * SPDX-License-Identifier:	GPL-2.0+
6   */
7  
8  #include <common.h>
9  #include <watchdog.h>
10  #include <command.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  
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  
34  static void zfree(void *x, void *addr, unsigned nb)
35  {
36  	free (addr);
37  }
38  
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   */
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