coreboot
coreboot is an Open Source project aimed at replacing the proprietary BIOS found in most computers.
lz4.c.inc
Go to the documentation of this file.
1 /*
2  LZ4 - Fast LZ compression algorithm
3  Copyright (C) 2011-2015, Yann Collet.
4 
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 source repository : https://github.com/Cyan4973/lz4
32  - LZ4 public forum : https://groups.google.com/forum/#!forum/lz4c
33 */
34 
35 
36 /**************************************
37 * Reading and writing into memory
38 **************************************/
39 
40 /* customized variant of memcpy, which can overwrite up to 7 bytes beyond dstEnd */
41 static void LZ4_wildCopy(void* dstPtr, const void* srcPtr, void* dstEnd)
42 {
43  BYTE* d = (BYTE*)dstPtr;
44  const BYTE* s = (const BYTE*)srcPtr;
45  BYTE* const e = (BYTE*)dstEnd;
46 
47 #if 0
48  const size_t l2 = 8 - (((size_t)d) & (sizeof(void*)-1));
49  LZ4_copy8(d,s); if (d>e-9) return;
50  d+=l2; s+=l2;
51 #endif /* join to align */
52 
53  do { LZ4_copy8(d,s); d+=8; s+=8; } while (d<e);
54 }
55 
56 
57 /**************************************
58 * Common Constants
59 **************************************/
60 #define MINMATCH 4
61 
62 #define WILDCOPYLENGTH 8
63 #define LASTLITERALS 5
64 #define MFLIMIT (WILDCOPYLENGTH+MINMATCH)
65 static const int LZ4_minLength = (MFLIMIT+1);
66 
67 #define KB *(1 <<10)
68 #define MB *(1 <<20)
69 #define GB *(1U<<30)
70 
71 #define MAXD_LOG 16
72 #define MAX_DISTANCE ((1 << MAXD_LOG) - 1)
73 
74 #define ML_BITS 4
75 #define ML_MASK ((1U<<ML_BITS)-1)
76 #define RUN_BITS (8-ML_BITS)
77 #define RUN_MASK ((1U<<RUN_BITS)-1)
78 
79 
80 /**************************************
81 * Local Structures and types
82 **************************************/
83 typedef enum { noDict = 0, withPrefix64k, usingExtDict } dict_directive;
84 typedef enum { endOnOutputSize = 0, endOnInputSize = 1 } endCondition_directive;
85 typedef enum { full = 0, partial = 1 } earlyEnd_directive;
86 
87 
88 
89 /*******************************
90 * Decompression functions
91 *******************************/
92 /*
93  * This generic decompression function cover all use cases.
94  * It shall be instantiated several times, using different sets of directives
95  * Note that it is essential this generic function is really inlined,
96  * in order to remove useless branches during compilation optimization.
97  */
98 FORCE_INLINE int LZ4_decompress_generic(
99  const char* const source,
100  char* const dest,
101  int inputSize,
102  int outputSize, /* If endOnInput==endOnInputSize, this value is the max size of Output Buffer. */
103 
104  int endOnInput, /* endOnOutputSize, endOnInputSize */
105  int partialDecoding, /* full, partial */
106  int targetOutputSize, /* only used if partialDecoding==partial */
107  int dict, /* noDict, withPrefix64k, usingExtDict */
108  const BYTE* const lowPrefix, /* == dest if dict == noDict */
109  const BYTE* const dictStart, /* only if dict==usingExtDict */
110  const size_t dictSize /* note : = 0 if noDict */
111  )
112 {
113  /* Local Variables */
114  const BYTE* ip = (const BYTE*) source;
115  const BYTE* const iend = ip + inputSize;
116 
117  BYTE* op = (BYTE*) dest;
118  BYTE* const oend = op + outputSize;
119  BYTE* cpy;
120  BYTE* oexit = op + targetOutputSize;
121  const BYTE* const lowLimit = lowPrefix - dictSize;
122 
123  const BYTE* const dictEnd = (const BYTE*)dictStart + dictSize;
124  const unsigned dec32table[] = {4, 1, 2, 1, 4, 4, 4, 4};
125  const int dec64table[] = {0, 0, 0, -1, 0, 1, 2, 3};
126 
127  const int safeDecode = (endOnInput==endOnInputSize);
128  const int checkOffset = ((safeDecode) && (dictSize < (int)(64 KB)));
129  const int inPlaceDecode = ((ip >= op) && (ip < oend));
130 
131 
132  /* Special cases */
133  if ((partialDecoding) && (oexit> oend-MFLIMIT)) oexit = oend-MFLIMIT; /* targetOutputSize too high => decode everything */
134  if ((endOnInput) && (unlikely(outputSize==0))) return ((inputSize==1) && (*ip==0)) ? 0 : -1; /* Empty output buffer */
135  if ((!endOnInput) && (unlikely(outputSize==0))) return (*ip==0?1:-1);
136 
137 
138  /* Main Loop */
139  while (1)
140  {
141  unsigned token;
142  size_t length;
143  const BYTE* match;
144  size_t offset;
145 
146  if (unlikely((inPlaceDecode) && (op + WILDCOPYLENGTH > ip))) goto _output_error; /* output stream ran over input stream */
147 
148  /* get literal length */
149  token = *ip++;
150  if ((length=(token>>ML_BITS)) == RUN_MASK)
151  {
152  unsigned s;
153  if ((endOnInput) && unlikely(ip>=iend-RUN_MASK)) goto _output_error; /* overflow detection */
154  do
155  {
156  s = *ip++;
157  length += s;
158  }
159  while ( likely(endOnInput ? ip<iend-RUN_MASK : 1) && (s==255) );
160  if ((safeDecode) && unlikely((size_t)(op+length)<(size_t)(op))) goto _output_error; /* overflow detection */
161  if ((safeDecode) && unlikely((size_t)(ip+length)<(size_t)(ip))) goto _output_error; /* overflow detection */
162  }
163 
164  /* copy literals */
165  cpy = op+length;
166  if (((endOnInput) && ((cpy>(partialDecoding?oexit:oend-MFLIMIT)) || (ip+length>iend-(2+1+LASTLITERALS))) )
167  || ((!endOnInput) && (cpy>oend-WILDCOPYLENGTH)))
168  {
169  if (partialDecoding)
170  {
171  if (cpy > oend) goto _output_error; /* Error : write attempt beyond end of output buffer */
172  if ((endOnInput) && (ip+length > iend)) goto _output_error; /* Error : read attempt beyond end of input buffer */
173  }
174  else
175  {
176  if ((!endOnInput) && (cpy != oend)) goto _output_error; /* Error : block decoding must stop exactly there */
177  if ((endOnInput) && ((ip+length != iend) || (cpy > oend))) goto _output_error; /* Error : input must be consumed */
178  }
179  memmove(op, ip, length);
180  ip += length;
181  op += length;
182  break; /* Necessarily EOF, due to parsing restrictions */
183  }
184  LZ4_wildCopy(op, ip, cpy);
185  ip += length; op = cpy;
186 
187  /* get offset */
188  offset = LZ4_readLE16(ip); ip+=2;
189  match = op - offset;
190  if ((checkOffset) && (unlikely(match < lowLimit))) goto _output_error; /* Error : offset outside buffers */
191 
192  /* get matchlength */
193  length = token & ML_MASK;
194  if (length == ML_MASK)
195  {
196  unsigned s;
197  do
198  {
199  if ((endOnInput) && (ip > iend-LASTLITERALS)) goto _output_error;
200  s = *ip++;
201  length += s;
202  } while (s==255);
203  if ((safeDecode) && unlikely((size_t)(op+length)<(size_t)op)) goto _output_error; /* overflow detection */
204  }
205  length += MINMATCH;
206 
207  /* check external dictionary */
208  if ((dict==usingExtDict) && (match < lowPrefix))
209  {
210  if (unlikely(op+length > oend-LASTLITERALS)) goto _output_error; /* doesn't respect parsing restriction */
211 
212  if (length <= (size_t)(lowPrefix-match))
213  {
214  /* match can be copied as a single segment from external dictionary */
215  match = dictEnd - (lowPrefix-match);
216  memmove(op, match, length); op += length;
217  }
218  else
219  {
220  /* match encompass external dictionary and current block */
221  size_t copySize = (size_t)(lowPrefix-match);
222  memcpy(op, dictEnd - copySize, copySize);
223  op += copySize;
224  copySize = length - copySize;
225  if (copySize > (size_t)(op-lowPrefix)) /* overlap copy */
226  {
227  BYTE* const endOfMatch = op + copySize;
228  const BYTE* copyFrom = lowPrefix;
229  while (op < endOfMatch) *op++ = *copyFrom++;
230  }
231  else
232  {
233  memcpy(op, lowPrefix, copySize);
234  op += copySize;
235  }
236  }
237  continue;
238  }
239 
240  /* copy match within block */
241  cpy = op + length;
242  if (unlikely(offset<8))
243  {
244  const int dec64 = dec64table[offset];
245  op[0] = match[0];
246  op[1] = match[1];
247  op[2] = match[2];
248  op[3] = match[3];
249  match += dec32table[offset];
250  memcpy(op+4, match, 4);
251  match -= dec64;
252  } else { LZ4_copy8(op, match); match+=8; }
253  op += 8;
254 
255  if (unlikely(cpy>oend-12))
256  {
257  BYTE* const oCopyLimit = oend-(WILDCOPYLENGTH-1);
258  if (cpy > oend-LASTLITERALS) goto _output_error; /* Error : last LASTLITERALS bytes must be literals (uncompressed) */
259  if (op < oCopyLimit)
260  {
261  LZ4_wildCopy(op, match, oCopyLimit);
262  match += oCopyLimit - op;
263  op = oCopyLimit;
264  }
265  while (op<cpy) *op++ = *match++;
266  }
267  else
268  LZ4_wildCopy(op, match, cpy);
269  op=cpy; /* correction */
270  }
271 
272  /* end of decoding */
273  if (endOnInput)
274  return (int) (((char*)op)-dest); /* Nb of output bytes decoded */
275  else
276  return (int) (((const char*)ip)-source); /* Nb of input bytes read */
277 
278  /* Overflow error detected */
279 _output_error:
280  return (int) (-(((const char*)ip)-source))-1;
281 }
void * memcpy(void *dest, const void *src, size_t n)
Definition: memcpy.c:7
void * memmove(void *dest, const void *src, size_t n)
Definition: memmove.c:10
static size_t offset
Definition: flashconsole.c:16
uint64_t length
Definition: fw_cfg_if.h:1
static uint16_t LZ4_readLE16(const void *src)
Definition: lz4_wrapper.c:13
static void LZ4_copy8(void *dst, const void *src)
Definition: lz4_wrapper.c:17
#define likely(expr)
Definition: lz4_wrapper.c:58
uint8_t BYTE
Definition: lz4_wrapper.c:51
#define FORCE_INLINE
Definition: lz4_wrapper.c:57
#define unlikely(expr)
Definition: lz4_wrapper.c:59
__SIZE_TYPE__ size_t
Definition: stddef.h:7
#define s(param, src_bits, pmcreg, dst_bits)