1ee5c12ba8478d9b0719f7ac315f020817234c55
[openwrt.git] / package / uboot-ifxmips / files / lib_generic / LzmaWrapper.c
1 /******************************************************************************
2 **
3 ** FILE NAME    : LzmaWrapper.c
4 ** PROJECT      : bootloader
5 ** MODULES      : U-boot
6 **
7 ** DATE         : 2 Nov 2006
8 ** AUTHOR       : Lin Mars
9 ** DESCRIPTION  : LZMA decoder support for U-boot 1.1.5
10 ** COPYRIGHT    :       Copyright (c) 2006
11 **                      Infineon Technologies AG
12 **                      Am Campeon 1-12, 85579 Neubiberg, Germany
13 **
14 **    This program is free software; you can redistribute it and/or modify
15 **    it under the terms of the GNU General Public License as published by
16 **    the Free Software Foundation; either version 2 of the License, or
17 **    (at your option) any later version.
18 **
19 ** HISTORY
20 ** $Date        $Author         $Comment
21 ** 2 Nov 2006   Lin Mars        init version which derived from LzmaTest.c from
22 **                              LZMA v4.43 SDK
23 ** 24 May 2007  Lin Mars        Fix issue for multiple lzma_inflate involved
24 *******************************************************************************/
25 #define LZMA_NO_STDIO
26 #ifndef LZMA_NO_STDIO
27 #include <stdio.h>
28 #include <stdlib.h>
29 #include <string.h>
30 #endif
31
32 #include <config.h>
33 #include <common.h>
34 #include <linux/types.h>
35 #include <linux/string.h>
36 #include <linux/ctype.h>
37 #include <malloc.h>
38
39 #ifdef CONFIG_LZMA
40
41 #include "LzmaDecode.h"
42 #include "LzmaWrapper.h"
43
44 #if defined(DEBUG_ENABLE_BOOTSTRAP_PRINTF) || !defined(CFG_BOOTSTRAP_CODE)
45 static const char *kCantReadMessage = "Can not read from source buffer";
46 static const char *kCantAllocateMessage = "Not enough buffer for decompression";
47 #endif
48
49 static size_t rpos=0, dpos=0;
50
51 static int MyReadFileAndCheck(unsigned char *src, void *dest, size_t size)
52 {
53   if (size == 0)
54     return 0;
55   memcpy(dest, src + rpos, size);
56   rpos += size;
57   return 1;
58 }
59
60 int lzma_inflate(unsigned char *source, int s_len, unsigned char *dest, int *d_len)
61 {
62   /* We use two 32-bit integers to construct 64-bit integer for file size.
63      You can remove outSizeHigh, if you don't need >= 4GB supporting,
64      or you can use UInt64 outSize, if your compiler supports 64-bit integers*/
65   UInt32 outSize = 0;
66   UInt32 outSizeHigh = 0;
67   SizeT outSizeFull;
68   unsigned char *outStream;
69   
70   int waitEOS = 1; 
71   /* waitEOS = 1, if there is no uncompressed size in headers, 
72    so decoder will wait EOS (End of Stream Marker) in compressed stream */
73
74   SizeT compressedSize;
75   unsigned char *inStream;
76
77   CLzmaDecoderState state;  /* it's about 24-80 bytes structure, if int is 32-bit */
78   unsigned char properties[LZMA_PROPERTIES_SIZE];
79
80   int res;
81
82   rpos=0; dpos=0;
83
84   if (sizeof(UInt32) < 4)
85   {
86 #if defined(DEBUG_ENABLE_BOOTSTRAP_PRINTF) || !defined(CFG_BOOTSTRAP_CODE)
87     printf("LZMA decoder needs correct UInt32\n");
88 #endif
89     return LZMA_RESULT_DATA_ERROR;
90   }
91
92   {
93     long length=s_len;
94     if ((long)(SizeT)length != length)
95     {
96 #if defined(DEBUG_ENABLE_BOOTSTRAP_PRINTF) || !defined(CFG_BOOTSTRAP_CODE)
97       printf("Too big compressed stream\n");
98 #endif
99       return LZMA_RESULT_DATA_ERROR;
100     }
101     compressedSize = (SizeT)(length - (LZMA_PROPERTIES_SIZE + 8));
102   }
103
104   /* Read LZMA properties for compressed stream */
105
106   if (!MyReadFileAndCheck(source, properties, sizeof(properties)))
107   {
108 #if defined(DEBUG_ENABLE_BOOTSTRAP_PRINTF) || !defined(CFG_BOOTSTRAP_CODE)
109     printf("%s\n", kCantReadMessage);
110 #endif
111     return LZMA_RESULT_DATA_ERROR;
112   }
113
114   /* Read uncompressed size */
115   {
116     int i;
117     for (i = 0; i < 8; i++)
118     {
119       unsigned char b;
120       if (!MyReadFileAndCheck(source, &b, 1))
121       {
122 #if defined(DEBUG_ENABLE_BOOTSTRAP_PRINTF) || !defined(CFG_BOOTSTRAP_CODE)
123         printf("%s\n", kCantReadMessage);
124 #endif
125         return LZMA_RESULT_DATA_ERROR;
126       }
127       if (b != 0xFF)
128         waitEOS = 0;
129       if (i < 4)
130         outSize += (UInt32)(b) << (i * 8);
131       else
132         outSizeHigh += (UInt32)(b) << ((i - 4) * 8);
133     }
134     
135     if (waitEOS)
136     {
137 #if defined(DEBUG_ENABLE_BOOTSTRAP_PRINTF) || !defined(CFG_BOOTSTRAP_CODE)
138       printf("Stream with EOS marker is not supported");
139 #endif
140       return LZMA_RESULT_DATA_ERROR;
141     }
142     outSizeFull = (SizeT)outSize;
143     if (sizeof(SizeT) >= 8)
144       outSizeFull |= (((SizeT)outSizeHigh << 16) << 16);
145     else if (outSizeHigh != 0 || (UInt32)(SizeT)outSize != outSize)
146     {
147 #if defined(DEBUG_ENABLE_BOOTSTRAP_PRINTF) || !defined(CFG_BOOTSTRAP_CODE)
148       printf("Too big uncompressed stream");
149 #endif
150       return LZMA_RESULT_DATA_ERROR;
151     }
152   }
153
154   /* Decode LZMA properties and allocate memory */
155   if (LzmaDecodeProperties(&state.Properties, properties, LZMA_PROPERTIES_SIZE) != LZMA_RESULT_OK)
156   {
157 #if defined(DEBUG_ENABLE_BOOTSTRAP_PRINTF) || !defined(CFG_BOOTSTRAP_CODE)
158     printf("Incorrect stream properties");
159 #endif
160     return LZMA_RESULT_DATA_ERROR;
161   }
162   state.Probs = (CProb *)malloc(LzmaGetNumProbs(&state.Properties) * sizeof(CProb));
163
164   if (outSizeFull == 0)
165     outStream = 0;
166   else
167   {
168     if (outSizeFull > d_len)
169       outStream = 0;
170     else
171       outStream = dest;
172   }
173
174   if (compressedSize == 0)
175     inStream = 0;
176   else
177   {
178     if ((compressedSize+rpos) > s_len )
179       inStream = 0;
180     else
181       inStream = source + rpos;
182   }
183
184   if (state.Probs == 0 
185     || (outStream == 0 && outSizeFull != 0)
186     || (inStream == 0 && compressedSize != 0)
187     )
188   {
189     free(state.Probs);
190 #if defined(DEBUG_ENABLE_BOOTSTRAP_PRINTF) || !defined(CFG_BOOTSTRAP_CODE)
191     printf("%s\n", kCantAllocateMessage);
192 #endif
193     return LZMA_RESULT_DATA_ERROR;
194   }
195
196   /* Decompress */
197   {
198     SizeT inProcessed;
199     SizeT outProcessed;
200     res = LzmaDecode(&state,
201       inStream, compressedSize, &inProcessed,
202       outStream, outSizeFull, &outProcessed);
203     if (res != 0)
204     {
205 #if defined(DEBUG_ENABLE_BOOTSTRAP_PRINTF) || !defined(CFG_BOOTSTRAP_CODE)
206       printf("\nDecoding error = %d\n", res);
207 #endif
208       res = 1;
209     }
210     else
211     {
212       *d_len = outProcessed;
213     }
214   }
215
216   free(state.Probs);
217   return res;
218 }
219
220 #endif /* CONFIG_LZMA */