]> git.proxmox.com Git - mirror_edk2.git/blame - BaseTools/Source/C/Common/Decompress.c
BaseTools: Add more checker in Decompress algorithm to access the valid buffer (CVE...
[mirror_edk2.git] / BaseTools / Source / C / Common / Decompress.c
CommitLineData
30fdf114 1/** @file\r
f7496d71 2Decompressor. Algorithm Ported from OPSD code (Decomp.asm) for Efi and Tiano\r
97fa0ee9 3compress algorithm.\r
30fdf114 4\r
f7496d71 5Copyright (c) 2004 - 2018, Intel Corporation. All rights reserved.<BR>\r
40d841f6 6This program and the accompanying materials\r
30fdf114
LG
7are licensed and made available under the terms and conditions of the BSD License\r
8which accompanies this distribution. The full text of the license may be found at\r
9http://opensource.org/licenses/bsd-license.php\r
10\r
11THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
12WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
13\r
30fdf114
LG
14--*/\r
15\r
16#include <stdlib.h>\r
17#include <string.h>\r
b3520abd 18#include <assert.h>\r
30fdf114
LG
19#include "Decompress.h"\r
20\r
21//\r
22// Decompression algorithm begins here\r
23//\r
24#define BITBUFSIZ 32\r
25#define MAXMATCH 256\r
26#define THRESHOLD 3\r
27#define CODE_BIT 16\r
28#define BAD_TABLE - 1\r
29\r
30//\r
31// C: Char&Len Set; P: Position Set; T: exTra Set\r
32//\r
33#define NC (0xff + MAXMATCH + 2 - THRESHOLD)\r
34#define CBIT 9\r
35#define EFIPBIT 4\r
36#define MAXPBIT 5\r
37#define TBIT 5\r
38#define MAXNP ((1U << MAXPBIT) - 1)\r
39#define NT (CODE_BIT + 3)\r
40#if NT > MAXNP\r
41#define NPT NT\r
42#else\r
43#define NPT MAXNP\r
44#endif\r
45\r
46typedef struct {\r
47 UINT8 *mSrcBase; // Starting address of compressed data\r
48 UINT8 *mDstBase; // Starting address of decompressed data\r
49 UINT32 mOutBuf;\r
50 UINT32 mInBuf;\r
51\r
52 UINT16 mBitCount;\r
53 UINT32 mBitBuf;\r
54 UINT32 mSubBitBuf;\r
55 UINT16 mBlockSize;\r
56 UINT32 mCompSize;\r
57 UINT32 mOrigSize;\r
58\r
59 UINT16 mBadTableFlag;\r
60\r
61 UINT16 mLeft[2 * NC - 1];\r
62 UINT16 mRight[2 * NC - 1];\r
63 UINT8 mCLen[NC];\r
64 UINT8 mPTLen[NPT];\r
65 UINT16 mCTable[4096];\r
66 UINT16 mPTTable[256];\r
67} SCRATCH_DATA;\r
68\r
69STATIC UINT16 mPbit = EFIPBIT;\r
70\r
71STATIC\r
72VOID\r
73FillBuf (\r
74 IN SCRATCH_DATA *Sd,\r
75 IN UINT16 NumOfBits\r
76 )\r
77/*++\r
78\r
79Routine Description:\r
80\r
81 Shift mBitBuf NumOfBits left. Read in NumOfBits of bits from source.\r
82\r
83Arguments:\r
84\r
85 Sd - The global scratch data\r
86 NumOfBit - The number of bits to shift and read.\r
87\r
88Returns: (VOID)\r
89\r
90--*/\r
91{\r
59bc913c 92 Sd->mBitBuf = (UINT32) (((UINT64)Sd->mBitBuf) << NumOfBits);\r
30fdf114
LG
93\r
94 while (NumOfBits > Sd->mBitCount) {\r
95\r
59bc913c 96 Sd->mBitBuf |= (UINT32) (((UINT64)Sd->mSubBitBuf) << (NumOfBits = (UINT16) (NumOfBits - Sd->mBitCount)));\r
30fdf114
LG
97\r
98 if (Sd->mCompSize > 0) {\r
99 //\r
100 // Get 1 byte into SubBitBuf\r
101 //\r
102 Sd->mCompSize--;\r
103 Sd->mSubBitBuf = 0;\r
104 Sd->mSubBitBuf = Sd->mSrcBase[Sd->mInBuf++];\r
105 Sd->mBitCount = 8;\r
106\r
107 } else {\r
108 //\r
109 // No more bits from the source, just pad zero bit.\r
110 //\r
111 Sd->mSubBitBuf = 0;\r
112 Sd->mBitCount = 8;\r
113\r
114 }\r
115 }\r
116\r
117 Sd->mBitCount = (UINT16) (Sd->mBitCount - NumOfBits);\r
118 Sd->mBitBuf |= Sd->mSubBitBuf >> Sd->mBitCount;\r
119}\r
120\r
121STATIC\r
122UINT32\r
123GetBits (\r
124 IN SCRATCH_DATA *Sd,\r
125 IN UINT16 NumOfBits\r
126 )\r
127/*++\r
128\r
129Routine Description:\r
130\r
131 Get NumOfBits of bits out from mBitBuf. Fill mBitBuf with subsequent\r
132 NumOfBits of bits from source. Returns NumOfBits of bits that are\r
133 popped out.\r
134\r
135Arguments:\r
136\r
137 Sd - The global scratch data.\r
138 NumOfBits - The number of bits to pop and read.\r
139\r
140Returns:\r
141\r
142 The bits that are popped out.\r
143\r
144--*/\r
145{\r
146 UINT32 OutBits;\r
147\r
148 OutBits = (UINT32) (Sd->mBitBuf >> (BITBUFSIZ - NumOfBits));\r
149\r
150 FillBuf (Sd, NumOfBits);\r
151\r
152 return OutBits;\r
153}\r
154\r
155STATIC\r
156UINT16\r
157MakeTable (\r
158 IN SCRATCH_DATA *Sd,\r
159 IN UINT16 NumOfChar,\r
160 IN UINT8 *BitLen,\r
161 IN UINT16 TableBits,\r
162 OUT UINT16 *Table\r
163 )\r
164/*++\r
165\r
166Routine Description:\r
167\r
168 Creates Huffman Code mapping table according to code length array.\r
169\r
170Arguments:\r
171\r
172 Sd - The global scratch data\r
173 NumOfChar - Number of symbols in the symbol set\r
174 BitLen - Code length array\r
175 TableBits - The width of the mapping table\r
176 Table - The table\r
177\r
178Returns:\r
179\r
180 0 - OK.\r
181 BAD_TABLE - The table is corrupted.\r
182\r
183--*/\r
184{\r
185 UINT16 Count[17];\r
186 UINT16 Weight[17];\r
187 UINT16 Start[18];\r
188 UINT16 *Pointer;\r
189 UINT16 Index3;\r
190 UINT16 Index;\r
191 UINT16 Len;\r
192 UINT16 Char;\r
193 UINT16 JuBits;\r
194 UINT16 Avail;\r
195 UINT16 NextCode;\r
196 UINT16 Mask;\r
041d89bc 197 UINT16 MaxTableLength;\r
30fdf114
LG
198\r
199 for (Index = 1; Index <= 16; Index++) {\r
200 Count[Index] = 0;\r
201 }\r
202\r
203 for (Index = 0; Index < NumOfChar; Index++) {\r
041d89bc
LG
204 if (BitLen[Index] > 16) {\r
205 return (UINT16) BAD_TABLE;\r
206 }\r
30fdf114
LG
207 Count[BitLen[Index]]++;\r
208 }\r
209\r
210 Start[1] = 0;\r
211\r
212 for (Index = 1; Index <= 16; Index++) {\r
213 Start[Index + 1] = (UINT16) (Start[Index] + (Count[Index] << (16 - Index)));\r
214 }\r
215\r
216 if (Start[17] != 0) {\r
217 /*(1U << 16)*/\r
218 return (UINT16) BAD_TABLE;\r
219 }\r
220\r
221 JuBits = (UINT16) (16 - TableBits);\r
222\r
223 for (Index = 1; Index <= TableBits; Index++) {\r
224 Start[Index] >>= JuBits;\r
225 Weight[Index] = (UINT16) (1U << (TableBits - Index));\r
226 }\r
227\r
228 while (Index <= 16) {\r
229 Weight[Index] = (UINT16) (1U << (16 - Index));\r
230 Index++;\r
231 }\r
232\r
233 Index = (UINT16) (Start[TableBits + 1] >> JuBits);\r
234\r
235 if (Index != 0) {\r
236 Index3 = (UINT16) (1U << TableBits);\r
237 while (Index != Index3) {\r
238 Table[Index++] = 0;\r
239 }\r
240 }\r
241\r
242 Avail = NumOfChar;\r
243 Mask = (UINT16) (1U << (15 - TableBits));\r
041d89bc 244 MaxTableLength = (UINT16) (1U << TableBits);\r
30fdf114
LG
245\r
246 for (Char = 0; Char < NumOfChar; Char++) {\r
247\r
248 Len = BitLen[Char];\r
b3520abd 249 if (Len == 0 || Len >= 17) {\r
30fdf114
LG
250 continue;\r
251 }\r
252\r
253 NextCode = (UINT16) (Start[Len] + Weight[Len]);\r
254\r
255 if (Len <= TableBits) {\r
256\r
257 for (Index = Start[Len]; Index < NextCode; Index++) {\r
041d89bc
LG
258 if (Index >= MaxTableLength) {\r
259 return (UINT16) BAD_TABLE;\r
260 }\r
30fdf114
LG
261 Table[Index] = Char;\r
262 }\r
263\r
264 } else {\r
265\r
266 Index3 = Start[Len];\r
267 Pointer = &Table[Index3 >> JuBits];\r
268 Index = (UINT16) (Len - TableBits);\r
269\r
270 while (Index != 0) {\r
271 if (*Pointer == 0) {\r
272 Sd->mRight[Avail] = Sd->mLeft[Avail] = 0;\r
273 *Pointer = Avail++;\r
274 }\r
275\r
276 if (Index3 & Mask) {\r
277 Pointer = &Sd->mRight[*Pointer];\r
278 } else {\r
279 Pointer = &Sd->mLeft[*Pointer];\r
280 }\r
281\r
282 Index3 <<= 1;\r
283 Index--;\r
284 }\r
285\r
286 *Pointer = Char;\r
287\r
288 }\r
289\r
290 Start[Len] = NextCode;\r
291 }\r
292 //\r
293 // Succeeds\r
294 //\r
295 return 0;\r
296}\r
297\r
298STATIC\r
299UINT32\r
300DecodeP (\r
301 IN SCRATCH_DATA *Sd\r
302 )\r
303/*++\r
304\r
305Routine Description:\r
306\r
307 Decodes a position value.\r
308\r
309Arguments:\r
310\r
311 Sd - the global scratch data\r
312\r
313Returns:\r
314\r
315 The position value decoded.\r
316\r
317--*/\r
318{\r
319 UINT16 Val;\r
320 UINT32 Mask;\r
321 UINT32 Pos;\r
322\r
323 Val = Sd->mPTTable[Sd->mBitBuf >> (BITBUFSIZ - 8)];\r
324\r
325 if (Val >= MAXNP) {\r
326 Mask = 1U << (BITBUFSIZ - 1 - 8);\r
327\r
328 do {\r
329\r
330 if (Sd->mBitBuf & Mask) {\r
331 Val = Sd->mRight[Val];\r
332 } else {\r
333 Val = Sd->mLeft[Val];\r
334 }\r
335\r
336 Mask >>= 1;\r
337 } while (Val >= MAXNP);\r
338 }\r
339 //\r
340 // Advance what we have read\r
341 //\r
342 FillBuf (Sd, Sd->mPTLen[Val]);\r
343\r
344 Pos = Val;\r
345 if (Val > 1) {\r
346 Pos = (UINT32) ((1U << (Val - 1)) + GetBits (Sd, (UINT16) (Val - 1)));\r
347 }\r
348\r
349 return Pos;\r
350}\r
351\r
352STATIC\r
353UINT16\r
354ReadPTLen (\r
355 IN SCRATCH_DATA *Sd,\r
356 IN UINT16 nn,\r
357 IN UINT16 nbit,\r
358 IN UINT16 Special\r
359 )\r
360/*++\r
361\r
362Routine Description:\r
363\r
364 Reads code lengths for the Extra Set or the Position Set\r
365\r
366Arguments:\r
367\r
368 Sd - The global scratch data\r
369 nn - Number of symbols\r
370 nbit - Number of bits needed to represent nn\r
371 Special - The special symbol that needs to be taken care of\r
372\r
373Returns:\r
374\r
375 0 - OK.\r
376 BAD_TABLE - Table is corrupted.\r
377\r
378--*/\r
379{\r
380 UINT16 Number;\r
381 UINT16 CharC;\r
382 UINT16 Index;\r
383 UINT32 Mask;\r
384\r
b3520abd
HW
385 assert (nn <= NPT);\r
386\r
30fdf114
LG
387 Number = (UINT16) GetBits (Sd, nbit);\r
388\r
389 if (Number == 0) {\r
390 CharC = (UINT16) GetBits (Sd, nbit);\r
391\r
392 for (Index = 0; Index < 256; Index++) {\r
393 Sd->mPTTable[Index] = CharC;\r
394 }\r
395\r
396 for (Index = 0; Index < nn; Index++) {\r
397 Sd->mPTLen[Index] = 0;\r
398 }\r
399\r
400 return 0;\r
401 }\r
402\r
403 Index = 0;\r
404\r
58356e94 405 while (Index < Number && Index < NPT) {\r
30fdf114
LG
406\r
407 CharC = (UINT16) (Sd->mBitBuf >> (BITBUFSIZ - 3));\r
408\r
409 if (CharC == 7) {\r
410 Mask = 1U << (BITBUFSIZ - 1 - 3);\r
411 while (Mask & Sd->mBitBuf) {\r
412 Mask >>= 1;\r
413 CharC += 1;\r
414 }\r
415 }\r
416\r
417 FillBuf (Sd, (UINT16) ((CharC < 7) ? 3 : CharC - 3));\r
418\r
419 Sd->mPTLen[Index++] = (UINT8) CharC;\r
420\r
421 if (Index == Special) {\r
422 CharC = (UINT16) GetBits (Sd, 2);\r
423 CharC--;\r
58356e94 424 while ((INT16) (CharC) >= 0 && Index < NPT) {\r
30fdf114
LG
425 Sd->mPTLen[Index++] = 0;\r
426 CharC--;\r
427 }\r
428 }\r
429 }\r
430\r
58356e94 431 while (Index < nn && Index < NPT) {\r
30fdf114
LG
432 Sd->mPTLen[Index++] = 0;\r
433 }\r
434\r
435 return MakeTable (Sd, nn, Sd->mPTLen, 8, Sd->mPTTable);\r
436}\r
437\r
438STATIC\r
439VOID\r
440ReadCLen (\r
441 SCRATCH_DATA *Sd\r
442 )\r
443/*++\r
444\r
445Routine Description:\r
446\r
447 Reads code lengths for Char&Len Set.\r
448\r
449Arguments:\r
450\r
451 Sd - the global scratch data\r
452\r
453Returns: (VOID)\r
454\r
455--*/\r
456{\r
457 UINT16 Number;\r
458 UINT16 CharC;\r
459 UINT16 Index;\r
460 UINT32 Mask;\r
461\r
462 Number = (UINT16) GetBits (Sd, CBIT);\r
463\r
464 if (Number == 0) {\r
465 CharC = (UINT16) GetBits (Sd, CBIT);\r
466\r
467 for (Index = 0; Index < NC; Index++) {\r
468 Sd->mCLen[Index] = 0;\r
469 }\r
470\r
471 for (Index = 0; Index < 4096; Index++) {\r
472 Sd->mCTable[Index] = CharC;\r
473 }\r
474\r
475 return ;\r
476 }\r
477\r
478 Index = 0;\r
479 while (Index < Number) {\r
480\r
481 CharC = Sd->mPTTable[Sd->mBitBuf >> (BITBUFSIZ - 8)];\r
482 if (CharC >= NT) {\r
483 Mask = 1U << (BITBUFSIZ - 1 - 8);\r
484\r
485 do {\r
486\r
487 if (Mask & Sd->mBitBuf) {\r
488 CharC = Sd->mRight[CharC];\r
489 } else {\r
490 CharC = Sd->mLeft[CharC];\r
491 }\r
492\r
493 Mask >>= 1;\r
494\r
495 } while (CharC >= NT);\r
496 }\r
497 //\r
498 // Advance what we have read\r
499 //\r
500 FillBuf (Sd, Sd->mPTLen[CharC]);\r
501\r
502 if (CharC <= 2) {\r
503\r
504 if (CharC == 0) {\r
505 CharC = 1;\r
506 } else if (CharC == 1) {\r
507 CharC = (UINT16) (GetBits (Sd, 4) + 3);\r
508 } else if (CharC == 2) {\r
509 CharC = (UINT16) (GetBits (Sd, CBIT) + 20);\r
510 }\r
511\r
512 CharC--;\r
513 while ((INT16) (CharC) >= 0) {\r
514 Sd->mCLen[Index++] = 0;\r
515 CharC--;\r
516 }\r
517\r
518 } else {\r
519\r
520 Sd->mCLen[Index++] = (UINT8) (CharC - 2);\r
521\r
522 }\r
523 }\r
524\r
525 while (Index < NC) {\r
526 Sd->mCLen[Index++] = 0;\r
527 }\r
528\r
529 MakeTable (Sd, NC, Sd->mCLen, 12, Sd->mCTable);\r
530\r
531 return ;\r
532}\r
533\r
534STATIC\r
535UINT16\r
536DecodeC (\r
537 SCRATCH_DATA *Sd\r
538 )\r
539/*++\r
540\r
541Routine Description:\r
542\r
543 Decode a character/length value.\r
544\r
545Arguments:\r
546\r
547 Sd - The global scratch data.\r
548\r
549Returns:\r
550\r
551 The value decoded.\r
552\r
553--*/\r
554{\r
555 UINT16 Index2;\r
556 UINT32 Mask;\r
557\r
558 if (Sd->mBlockSize == 0) {\r
559 //\r
560 // Starting a new block\r
561 //\r
562 Sd->mBlockSize = (UINT16) GetBits (Sd, 16);\r
563 Sd->mBadTableFlag = ReadPTLen (Sd, NT, TBIT, 3);\r
564 if (Sd->mBadTableFlag != 0) {\r
565 return 0;\r
566 }\r
567\r
568 ReadCLen (Sd);\r
569\r
570 Sd->mBadTableFlag = ReadPTLen (Sd, MAXNP, mPbit, (UINT16) (-1));\r
571 if (Sd->mBadTableFlag != 0) {\r
572 return 0;\r
573 }\r
574 }\r
575\r
576 Sd->mBlockSize--;\r
577 Index2 = Sd->mCTable[Sd->mBitBuf >> (BITBUFSIZ - 12)];\r
578\r
579 if (Index2 >= NC) {\r
580 Mask = 1U << (BITBUFSIZ - 1 - 12);\r
581\r
582 do {\r
583 if (Sd->mBitBuf & Mask) {\r
584 Index2 = Sd->mRight[Index2];\r
585 } else {\r
586 Index2 = Sd->mLeft[Index2];\r
587 }\r
588\r
589 Mask >>= 1;\r
590 } while (Index2 >= NC);\r
591 }\r
592 //\r
593 // Advance what we have read\r
594 //\r
595 FillBuf (Sd, Sd->mCLen[Index2]);\r
596\r
597 return Index2;\r
598}\r
599\r
600STATIC\r
601VOID\r
602Decode (\r
603 SCRATCH_DATA *Sd\r
604 )\r
605/*++\r
606\r
607Routine Description:\r
608\r
609 Decode the source data and put the resulting data into the destination buffer.\r
610\r
611Arguments:\r
612\r
613 Sd - The global scratch data\r
614\r
615Returns: (VOID)\r
616\r
617 --*/\r
618{\r
619 UINT16 BytesRemain;\r
620 UINT32 DataIdx;\r
621 UINT16 CharC;\r
622\r
623 BytesRemain = (UINT16) (-1);\r
624\r
625 DataIdx = 0;\r
626\r
627 for (;;) {\r
628 CharC = DecodeC (Sd);\r
629 if (Sd->mBadTableFlag != 0) {\r
630 return ;\r
631 }\r
632\r
633 if (CharC < 256) {\r
634 //\r
635 // Process an Original character\r
636 //\r
637 Sd->mDstBase[Sd->mOutBuf++] = (UINT8) CharC;\r
638 if (Sd->mOutBuf >= Sd->mOrigSize) {\r
639 return ;\r
640 }\r
641\r
642 } else {\r
643 //\r
644 // Process a Pointer\r
645 //\r
646 CharC = (UINT16) (CharC - (UINT8_MAX + 1 - THRESHOLD));\r
647\r
648 BytesRemain = CharC;\r
649\r
650 DataIdx = Sd->mOutBuf - DecodeP (Sd) - 1;\r
651\r
652 BytesRemain--;\r
653 while ((INT16) (BytesRemain) >= 0) {\r
30fdf114
LG
654 if (Sd->mOutBuf >= Sd->mOrigSize) {\r
655 return ;\r
656 }\r
041d89bc
LG
657 if (DataIdx >= Sd->mOrigSize) {\r
658 Sd->mBadTableFlag = (UINT16) BAD_TABLE;\r
659 return ;\r
660 }\r
661 Sd->mDstBase[Sd->mOutBuf++] = Sd->mDstBase[DataIdx++];\r
30fdf114
LG
662\r
663 BytesRemain--;\r
664 }\r
665 }\r
666 }\r
667\r
668 return ;\r
669}\r
670\r
671EFI_STATUS\r
672GetInfo (\r
673 IN VOID *Source,\r
674 IN UINT32 SrcSize,\r
675 OUT UINT32 *DstSize,\r
676 OUT UINT32 *ScratchSize\r
677 )\r
678/*++\r
679\r
680Routine Description:\r
681\r
682 The implementation of EFI_DECOMPRESS_PROTOCOL.GetInfo().\r
683\r
684Arguments:\r
685\r
686 Source - The source buffer containing the compressed data.\r
687 SrcSize - The size of source buffer\r
688 DstSize - The size of destination buffer.\r
689 ScratchSize - The size of scratch buffer.\r
690\r
691Returns:\r
692\r
99e55970 693 EFI_SUCCESS - The size of destination buffer and the size of scratch buffer are successfully retrieved.\r
30fdf114
LG
694 EFI_INVALID_PARAMETER - The source data is corrupted\r
695\r
696--*/\r
697{\r
698 UINT8 *Src;\r
041d89bc 699 UINT32 CompSize;\r
30fdf114
LG
700\r
701 *ScratchSize = sizeof (SCRATCH_DATA);\r
702\r
703 Src = Source;\r
704 if (SrcSize < 8) {\r
705 return EFI_INVALID_PARAMETER;\r
706 }\r
707\r
041d89bc 708 CompSize = Src[0] + (Src[1] << 8) + (Src[2] << 16) + (Src[3] << 24);\r
30fdf114 709 *DstSize = Src[4] + (Src[5] << 8) + (Src[6] << 16) + (Src[7] << 24);\r
041d89bc
LG
710\r
711 if (SrcSize < CompSize + 8 || (CompSize + 8) < 8) {\r
712 return EFI_INVALID_PARAMETER;\r
713 }\r
714\r
30fdf114
LG
715 return EFI_SUCCESS;\r
716}\r
717\r
718EFI_STATUS\r
719Decompress (\r
720 IN VOID *Source,\r
721 IN UINT32 SrcSize,\r
722 IN OUT VOID *Destination,\r
723 IN UINT32 DstSize,\r
724 IN OUT VOID *Scratch,\r
725 IN UINT32 ScratchSize\r
726 )\r
727/*++\r
728\r
729Routine Description:\r
730\r
731 The implementation Efi and Tiano Decompress().\r
732\r
733Arguments:\r
734\r
735 Source - The source buffer containing the compressed data.\r
736 SrcSize - The size of source buffer\r
737 Destination - The destination buffer to store the decompressed data\r
738 DstSize - The size of destination buffer.\r
739 Scratch - The buffer used internally by the decompress routine. This buffer is needed to store intermediate data.\r
740 ScratchSize - The size of scratch buffer.\r
741\r
742Returns:\r
743\r
744 EFI_SUCCESS - Decompression is successfull\r
745 EFI_INVALID_PARAMETER - The source data is corrupted\r
746\r
747--*/\r
748{\r
749 UINT32 Index;\r
750 UINT32 CompSize;\r
751 UINT32 OrigSize;\r
752 EFI_STATUS Status;\r
753 SCRATCH_DATA *Sd;\r
754 UINT8 *Src;\r
755 UINT8 *Dst;\r
756\r
757 Status = EFI_SUCCESS;\r
758 Src = Source;\r
759 Dst = Destination;\r
760\r
761 if (ScratchSize < sizeof (SCRATCH_DATA)) {\r
762 return EFI_INVALID_PARAMETER;\r
763 }\r
764\r
765 Sd = (SCRATCH_DATA *) Scratch;\r
766\r
767 if (SrcSize < 8) {\r
768 return EFI_INVALID_PARAMETER;\r
769 }\r
770\r
771 CompSize = Src[0] + (Src[1] << 8) + (Src[2] << 16) + (Src[3] << 24);\r
772 OrigSize = Src[4] + (Src[5] << 8) + (Src[6] << 16) + (Src[7] << 24);\r
773\r
041d89bc 774 if (SrcSize < CompSize + 8 || (CompSize + 8) < 8) {\r
30fdf114
LG
775 return EFI_INVALID_PARAMETER;\r
776 }\r
777\r
778 if (DstSize != OrigSize) {\r
779 return EFI_INVALID_PARAMETER;\r
780 }\r
781\r
782 Src = Src + 8;\r
783\r
784 for (Index = 0; Index < sizeof (SCRATCH_DATA); Index++) {\r
785 ((UINT8 *) Sd)[Index] = 0;\r
786 }\r
787\r
788 Sd->mSrcBase = Src;\r
789 Sd->mDstBase = Dst;\r
790 Sd->mCompSize = CompSize;\r
791 Sd->mOrigSize = OrigSize;\r
792\r
793 //\r
794 // Fill the first BITBUFSIZ bits\r
795 //\r
796 FillBuf (Sd, BITBUFSIZ);\r
797\r
798 //\r
799 // Decompress it\r
800 //\r
801 Decode (Sd);\r
802\r
803 if (Sd->mBadTableFlag != 0) {\r
804 //\r
805 // Something wrong with the source\r
806 //\r
807 Status = EFI_INVALID_PARAMETER;\r
808 }\r
809\r
810 return Status;\r
811}\r
812\r
813EFI_STATUS\r
814EfiGetInfo (\r
815 IN VOID *Source,\r
816 IN UINT32 SrcSize,\r
817 OUT UINT32 *DstSize,\r
818 OUT UINT32 *ScratchSize\r
819 )\r
820/*++\r
821\r
822Routine Description:\r
823\r
824 The implementation Efi Decompress GetInfo().\r
825\r
826Arguments:\r
827\r
828 Source - The source buffer containing the compressed data.\r
829 SrcSize - The size of source buffer\r
830 DstSize - The size of destination buffer.\r
831 ScratchSize - The size of scratch buffer.\r
832\r
833Returns:\r
834\r
99e55970 835 EFI_SUCCESS - The size of destination buffer and the size of scratch buffer are successfully retrieved.\r
30fdf114
LG
836 EFI_INVALID_PARAMETER - The source data is corrupted\r
837\r
838--*/\r
839{\r
840 return GetInfo (Source, SrcSize, DstSize, ScratchSize);\r
841}\r
842\r
843EFI_STATUS\r
844TianoGetInfo (\r
845 IN VOID *Source,\r
846 IN UINT32 SrcSize,\r
847 OUT UINT32 *DstSize,\r
848 OUT UINT32 *ScratchSize\r
849 )\r
850/*++\r
851\r
852Routine Description:\r
853\r
854 The implementation Tiano Decompress GetInfo().\r
855\r
856Arguments:\r
857\r
858 Source - The source buffer containing the compressed data.\r
859 SrcSize - The size of source buffer\r
860 DstSize - The size of destination buffer.\r
861 ScratchSize - The size of scratch buffer.\r
862\r
863Returns:\r
864\r
99e55970 865 EFI_SUCCESS - The size of destination buffer and the size of scratch buffer are successfully retrieved.\r
30fdf114
LG
866 EFI_INVALID_PARAMETER - The source data is corrupted\r
867\r
868--*/\r
869{\r
870 return GetInfo (Source, SrcSize, DstSize, ScratchSize);\r
871}\r
872\r
873EFI_STATUS\r
874EfiDecompress (\r
875 IN VOID *Source,\r
876 IN UINT32 SrcSize,\r
877 IN OUT VOID *Destination,\r
878 IN UINT32 DstSize,\r
879 IN OUT VOID *Scratch,\r
880 IN UINT32 ScratchSize\r
881 )\r
882/*++\r
883\r
884Routine Description:\r
885\r
886 The implementation of Efi Decompress().\r
887\r
888Arguments:\r
889\r
890 Source - The source buffer containing the compressed data.\r
891 SrcSize - The size of source buffer\r
892 Destination - The destination buffer to store the decompressed data\r
893 DstSize - The size of destination buffer.\r
894 Scratch - The buffer used internally by the decompress routine. This buffer is needed to store intermediate data.\r
895 ScratchSize - The size of scratch buffer.\r
896\r
897Returns:\r
898\r
899 EFI_SUCCESS - Decompression is successfull\r
900 EFI_INVALID_PARAMETER - The source data is corrupted\r
901\r
902--*/\r
903{\r
904 mPbit = EFIPBIT;\r
905 return Decompress (Source, SrcSize, Destination, DstSize, Scratch, ScratchSize);\r
906}\r
907\r
908EFI_STATUS\r
909TianoDecompress (\r
910 IN VOID *Source,\r
911 IN UINT32 SrcSize,\r
912 IN OUT VOID *Destination,\r
913 IN UINT32 DstSize,\r
914 IN OUT VOID *Scratch,\r
915 IN UINT32 ScratchSize\r
916 )\r
917/*++\r
918\r
919Routine Description:\r
920\r
921 The implementation of Tiano Decompress().\r
922\r
923Arguments:\r
924\r
925 Source - The source buffer containing the compressed data.\r
926 SrcSize - The size of source buffer\r
927 Destination - The destination buffer to store the decompressed data\r
928 DstSize - The size of destination buffer.\r
929 Scratch - The buffer used internally by the decompress routine. This buffer is needed to store intermediate data.\r
930 ScratchSize - The size of scratch buffer.\r
931\r
932Returns:\r
933\r
934 EFI_SUCCESS - Decompression is successfull\r
935 EFI_INVALID_PARAMETER - The source data is corrupted\r
936\r
937--*/\r
938{\r
939 mPbit = MAXPBIT;\r
940 return Decompress (Source, SrcSize, Destination, DstSize, Scratch, ScratchSize);\r
941}\r
942\r
943EFI_STATUS\r
944Extract (\r
945 IN VOID *Source,\r
946 IN UINT32 SrcSize,\r
947 OUT VOID **Destination,\r
948 OUT UINT32 *DstSize,\r
949 IN UINTN Algorithm\r
950 )\r
951{\r
952 VOID *Scratch;\r
953 UINT32 ScratchSize;\r
954 EFI_STATUS Status;\r
955\r
aee34651
HW
956 Scratch = NULL;\r
957 Status = EFI_SUCCESS;\r
958\r
30fdf114
LG
959 switch (Algorithm) {\r
960 case 0:\r
961 *Destination = (VOID *)malloc(SrcSize);\r
962 if (*Destination != NULL) {\r
963 memcpy(*Destination, Source, SrcSize);\r
964 } else {\r
965 Status = EFI_OUT_OF_RESOURCES;\r
966 }\r
967 break;\r
968 case 1:\r
969 Status = EfiGetInfo(Source, SrcSize, DstSize, &ScratchSize);\r
970 if (Status == EFI_SUCCESS) {\r
971 Scratch = (VOID *)malloc(ScratchSize);\r
aee34651
HW
972 if (Scratch == NULL) {\r
973 return EFI_OUT_OF_RESOURCES;\r
974 }\r
975\r
30fdf114 976 *Destination = (VOID *)malloc(*DstSize);\r
aee34651
HW
977 if (*Destination == NULL) {\r
978 free (Scratch);\r
979 return EFI_OUT_OF_RESOURCES;\r
30fdf114 980 }\r
aee34651
HW
981\r
982 Status = EfiDecompress(Source, SrcSize, *Destination, *DstSize, Scratch, ScratchSize);\r
30fdf114
LG
983 }\r
984 break;\r
985 case 2:\r
986 Status = TianoGetInfo(Source, SrcSize, DstSize, &ScratchSize);\r
987 if (Status == EFI_SUCCESS) {\r
988 Scratch = (VOID *)malloc(ScratchSize);\r
aee34651
HW
989 if (Scratch == NULL) {\r
990 return EFI_OUT_OF_RESOURCES;\r
991 }\r
992\r
30fdf114 993 *Destination = (VOID *)malloc(*DstSize);\r
aee34651
HW
994 if (*Destination == NULL) {\r
995 free (Scratch);\r
996 return EFI_OUT_OF_RESOURCES;\r
30fdf114 997 }\r
aee34651
HW
998\r
999 Status = TianoDecompress(Source, SrcSize, *Destination, *DstSize, Scratch, ScratchSize);\r
30fdf114
LG
1000 }\r
1001 break;\r
1002 default:\r
1003 Status = EFI_INVALID_PARAMETER;\r
1004 }\r
1005\r
aee34651
HW
1006 if (Scratch != NULL) {\r
1007 free (Scratch);\r
1008 }\r
1009\r
30fdf114
LG
1010 return Status;\r
1011}\r
1012\r
1013\r