blob: a83f4af08af27566d889f884fc8465fbe9681e63 [file] [log] [blame]
Lei Wen88d52c62012-09-28 04:26:46 +00001/*
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
37static 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
49static void zfree(void *x, void *addr, unsigned nb)
50{
51 free (addr);
52}
53
54int 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 */
63int 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;
138bail:
139 deflateEnd(&s);
140 *lenp = orig - *lenp;
141 return r;
142}