blob: f469fcbeadb5c0ceb77bc2e3b7a78a15797ffe6a [file] [log] [blame]
Marian Balakowiczbe946ba2008-01-08 18:11:43 +01001/*
2 * (C) Copyright 2000-2006
3 * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
4 *
Wolfgang Denkd79de1d2013-07-08 09:37:19 +02005 * SPDX-License-Identifier: GPL-2.0+
Marian Balakowiczbe946ba2008-01-08 18:11:43 +01006 */
7
8#include <common.h>
9#include <watchdog.h>
10#include <command.h>
11#include <image.h>
12#include <malloc.h>
Jean-Christophe PLAGNIOL-VILLARD6bb94492009-04-04 12:49:11 +020013#include <u-boot/zlib.h>
Marian Balakowiczbe946ba2008-01-08 18:11:43 +010014
15#define ZALLOC_ALIGNMENT 16
16#define HEAD_CRC 2
17#define EXTRA_FIELD 4
18#define ORIG_NAME 8
19#define COMMENT 0x10
20#define RESERVED 0xe0
21#define DEFLATED 8
22
Mike Frysinger802383b2012-04-09 13:39:53 +000023void *gzalloc(void *x, unsigned items, unsigned size)
Marian Balakowiczbe946ba2008-01-08 18:11:43 +010024{
25 void *p;
26
27 size *= items;
28 size = (size + ZALLOC_ALIGNMENT - 1) & ~(ZALLOC_ALIGNMENT - 1);
29
30 p = malloc (size);
31
32 return (p);
33}
34
Mike Frysinger802383b2012-04-09 13:39:53 +000035void gzfree(void *x, void *addr, unsigned nb)
Marian Balakowiczbe946ba2008-01-08 18:11:43 +010036{
37 free (addr);
38}
39
40int gunzip(void *dst, int dstlen, unsigned char *src, unsigned long *lenp)
41{
Ricardo Ribalda Delgado4dc9fa62009-04-27 18:33:32 +020042 int i, flags;
Marian Balakowiczbe946ba2008-01-08 18:11:43 +010043
44 /* skip header */
45 i = 10;
46 flags = src[3];
47 if (src[2] != DEFLATED || (flags & RESERVED) != 0) {
48 puts ("Error: Bad gzipped data\n");
49 return (-1);
50 }
51 if ((flags & EXTRA_FIELD) != 0)
52 i = 12 + src[10] + (src[11] << 8);
53 if ((flags & ORIG_NAME) != 0)
54 while (src[i++] != 0)
55 ;
56 if ((flags & COMMENT) != 0)
57 while (src[i++] != 0)
58 ;
59 if ((flags & HEAD_CRC) != 0)
60 i += 2;
61 if (i >= *lenp) {
62 puts ("Error: gunzip out of data in header\n");
63 return (-1);
64 }
65
Ricardo Ribalda Delgado4dc9fa62009-04-27 18:33:32 +020066 return zunzip(dst, dstlen, src, lenp, 1, i);
67}
68
69/*
70 * Uncompress blocks compressed with zlib without headers
71 */
72int zunzip(void *dst, int dstlen, unsigned char *src, unsigned long *lenp,
73 int stoponerr, int offset)
74{
75 z_stream s;
Simon Glass49d42c02014-12-02 13:17:39 -070076 int err = 0;
Ricardo Ribalda Delgado4dc9fa62009-04-27 18:33:32 +020077 int r;
78
Mike Frysinger802383b2012-04-09 13:39:53 +000079 s.zalloc = gzalloc;
80 s.zfree = gzfree;
Marian Balakowiczbe946ba2008-01-08 18:11:43 +010081
82 r = inflateInit2(&s, -MAX_WBITS);
83 if (r != Z_OK) {
84 printf ("Error: inflateInit2() returned %d\n", r);
Ricardo Ribalda Delgado4dc9fa62009-04-27 18:33:32 +020085 return -1;
Marian Balakowiczbe946ba2008-01-08 18:11:43 +010086 }
Ricardo Ribalda Delgado4dc9fa62009-04-27 18:33:32 +020087 s.next_in = src + offset;
88 s.avail_in = *lenp - offset;
Marian Balakowiczbe946ba2008-01-08 18:11:43 +010089 s.next_out = dst;
90 s.avail_out = dstlen;
Catalin Radu456874f2011-02-04 14:35:47 +020091 do {
92 r = inflate(&s, Z_FINISH);
Kees Cooked1469a2013-08-16 07:59:13 -070093 if (stoponerr == 1 && r != Z_STREAM_END &&
94 (s.avail_out == 0 || r != Z_BUF_ERROR)) {
Catalin Radu456874f2011-02-04 14:35:47 +020095 printf("Error: inflate() returned %d\n", r);
Simon Glass49d42c02014-12-02 13:17:39 -070096 err = -1;
97 break;
Catalin Radu456874f2011-02-04 14:35:47 +020098 }
99 s.avail_in = *lenp - offset - (int)(s.next_out - (unsigned char*)dst);
Catalin Radu456874f2011-02-04 14:35:47 +0200100 } while (r == Z_BUF_ERROR);
Marian Balakowiczbe946ba2008-01-08 18:11:43 +0100101 *lenp = s.next_out - (unsigned char *) dst;
102 inflateEnd(&s);
103
Simon Glass49d42c02014-12-02 13:17:39 -0700104 return err;
Marian Balakowiczbe946ba2008-01-08 18:11:43 +0100105}