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