1 /* 2 * (C) Copyright 2012 3 * Lei Wen <leiwen@marvell.com>, Marvell Inc. 4 * 5 * See file CREDITS for list of people who contributed to this 6 * project. 7 * 8 * This program is free software; you can redistribute it and/or 9 * modify it under the terms of the GNU General Public License as 10 * published by the Free Software Foundation; either version 2 of 11 * the License, or (at your option) any later version. 12 * 13 * This program is distributed in the hope that it will be useful, 14 * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 * GNU General Public License for more details. 17 * 18 * You should have received a copy of the GNU General Public License 19 * along with this program; if not, write to the Free Software 20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, 21 * MA 02111-1307 USA 22 */ 23 24 #include <common.h> 25 #include <watchdog.h> 26 #include <command.h> 27 #include <image.h> 28 #include <malloc.h> 29 #include <u-boot/zlib.h> 30 #include "zlib/zutil.h" 31 32 #ifndef CONFIG_GZIP_COMPRESS_DEF_SZ 33 #define CONFIG_GZIP_COMPRESS_DEF_SZ 0x200 34 #endif 35 #define ZALLOC_ALIGNMENT 16 36 37 static void *zalloc(void *x, unsigned items, unsigned size) 38 { 39 void *p; 40 41 size *= items; 42 size = (size + ZALLOC_ALIGNMENT - 1) & ~(ZALLOC_ALIGNMENT - 1); 43 44 p = malloc (size); 45 46 return (p); 47 } 48 49 static void zfree(void *x, void *addr, unsigned nb) 50 { 51 free (addr); 52 } 53 54 int gzip(void *dst, unsigned long *lenp, 55 unsigned char *src, unsigned long srclen) 56 { 57 return zzip(dst, lenp, src, srclen, 1, NULL); 58 } 59 60 /* 61 * Compress blocks with zlib 62 */ 63 int zzip(void *dst, unsigned long *lenp, unsigned char *src, 64 unsigned long srclen, int stoponerr, 65 int (*func)(unsigned long, unsigned long)) 66 { 67 z_stream s; 68 int r, flush, orig, window; 69 unsigned long comp_len, left_len; 70 71 if (!srclen) 72 return 0; 73 74 #ifndef CONFIG_GZIP 75 window = MAX_WBITS; 76 #else 77 window = 2 * MAX_WBITS; 78 #endif 79 orig = *lenp; 80 s.zalloc = zalloc; 81 s.zfree = zfree; 82 s.opaque = Z_NULL; 83 84 r = deflateInit2_(&s, Z_BEST_SPEED, Z_DEFLATED, window, 85 DEF_MEM_LEVEL, Z_DEFAULT_STRATEGY, 86 ZLIB_VERSION, sizeof(z_stream)); 87 if (r != Z_OK) { 88 printf ("Error: deflateInit2_() returned %d\n", r); 89 return -1; 90 } 91 92 while (srclen > 0) { 93 comp_len = (srclen > CONFIG_GZIP_COMPRESS_DEF_SZ) ? 94 CONFIG_GZIP_COMPRESS_DEF_SZ : srclen; 95 96 s.next_in = src; 97 s.avail_in = comp_len; 98 flush = (srclen > CONFIG_GZIP_COMPRESS_DEF_SZ)? 99 Z_NO_FLUSH : Z_FINISH; 100 101 do { 102 left_len = (*lenp > CONFIG_GZIP_COMPRESS_DEF_SZ) ? 103 CONFIG_GZIP_COMPRESS_DEF_SZ : *lenp; 104 s.next_out = dst; 105 s.avail_out = left_len; 106 r = deflate(&s, flush); 107 if (r == Z_STREAM_ERROR && stoponerr == 1) { 108 printf("Error: deflate() returned %d\n", r); 109 r = -1; 110 goto bail; 111 } 112 if (!func) { 113 dst += (left_len - s.avail_out); 114 *lenp -= (left_len - s.avail_out); 115 } else if (left_len - s.avail_out > 0) { 116 r = func((unsigned long)dst, 117 left_len - s.avail_out); 118 if (r < 0) 119 goto bail; 120 } 121 } while (s.avail_out == 0 && (*lenp > 0)); 122 if (s.avail_in) { 123 printf("Deflate failed to consume %u bytes", s.avail_in); 124 r = -1; 125 goto bail; 126 } 127 if (*lenp == 0) { 128 printf("Deflate need more space to compress " 129 "left %lu bytes\n", srclen); 130 r = -1; 131 goto bail; 132 } 133 srclen -= comp_len; 134 src += comp_len; 135 } 136 137 r = 0; 138 bail: 139 deflateEnd(&s); 140 *lenp = orig - *lenp; 141 return r; 142 } 143