xref: /openbmc/u-boot/lib/gzip.c (revision e8f80a5a)
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 <image.h>
11 #include <malloc.h>
12 #include <memalign.h>
13 #include <u-boot/zlib.h>
14 #include "zlib/zutil.h"
15 
16 #ifndef CONFIG_GZIP_COMPRESS_DEF_SZ
17 #define CONFIG_GZIP_COMPRESS_DEF_SZ	0x200
18 #endif
19 #define ZALLOC_ALIGNMENT		16
20 
zalloc(void * x,unsigned items,unsigned size)21 static 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 
zfree(void * x,void * addr,unsigned nb)33 static void zfree(void *x, void *addr, unsigned nb)
34 {
35 	free (addr);
36 }
37 
gzip(void * dst,unsigned long * lenp,unsigned char * src,unsigned long srclen)38 int 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  */
zzip(void * dst,unsigned long * lenp,unsigned char * src,unsigned long srclen,int stoponerr,int (* func)(unsigned long,unsigned long))47 int 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 			ZLIB_VERSION, 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 > CONFIG_GZIP_COMPRESS_DEF_SZ) ?
78 				CONFIG_GZIP_COMPRESS_DEF_SZ : srclen;
79 
80 		s.next_in = src;
81 		s.avail_in = comp_len;
82 		flush = (srclen > CONFIG_GZIP_COMPRESS_DEF_SZ)?
83 			Z_NO_FLUSH : Z_FINISH;
84 
85 		do {
86 			left_len = (*lenp > CONFIG_GZIP_COMPRESS_DEF_SZ) ?
87 					CONFIG_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;
122 bail:
123 	deflateEnd(&s);
124 	*lenp = orig - *lenp;
125 	return r;
126 }
127