zfs_lz4.c 7.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286
  1. /*
  2. * LZ4 - Fast LZ compression algorithm
  3. * Header File
  4. * Copyright (C) 2011-2013, Yann Collet.
  5. * BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php)
  6. *
  7. * Redistribution and use in source and binary forms, with or without
  8. * modification, are permitted provided that the following conditions are
  9. * met:
  10. *
  11. * * Redistributions of source code must retain the above copyright
  12. * notice, this list of conditions and the following disclaimer.
  13. * * Redistributions in binary form must reproduce the above
  14. * copyright notice, this list of conditions and the following disclaimer
  15. * in the documentation and/or other materials provided with the
  16. * distribution.
  17. *
  18. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  19. * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  20. * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
  21. * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
  22. * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  23. * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
  24. * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
  25. * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
  26. * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  27. * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
  28. * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  29. *
  30. * You can contact the author at :
  31. * - LZ4 homepage : http://fastcompression.blogspot.com/p/lz4.html
  32. * - LZ4 source repository : http://code.google.com/p/lz4/
  33. */
  34. #include <grub/err.h>
  35. #include <grub/mm.h>
  36. #include <grub/misc.h>
  37. #include <grub/types.h>
  38. static int LZ4_uncompress_unknownOutputSize(const char *source, char *dest,
  39. int isize, int maxOutputSize);
  40. /*
  41. * CPU Feature Detection
  42. */
  43. /* 32 or 64 bits ? */
  44. #if (GRUB_CPU_SIZEOF_VOID_P == 8)
  45. #define LZ4_ARCH64 1
  46. #else
  47. #define LZ4_ARCH64 0
  48. #endif
  49. /*
  50. * Compiler Options
  51. */
  52. #define GCC_VERSION (__GNUC__ * 100 + __GNUC_MINOR__)
  53. #if (GCC_VERSION >= 302) || (defined (__INTEL_COMPILER) && __INTEL_COMPILER >= 800) || defined(__clang__)
  54. #define expect(expr, value) (__builtin_expect((expr), (value)))
  55. #else
  56. #define expect(expr, value) (expr)
  57. #endif
  58. #define likely(expr) expect((expr) != 0, 1)
  59. #define unlikely(expr) expect((expr) != 0, 0)
  60. /* Basic types */
  61. #define BYTE grub_uint8_t
  62. #define U16 grub_uint16_t
  63. #define U32 grub_uint32_t
  64. #define S32 grub_int32_t
  65. #define U64 grub_uint64_t
  66. typedef struct _U16_S {
  67. U16 v;
  68. } GRUB_PACKED U16_S;
  69. typedef struct _U32_S {
  70. U32 v;
  71. } GRUB_PACKED U32_S;
  72. typedef struct _U64_S {
  73. U64 v;
  74. } GRUB_PACKED U64_S;
  75. #define A64(x) (((U64_S *)(x))->v)
  76. #define A32(x) (((U32_S *)(x))->v)
  77. #define A16(x) (((U16_S *)(x))->v)
  78. /*
  79. * Constants
  80. */
  81. #define MINMATCH 4
  82. #define COPYLENGTH 8
  83. #define LASTLITERALS 5
  84. #define ML_BITS 4
  85. #define ML_MASK ((1U<<ML_BITS)-1)
  86. #define RUN_BITS (8-ML_BITS)
  87. #define RUN_MASK ((1U<<RUN_BITS)-1)
  88. /*
  89. * Architecture-specific macros
  90. */
  91. #if LZ4_ARCH64
  92. #define STEPSIZE 8
  93. #define UARCH U64
  94. #define AARCH A64
  95. #define LZ4_COPYSTEP(s, d) A64(d) = A64(s); d += 8; s += 8;
  96. #define LZ4_COPYPACKET(s, d) LZ4_COPYSTEP(s, d)
  97. #define LZ4_SECURECOPY(s, d, e) if (d < e) LZ4_WILDCOPY(s, d, e)
  98. #define HTYPE U32
  99. #define INITBASE(base) const BYTE* const base = ip
  100. #else
  101. #define STEPSIZE 4
  102. #define UARCH U32
  103. #define AARCH A32
  104. #define LZ4_COPYSTEP(s, d) A32(d) = A32(s); d += 4; s += 4;
  105. #define LZ4_COPYPACKET(s, d) LZ4_COPYSTEP(s, d); LZ4_COPYSTEP(s, d);
  106. #define LZ4_SECURECOPY LZ4_WILDCOPY
  107. #define HTYPE const BYTE*
  108. #define INITBASE(base) const int base = 0
  109. #endif
  110. #define LZ4_READ_LITTLEENDIAN_16(d, s, p) { d = (s) - grub_le_to_cpu16 (A16 (p)); }
  111. #define LZ4_WRITE_LITTLEENDIAN_16(p, v) { A16(p) = grub_cpu_to_le16 (v); p += 2; }
  112. /* Macros */
  113. #define LZ4_WILDCOPY(s, d, e) do { LZ4_COPYPACKET(s, d) } while (d < e);
  114. /* Decompression functions */
  115. grub_err_t
  116. lz4_decompress(void *s_start, void *d_start, grub_size_t s_len, grub_size_t d_len);
  117. grub_err_t
  118. lz4_decompress(void *s_start, void *d_start, grub_size_t s_len, grub_size_t d_len)
  119. {
  120. const BYTE *src = s_start;
  121. U32 bufsiz = (src[0] << 24) | (src[1] << 16) | (src[2] << 8) |
  122. src[3];
  123. /* invalid compressed buffer size encoded at start */
  124. if (bufsiz + 4 > s_len)
  125. return grub_error(GRUB_ERR_BAD_FS,"lz4 decompression failed.");
  126. /*
  127. * Returns 0 on success (decompression function returned non-negative)
  128. * and appropriate error on failure (decompression function returned negative).
  129. */
  130. return (LZ4_uncompress_unknownOutputSize((char*)s_start + 4, d_start, bufsiz,
  131. d_len) < 0)?grub_error(GRUB_ERR_BAD_FS,"lz4 decompression failed."):0;
  132. }
  133. static int
  134. LZ4_uncompress_unknownOutputSize(const char *source,
  135. char *dest, int isize, int maxOutputSize)
  136. {
  137. /* Local Variables */
  138. const BYTE * ip = (const BYTE *) source;
  139. const BYTE *const iend = ip + isize;
  140. const BYTE * ref;
  141. BYTE * op = (BYTE *) dest;
  142. BYTE *const oend = op + maxOutputSize;
  143. BYTE *cpy;
  144. grub_size_t dec[] = { 0, 3, 2, 3, 0, 0, 0, 0 };
  145. /* Main Loop */
  146. while (ip < iend) {
  147. BYTE token;
  148. int length;
  149. /* get runlength */
  150. token = *ip++;
  151. if ((length = (token >> ML_BITS)) == RUN_MASK) {
  152. int s = 255;
  153. while ((ip < iend) && (s == 255)) {
  154. s = *ip++;
  155. length += s;
  156. }
  157. }
  158. /* copy literals */
  159. if ((grub_addr_t) length > ~(grub_addr_t)op)
  160. goto _output_error;
  161. cpy = op + length;
  162. if ((cpy > oend - COPYLENGTH) ||
  163. (ip + length > iend - COPYLENGTH)) {
  164. if (cpy > oend)
  165. /*
  166. * Error: request to write beyond destination
  167. * buffer.
  168. */
  169. goto _output_error;
  170. if (ip + length > iend)
  171. /*
  172. * Error : request to read beyond source
  173. * buffer.
  174. */
  175. goto _output_error;
  176. grub_memcpy(op, ip, length);
  177. op += length;
  178. ip += length;
  179. if (ip < iend)
  180. /* Error : LZ4 format violation */
  181. goto _output_error;
  182. /* Necessarily EOF, due to parsing restrictions. */
  183. break;
  184. }
  185. LZ4_WILDCOPY(ip, op, cpy);
  186. ip -= (op - cpy);
  187. op = cpy;
  188. /* get offset */
  189. LZ4_READ_LITTLEENDIAN_16(ref, cpy, ip);
  190. ip += 2;
  191. if (ref < (BYTE * const) dest)
  192. /*
  193. * Error: offset creates reference outside of
  194. * destination buffer.
  195. */
  196. goto _output_error;
  197. /* get matchlength */
  198. if ((length = (token & ML_MASK)) == ML_MASK) {
  199. while (ip < iend) {
  200. int s = *ip++;
  201. length += s;
  202. if (s == 255)
  203. continue;
  204. break;
  205. }
  206. }
  207. /* copy repeated sequence */
  208. if unlikely(op - ref < STEPSIZE) {
  209. #if LZ4_ARCH64
  210. grub_size_t dec2table[] = { 0, 0, 0, -1, 0, 1, 2, 3 };
  211. grub_size_t dec2 = dec2table[op - ref];
  212. #else
  213. const int dec2 = 0;
  214. #endif
  215. *op++ = *ref++;
  216. *op++ = *ref++;
  217. *op++ = *ref++;
  218. *op++ = *ref++;
  219. ref -= dec[op - ref];
  220. A32(op) = A32(ref);
  221. op += STEPSIZE - 4;
  222. ref -= dec2;
  223. } else {
  224. LZ4_COPYSTEP(ref, op);
  225. }
  226. cpy = op + length - (STEPSIZE - 4);
  227. if (cpy > oend - COPYLENGTH) {
  228. if (cpy > oend)
  229. /*
  230. * Error: request to write outside of
  231. * destination buffer.
  232. */
  233. goto _output_error;
  234. LZ4_SECURECOPY(ref, op, (oend - COPYLENGTH));
  235. while (op < cpy)
  236. *op++ = *ref++;
  237. op = cpy;
  238. if (op == oend)
  239. /*
  240. * Check EOF (should never happen, since last
  241. * 5 bytes are supposed to be literals).
  242. */
  243. break;
  244. continue;
  245. }
  246. LZ4_SECURECOPY(ref, op, cpy);
  247. op = cpy; /* correction */
  248. }
  249. /* end of decoding */
  250. return (int)(((char *)op) - dest);
  251. /* write overflow error detected */
  252. _output_error:
  253. return (int)(-(((char *)ip) - source));
  254. }