| /* | 
 |  * (C) Copyright 2012 | 
 |  * Lei Wen <leiwen@marvell.com>, Marvell Inc. | 
 |  * | 
 |  * SPDX-License-Identifier:	GPL-2.0+ | 
 |  */ | 
 |  | 
 | #include <common.h> | 
 | #include <watchdog.h> | 
 | #include <command.h> | 
 | #include <image.h> | 
 | #include <malloc.h> | 
 | #include <memalign.h> | 
 | #include <u-boot/zlib.h> | 
 | #include "zlib/zutil.h" | 
 |  | 
 | #ifndef CONFIG_GZIP_COMPRESS_DEF_SZ | 
 | #define CONFIG_GZIP_COMPRESS_DEF_SZ	0x200 | 
 | #endif | 
 | #define ZALLOC_ALIGNMENT		16 | 
 |  | 
 | static void *zalloc(void *x, unsigned items, unsigned size) | 
 | { | 
 | 	void *p; | 
 |  | 
 | 	size *= items; | 
 | 	size = (size + ZALLOC_ALIGNMENT - 1) & ~(ZALLOC_ALIGNMENT - 1); | 
 |  | 
 | 	p = malloc_cache_aligned(size); | 
 |  | 
 | 	return (p); | 
 | } | 
 |  | 
 | static void zfree(void *x, void *addr, unsigned nb) | 
 | { | 
 | 	free (addr); | 
 | } | 
 |  | 
 | int gzip(void *dst, unsigned long *lenp, | 
 | 		unsigned char *src, unsigned long srclen) | 
 | { | 
 | 	return zzip(dst, lenp, src, srclen, 1, NULL); | 
 | } | 
 |  | 
 | /* | 
 |  * Compress blocks with zlib | 
 |  */ | 
 | int zzip(void *dst, unsigned long *lenp, unsigned char *src, | 
 | 		unsigned long srclen, int stoponerr, | 
 | 		int (*func)(unsigned long, unsigned long)) | 
 | { | 
 | 	z_stream s; | 
 | 	int r, flush, orig, window; | 
 | 	unsigned long comp_len, left_len; | 
 |  | 
 | 	if (!srclen) | 
 | 		return 0; | 
 |  | 
 | #ifndef CONFIG_GZIP | 
 | 	window = MAX_WBITS; | 
 | #else | 
 | 	window = 2 * MAX_WBITS; | 
 | #endif | 
 | 	orig = *lenp; | 
 | 	s.zalloc = zalloc; | 
 | 	s.zfree = zfree; | 
 | 	s.opaque = Z_NULL; | 
 |  | 
 | 	r = deflateInit2_(&s, Z_BEST_SPEED, Z_DEFLATED,	window, | 
 | 			DEF_MEM_LEVEL, Z_DEFAULT_STRATEGY, | 
 | 			ZLIB_VERSION, sizeof(z_stream)); | 
 | 	if (r != Z_OK) { | 
 | 		printf ("Error: deflateInit2_() returned %d\n", r); | 
 | 		return -1; | 
 | 	} | 
 |  | 
 | 	while (srclen > 0) { | 
 | 		comp_len = (srclen > CONFIG_GZIP_COMPRESS_DEF_SZ) ? | 
 | 				CONFIG_GZIP_COMPRESS_DEF_SZ : srclen; | 
 |  | 
 | 		s.next_in = src; | 
 | 		s.avail_in = comp_len; | 
 | 		flush = (srclen > CONFIG_GZIP_COMPRESS_DEF_SZ)? | 
 | 			Z_NO_FLUSH : Z_FINISH; | 
 |  | 
 | 		do { | 
 | 			left_len = (*lenp > CONFIG_GZIP_COMPRESS_DEF_SZ) ? | 
 | 					CONFIG_GZIP_COMPRESS_DEF_SZ : *lenp; | 
 | 			s.next_out = dst; | 
 | 			s.avail_out = left_len; | 
 | 			r = deflate(&s, flush); | 
 | 			if (r == Z_STREAM_ERROR && stoponerr == 1) { | 
 | 				printf("Error: deflate() returned %d\n", r); | 
 | 				r = -1; | 
 | 				goto bail; | 
 | 			} | 
 | 			if (!func) { | 
 | 				dst += (left_len - s.avail_out); | 
 | 				*lenp -= (left_len - s.avail_out); | 
 | 			} else if (left_len - s.avail_out > 0) { | 
 | 				r = func((unsigned long)dst, | 
 | 					left_len - s.avail_out); | 
 | 				if (r < 0) | 
 | 					goto bail; | 
 | 			} | 
 | 		} while (s.avail_out == 0 && (*lenp > 0)); | 
 | 		if (s.avail_in) { | 
 | 			printf("Deflate failed to consume %u bytes", s.avail_in); | 
 | 			r = -1; | 
 | 			goto bail; | 
 | 		} | 
 | 		if (*lenp == 0) { | 
 | 			printf("Deflate need more space to compress " | 
 | 				"left %lu bytes\n", srclen); | 
 | 			r = -1; | 
 | 			goto bail; | 
 | 		} | 
 | 		srclen -= comp_len; | 
 | 		src += comp_len; | 
 | 	} | 
 |  | 
 | 	r = 0; | 
 | bail: | 
 | 	deflateEnd(&s); | 
 | 	*lenp = orig - *lenp; | 
 | 	return r; | 
 | } |