Drop in tinflate lib.
[oweals/u-boot_mod.git] / u-boot / lib_generic / tinfgzip.c
1 /*
2  * tinfgzip  -  tiny gzip decompressor
3  *
4  * Copyright (c) 2003 by Joergen Ibsen / Jibz
5  * All Rights Reserved
6  *
7  * http://www.ibsensoftware.com/
8  *
9  * This software is provided 'as-is', without any express
10  * or implied warranty.  In no event will the authors be
11  * held liable for any damages arising from the use of
12  * this software.
13  *
14  * Permission is granted to anyone to use this software
15  * for any purpose, including commercial applications,
16  * and to alter it and redistribute it freely, subject to
17  * the following restrictions:
18  *
19  * 1. The origin of this software must not be
20  *    misrepresented; you must not claim that you
21  *    wrote the original software. If you use this
22  *    software in a product, an acknowledgment in
23  *    the product documentation would be appreciated
24  *    but is not required.
25  *
26  * 2. Altered source versions must be plainly marked
27  *    as such, and must not be misrepresented as
28  *    being the original software.
29  *
30  * 3. This notice may not be removed or altered from
31  *    any source distribution.
32  */
33
34 #include "tinf.h"
35 #include <stdio.h>
36
37 #define FTEXT    1
38 #define FHCRC    2
39 #define FEXTRA   4
40 #define FNAME    8
41 #define FCOMMENT 16
42
43 int tinf_gzip_uncompress(void *dest, unsigned int *destLen,
44                          const void *source, unsigned int sourceLen)
45 {
46     unsigned char *src = (unsigned char *)source;
47     unsigned char *dst = (unsigned char *)dest;
48     unsigned char *start;
49     unsigned int dlen, crc32;
50     int res;
51     unsigned char flg;
52
53     /* -- check format -- */
54
55     /* check id bytes */
56     if (src[0] != 0x1f || src[1] != 0x8b) return TINF_DATA_ERROR;
57
58     /* check method is deflate */
59     if (src[2] != 8) return TINF_DATA_ERROR;
60
61     /* get flag byte */
62     flg = src[3];
63
64     /* check that reserved bits are zero */
65     if (flg & 0xe0) return TINF_DATA_ERROR;
66
67     /* -- find start of compressed data -- */
68
69     /* skip base header of 10 bytes */
70     start = src + 10;
71
72     /* skip extra data if present */
73     if (flg & FEXTRA)
74     {
75        unsigned int xlen = start[1];
76        xlen = 256*xlen + start[0];
77        start += xlen + 2;
78     }
79
80     /* skip file name if present */
81     if (flg & FNAME) { while (*start) ++start; ++start; }
82
83     /* skip file comment if present */
84     if (flg & FCOMMENT) { while (*start) ++start; ++start; }
85
86     /* check header crc if present */
87     if (flg & FHCRC)
88     {
89        unsigned int hcrc = start[1];
90        hcrc = 256*hcrc + start[0];
91
92        if (hcrc != (tinf_crc32(src, start - src) & 0x0000ffff))
93           return TINF_DATA_ERROR;
94
95        start += 2;
96     }
97
98     /* -- get decompressed length -- */
99
100     dlen =            src[sourceLen - 1];
101     dlen = 256*dlen + src[sourceLen - 2];
102     dlen = 256*dlen + src[sourceLen - 3];
103     dlen = 256*dlen + src[sourceLen - 4];
104
105     /* -- get crc32 of decompressed data -- */
106
107     crc32 =             src[sourceLen - 5];
108     crc32 = 256*crc32 + src[sourceLen - 6];
109     crc32 = 256*crc32 + src[sourceLen - 7];
110     crc32 = 256*crc32 + src[sourceLen - 8];
111
112     /* -- decompress data -- */
113
114     res = tinf_uncompress(dst, destLen, start, src + sourceLen - start - 8);
115
116     if (res != TINF_OK) {
117         puts("uncompress error");
118         return TINF_DATA_ERROR;
119     }
120
121 #if 0
122     if (*destLen != dlen) {
123         printf("len error %d != %d", *destLen, dlen);
124         return TINF_DATA_ERROR;
125     }
126
127     /* -- check CRC32 checksum -- */
128
129     if (crc32 != tinf_crc32(dst, *destLen)) {
130         return TINF_DATA_ERROR;
131     }
132 #endif
133     printf("expected len %08x vs decoded %08x\n", dlen, *destLen);
134     printf("expected crc32 %08x vs calculated %08x\n", crc32, tinf_crc32(dst, *destLen));
135
136     return TINF_OK;
137 }