Skip to content
Snippets Groups Projects
gzip.c 2.56 KiB
Newer Older
  • Learn to ignore specific revisions
  • /*
     * (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 <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 (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;
    }