1 /** @file
2   UEFI Decompress Library implementation refer to UEFI specification.
3 
4   Copyright (c) 2006 - 2019, Intel Corporation. All rights reserved.<BR>
5   Portions copyright (c) 2008 - 2009, Apple Inc. All rights reserved.<BR>
6   SPDX-License-Identifier: BSD-2-Clause-Patent
7 
8 **/
9 
10 #include "BaseUefiDecompressLibInternals.h"
11 
12 /**
13   Read NumOfBit of bits from source into mBitBuf.
14 
15   Shift mBitBuf NumOfBits left. Read in NumOfBits of bits from source.
16 
17   @param  Sd        The global scratch data.
18   @param  NumOfBits The number of bits to shift and read.
19 
20 **/
21 VOID
FillBuf(IN SCRATCH_DATA * Sd,IN UINT16 NumOfBits)22 FillBuf (
23   IN  SCRATCH_DATA  *Sd,
24   IN  UINT16        NumOfBits
25   )
26 {
27   //
28   // Left shift NumOfBits of bits in advance
29   //
30   Sd->mBitBuf = (UINT32) LShiftU64 (((UINT64)Sd->mBitBuf), NumOfBits);
31 
32   //
33   // Copy data needed in bytes into mSbuBitBuf
34   //
35   while (NumOfBits > Sd->mBitCount) {
36     NumOfBits = (UINT16) (NumOfBits - Sd->mBitCount);
37     Sd->mBitBuf |= (UINT32) LShiftU64 (((UINT64)Sd->mSubBitBuf), NumOfBits);
38 
39     if (Sd->mCompSize > 0) {
40       //
41       // Get 1 byte into SubBitBuf
42       //
43       Sd->mCompSize--;
44       Sd->mSubBitBuf  = Sd->mSrcBase[Sd->mInBuf++];
45       Sd->mBitCount   = 8;
46 
47     } else {
48       //
49       // No more bits from the source, just pad zero bit.
50       //
51       Sd->mSubBitBuf  = 0;
52       Sd->mBitCount   = 8;
53 
54     }
55   }
56 
57   //
58   // Calculate additional bit count read to update mBitCount
59   //
60   Sd->mBitCount = (UINT16) (Sd->mBitCount - NumOfBits);
61 
62   //
63   // Copy NumOfBits of bits from mSubBitBuf into mBitBuf
64   //
65   Sd->mBitBuf |= Sd->mSubBitBuf >> Sd->mBitCount;
66 }
67 
68 /**
69   Get NumOfBits of bits out from mBitBuf.
70 
71   Get NumOfBits of bits out from mBitBuf. Fill mBitBuf with subsequent
72   NumOfBits of bits from source. Returns NumOfBits of bits that are
73   popped out.
74 
75   @param  Sd        The global scratch data.
76   @param  NumOfBits The number of bits to pop and read.
77 
78   @return The bits that are popped out.
79 
80 **/
81 UINT32
GetBits(IN SCRATCH_DATA * Sd,IN UINT16 NumOfBits)82 GetBits (
83   IN  SCRATCH_DATA  *Sd,
84   IN  UINT16        NumOfBits
85   )
86 {
87   UINT32  OutBits;
88 
89   //
90   // Pop NumOfBits of Bits from Left
91   //
92   OutBits = (UINT32) (Sd->mBitBuf >> (BITBUFSIZ - NumOfBits));
93 
94   //
95   // Fill up mBitBuf from source
96   //
97   FillBuf (Sd, NumOfBits);
98 
99   return OutBits;
100 }
101 
102 /**
103   Creates Huffman Code mapping table according to code length array.
104 
105   Creates Huffman Code mapping table for Extra Set, Char&Len Set
106   and Position Set according to code length array.
107   If TableBits > 16, then ASSERT ().
108 
109   @param  Sd        The global scratch data.
110   @param  NumOfChar The number of symbols in the symbol set.
111   @param  BitLen    Code length array.
112   @param  TableBits The width of the mapping table.
113   @param  Table     The table to be created.
114 
115   @retval  0 OK.
116   @retval  BAD_TABLE The table is corrupted.
117 
118 **/
119 UINT16
MakeTable(IN SCRATCH_DATA * Sd,IN UINT16 NumOfChar,IN UINT8 * BitLen,IN UINT16 TableBits,OUT UINT16 * Table)120 MakeTable (
121   IN  SCRATCH_DATA  *Sd,
122   IN  UINT16        NumOfChar,
123   IN  UINT8         *BitLen,
124   IN  UINT16        TableBits,
125   OUT UINT16        *Table
126   )
127 {
128   UINT16  Count[17];
129   UINT16  Weight[17];
130   UINT16  Start[18];
131   UINT16  *Pointer;
132   UINT16  Index3;
133   UINT16  Index;
134   UINT16  Len;
135   UINT16  Char;
136   UINT16  JuBits;
137   UINT16  Avail;
138   UINT16  NextCode;
139   UINT16  Mask;
140   UINT16  WordOfStart;
141   UINT16  WordOfCount;
142   UINT16  MaxTableLength;
143 
144   //
145   // The maximum mapping table width supported by this internal
146   // working function is 16.
147   //
148   ASSERT (TableBits <= 16);
149 
150   for (Index = 0; Index <= 16; Index++) {
151     Count[Index] = 0;
152   }
153 
154   for (Index = 0; Index < NumOfChar; Index++) {
155     if (BitLen[Index] > 16) {
156       return (UINT16) BAD_TABLE;
157     }
158     Count[BitLen[Index]]++;
159   }
160 
161   Start[0] = 0;
162   Start[1] = 0;
163 
164   for (Index = 1; Index <= 16; Index++) {
165     WordOfStart = Start[Index];
166     WordOfCount = Count[Index];
167     Start[Index + 1] = (UINT16) (WordOfStart + (WordOfCount << (16 - Index)));
168   }
169 
170   if (Start[17] != 0) {
171     /*(1U << 16)*/
172     return (UINT16) BAD_TABLE;
173   }
174 
175   JuBits = (UINT16) (16 - TableBits);
176 
177   Weight[0] = 0;
178   for (Index = 1; Index <= TableBits; Index++) {
179     Start[Index] >>= JuBits;
180     Weight[Index] = (UINT16) (1U << (TableBits - Index));
181   }
182 
183   while (Index <= 16) {
184     Weight[Index] = (UINT16) (1U << (16 - Index));
185     Index++;
186   }
187 
188   Index = (UINT16) (Start[TableBits + 1] >> JuBits);
189 
190   if (Index != 0) {
191     Index3 = (UINT16) (1U << TableBits);
192     if (Index < Index3) {
193       SetMem16 (Table + Index, (Index3 - Index) * sizeof (*Table), 0);
194     }
195   }
196 
197   Avail = NumOfChar;
198   Mask  = (UINT16) (1U << (15 - TableBits));
199   MaxTableLength = (UINT16) (1U << TableBits);
200 
201   for (Char = 0; Char < NumOfChar; Char++) {
202 
203     Len = BitLen[Char];
204     if (Len == 0 || Len >= 17) {
205       continue;
206     }
207 
208     NextCode = (UINT16) (Start[Len] + Weight[Len]);
209 
210     if (Len <= TableBits) {
211 
212       if (Start[Len] >= NextCode || NextCode > MaxTableLength){
213         return (UINT16) BAD_TABLE;
214       }
215 
216       for (Index = Start[Len]; Index < NextCode; Index++) {
217         Table[Index] = Char;
218       }
219 
220     } else {
221 
222       Index3  = Start[Len];
223       Pointer = &Table[Index3 >> JuBits];
224       Index   = (UINT16) (Len - TableBits);
225 
226       while (Index != 0) {
227         if (*Pointer == 0 && Avail < (2 * NC - 1)) {
228           Sd->mRight[Avail] = Sd->mLeft[Avail] = 0;
229           *Pointer = Avail++;
230         }
231 
232         if (*Pointer < (2 * NC - 1)) {
233           if ((Index3 & Mask) != 0) {
234             Pointer = &Sd->mRight[*Pointer];
235           } else {
236             Pointer = &Sd->mLeft[*Pointer];
237           }
238         }
239 
240         Index3 <<= 1;
241         Index--;
242       }
243 
244       *Pointer = Char;
245 
246     }
247 
248     Start[Len] = NextCode;
249   }
250   //
251   // Succeeds
252   //
253   return 0;
254 }
255 
256 /**
257   Decodes a position value.
258 
259   Get a position value according to Position Huffman Table.
260 
261   @param  Sd The global scratch data.
262 
263   @return The position value decoded.
264 
265 **/
266 UINT32
DecodeP(IN SCRATCH_DATA * Sd)267 DecodeP (
268   IN  SCRATCH_DATA  *Sd
269   )
270 {
271   UINT16  Val;
272   UINT32  Mask;
273   UINT32  Pos;
274 
275   Val = Sd->mPTTable[Sd->mBitBuf >> (BITBUFSIZ - 8)];
276 
277   if (Val >= MAXNP) {
278     Mask = 1U << (BITBUFSIZ - 1 - 8);
279 
280     do {
281 
282       if ((Sd->mBitBuf & Mask) != 0) {
283         Val = Sd->mRight[Val];
284       } else {
285         Val = Sd->mLeft[Val];
286       }
287 
288       Mask >>= 1;
289     } while (Val >= MAXNP);
290   }
291   //
292   // Advance what we have read
293   //
294   FillBuf (Sd, Sd->mPTLen[Val]);
295 
296   Pos = Val;
297   if (Val > 1) {
298     Pos = (UINT32) ((1U << (Val - 1)) + GetBits (Sd, (UINT16) (Val - 1)));
299   }
300 
301   return Pos;
302 }
303 
304 /**
305   Reads code lengths for the Extra Set or the Position Set.
306 
307   Read in the Extra Set or Position Set Length Array, then
308   generate the Huffman code mapping for them.
309 
310   @param  Sd      The global scratch data.
311   @param  nn      The number of symbols.
312   @param  nbit    The number of bits needed to represent nn.
313   @param  Special The special symbol that needs to be taken care of.
314 
315   @retval  0 OK.
316   @retval  BAD_TABLE Table is corrupted.
317 
318 **/
319 UINT16
ReadPTLen(IN SCRATCH_DATA * Sd,IN UINT16 nn,IN UINT16 nbit,IN UINT16 Special)320 ReadPTLen (
321   IN  SCRATCH_DATA  *Sd,
322   IN  UINT16        nn,
323   IN  UINT16        nbit,
324   IN  UINT16        Special
325   )
326 {
327   UINT16  Number;
328   UINT16  CharC;
329   UINT16  Index;
330   UINT32  Mask;
331 
332   ASSERT (nn <= NPT);
333   //
334   // Read Extra Set Code Length Array size
335   //
336   Number = (UINT16) GetBits (Sd, nbit);
337 
338   if (Number == 0) {
339     //
340     // This represents only Huffman code used
341     //
342     CharC = (UINT16) GetBits (Sd, nbit);
343 
344     SetMem16 (&Sd->mPTTable[0] , sizeof (Sd->mPTTable), CharC);
345 
346     SetMem (Sd->mPTLen, nn, 0);
347 
348     return 0;
349   }
350 
351   Index = 0;
352 
353   while (Index < Number && Index < NPT) {
354 
355     CharC = (UINT16) (Sd->mBitBuf >> (BITBUFSIZ - 3));
356 
357     //
358     // If a code length is less than 7, then it is encoded as a 3-bit
359     // value. Or it is encoded as a series of "1"s followed by a
360     // terminating "0". The number of "1"s = Code length - 4.
361     //
362     if (CharC == 7) {
363       Mask = 1U << (BITBUFSIZ - 1 - 3);
364       while (Mask & Sd->mBitBuf) {
365         Mask >>= 1;
366         CharC += 1;
367       }
368     }
369 
370     FillBuf (Sd, (UINT16) ((CharC < 7) ? 3 : CharC - 3));
371 
372     Sd->mPTLen[Index++] = (UINT8) CharC;
373 
374     //
375     // For Code&Len Set,
376     // After the third length of the code length concatenation,
377     // a 2-bit value is used to indicated the number of consecutive
378     // zero lengths after the third length.
379     //
380     if (Index == Special) {
381       CharC = (UINT16) GetBits (Sd, 2);
382       while ((INT16) (--CharC) >= 0 && Index < NPT) {
383         Sd->mPTLen[Index++] = 0;
384       }
385     }
386   }
387 
388   while (Index < nn && Index < NPT) {
389     Sd->mPTLen[Index++] = 0;
390   }
391 
392   return MakeTable (Sd, nn, Sd->mPTLen, 8, Sd->mPTTable);
393 }
394 
395 /**
396   Reads code lengths for Char&Len Set.
397 
398   Read in and decode the Char&Len Set Code Length Array, then
399   generate the Huffman Code mapping table for the Char&Len Set.
400 
401   @param  Sd The global scratch data.
402 
403 **/
404 VOID
ReadCLen(SCRATCH_DATA * Sd)405 ReadCLen (
406   SCRATCH_DATA  *Sd
407   )
408 {
409   UINT16           Number;
410   UINT16           CharC;
411   UINT16           Index;
412   UINT32           Mask;
413 
414   Number = (UINT16) GetBits (Sd, CBIT);
415 
416   if (Number == 0) {
417     //
418     // This represents only Huffman code used
419     //
420     CharC = (UINT16) GetBits (Sd, CBIT);
421 
422     SetMem (Sd->mCLen, NC, 0);
423     SetMem16 (&Sd->mCTable[0], sizeof (Sd->mCTable), CharC);
424 
425     return ;
426   }
427 
428   Index = 0;
429   while (Index < Number && Index < NC) {
430     CharC = Sd->mPTTable[Sd->mBitBuf >> (BITBUFSIZ - 8)];
431     if (CharC >= NT) {
432       Mask = 1U << (BITBUFSIZ - 1 - 8);
433 
434       do {
435 
436         if (Mask & Sd->mBitBuf) {
437           CharC = Sd->mRight[CharC];
438         } else {
439           CharC = Sd->mLeft[CharC];
440         }
441 
442         Mask >>= 1;
443 
444       } while (CharC >= NT);
445     }
446     //
447     // Advance what we have read
448     //
449     FillBuf (Sd, Sd->mPTLen[CharC]);
450 
451     if (CharC <= 2) {
452 
453       if (CharC == 0) {
454         CharC = 1;
455       } else if (CharC == 1) {
456         CharC = (UINT16) (GetBits (Sd, 4) + 3);
457       } else if (CharC == 2) {
458         CharC = (UINT16) (GetBits (Sd, CBIT) + 20);
459       }
460 
461       while ((INT16) (--CharC) >= 0 && Index < NC) {
462         Sd->mCLen[Index++] = 0;
463       }
464 
465     } else {
466 
467       Sd->mCLen[Index++] = (UINT8) (CharC - 2);
468 
469     }
470   }
471 
472   SetMem (Sd->mCLen + Index, NC - Index, 0);
473 
474   MakeTable (Sd, NC, Sd->mCLen, 12, Sd->mCTable);
475 
476   return ;
477 }
478 
479 /**
480   Decode a character/length value.
481 
482   Read one value from mBitBuf, Get one code from mBitBuf. If it is at block boundary, generates
483   Huffman code mapping table for Extra Set, Code&Len Set and
484   Position Set.
485 
486   @param  Sd The global scratch data.
487 
488   @return The value decoded.
489 
490 **/
491 UINT16
DecodeC(SCRATCH_DATA * Sd)492 DecodeC (
493   SCRATCH_DATA  *Sd
494   )
495 {
496   UINT16  Index2;
497   UINT32  Mask;
498 
499   if (Sd->mBlockSize == 0) {
500     //
501     // Starting a new block
502     // Read BlockSize from block header
503     //
504     Sd->mBlockSize    = (UINT16) GetBits (Sd, 16);
505 
506     //
507     // Read in the Extra Set Code Length Array,
508     // Generate the Huffman code mapping table for Extra Set.
509     //
510     Sd->mBadTableFlag = ReadPTLen (Sd, NT, TBIT, 3);
511     if (Sd->mBadTableFlag != 0) {
512       return 0;
513     }
514 
515     //
516     // Read in and decode the Char&Len Set Code Length Array,
517     // Generate the Huffman code mapping table for Char&Len Set.
518     //
519     ReadCLen (Sd);
520 
521     //
522     // Read in the Position Set Code Length Array,
523     // Generate the Huffman code mapping table for the Position Set.
524     //
525     Sd->mBadTableFlag = ReadPTLen (Sd, MAXNP, Sd->mPBit, (UINT16) (-1));
526     if (Sd->mBadTableFlag != 0) {
527       return 0;
528     }
529   }
530 
531   //
532   // Get one code according to Code&Set Huffman Table
533   //
534   Sd->mBlockSize--;
535   Index2 = Sd->mCTable[Sd->mBitBuf >> (BITBUFSIZ - 12)];
536 
537   if (Index2 >= NC) {
538     Mask = 1U << (BITBUFSIZ - 1 - 12);
539 
540     do {
541       if ((Sd->mBitBuf & Mask) != 0) {
542         Index2 = Sd->mRight[Index2];
543       } else {
544         Index2 = Sd->mLeft[Index2];
545       }
546 
547       Mask >>= 1;
548     } while (Index2 >= NC);
549   }
550   //
551   // Advance what we have read
552   //
553   FillBuf (Sd, Sd->mCLen[Index2]);
554 
555   return Index2;
556 }
557 
558 /**
559   Decode the source data and put the resulting data into the destination buffer.
560 
561   @param  Sd The global scratch data.
562 
563 **/
564 VOID
Decode(SCRATCH_DATA * Sd)565 Decode (
566   SCRATCH_DATA  *Sd
567   )
568 {
569   UINT16  BytesRemain;
570   UINT32  DataIdx;
571   UINT16  CharC;
572 
573   BytesRemain = (UINT16) (-1);
574 
575   DataIdx     = 0;
576 
577   for (;;) {
578     //
579     // Get one code from mBitBuf
580     //
581     CharC = DecodeC (Sd);
582     if (Sd->mBadTableFlag != 0) {
583       goto Done;
584     }
585 
586     if (CharC < 256) {
587       //
588       // Process an Original character
589       //
590       if (Sd->mOutBuf >= Sd->mOrigSize) {
591         goto Done;
592       } else {
593         //
594         // Write orignal character into mDstBase
595         //
596         Sd->mDstBase[Sd->mOutBuf++] = (UINT8) CharC;
597       }
598 
599     } else {
600       //
601       // Process a Pointer
602       //
603       CharC       = (UINT16) (CharC - (BIT8 - THRESHOLD));
604 
605       //
606       // Get string length
607       //
608       BytesRemain = CharC;
609 
610       //
611       // Locate string position
612       //
613       DataIdx     = Sd->mOutBuf - DecodeP (Sd) - 1;
614 
615       //
616       // Write BytesRemain of bytes into mDstBase
617       //
618       BytesRemain--;
619 
620       while ((INT16) (BytesRemain) >= 0) {
621         if (Sd->mOutBuf >= Sd->mOrigSize) {
622           goto Done;
623         }
624         if (DataIdx >= Sd->mOrigSize) {
625           Sd->mBadTableFlag = (UINT16) BAD_TABLE;
626           goto Done;
627         }
628         Sd->mDstBase[Sd->mOutBuf++] = Sd->mDstBase[DataIdx++];
629 
630         BytesRemain--;
631       }
632       //
633       // Once mOutBuf is fully filled, directly return
634       //
635       if (Sd->mOutBuf >= Sd->mOrigSize) {
636         goto Done;
637       }
638     }
639   }
640 
641 Done:
642   return ;
643 }
644 
645 /**
646   Given a compressed source buffer, this function retrieves the size of
647   the uncompressed buffer and the size of the scratch buffer required
648   to decompress the compressed source buffer.
649 
650   Retrieves the size of the uncompressed buffer and the temporary scratch buffer
651   required to decompress the buffer specified by Source and SourceSize.
652   If the size of the uncompressed buffer or the size of the scratch buffer cannot
653   be determined from the compressed data specified by Source and SourceData,
654   then RETURN_INVALID_PARAMETER is returned.  Otherwise, the size of the uncompressed
655   buffer is returned in DestinationSize, the size of the scratch buffer is returned
656   in ScratchSize, and RETURN_SUCCESS is returned.
657   This function does not have scratch buffer available to perform a thorough
658   checking of the validity of the source data.  It just retrieves the "Original Size"
659   field from the beginning bytes of the source data and output it as DestinationSize.
660   And ScratchSize is specific to the decompression implementation.
661 
662   If Source is NULL, then ASSERT().
663   If DestinationSize is NULL, then ASSERT().
664   If ScratchSize is NULL, then ASSERT().
665 
666   @param  Source          The source buffer containing the compressed data.
667   @param  SourceSize      The size, in bytes, of the source buffer.
668   @param  DestinationSize A pointer to the size, in bytes, of the uncompressed buffer
669                           that will be generated when the compressed buffer specified
670                           by Source and SourceSize is decompressed.
671   @param  ScratchSize     A pointer to the size, in bytes, of the scratch buffer that
672                           is required to decompress the compressed buffer specified
673                           by Source and SourceSize.
674 
675   @retval  RETURN_SUCCESS The size of the uncompressed data was returned
676                           in DestinationSize, and the size of the scratch
677                           buffer was returned in ScratchSize.
678   @retval  RETURN_INVALID_PARAMETER
679                           The size of the uncompressed data or the size of
680                           the scratch buffer cannot be determined from
681                           the compressed data specified by Source
682                           and SourceSize.
683 **/
684 RETURN_STATUS
685 EFIAPI
UefiDecompressGetInfo(IN CONST VOID * Source,IN UINT32 SourceSize,OUT UINT32 * DestinationSize,OUT UINT32 * ScratchSize)686 UefiDecompressGetInfo (
687   IN  CONST VOID  *Source,
688   IN  UINT32      SourceSize,
689   OUT UINT32      *DestinationSize,
690   OUT UINT32      *ScratchSize
691   )
692 {
693   UINT32  CompressedSize;
694 
695   ASSERT (Source != NULL);
696   ASSERT (DestinationSize != NULL);
697   ASSERT (ScratchSize != NULL);
698 
699   if (SourceSize < 8) {
700     return RETURN_INVALID_PARAMETER;
701   }
702 
703   CompressedSize   = ReadUnaligned32 ((UINT32 *)Source);
704   if (SourceSize < (CompressedSize + 8) || (CompressedSize + 8) < 8) {
705     return RETURN_INVALID_PARAMETER;
706   }
707 
708   *ScratchSize  = sizeof (SCRATCH_DATA);
709   *DestinationSize = ReadUnaligned32 ((UINT32 *)Source + 1);
710 
711   return RETURN_SUCCESS;
712 }
713 
714 /**
715   Decompresses a compressed source buffer.
716 
717   Extracts decompressed data to its original form.
718   This function is designed so that the decompression algorithm can be implemented
719   without using any memory services.  As a result, this function is not allowed to
720   call any memory allocation services in its implementation.  It is the caller's
721   responsibility to allocate and free the Destination and Scratch buffers.
722   If the compressed source data specified by Source is successfully decompressed
723   into Destination, then RETURN_SUCCESS is returned.  If the compressed source data
724   specified by Source is not in a valid compressed data format,
725   then RETURN_INVALID_PARAMETER is returned.
726 
727   If Source is NULL, then ASSERT().
728   If Destination is NULL, then ASSERT().
729   If the required scratch buffer size > 0 and Scratch is NULL, then ASSERT().
730   If the Version is not 1 or 2, then ASSERT().
731 
732   @param  Source      The source buffer containing the compressed data.
733   @param  Destination The destination buffer to store the decompressed data.
734   @param  Scratch     A temporary scratch buffer that is used to perform the decompression.
735                       This is an optional parameter that may be NULL if the
736                       required scratch buffer size is 0.
737   @param  Version     1 for UEFI Decompress algoruthm, 2 for Tiano Decompess algorithm.
738 
739   @retval  RETURN_SUCCESS Decompression completed successfully, and
740                           the uncompressed buffer is returned in Destination.
741   @retval  RETURN_INVALID_PARAMETER
742                           The source buffer specified by Source is corrupted
743                           (not in a valid compressed format).
744 **/
745 RETURN_STATUS
UefiTianoDecompress(IN CONST VOID * Source,IN OUT VOID * Destination,IN OUT VOID * Scratch,IN UINT32 Version)746 UefiTianoDecompress (
747   IN CONST VOID  *Source,
748   IN OUT VOID    *Destination,
749   IN OUT VOID    *Scratch,
750   IN UINT32      Version
751   )
752 {
753   UINT32           CompSize;
754   UINT32           OrigSize;
755   SCRATCH_DATA     *Sd;
756   CONST UINT8      *Src;
757   UINT8            *Dst;
758 
759   ASSERT (Source != NULL);
760   ASSERT (Destination != NULL);
761   ASSERT (Scratch != NULL);
762   ASSERT (Version == 1 || Version == 2);
763 
764   Src     = Source;
765   Dst     = Destination;
766 
767   Sd = (SCRATCH_DATA *) Scratch;
768 
769   CompSize  = Src[0] + (Src[1] << 8) + (Src[2] << 16) + (Src[3] << 24);
770   OrigSize  = Src[4] + (Src[5] << 8) + (Src[6] << 16) + (Src[7] << 24);
771 
772   //
773   // If compressed file size is 0, return
774   //
775   if (OrigSize == 0) {
776     return RETURN_SUCCESS;
777   }
778 
779   Src = Src + 8;
780   SetMem (Sd, sizeof (SCRATCH_DATA), 0);
781 
782   //
783   // The length of the field 'Position Set Code Length Array Size' in Block Header.
784   // For UEFI 2.0 de/compression algorithm(Version 1), mPBit = 4
785   // For Tiano de/compression algorithm(Version 2), mPBit = 5
786   //
787   switch (Version) {
788     case 1 :
789       Sd->mPBit = 4;
790       break;
791     case 2 :
792       Sd->mPBit = 5;
793       break;
794     default:
795       ASSERT (FALSE);
796   }
797   Sd->mSrcBase  = (UINT8 *)Src;
798   Sd->mDstBase  = Dst;
799   //
800   // CompSize and OrigSize are calculated in bytes
801   //
802   Sd->mCompSize = CompSize;
803   Sd->mOrigSize = OrigSize;
804 
805   //
806   // Fill the first BITBUFSIZ bits
807   //
808   FillBuf (Sd, BITBUFSIZ);
809 
810   //
811   // Decompress it
812   //
813   Decode (Sd);
814 
815   if (Sd->mBadTableFlag != 0) {
816     //
817     // Something wrong with the source
818     //
819     return RETURN_INVALID_PARAMETER;
820   }
821 
822   return RETURN_SUCCESS;
823 }
824 
825 /**
826   Decompresses a UEFI compressed source buffer.
827 
828   Extracts decompressed data to its original form.
829   This function is designed so that the decompression algorithm can be implemented
830   without using any memory services.  As a result, this function is not allowed to
831   call any memory allocation services in its implementation.  It is the caller's
832   responsibility to allocate and free the Destination and Scratch buffers.
833   If the compressed source data specified by Source is successfully decompressed
834   into Destination, then RETURN_SUCCESS is returned.  If the compressed source data
835   specified by Source is not in a valid compressed data format,
836   then RETURN_INVALID_PARAMETER is returned.
837 
838   If Source is NULL, then ASSERT().
839   If Destination is NULL, then ASSERT().
840   If the required scratch buffer size > 0 and Scratch is NULL, then ASSERT().
841 
842   @param  Source      The source buffer containing the compressed data.
843   @param  Destination The destination buffer to store the decompressed data
844   @param  Scratch     A temporary scratch buffer that is used to perform the decompression.
845                       This is an optional parameter that may be NULL if the
846                       required scratch buffer size is 0.
847 
848   @retval  RETURN_SUCCESS Decompression completed successfully, and
849                           the uncompressed buffer is returned in Destination.
850   @retval  RETURN_INVALID_PARAMETER
851                           The source buffer specified by Source is corrupted
852                           (not in a valid compressed format).
853 **/
854 RETURN_STATUS
855 EFIAPI
UefiDecompress(IN CONST VOID * Source,IN OUT VOID * Destination,IN OUT VOID * Scratch OPTIONAL)856 UefiDecompress (
857   IN CONST VOID  *Source,
858   IN OUT VOID    *Destination,
859   IN OUT VOID    *Scratch  OPTIONAL
860   )
861 {
862   return UefiTianoDecompress (Source, Destination, Scratch, 1);
863 }
864