]> git.proxmox.com Git - mirror_edk2.git/blame - BaseTools/Source/C/Common/Decompress.c
BaseTools/C/Common: Improve performance of boundary validation
[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
55756c88
SZ
257 if (Start[Len] >= NextCode || NextCode > MaxTableLength){\r
258 return (UINT16) BAD_TABLE;\r
259 }\r
260\r
30fdf114
LG
261 for (Index = Start[Len]; Index < NextCode; Index++) {\r
262 Table[Index] = Char;\r
263 }\r
264\r
265 } else {\r
266\r
267 Index3 = Start[Len];\r
268 Pointer = &Table[Index3 >> JuBits];\r
269 Index = (UINT16) (Len - TableBits);\r
270\r
271 while (Index != 0) {\r
272 if (*Pointer == 0) {\r
273 Sd->mRight[Avail] = Sd->mLeft[Avail] = 0;\r
274 *Pointer = Avail++;\r
275 }\r
276\r
277 if (Index3 & Mask) {\r
278 Pointer = &Sd->mRight[*Pointer];\r
279 } else {\r
280 Pointer = &Sd->mLeft[*Pointer];\r
281 }\r
282\r
283 Index3 <<= 1;\r
284 Index--;\r
285 }\r
286\r
287 *Pointer = Char;\r
288\r
289 }\r
290\r
291 Start[Len] = NextCode;\r
292 }\r
293 //\r
294 // Succeeds\r
295 //\r
296 return 0;\r
297}\r
298\r
299STATIC\r
300UINT32\r
301DecodeP (\r
302 IN SCRATCH_DATA *Sd\r
303 )\r
304/*++\r
305\r
306Routine Description:\r
307\r
308 Decodes a position value.\r
309\r
310Arguments:\r
311\r
312 Sd - the global scratch data\r
313\r
314Returns:\r
315\r
316 The position value decoded.\r
317\r
318--*/\r
319{\r
320 UINT16 Val;\r
321 UINT32 Mask;\r
322 UINT32 Pos;\r
323\r
324 Val = Sd->mPTTable[Sd->mBitBuf >> (BITBUFSIZ - 8)];\r
325\r
326 if (Val >= MAXNP) {\r
327 Mask = 1U << (BITBUFSIZ - 1 - 8);\r
328\r
329 do {\r
330\r
331 if (Sd->mBitBuf & Mask) {\r
332 Val = Sd->mRight[Val];\r
333 } else {\r
334 Val = Sd->mLeft[Val];\r
335 }\r
336\r
337 Mask >>= 1;\r
338 } while (Val >= MAXNP);\r
339 }\r
340 //\r
341 // Advance what we have read\r
342 //\r
343 FillBuf (Sd, Sd->mPTLen[Val]);\r
344\r
345 Pos = Val;\r
346 if (Val > 1) {\r
347 Pos = (UINT32) ((1U << (Val - 1)) + GetBits (Sd, (UINT16) (Val - 1)));\r
348 }\r
349\r
350 return Pos;\r
351}\r
352\r
353STATIC\r
354UINT16\r
355ReadPTLen (\r
356 IN SCRATCH_DATA *Sd,\r
357 IN UINT16 nn,\r
358 IN UINT16 nbit,\r
359 IN UINT16 Special\r
360 )\r
361/*++\r
362\r
363Routine Description:\r
364\r
365 Reads code lengths for the Extra Set or the Position Set\r
366\r
367Arguments:\r
368\r
369 Sd - The global scratch data\r
370 nn - Number of symbols\r
371 nbit - Number of bits needed to represent nn\r
372 Special - The special symbol that needs to be taken care of\r
373\r
374Returns:\r
375\r
376 0 - OK.\r
377 BAD_TABLE - Table is corrupted.\r
378\r
379--*/\r
380{\r
381 UINT16 Number;\r
382 UINT16 CharC;\r
383 UINT16 Index;\r
384 UINT32 Mask;\r
385\r
b3520abd
HW
386 assert (nn <= NPT);\r
387\r
30fdf114
LG
388 Number = (UINT16) GetBits (Sd, nbit);\r
389\r
390 if (Number == 0) {\r
391 CharC = (UINT16) GetBits (Sd, nbit);\r
392\r
393 for (Index = 0; Index < 256; Index++) {\r
394 Sd->mPTTable[Index] = CharC;\r
395 }\r
396\r
397 for (Index = 0; Index < nn; Index++) {\r
398 Sd->mPTLen[Index] = 0;\r
399 }\r
400\r
401 return 0;\r
402 }\r
403\r
404 Index = 0;\r
405\r
58356e94 406 while (Index < Number && Index < NPT) {\r
30fdf114
LG
407\r
408 CharC = (UINT16) (Sd->mBitBuf >> (BITBUFSIZ - 3));\r
409\r
410 if (CharC == 7) {\r
411 Mask = 1U << (BITBUFSIZ - 1 - 3);\r
412 while (Mask & Sd->mBitBuf) {\r
413 Mask >>= 1;\r
414 CharC += 1;\r
415 }\r
416 }\r
417\r
418 FillBuf (Sd, (UINT16) ((CharC < 7) ? 3 : CharC - 3));\r
419\r
420 Sd->mPTLen[Index++] = (UINT8) CharC;\r
421\r
422 if (Index == Special) {\r
423 CharC = (UINT16) GetBits (Sd, 2);\r
424 CharC--;\r
58356e94 425 while ((INT16) (CharC) >= 0 && Index < NPT) {\r
30fdf114
LG
426 Sd->mPTLen[Index++] = 0;\r
427 CharC--;\r
428 }\r
429 }\r
430 }\r
431\r
58356e94 432 while (Index < nn && Index < NPT) {\r
30fdf114
LG
433 Sd->mPTLen[Index++] = 0;\r
434 }\r
435\r
436 return MakeTable (Sd, nn, Sd->mPTLen, 8, Sd->mPTTable);\r
437}\r
438\r
439STATIC\r
440VOID\r
441ReadCLen (\r
442 SCRATCH_DATA *Sd\r
443 )\r
444/*++\r
445\r
446Routine Description:\r
447\r
448 Reads code lengths for Char&Len Set.\r
449\r
450Arguments:\r
451\r
452 Sd - the global scratch data\r
453\r
454Returns: (VOID)\r
455\r
456--*/\r
457{\r
458 UINT16 Number;\r
459 UINT16 CharC;\r
460 UINT16 Index;\r
461 UINT32 Mask;\r
462\r
463 Number = (UINT16) GetBits (Sd, CBIT);\r
464\r
465 if (Number == 0) {\r
466 CharC = (UINT16) GetBits (Sd, CBIT);\r
467\r
468 for (Index = 0; Index < NC; Index++) {\r
469 Sd->mCLen[Index] = 0;\r
470 }\r
471\r
472 for (Index = 0; Index < 4096; Index++) {\r
473 Sd->mCTable[Index] = CharC;\r
474 }\r
475\r
476 return ;\r
477 }\r
478\r
479 Index = 0;\r
480 while (Index < Number) {\r
481\r
482 CharC = Sd->mPTTable[Sd->mBitBuf >> (BITBUFSIZ - 8)];\r
483 if (CharC >= NT) {\r
484 Mask = 1U << (BITBUFSIZ - 1 - 8);\r
485\r
486 do {\r
487\r
488 if (Mask & Sd->mBitBuf) {\r
489 CharC = Sd->mRight[CharC];\r
490 } else {\r
491 CharC = Sd->mLeft[CharC];\r
492 }\r
493\r
494 Mask >>= 1;\r
495\r
496 } while (CharC >= NT);\r
497 }\r
498 //\r
499 // Advance what we have read\r
500 //\r
501 FillBuf (Sd, Sd->mPTLen[CharC]);\r
502\r
503 if (CharC <= 2) {\r
504\r
505 if (CharC == 0) {\r
506 CharC = 1;\r
507 } else if (CharC == 1) {\r
508 CharC = (UINT16) (GetBits (Sd, 4) + 3);\r
509 } else if (CharC == 2) {\r
510 CharC = (UINT16) (GetBits (Sd, CBIT) + 20);\r
511 }\r
512\r
513 CharC--;\r
514 while ((INT16) (CharC) >= 0) {\r
515 Sd->mCLen[Index++] = 0;\r
516 CharC--;\r
517 }\r
518\r
519 } else {\r
520\r
521 Sd->mCLen[Index++] = (UINT8) (CharC - 2);\r
522\r
523 }\r
524 }\r
525\r
526 while (Index < NC) {\r
527 Sd->mCLen[Index++] = 0;\r
528 }\r
529\r
530 MakeTable (Sd, NC, Sd->mCLen, 12, Sd->mCTable);\r
531\r
532 return ;\r
533}\r
534\r
535STATIC\r
536UINT16\r
537DecodeC (\r
538 SCRATCH_DATA *Sd\r
539 )\r
540/*++\r
541\r
542Routine Description:\r
543\r
544 Decode a character/length value.\r
545\r
546Arguments:\r
547\r
548 Sd - The global scratch data.\r
549\r
550Returns:\r
551\r
552 The value decoded.\r
553\r
554--*/\r
555{\r
556 UINT16 Index2;\r
557 UINT32 Mask;\r
558\r
559 if (Sd->mBlockSize == 0) {\r
560 //\r
561 // Starting a new block\r
562 //\r
563 Sd->mBlockSize = (UINT16) GetBits (Sd, 16);\r
564 Sd->mBadTableFlag = ReadPTLen (Sd, NT, TBIT, 3);\r
565 if (Sd->mBadTableFlag != 0) {\r
566 return 0;\r
567 }\r
568\r
569 ReadCLen (Sd);\r
570\r
571 Sd->mBadTableFlag = ReadPTLen (Sd, MAXNP, mPbit, (UINT16) (-1));\r
572 if (Sd->mBadTableFlag != 0) {\r
573 return 0;\r
574 }\r
575 }\r
576\r
577 Sd->mBlockSize--;\r
578 Index2 = Sd->mCTable[Sd->mBitBuf >> (BITBUFSIZ - 12)];\r
579\r
580 if (Index2 >= NC) {\r
581 Mask = 1U << (BITBUFSIZ - 1 - 12);\r
582\r
583 do {\r
584 if (Sd->mBitBuf & Mask) {\r
585 Index2 = Sd->mRight[Index2];\r
586 } else {\r
587 Index2 = Sd->mLeft[Index2];\r
588 }\r
589\r
590 Mask >>= 1;\r
591 } while (Index2 >= NC);\r
592 }\r
593 //\r
594 // Advance what we have read\r
595 //\r
596 FillBuf (Sd, Sd->mCLen[Index2]);\r
597\r
598 return Index2;\r
599}\r
600\r
601STATIC\r
602VOID\r
603Decode (\r
604 SCRATCH_DATA *Sd\r
605 )\r
606/*++\r
607\r
608Routine Description:\r
609\r
610 Decode the source data and put the resulting data into the destination buffer.\r
611\r
612Arguments:\r
613\r
614 Sd - The global scratch data\r
615\r
616Returns: (VOID)\r
617\r
618 --*/\r
619{\r
620 UINT16 BytesRemain;\r
621 UINT32 DataIdx;\r
622 UINT16 CharC;\r
623\r
624 BytesRemain = (UINT16) (-1);\r
625\r
626 DataIdx = 0;\r
627\r
628 for (;;) {\r
629 CharC = DecodeC (Sd);\r
630 if (Sd->mBadTableFlag != 0) {\r
631 return ;\r
632 }\r
633\r
634 if (CharC < 256) {\r
635 //\r
636 // Process an Original character\r
637 //\r
638 Sd->mDstBase[Sd->mOutBuf++] = (UINT8) CharC;\r
639 if (Sd->mOutBuf >= Sd->mOrigSize) {\r
640 return ;\r
641 }\r
642\r
643 } else {\r
644 //\r
645 // Process a Pointer\r
646 //\r
647 CharC = (UINT16) (CharC - (UINT8_MAX + 1 - THRESHOLD));\r
648\r
649 BytesRemain = CharC;\r
650\r
651 DataIdx = Sd->mOutBuf - DecodeP (Sd) - 1;\r
652\r
653 BytesRemain--;\r
654 while ((INT16) (BytesRemain) >= 0) {\r
30fdf114
LG
655 if (Sd->mOutBuf >= Sd->mOrigSize) {\r
656 return ;\r
657 }\r
041d89bc
LG
658 if (DataIdx >= Sd->mOrigSize) {\r
659 Sd->mBadTableFlag = (UINT16) BAD_TABLE;\r
660 return ;\r
661 }\r
662 Sd->mDstBase[Sd->mOutBuf++] = Sd->mDstBase[DataIdx++];\r
30fdf114
LG
663\r
664 BytesRemain--;\r
665 }\r
5e45a1fd
LG
666 //\r
667 // Once mOutBuf is fully filled, directly return\r
668 //\r
669 if (Sd->mOutBuf >= Sd->mOrigSize) {\r
670 return ;\r
671 }\r
30fdf114
LG
672 }\r
673 }\r
674\r
675 return ;\r
676}\r
677\r
678EFI_STATUS\r
679GetInfo (\r
680 IN VOID *Source,\r
681 IN UINT32 SrcSize,\r
682 OUT UINT32 *DstSize,\r
683 OUT UINT32 *ScratchSize\r
684 )\r
685/*++\r
686\r
687Routine Description:\r
688\r
689 The implementation of EFI_DECOMPRESS_PROTOCOL.GetInfo().\r
690\r
691Arguments:\r
692\r
693 Source - The source buffer containing the compressed data.\r
694 SrcSize - The size of source buffer\r
695 DstSize - The size of destination buffer.\r
696 ScratchSize - The size of scratch buffer.\r
697\r
698Returns:\r
699\r
99e55970 700 EFI_SUCCESS - The size of destination buffer and the size of scratch buffer are successfully retrieved.\r
30fdf114
LG
701 EFI_INVALID_PARAMETER - The source data is corrupted\r
702\r
703--*/\r
704{\r
705 UINT8 *Src;\r
041d89bc 706 UINT32 CompSize;\r
30fdf114
LG
707\r
708 *ScratchSize = sizeof (SCRATCH_DATA);\r
709\r
710 Src = Source;\r
711 if (SrcSize < 8) {\r
712 return EFI_INVALID_PARAMETER;\r
713 }\r
714\r
041d89bc 715 CompSize = Src[0] + (Src[1] << 8) + (Src[2] << 16) + (Src[3] << 24);\r
30fdf114 716 *DstSize = Src[4] + (Src[5] << 8) + (Src[6] << 16) + (Src[7] << 24);\r
041d89bc
LG
717\r
718 if (SrcSize < CompSize + 8 || (CompSize + 8) < 8) {\r
719 return EFI_INVALID_PARAMETER;\r
720 }\r
721\r
30fdf114
LG
722 return EFI_SUCCESS;\r
723}\r
724\r
725EFI_STATUS\r
726Decompress (\r
727 IN VOID *Source,\r
728 IN UINT32 SrcSize,\r
729 IN OUT VOID *Destination,\r
730 IN UINT32 DstSize,\r
731 IN OUT VOID *Scratch,\r
732 IN UINT32 ScratchSize\r
733 )\r
734/*++\r
735\r
736Routine Description:\r
737\r
738 The implementation Efi and Tiano Decompress().\r
739\r
740Arguments:\r
741\r
742 Source - The source buffer containing the compressed data.\r
743 SrcSize - The size of source buffer\r
744 Destination - The destination buffer to store the decompressed data\r
745 DstSize - The size of destination buffer.\r
746 Scratch - The buffer used internally by the decompress routine. This buffer is needed to store intermediate data.\r
747 ScratchSize - The size of scratch buffer.\r
748\r
749Returns:\r
750\r
fb0b35e0 751 EFI_SUCCESS - Decompression is successful\r
30fdf114
LG
752 EFI_INVALID_PARAMETER - The source data is corrupted\r
753\r
754--*/\r
755{\r
756 UINT32 Index;\r
757 UINT32 CompSize;\r
758 UINT32 OrigSize;\r
759 EFI_STATUS Status;\r
760 SCRATCH_DATA *Sd;\r
761 UINT8 *Src;\r
762 UINT8 *Dst;\r
763\r
764 Status = EFI_SUCCESS;\r
765 Src = Source;\r
766 Dst = Destination;\r
767\r
768 if (ScratchSize < sizeof (SCRATCH_DATA)) {\r
769 return EFI_INVALID_PARAMETER;\r
770 }\r
771\r
772 Sd = (SCRATCH_DATA *) Scratch;\r
773\r
774 if (SrcSize < 8) {\r
775 return EFI_INVALID_PARAMETER;\r
776 }\r
777\r
778 CompSize = Src[0] + (Src[1] << 8) + (Src[2] << 16) + (Src[3] << 24);\r
779 OrigSize = Src[4] + (Src[5] << 8) + (Src[6] << 16) + (Src[7] << 24);\r
780\r
041d89bc 781 if (SrcSize < CompSize + 8 || (CompSize + 8) < 8) {\r
30fdf114
LG
782 return EFI_INVALID_PARAMETER;\r
783 }\r
784\r
785 if (DstSize != OrigSize) {\r
786 return EFI_INVALID_PARAMETER;\r
787 }\r
788\r
789 Src = Src + 8;\r
790\r
791 for (Index = 0; Index < sizeof (SCRATCH_DATA); Index++) {\r
792 ((UINT8 *) Sd)[Index] = 0;\r
793 }\r
794\r
795 Sd->mSrcBase = Src;\r
796 Sd->mDstBase = Dst;\r
797 Sd->mCompSize = CompSize;\r
798 Sd->mOrigSize = OrigSize;\r
799\r
800 //\r
801 // Fill the first BITBUFSIZ bits\r
802 //\r
803 FillBuf (Sd, BITBUFSIZ);\r
804\r
805 //\r
806 // Decompress it\r
807 //\r
808 Decode (Sd);\r
809\r
810 if (Sd->mBadTableFlag != 0) {\r
811 //\r
812 // Something wrong with the source\r
813 //\r
814 Status = EFI_INVALID_PARAMETER;\r
815 }\r
816\r
817 return Status;\r
818}\r
819\r
820EFI_STATUS\r
821EfiGetInfo (\r
822 IN VOID *Source,\r
823 IN UINT32 SrcSize,\r
824 OUT UINT32 *DstSize,\r
825 OUT UINT32 *ScratchSize\r
826 )\r
827/*++\r
828\r
829Routine Description:\r
830\r
831 The implementation Efi Decompress GetInfo().\r
832\r
833Arguments:\r
834\r
835 Source - The source buffer containing the compressed data.\r
836 SrcSize - The size of source buffer\r
837 DstSize - The size of destination buffer.\r
838 ScratchSize - The size of scratch buffer.\r
839\r
840Returns:\r
841\r
99e55970 842 EFI_SUCCESS - The size of destination buffer and the size of scratch buffer are successfully retrieved.\r
30fdf114
LG
843 EFI_INVALID_PARAMETER - The source data is corrupted\r
844\r
845--*/\r
846{\r
847 return GetInfo (Source, SrcSize, DstSize, ScratchSize);\r
848}\r
849\r
850EFI_STATUS\r
851TianoGetInfo (\r
852 IN VOID *Source,\r
853 IN UINT32 SrcSize,\r
854 OUT UINT32 *DstSize,\r
855 OUT UINT32 *ScratchSize\r
856 )\r
857/*++\r
858\r
859Routine Description:\r
860\r
861 The implementation Tiano Decompress GetInfo().\r
862\r
863Arguments:\r
864\r
865 Source - The source buffer containing the compressed data.\r
866 SrcSize - The size of source buffer\r
867 DstSize - The size of destination buffer.\r
868 ScratchSize - The size of scratch buffer.\r
869\r
870Returns:\r
871\r
99e55970 872 EFI_SUCCESS - The size of destination buffer and the size of scratch buffer are successfully retrieved.\r
30fdf114
LG
873 EFI_INVALID_PARAMETER - The source data is corrupted\r
874\r
875--*/\r
876{\r
877 return GetInfo (Source, SrcSize, DstSize, ScratchSize);\r
878}\r
879\r
880EFI_STATUS\r
881EfiDecompress (\r
882 IN VOID *Source,\r
883 IN UINT32 SrcSize,\r
884 IN OUT VOID *Destination,\r
885 IN UINT32 DstSize,\r
886 IN OUT VOID *Scratch,\r
887 IN UINT32 ScratchSize\r
888 )\r
889/*++\r
890\r
891Routine Description:\r
892\r
893 The implementation of Efi Decompress().\r
894\r
895Arguments:\r
896\r
897 Source - The source buffer containing the compressed data.\r
898 SrcSize - The size of source buffer\r
899 Destination - The destination buffer to store the decompressed data\r
900 DstSize - The size of destination buffer.\r
901 Scratch - The buffer used internally by the decompress routine. This buffer is needed to store intermediate data.\r
902 ScratchSize - The size of scratch buffer.\r
903\r
904Returns:\r
905\r
fb0b35e0 906 EFI_SUCCESS - Decompression is successful\r
30fdf114
LG
907 EFI_INVALID_PARAMETER - The source data is corrupted\r
908\r
909--*/\r
910{\r
911 mPbit = EFIPBIT;\r
912 return Decompress (Source, SrcSize, Destination, DstSize, Scratch, ScratchSize);\r
913}\r
914\r
915EFI_STATUS\r
916TianoDecompress (\r
917 IN VOID *Source,\r
918 IN UINT32 SrcSize,\r
919 IN OUT VOID *Destination,\r
920 IN UINT32 DstSize,\r
921 IN OUT VOID *Scratch,\r
922 IN UINT32 ScratchSize\r
923 )\r
924/*++\r
925\r
926Routine Description:\r
927\r
928 The implementation of Tiano Decompress().\r
929\r
930Arguments:\r
931\r
932 Source - The source buffer containing the compressed data.\r
933 SrcSize - The size of source buffer\r
934 Destination - The destination buffer to store the decompressed data\r
935 DstSize - The size of destination buffer.\r
936 Scratch - The buffer used internally by the decompress routine. This buffer is needed to store intermediate data.\r
937 ScratchSize - The size of scratch buffer.\r
938\r
939Returns:\r
940\r
fb0b35e0 941 EFI_SUCCESS - Decompression is successful\r
30fdf114
LG
942 EFI_INVALID_PARAMETER - The source data is corrupted\r
943\r
944--*/\r
945{\r
946 mPbit = MAXPBIT;\r
947 return Decompress (Source, SrcSize, Destination, DstSize, Scratch, ScratchSize);\r
948}\r
949\r
950EFI_STATUS\r
951Extract (\r
952 IN VOID *Source,\r
953 IN UINT32 SrcSize,\r
954 OUT VOID **Destination,\r
955 OUT UINT32 *DstSize,\r
956 IN UINTN Algorithm\r
957 )\r
958{\r
959 VOID *Scratch;\r
960 UINT32 ScratchSize;\r
961 EFI_STATUS Status;\r
962\r
aee34651
HW
963 Scratch = NULL;\r
964 Status = EFI_SUCCESS;\r
965\r
30fdf114
LG
966 switch (Algorithm) {\r
967 case 0:\r
968 *Destination = (VOID *)malloc(SrcSize);\r
969 if (*Destination != NULL) {\r
970 memcpy(*Destination, Source, SrcSize);\r
971 } else {\r
972 Status = EFI_OUT_OF_RESOURCES;\r
973 }\r
974 break;\r
975 case 1:\r
976 Status = EfiGetInfo(Source, SrcSize, DstSize, &ScratchSize);\r
977 if (Status == EFI_SUCCESS) {\r
978 Scratch = (VOID *)malloc(ScratchSize);\r
aee34651
HW
979 if (Scratch == NULL) {\r
980 return EFI_OUT_OF_RESOURCES;\r
981 }\r
982\r
30fdf114 983 *Destination = (VOID *)malloc(*DstSize);\r
aee34651
HW
984 if (*Destination == NULL) {\r
985 free (Scratch);\r
986 return EFI_OUT_OF_RESOURCES;\r
30fdf114 987 }\r
aee34651
HW
988\r
989 Status = EfiDecompress(Source, SrcSize, *Destination, *DstSize, Scratch, ScratchSize);\r
30fdf114
LG
990 }\r
991 break;\r
992 case 2:\r
993 Status = TianoGetInfo(Source, SrcSize, DstSize, &ScratchSize);\r
994 if (Status == EFI_SUCCESS) {\r
995 Scratch = (VOID *)malloc(ScratchSize);\r
aee34651
HW
996 if (Scratch == NULL) {\r
997 return EFI_OUT_OF_RESOURCES;\r
998 }\r
999\r
30fdf114 1000 *Destination = (VOID *)malloc(*DstSize);\r
aee34651
HW
1001 if (*Destination == NULL) {\r
1002 free (Scratch);\r
1003 return EFI_OUT_OF_RESOURCES;\r
30fdf114 1004 }\r
aee34651
HW
1005\r
1006 Status = TianoDecompress(Source, SrcSize, *Destination, *DstSize, Scratch, ScratchSize);\r
30fdf114
LG
1007 }\r
1008 break;\r
1009 default:\r
1010 Status = EFI_INVALID_PARAMETER;\r
1011 }\r
1012\r
aee34651
HW
1013 if (Scratch != NULL) {\r
1014 free (Scratch);\r
1015 }\r
1016\r
30fdf114
LG
1017 return Status;\r
1018}\r
1019\r
1020\r