]>
git.ipfire.org Git - people/ms/u-boot.git/blob - lib/gunzip.c
2 * (C) Copyright 2000-2006
3 * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
5 * SPDX-License-Identifier: GPL-2.0+
15 #include <u-boot/zlib.h>
18 #define HEADER0 '\x1f'
19 #define HEADER1 '\x8b'
20 #define ZALLOC_ALIGNMENT 16
28 void *gzalloc(void *x
, unsigned items
, unsigned size
)
33 size
= (size
+ ZALLOC_ALIGNMENT
- 1) & ~(ZALLOC_ALIGNMENT
- 1);
40 void gzfree(void *x
, void *addr
, unsigned nb
)
45 int gzip_parse_header(const unsigned char *src
, unsigned long len
)
52 if (src
[2] != DEFLATED
|| (flags
& RESERVED
) != 0) {
53 puts ("Error: Bad gzipped data\n");
56 if ((flags
& EXTRA_FIELD
) != 0)
57 i
= 12 + src
[10] + (src
[11] << 8);
58 if ((flags
& ORIG_NAME
) != 0)
61 if ((flags
& COMMENT
) != 0)
64 if ((flags
& HEAD_CRC
) != 0)
67 puts ("Error: gunzip out of data in header\n");
73 int gunzip(void *dst
, int dstlen
, unsigned char *src
, unsigned long *lenp
)
75 int offset
= gzip_parse_header(src
, *lenp
);
80 return zunzip(dst
, dstlen
, src
, lenp
, 1, offset
);
83 #ifdef CONFIG_CMD_UNZIP
85 void gzwrite_progress_init(u64 expectedsize
)
91 void gzwrite_progress(int iteration
,
95 if (0 == (iteration
& 3))
96 printf("%llu/%llu\r", bytes_written
, total_bytes
);
100 void gzwrite_progress_finish(int returnval
,
106 if (0 == returnval
) {
107 printf("\n\t%llu bytes, crc 0x%08x\n",
108 total_bytes
, calculated_crc
);
110 printf("\n\tuncompressed %llu of %llu\n"
111 "\tcrcs == 0x%08x/0x%08x\n",
112 bytes_written
, total_bytes
,
113 expected_crc
, calculated_crc
);
117 int gzwrite(unsigned char *src
, int len
,
118 struct blk_desc
*dev
,
119 unsigned long szwritebuf
,
126 unsigned char *writebuf
;
129 lbaint_t blksperbuf
, outblock
;
135 (szwritebuf
% dev
->blksz
) ||
136 (szwritebuf
< dev
->blksz
)) {
137 printf("%s: size %lu not a multiple of %lu\n",
138 __func__
, szwritebuf
, dev
->blksz
);
142 if (startoffs
& (dev
->blksz
-1)) {
143 printf("%s: start offset %llu not a multiple of %lu\n",
144 __func__
, startoffs
, dev
->blksz
);
148 blksperbuf
= szwritebuf
/ dev
->blksz
;
149 outblock
= lldiv(startoffs
, dev
->blksz
);
154 if (src
[2] != DEFLATED
|| (flags
& RESERVED
) != 0) {
155 puts("Error: Bad gzipped data\n");
158 if ((flags
& EXTRA_FIELD
) != 0)
159 i
= 12 + src
[10] + (src
[11] << 8);
160 if ((flags
& ORIG_NAME
) != 0)
161 while (src
[i
++] != 0)
163 if ((flags
& COMMENT
) != 0)
164 while (src
[i
++] != 0)
166 if ((flags
& HEAD_CRC
) != 0)
170 puts("Error: gunzip out of data in header");
174 payload_size
= len
- i
- 8;
176 memcpy(&expected_crc
, src
+ len
- 8, sizeof(expected_crc
));
177 expected_crc
= le32_to_cpu(expected_crc
);
179 memcpy(&szuncompressed
, src
+ len
- 4, sizeof(szuncompressed
));
180 if (szexpected
== 0) {
181 szexpected
= le32_to_cpu(szuncompressed
);
182 } else if (szuncompressed
!= (u32
)szexpected
) {
183 printf("size of %llx doesn't match trailer low bits %x\n",
184 szexpected
, szuncompressed
);
187 if (lldiv(szexpected
, dev
->blksz
) > (dev
->lba
- outblock
)) {
188 printf("%s: uncompressed size %llu exceeds device size\n",
189 __func__
, szexpected
);
193 gzwrite_progress_init(szexpected
);
198 r
= inflateInit2(&s
, -MAX_WBITS
);
200 printf("Error: inflateInit2() returned %d\n", r
);
205 s
.avail_in
= payload_size
+8;
206 writebuf
= (unsigned char *)malloc_cache_aligned(szwritebuf
);
208 /* decompress until deflate stream ends or end of file */
210 if (s
.avail_in
== 0) {
211 printf("%s: weird termination with result %d\n",
216 /* run inflate() on input until output buffer not full */
218 unsigned long blocks_written
;
220 lbaint_t writeblocks
;
222 s
.avail_out
= szwritebuf
;
223 s
.next_out
= writebuf
;
224 r
= inflate(&s
, Z_SYNC_FLUSH
);
226 (r
!= Z_STREAM_END
)) {
227 printf("Error: inflate() returned %d\n", r
);
230 numfilled
= szwritebuf
- s
.avail_out
;
231 crc
= crc32(crc
, writebuf
, numfilled
);
232 totalfilled
+= numfilled
;
233 if (numfilled
< szwritebuf
) {
234 writeblocks
= (numfilled
+dev
->blksz
-1)
236 memset(writebuf
+numfilled
, 0,
237 dev
->blksz
-(numfilled
%dev
->blksz
));
239 writeblocks
= blksperbuf
;
242 gzwrite_progress(iteration
++,
245 blocks_written
= blk_dwrite(dev
, outblock
,
246 writeblocks
, writebuf
);
247 outblock
+= blocks_written
;
253 } while (s
.avail_out
== 0);
254 /* done when inflate() says it's done */
255 } while (r
!= Z_STREAM_END
);
257 if ((szexpected
!= totalfilled
) ||
258 (crc
!= expected_crc
))
264 gzwrite_progress_finish(r
, totalfilled
, szexpected
,
274 * Uncompress blocks compressed with zlib without headers
276 int zunzip(void *dst
, int dstlen
, unsigned char *src
, unsigned long *lenp
,
277 int stoponerr
, int offset
)
286 r
= inflateInit2(&s
, -MAX_WBITS
);
288 printf("Error: inflateInit2() returned %d\n", r
);
291 s
.next_in
= src
+ offset
;
292 s
.avail_in
= *lenp
- offset
;
294 s
.avail_out
= dstlen
;
296 r
= inflate(&s
, Z_FINISH
);
297 if (stoponerr
== 1 && r
!= Z_STREAM_END
&&
298 (s
.avail_in
== 0 || s
.avail_out
== 0 || r
!= Z_BUF_ERROR
)) {
299 printf("Error: inflate() returned %d\n", r
);
303 } while (r
== Z_BUF_ERROR
);
304 *lenp
= s
.next_out
- (unsigned char *) dst
;