LzmaWrapper.c 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220
  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. #include <config.h>
  32. #include <common.h>
  33. #include <linux/types.h>
  34. #include <linux/string.h>
  35. #include <linux/ctype.h>
  36. #include <malloc.h>
  37. #ifdef CONFIG_LZMA
  38. #include "LzmaDecode.h"
  39. #include "LzmaWrapper.h"
  40. #if defined(DEBUG_ENABLE_BOOTSTRAP_PRINTF) || !defined(CFG_BOOTSTRAP_CODE)
  41. static const char *kCantReadMessage = "Can not read from source buffer";
  42. static const char *kCantAllocateMessage = "Not enough buffer for decompression";
  43. #endif
  44. static size_t rpos=0, dpos=0;
  45. static int MyReadFileAndCheck(unsigned char *src, void *dest, size_t size)
  46. {
  47. if (size == 0)
  48. return 0;
  49. memcpy(dest, src + rpos, size);
  50. rpos += size;
  51. return 1;
  52. }
  53. int lzma_inflate(unsigned char *source, int s_len, unsigned char *dest, int *d_len)
  54. {
  55. /* We use two 32-bit integers to construct 64-bit integer for file size.
  56. You can remove outSizeHigh, if you don't need >= 4GB supporting,
  57. or you can use UInt64 outSize, if your compiler supports 64-bit integers*/
  58. UInt32 outSize = 0;
  59. UInt32 outSizeHigh = 0;
  60. SizeT outSizeFull;
  61. unsigned char *outStream;
  62. int waitEOS = 1;
  63. /* waitEOS = 1, if there is no uncompressed size in headers,
  64. so decoder will wait EOS (End of Stream Marker) in compressed stream */
  65. SizeT compressedSize;
  66. unsigned char *inStream;
  67. CLzmaDecoderState state; /* it's about 24-80 bytes structure, if int is 32-bit */
  68. unsigned char properties[LZMA_PROPERTIES_SIZE];
  69. int res;
  70. rpos=0; dpos=0;
  71. if (sizeof(UInt32) < 4)
  72. {
  73. #if defined(DEBUG_ENABLE_BOOTSTRAP_PRINTF) || !defined(CFG_BOOTSTRAP_CODE)
  74. printf("LZMA decoder needs correct UInt32\n");
  75. #endif
  76. return LZMA_RESULT_DATA_ERROR;
  77. }
  78. {
  79. long length=s_len;
  80. if ((long)(SizeT)length != length)
  81. {
  82. #if defined(DEBUG_ENABLE_BOOTSTRAP_PRINTF) || !defined(CFG_BOOTSTRAP_CODE)
  83. printf("Too big compressed stream\n");
  84. #endif
  85. return LZMA_RESULT_DATA_ERROR;
  86. }
  87. compressedSize = (SizeT)(length - (LZMA_PROPERTIES_SIZE + 8));
  88. }
  89. /* Read LZMA properties for compressed stream */
  90. if (!MyReadFileAndCheck(source, properties, sizeof(properties)))
  91. {
  92. #if defined(DEBUG_ENABLE_BOOTSTRAP_PRINTF) || !defined(CFG_BOOTSTRAP_CODE)
  93. printf("%s\n", kCantReadMessage);
  94. #endif
  95. return LZMA_RESULT_DATA_ERROR;
  96. }
  97. /* Read uncompressed size */
  98. {
  99. int i;
  100. for (i = 0; i < 8; i++)
  101. {
  102. unsigned char b;
  103. if (!MyReadFileAndCheck(source, &b, 1))
  104. {
  105. #if defined(DEBUG_ENABLE_BOOTSTRAP_PRINTF) || !defined(CFG_BOOTSTRAP_CODE)
  106. printf("%s\n", kCantReadMessage);
  107. #endif
  108. return LZMA_RESULT_DATA_ERROR;
  109. }
  110. if (b != 0xFF)
  111. waitEOS = 0;
  112. if (i < 4)
  113. outSize += (UInt32)(b) << (i * 8);
  114. else
  115. outSizeHigh += (UInt32)(b) << ((i - 4) * 8);
  116. }
  117. if (waitEOS)
  118. {
  119. #if defined(DEBUG_ENABLE_BOOTSTRAP_PRINTF) || !defined(CFG_BOOTSTRAP_CODE)
  120. printf("Stream with EOS marker is not supported");
  121. #endif
  122. return LZMA_RESULT_DATA_ERROR;
  123. }
  124. outSizeFull = (SizeT)outSize;
  125. if (sizeof(SizeT) >= 8)
  126. outSizeFull |= (((SizeT)outSizeHigh << 16) << 16);
  127. else if (outSizeHigh != 0 || (UInt32)(SizeT)outSize != outSize)
  128. {
  129. #if defined(DEBUG_ENABLE_BOOTSTRAP_PRINTF) || !defined(CFG_BOOTSTRAP_CODE)
  130. printf("Too big uncompressed stream");
  131. #endif
  132. return LZMA_RESULT_DATA_ERROR;
  133. }
  134. }
  135. /* Decode LZMA properties and allocate memory */
  136. if (LzmaDecodeProperties(&state.Properties, properties, LZMA_PROPERTIES_SIZE) != LZMA_RESULT_OK)
  137. {
  138. #if defined(DEBUG_ENABLE_BOOTSTRAP_PRINTF) || !defined(CFG_BOOTSTRAP_CODE)
  139. printf("Incorrect stream properties");
  140. #endif
  141. return LZMA_RESULT_DATA_ERROR;
  142. }
  143. state.Probs = (CProb *)malloc(LzmaGetNumProbs(&state.Properties) * sizeof(CProb));
  144. if (outSizeFull == 0)
  145. outStream = 0;
  146. else
  147. {
  148. if (outSizeFull > d_len)
  149. outStream = 0;
  150. else
  151. outStream = dest;
  152. }
  153. if (compressedSize == 0)
  154. inStream = 0;
  155. else
  156. {
  157. if ((compressedSize+rpos) > s_len )
  158. inStream = 0;
  159. else
  160. inStream = source + rpos;
  161. }
  162. if (state.Probs == 0
  163. || (outStream == 0 && outSizeFull != 0)
  164. || (inStream == 0 && compressedSize != 0)
  165. )
  166. {
  167. free(state.Probs);
  168. #if defined(DEBUG_ENABLE_BOOTSTRAP_PRINTF) || !defined(CFG_BOOTSTRAP_CODE)
  169. printf("%s\n", kCantAllocateMessage);
  170. #endif
  171. return LZMA_RESULT_DATA_ERROR;
  172. }
  173. /* Decompress */
  174. {
  175. SizeT inProcessed;
  176. SizeT outProcessed;
  177. res = LzmaDecode(&state,
  178. inStream, compressedSize, &inProcessed,
  179. outStream, outSizeFull, &outProcessed);
  180. if (res != 0)
  181. {
  182. #if defined(DEBUG_ENABLE_BOOTSTRAP_PRINTF) || !defined(CFG_BOOTSTRAP_CODE)
  183. printf("\nDecoding error = %d\n", res);
  184. #endif
  185. res = 1;
  186. }
  187. else
  188. {
  189. *d_len = outProcessed;
  190. }
  191. }
  192. free(state.Probs);
  193. return res;
  194. }
  195. #endif /* CONFIG_LZMA */