1 /** @file
2   UEFI and Tiano Custom Decompress Library
3   It will do Tiano or UEFI decompress with different verison parameter.
4 
5 Copyright (c) 2006 - 2015, Intel Corporation. All rights reserved.<BR>
6 This program and the accompanying materials
7 are licensed and made available under the terms and conditions of the BSD License
8 which accompanies this distribution.  The full text of the license may be found at
9 http://opensource.org/licenses/bsd-license.php
10 
11 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
12 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
13 
14 **/
15 
16 #include "BaseUefiTianoCustomDecompressLibInternals.h"
17 
18 /**
19   Shift mBitBuf NumOfBits left. Read in NumOfBits of bits from source.
20 
21   @param Sd         The global scratch data
22   @param NumOfBits  The number of bits to shift and read.
23 **/
24 VOID
FillBuf(IN SCRATCH_DATA * Sd,IN UINT16 NumOfBits)25 FillBuf (
26   IN  SCRATCH_DATA  *Sd,
27   IN  UINT16        NumOfBits
28   )
29 {
30   //
31   // Left shift NumOfBits of bits in advance
32   //
33   Sd->mBitBuf = (UINT32) (Sd->mBitBuf << NumOfBits);
34 
35   //
36   // Copy data needed in bytes into mSbuBitBuf
37   //
38   while (NumOfBits > Sd->mBitCount) {
39 
40     Sd->mBitBuf |= (UINT32) (Sd->mSubBitBuf << (NumOfBits = (UINT16) (NumOfBits - Sd->mBitCount)));
41 
42     if (Sd->mCompSize > 0) {
43       //
44       // Get 1 byte into SubBitBuf
45       //
46       Sd->mCompSize--;
47       Sd->mSubBitBuf  = 0;
48       Sd->mSubBitBuf  = Sd->mSrcBase[Sd->mInBuf++];
49       Sd->mBitCount   = 8;
50 
51     } else {
52       //
53       // No more bits from the source, just pad zero bit.
54       //
55       Sd->mSubBitBuf  = 0;
56       Sd->mBitCount   = 8;
57 
58     }
59   }
60 
61   //
62   // Calculate additional bit count read to update mBitCount
63   //
64   Sd->mBitCount = (UINT16) (Sd->mBitCount - NumOfBits);
65 
66   //
67   // Copy NumOfBits of bits from mSubBitBuf into mBitBuf
68   //
69   Sd->mBitBuf |= Sd->mSubBitBuf >> Sd->mBitCount;
70 }
71 
72 /**
73   Get NumOfBits of bits out from mBitBuf
74 
75   Get NumOfBits of bits out from mBitBuf. Fill mBitBuf with subsequent
76   NumOfBits of bits from source. Returns NumOfBits of bits that are
77   popped out.
78 
79   @param  Sd        The global scratch data.
80   @param  NumOfBits The number of bits to pop and read.
81 
82   @return The bits that are popped out.
83 
84 **/
85 UINT32
GetBits(IN SCRATCH_DATA * Sd,IN UINT16 NumOfBits)86 GetBits (
87   IN  SCRATCH_DATA  *Sd,
88   IN  UINT16        NumOfBits
89   )
90 {
91   UINT32  OutBits;
92 
93   //
94   // Pop NumOfBits of Bits from Left
95   //
96   OutBits = (UINT32) (Sd->mBitBuf >> (BITBUFSIZ - NumOfBits));
97 
98   //
99   // Fill up mBitBuf from source
100   //
101   FillBuf (Sd, NumOfBits);
102 
103   return OutBits;
104 }
105 
106 /**
107   Creates Huffman Code mapping table according to code length array.
108 
109   Creates Huffman Code mapping table for Extra Set, Char&Len Set
110   and Position Set according to code length array.
111   If TableBits > 16, then ASSERT ().
112 
113   @param  Sd        The global scratch data
114   @param  NumOfChar Number of symbols in the symbol set
115   @param  BitLen    Code length array
116   @param  TableBits The width of the mapping table
117   @param  Table     The table to be created.
118 
119   @retval  0 OK.
120   @retval  BAD_TABLE The table is corrupted.
121 
122 **/
123 UINT16
MakeTable(IN SCRATCH_DATA * Sd,IN UINT16 NumOfChar,IN UINT8 * BitLen,IN UINT16 TableBits,OUT UINT16 * Table)124 MakeTable (
125   IN  SCRATCH_DATA  *Sd,
126   IN  UINT16        NumOfChar,
127   IN  UINT8         *BitLen,
128   IN  UINT16        TableBits,
129   OUT UINT16        *Table
130   )
131 {
132   UINT16  Count[17];
133   UINT16  Weight[17];
134   UINT16  Start[18];
135   UINT16  *Pointer;
136   UINT16  Index3;
137   UINT16  Index;
138   UINT16  Len;
139   UINT16  Char;
140   UINT16  JuBits;
141   UINT16  Avail;
142   UINT16  NextCode;
143   UINT16  Mask;
144   UINT16  WordOfStart;
145   UINT16  WordOfCount;
146 
147   //
148   // The maximum mapping table width supported by this internal
149   // working function is 16.
150   //
151   ASSERT (TableBits <= 16);
152 
153   for (Index = 0; Index <= 16; Index++) {
154     Count[Index] = 0;
155   }
156 
157   for (Index = 0; Index < NumOfChar; Index++) {
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 
200   for (Char = 0; Char < NumOfChar; Char++) {
201 
202     Len = BitLen[Char];
203     if (Len == 0 || Len >= 17) {
204       continue;
205     }
206 
207     NextCode = (UINT16) (Start[Len] + Weight[Len]);
208 
209     if (Len <= TableBits) {
210 
211       for (Index = Start[Len]; Index < NextCode; Index++) {
212         Table[Index] = Char;
213       }
214 
215     } else {
216 
217       Index3  = Start[Len];
218       Pointer = &Table[Index3 >> JuBits];
219       Index   = (UINT16) (Len - TableBits);
220 
221       while (Index != 0) {
222         if (*Pointer == 0 && Avail < (2 * NC - 1)) {
223           Sd->mRight[Avail] = Sd->mLeft[Avail] = 0;
224           *Pointer = Avail++;
225         }
226 
227         if (*Pointer < (2 * NC - 1)) {
228           if ((Index3 & Mask) != 0) {
229             Pointer = &Sd->mRight[*Pointer];
230           } else {
231             Pointer = &Sd->mLeft[*Pointer];
232           }
233         }
234 
235         Index3 <<= 1;
236         Index--;
237       }
238 
239       *Pointer = Char;
240 
241     }
242 
243     Start[Len] = NextCode;
244   }
245   //
246   // Succeeds
247   //
248   return 0;
249 }
250 
251 /**
252   Decodes a position value.
253 
254   Get a position value according to Position Huffman Table.
255 
256   @param Sd      the global scratch data
257 
258   @return The position value decoded.
259 **/
260 UINT32
DecodeP(IN SCRATCH_DATA * Sd)261 DecodeP (
262   IN  SCRATCH_DATA  *Sd
263   )
264 {
265   UINT16  Val;
266   UINT32  Mask;
267   UINT32  Pos;
268 
269   Val = Sd->mPTTable[Sd->mBitBuf >> (BITBUFSIZ - 8)];
270 
271   if (Val >= MAXNP) {
272     Mask = 1U << (BITBUFSIZ - 1 - 8);
273 
274     do {
275 
276       if ((Sd->mBitBuf & Mask) != 0) {
277         Val = Sd->mRight[Val];
278       } else {
279         Val = Sd->mLeft[Val];
280       }
281 
282       Mask >>= 1;
283     } while (Val >= MAXNP);
284   }
285   //
286   // Advance what we have read
287   //
288   FillBuf (Sd, Sd->mPTLen[Val]);
289 
290   Pos = Val;
291   if (Val > 1) {
292     Pos = (UINT32) ((1U << (Val - 1)) + GetBits (Sd, (UINT16) (Val - 1)));
293   }
294 
295   return Pos;
296 }
297 
298 /**
299   Reads code lengths for the Extra Set or the Position Set.
300 
301   Read in the Extra Set or Position Set Length Array, then
302   generate the Huffman code mapping for them.
303 
304   @param  Sd      The global scratch data.
305   @param  nn      Number of symbols.
306   @param  nbit    Number of bits needed to represent nn.
307   @param  Special The special symbol that needs to be taken care of.
308 
309   @retval  0 OK.
310   @retval  BAD_TABLE Table is corrupted.
311 
312 **/
313 UINT16
ReadPTLen(IN SCRATCH_DATA * Sd,IN UINT16 nn,IN UINT16 nbit,IN UINT16 Special)314 ReadPTLen (
315   IN  SCRATCH_DATA  *Sd,
316   IN  UINT16        nn,
317   IN  UINT16        nbit,
318   IN  UINT16        Special
319   )
320 {
321   UINT16  Number;
322   UINT16  CharC;
323   UINT16  Index;
324   UINT32  Mask;
325 
326   ASSERT (nn <= NPT);
327   //
328   // Read Extra Set Code Length Array size
329   //
330   Number = (UINT16) GetBits (Sd, nbit);
331 
332   if (Number == 0) {
333     //
334     // This represents only Huffman code used
335     //
336     CharC = (UINT16) GetBits (Sd, nbit);
337 
338     for (Index = 0; Index < 256; Index++) {
339       Sd->mPTTable[Index] = CharC;
340     }
341 
342     SetMem (Sd->mPTLen, nn, 0);
343 
344     return 0;
345   }
346 
347   Index = 0;
348 
349   while (Index < Number && Index < NPT) {
350 
351     CharC = (UINT16) (Sd->mBitBuf >> (BITBUFSIZ - 3));
352 
353     //
354     // If a code length is less than 7, then it is encoded as a 3-bit
355     // value. Or it is encoded as a series of "1"s followed by a
356     // terminating "0". The number of "1"s = Code length - 4.
357     //
358     if (CharC == 7) {
359       Mask = 1U << (BITBUFSIZ - 1 - 3);
360       while (Mask & Sd->mBitBuf) {
361         Mask >>= 1;
362         CharC += 1;
363       }
364     }
365 
366     FillBuf (Sd, (UINT16) ((CharC < 7) ? 3 : CharC - 3));
367 
368     Sd->mPTLen[Index++] = (UINT8) CharC;
369 
370     //
371     // For Code&Len Set,
372     // After the third length of the code length concatenation,
373     // a 2-bit value is used to indicated the number of consecutive
374     // zero lengths after the third length.
375     //
376     if (Index == Special) {
377       CharC = (UINT16) GetBits (Sd, 2);
378       while ((INT16) (--CharC) >= 0 && Index < NPT) {
379         Sd->mPTLen[Index++] = 0;
380       }
381     }
382   }
383 
384   while (Index < nn && Index < NPT) {
385     Sd->mPTLen[Index++] = 0;
386   }
387 
388   return MakeTable (Sd, nn, Sd->mPTLen, 8, Sd->mPTTable);
389 }
390 
391 /**
392   Reads code lengths for Char&Len Set.
393 
394   Read in and decode the Char&Len Set Code Length Array, then
395   generate the Huffman Code mapping table for the Char&Len Set.
396 
397   @param  Sd the global scratch data
398 
399 **/
400 VOID
ReadCLen(SCRATCH_DATA * Sd)401 ReadCLen (
402   SCRATCH_DATA  *Sd
403   )
404 {
405   UINT16  Number;
406   UINT16  CharC;
407   UINT16  Index;
408   UINT32  Mask;
409 
410   Number = (UINT16) GetBits (Sd, CBIT);
411 
412   if (Number == 0) {
413     //
414     // This represents only Huffman code used
415     //
416     CharC = (UINT16) GetBits (Sd, CBIT);
417 
418     SetMem (Sd->mCLen, NC, 0);
419 
420     for (Index = 0; Index < 4096; Index++) {
421       Sd->mCTable[Index] = CharC;
422     }
423 
424     return ;
425   }
426 
427   Index = 0;
428   while (Index < Number && Index < NC) {
429     CharC = Sd->mPTTable[Sd->mBitBuf >> (BITBUFSIZ - 8)];
430     if (CharC >= NT) {
431       Mask = 1U << (BITBUFSIZ - 1 - 8);
432 
433       do {
434 
435         if (Mask & Sd->mBitBuf) {
436           CharC = Sd->mRight[CharC];
437         } else {
438           CharC = Sd->mLeft[CharC];
439         }
440 
441         Mask >>= 1;
442 
443       } while (CharC >= NT);
444     }
445     //
446     // Advance what we have read
447     //
448     FillBuf (Sd, Sd->mPTLen[CharC]);
449 
450     if (CharC <= 2) {
451 
452       if (CharC == 0) {
453         CharC = 1;
454       } else if (CharC == 1) {
455         CharC = (UINT16) (GetBits (Sd, 4) + 3);
456       } else if (CharC == 2) {
457         CharC = (UINT16) (GetBits (Sd, CBIT) + 20);
458       }
459 
460       while ((INT16) (--CharC) >= 0 && Index < NC) {
461         Sd->mCLen[Index++] = 0;
462       }
463 
464     } else {
465 
466       Sd->mCLen[Index++] = (UINT8) (CharC - 2);
467 
468     }
469   }
470 
471   SetMem (Sd->mCLen + Index, NC - Index, 0);
472 
473   MakeTable (Sd, NC, Sd->mCLen, 12, Sd->mCTable);
474 
475   return ;
476 }
477 
478 /**
479   Decode a character/length value.
480 
481   Read one value from mBitBuf, Get one code from mBitBuf. If it is at block boundary, generates
482   Huffman code mapping table for Extra Set, Code&Len Set and
483   Position Set.
484 
485   @param  Sd The global scratch data.
486 
487   @return The value decoded.
488 
489 **/
490 UINT16
DecodeC(SCRATCH_DATA * Sd)491 DecodeC (
492   SCRATCH_DATA  *Sd
493   )
494 {
495   UINT16  Index2;
496   UINT32  Mask;
497 
498   if (Sd->mBlockSize == 0) {
499     //
500     // Starting a new block
501     // Read BlockSize from block header
502     //
503     Sd->mBlockSize    = (UINT16) GetBits (Sd, 16);
504 
505     //
506     // Read in the Extra Set Code Length Array,
507     // Generate the Huffman code mapping table for Extra Set.
508     //
509     Sd->mBadTableFlag = ReadPTLen (Sd, NT, TBIT, 3);
510     if (Sd->mBadTableFlag != 0) {
511       return 0;
512     }
513 
514     //
515     // Read in and decode the Char&Len Set Code Length Array,
516     // Generate the Huffman code mapping table for Char&Len Set.
517     //
518     ReadCLen (Sd);
519 
520     //
521     // Read in the Position Set Code Length Array,
522     // Generate the Huffman code mapping table for the Position Set.
523     //
524     Sd->mBadTableFlag = ReadPTLen (Sd, MAXNP, Sd->mPBit, (UINT16) (-1));
525     if (Sd->mBadTableFlag != 0) {
526       return 0;
527     }
528   }
529 
530   //
531   // Get one code according to Code&Set Huffman Table
532   //
533   Sd->mBlockSize--;
534   Index2 = Sd->mCTable[Sd->mBitBuf >> (BITBUFSIZ - 12)];
535 
536   if (Index2 >= NC) {
537     Mask = 1U << (BITBUFSIZ - 1 - 12);
538 
539     do {
540       if ((Sd->mBitBuf & Mask) != 0) {
541         Index2 = Sd->mRight[Index2];
542       } else {
543         Index2 = Sd->mLeft[Index2];
544       }
545 
546       Mask >>= 1;
547     } while (Index2 >= NC);
548   }
549   //
550   // Advance what we have read
551   //
552   FillBuf (Sd, Sd->mCLen[Index2]);
553 
554   return Index2;
555 }
556 
557 /**
558   Decode the source data and put the resulting data into the destination buffer.
559 
560   @param  Sd The global scratch data
561 **/
562 VOID
Decode(SCRATCH_DATA * Sd)563 Decode (
564   SCRATCH_DATA  *Sd
565   )
566 {
567   UINT16  BytesRemain;
568   UINT32  DataIdx;
569   UINT16  CharC;
570 
571   BytesRemain = (UINT16) (-1);
572 
573   DataIdx     = 0;
574 
575   for (;;) {
576     //
577     // Get one code from mBitBuf
578     //
579     CharC = DecodeC (Sd);
580     if (Sd->mBadTableFlag != 0) {
581       goto Done;
582     }
583 
584     if (CharC < 256) {
585       //
586       // Process an Original character
587       //
588       if (Sd->mOutBuf >= Sd->mOrigSize) {
589         goto Done;
590       } else {
591         //
592         // Write orignal character into mDstBase
593         //
594         Sd->mDstBase[Sd->mOutBuf++] = (UINT8) CharC;
595       }
596 
597     } else {
598       //
599       // Process a Pointer
600       //
601       CharC       = (UINT16) (CharC - (BIT8 - THRESHOLD));
602 
603       //
604       // Get string length
605       //
606       BytesRemain = CharC;
607 
608       //
609       // Locate string position
610       //
611       DataIdx     = Sd->mOutBuf - DecodeP (Sd) - 1;
612 
613       //
614       // Write BytesRemain of bytes into mDstBase
615       //
616       BytesRemain--;
617       while ((INT16) (BytesRemain) >= 0) {
618         Sd->mDstBase[Sd->mOutBuf++] = Sd->mDstBase[DataIdx++];
619         if (Sd->mOutBuf >= Sd->mOrigSize) {
620           goto Done ;
621         }
622 
623         BytesRemain--;
624       }
625     }
626   }
627 
628 Done:
629   return ;
630 }
631 
632 /**
633   Given a compressed source buffer, this function retrieves the size of
634   the uncompressed buffer and the size of the scratch buffer required
635   to decompress the compressed source buffer.
636 
637   Retrieves the size of the uncompressed buffer and the temporary scratch buffer
638   required to decompress the buffer specified by Source and SourceSize.
639   If the size of the uncompressed buffer or the size of the scratch buffer cannot
640   be determined from the compressed data specified by Source and SourceData,
641   then RETURN_INVALID_PARAMETER is returned.  Otherwise, the size of the uncompressed
642   buffer is returned in DestinationSize, the size of the scratch buffer is returned
643   in ScratchSize, and RETURN_SUCCESS is returned.
644   This function does not have scratch buffer available to perform a thorough
645   checking of the validity of the source data.  It just retrieves the "Original Size"
646   field from the beginning bytes of the source data and output it as DestinationSize.
647   And ScratchSize is specific to the decompression implementation.
648 
649   If Source is NULL, then ASSERT().
650   If DestinationSize is NULL, then ASSERT().
651   If ScratchSize is NULL, then ASSERT().
652 
653   @param  Source          The source buffer containing the compressed data.
654   @param  SourceSize      The size, in bytes, of the source buffer.
655   @param  DestinationSize A pointer to the size, in bytes, of the uncompressed buffer
656                           that will be generated when the compressed buffer specified
657                           by Source and SourceSize is decompressed..
658   @param  ScratchSize     A pointer to the size, in bytes, of the scratch buffer that
659                           is required to decompress the compressed buffer specified
660                           by Source and SourceSize.
661 
662   @retval  RETURN_SUCCESS The size of the uncompressed data was returned
663                           in DestinationSize and the size of the scratch
664                           buffer was returned in ScratchSize.
665   @retval  RETURN_INVALID_PARAMETER
666                           The size of the uncompressed data or the size of
667                           the scratch buffer cannot be determined from
668                           the compressed data specified by Source
669                           and SourceSize.
670 **/
671 RETURN_STATUS
672 EFIAPI
UefiDecompressGetInfo(IN CONST VOID * Source,IN UINT32 SourceSize,OUT UINT32 * DestinationSize,OUT UINT32 * ScratchSize)673 UefiDecompressGetInfo (
674   IN  CONST VOID  *Source,
675   IN  UINT32      SourceSize,
676   OUT UINT32      *DestinationSize,
677   OUT UINT32      *ScratchSize
678   )
679 {
680   UINT32  CompressedSize;
681 
682   ASSERT (Source != NULL);
683   ASSERT (DestinationSize != NULL);
684   ASSERT (ScratchSize != NULL);
685 
686   if (SourceSize < 8) {
687     return RETURN_INVALID_PARAMETER;
688   }
689 
690   CompressedSize   = ReadUnaligned32 ((UINT32 *)Source);
691   if (SourceSize < (CompressedSize + 8)) {
692     return RETURN_INVALID_PARAMETER;
693   }
694 
695   *ScratchSize  = sizeof (SCRATCH_DATA);
696   *DestinationSize = ReadUnaligned32 ((UINT32 *)Source + 1);
697 
698   return RETURN_SUCCESS;
699 }
700 
701 /**
702   Decompresses a compressed source buffer by EFI or Tiano algorithm.
703 
704   Extracts decompressed data to its original form.
705   This function is designed so that the decompression algorithm can be implemented
706   without using any memory services.  As a result, this function is not allowed to
707   call any memory allocation services in its implementation.  It is the caller's
708   responsibility to allocate and free the Destination and Scratch buffers.
709   If the compressed source data specified by Source is successfully decompressed
710   into Destination, then RETURN_SUCCESS is returned.  If the compressed source data
711   specified by Source is not in a valid compressed data format,
712   then RETURN_INVALID_PARAMETER is returned.
713 
714   If Source is NULL, then ASSERT().
715   If Destination is NULL, then ASSERT().
716   If the required scratch buffer size > 0 and Scratch is NULL, then ASSERT().
717 
718   @param  Source      The source buffer containing the compressed data.
719   @param  Destination The destination buffer to store the decompressed data
720   @param  Scratch     A temporary scratch buffer that is used to perform the decompression.
721                       This is an optional parameter that may be NULL if the
722                       required scratch buffer size is 0.
723   @param  Version     1 for UEFI Decompress algoruthm, 2 for Tiano Decompess algorithm.
724 
725   @retval  RETURN_SUCCESS Decompression completed successfully, and
726                           the uncompressed buffer is returned in Destination.
727   @retval  RETURN_INVALID_PARAMETER
728                           The source buffer specified by Source is corrupted
729                           (not in a valid compressed format).
730 **/
731 RETURN_STATUS
732 EFIAPI
UefiTianoDecompress(IN CONST VOID * Source,IN OUT VOID * Destination,IN OUT VOID * Scratch,IN UINT32 Version)733 UefiTianoDecompress (
734   IN CONST VOID  *Source,
735   IN OUT VOID    *Destination,
736   IN OUT VOID    *Scratch,
737   IN UINT32      Version
738   )
739 {
740   UINT32           CompSize;
741   UINT32           OrigSize;
742   SCRATCH_DATA     *Sd;
743   CONST UINT8      *Src;
744   UINT8            *Dst;
745 
746   ASSERT (Source != NULL);
747   ASSERT (Destination != NULL);
748   ASSERT (Scratch != NULL);
749 
750   Src     = Source;
751   Dst     = Destination;
752 
753   Sd = (SCRATCH_DATA *) Scratch;
754 
755   CompSize  = Src[0] + (Src[1] << 8) + (Src[2] << 16) + (Src[3] << 24);
756   OrigSize  = Src[4] + (Src[5] << 8) + (Src[6] << 16) + (Src[7] << 24);
757 
758   //
759   // If compressed file size is 0, return
760   //
761   if (OrigSize == 0) {
762     return RETURN_SUCCESS;
763   }
764 
765   Src = Src + 8;
766 
767   SetMem (Sd, sizeof (SCRATCH_DATA), 0);
768 
769   //
770   // The length of the field 'Position Set Code Length Array Size' in Block Header.
771   // For UEFI 2.0 de/compression algorithm(Version 1), mPBit = 4
772   // For Tiano de/compression algorithm(Version 2), mPBit = 5
773   //
774   switch (Version) {
775     case 1 :
776       Sd->mPBit = 4;
777       break;
778     case 2 :
779       Sd->mPBit = 5;
780       break;
781     default:
782       ASSERT (FALSE);
783   }
784   Sd->mSrcBase  = (UINT8 *)Src;
785   Sd->mDstBase  = Dst;
786   //
787   // CompSize and OrigSize are calculated in bytes
788   //
789   Sd->mCompSize = CompSize;
790   Sd->mOrigSize = OrigSize;
791 
792   //
793   // Fill the first BITBUFSIZ bits
794   //
795   FillBuf (Sd, BITBUFSIZ);
796 
797   //
798   // Decompress it
799   //
800   Decode (Sd);
801 
802   if (Sd->mBadTableFlag != 0) {
803     //
804     // Something wrong with the source
805     //
806     return RETURN_INVALID_PARAMETER;
807   }
808 
809   return RETURN_SUCCESS;
810 }
811 
812 /**
813   Decompresses a UEFI compressed source buffer.
814 
815   Extracts decompressed data to its original form.
816   This function is designed so that the decompression algorithm can be implemented
817   without using any memory services.  As a result, this function is not allowed to
818   call any memory allocation services in its implementation.  It is the caller's
819   responsibility to allocate and free the Destination and Scratch buffers.
820   If the compressed source data specified by Source is successfully decompressed
821   into Destination, then RETURN_SUCCESS is returned.  If the compressed source data
822   specified by Source is not in a valid compressed data format,
823   then RETURN_INVALID_PARAMETER is returned.
824 
825   If Source is NULL, then ASSERT().
826   If Destination is NULL, then ASSERT().
827   If the required scratch buffer size > 0 and Scratch is NULL, then ASSERT().
828 
829   @param  Source      The source buffer containing the compressed data.
830   @param  Destination The destination buffer to store the decompressed data
831   @param  Scratch     A temporary scratch buffer that is used to perform the decompression.
832                       This is an optional parameter that may be NULL if the
833                       required scratch buffer size is 0.
834 
835   @retval  RETURN_SUCCESS Decompression completed successfully, and
836                           the uncompressed buffer is returned in Destination.
837   @retval  RETURN_INVALID_PARAMETER
838                           The source buffer specified by Source is corrupted
839                           (not in a valid compressed format).
840 **/
841 RETURN_STATUS
842 EFIAPI
UefiDecompress(IN CONST VOID * Source,IN OUT VOID * Destination,IN OUT VOID * Scratch OPTIONAL)843 UefiDecompress (
844   IN CONST VOID  *Source,
845   IN OUT VOID    *Destination,
846   IN OUT VOID    *Scratch  OPTIONAL
847   )
848 {
849   return UefiTianoDecompress (Source, Destination, Scratch, 1);
850 }
851 
852 /**
853   Examines a GUIDed section and returns the size of the decoded buffer and the
854   size of an optional scratch buffer required to actually decode the data in a GUIDed section.
855 
856   Examines a GUIDed section specified by InputSection.
857   If GUID for InputSection does not match the GUID that this handler supports,
858   then RETURN_UNSUPPORTED is returned.
859   If the required information can not be retrieved from InputSection,
860   then RETURN_INVALID_PARAMETER is returned.
861   If the GUID of InputSection does match the GUID that this handler supports,
862   then the size required to hold the decoded buffer is returned in OututBufferSize,
863   the size of an optional scratch buffer is returned in ScratchSize, and the Attributes field
864   from EFI_GUID_DEFINED_SECTION header of InputSection is returned in SectionAttribute.
865 
866   If InputSection is NULL, then ASSERT().
867   If OutputBufferSize is NULL, then ASSERT().
868   If ScratchBufferSize is NULL, then ASSERT().
869   If SectionAttribute is NULL, then ASSERT().
870 
871 
872   @param[in]  InputSection       A pointer to a GUIDed section of an FFS formatted file.
873   @param[out] OutputBufferSize   A pointer to the size, in bytes, of an output buffer required
874                                  if the buffer specified by InputSection were decoded.
875   @param[out] ScratchBufferSize  A pointer to the size, in bytes, required as scratch space
876                                  if the buffer specified by InputSection were decoded.
877   @param[out] SectionAttribute   A pointer to the attributes of the GUIDed section. See the Attributes
878                                  field of EFI_GUID_DEFINED_SECTION in the PI Specification.
879 
880   @retval  RETURN_SUCCESS            The information about InputSection was returned.
881   @retval  RETURN_UNSUPPORTED        The section specified by InputSection does not match the GUID this handler supports.
882   @retval  RETURN_INVALID_PARAMETER  The information can not be retrieved from the section specified by InputSection.
883 
884 **/
885 RETURN_STATUS
886 EFIAPI
TianoDecompressGetInfo(IN CONST VOID * InputSection,OUT UINT32 * OutputBufferSize,OUT UINT32 * ScratchBufferSize,OUT UINT16 * SectionAttribute)887 TianoDecompressGetInfo (
888   IN  CONST VOID  *InputSection,
889   OUT UINT32      *OutputBufferSize,
890   OUT UINT32      *ScratchBufferSize,
891   OUT UINT16      *SectionAttribute
892   )
893 
894 {
895   ASSERT (SectionAttribute != NULL);
896 
897   if (InputSection == NULL) {
898     return RETURN_INVALID_PARAMETER;
899   }
900 
901   if (IS_SECTION2 (InputSection)) {
902     if (!CompareGuid (
903         &gTianoCustomDecompressGuid,
904         &(((EFI_GUID_DEFINED_SECTION2 *) InputSection)->SectionDefinitionGuid))) {
905       return RETURN_INVALID_PARAMETER;
906     }
907     //
908     // Get guid attribute of guid section.
909     //
910     *SectionAttribute = ((EFI_GUID_DEFINED_SECTION2 *) InputSection)->Attributes;
911 
912     //
913     // Call Tiano GetInfo to get the required size info.
914     //
915     return UefiDecompressGetInfo (
916              (UINT8 *) InputSection + ((EFI_GUID_DEFINED_SECTION2 *) InputSection)->DataOffset,
917              SECTION2_SIZE (InputSection) - ((EFI_GUID_DEFINED_SECTION2 *) InputSection)->DataOffset,
918              OutputBufferSize,
919              ScratchBufferSize
920              );
921   } else {
922     if (!CompareGuid (
923         &gTianoCustomDecompressGuid,
924         &(((EFI_GUID_DEFINED_SECTION *) InputSection)->SectionDefinitionGuid))) {
925       return RETURN_INVALID_PARAMETER;
926     }
927     //
928     // Get guid attribute of guid section.
929     //
930     *SectionAttribute = ((EFI_GUID_DEFINED_SECTION *) InputSection)->Attributes;
931 
932     //
933     // Call Tiano GetInfo to get the required size info.
934     //
935     return UefiDecompressGetInfo (
936              (UINT8 *) InputSection + ((EFI_GUID_DEFINED_SECTION *) InputSection)->DataOffset,
937              SECTION_SIZE (InputSection) - ((EFI_GUID_DEFINED_SECTION *) InputSection)->DataOffset,
938              OutputBufferSize,
939              ScratchBufferSize
940              );
941   }
942 }
943 
944 /**
945   Decompress a Tiano compressed GUIDed section into a caller allocated output buffer.
946 
947   Decodes the GUIDed section specified by InputSection.
948   If GUID for InputSection does not match the GUID that this handler supports, then RETURN_UNSUPPORTED is returned.
949   If the data in InputSection can not be decoded, then RETURN_INVALID_PARAMETER is returned.
950   If the GUID of InputSection does match the GUID that this handler supports, then InputSection
951   is decoded into the buffer specified by OutputBuffer and the authentication status of this
952   decode operation is returned in AuthenticationStatus.  If the decoded buffer is identical to the
953   data in InputSection, then OutputBuffer is set to point at the data in InputSection.  Otherwise,
954   the decoded data will be placed in caller allocated buffer specified by OutputBuffer.
955 
956   If InputSection is NULL, then ASSERT().
957   If OutputBuffer is NULL, then ASSERT().
958   If ScratchBuffer is NULL and this decode operation requires a scratch buffer, then ASSERT().
959   If AuthenticationStatus is NULL, then ASSERT().
960 
961 
962   @param[in]  InputSection  A pointer to a GUIDed section of an FFS formatted file.
963   @param[out] OutputBuffer  A pointer to a buffer that contains the result of a decode operation.
964   @param[in] ScratchBuffer  A caller allocated buffer that may be required by this function
965                             as a scratch buffer to perform the decode operation.
966   @param[out] AuthenticationStatus
967                             A pointer to the authentication status of the decoded output buffer.
968                             See the definition of authentication status in the EFI_PEI_GUIDED_SECTION_EXTRACTION_PPI
969                             section of the PI Specification. EFI_AUTH_STATUS_PLATFORM_OVERRIDE must
970                             never be set by this handler.
971 
972   @retval  RETURN_SUCCESS            The buffer specified by InputSection was decoded.
973   @retval  RETURN_UNSUPPORTED        The section specified by InputSection does not match the GUID this handler supports.
974   @retval  RETURN_INVALID_PARAMETER  The section specified by InputSection can not be decoded.
975 
976 **/
977 RETURN_STATUS
978 EFIAPI
TianoDecompress(IN CONST VOID * InputSection,OUT VOID ** OutputBuffer,IN VOID * ScratchBuffer,OPTIONAL OUT UINT32 * AuthenticationStatus)979 TianoDecompress (
980   IN CONST  VOID    *InputSection,
981   OUT       VOID    **OutputBuffer,
982   IN        VOID    *ScratchBuffer,        OPTIONAL
983   OUT       UINT32  *AuthenticationStatus
984   )
985 {
986   ASSERT (OutputBuffer != NULL);
987   ASSERT (InputSection != NULL);
988 
989   if (IS_SECTION2 (InputSection)) {
990     if (!CompareGuid (
991         &gTianoCustomDecompressGuid,
992         &(((EFI_GUID_DEFINED_SECTION2 *) InputSection)->SectionDefinitionGuid))) {
993       return RETURN_INVALID_PARAMETER;
994     }
995 
996     //
997     // Set Authentication to Zero.
998     //
999     *AuthenticationStatus = 0;
1000 
1001     //
1002     // Call Tiano Decompress to get the raw data
1003     //
1004     return UefiTianoDecompress (
1005              (UINT8 *) InputSection + ((EFI_GUID_DEFINED_SECTION2 *) InputSection)->DataOffset,
1006              *OutputBuffer,
1007              ScratchBuffer,
1008              2
1009            );
1010   } else {
1011     if (!CompareGuid (
1012         &gTianoCustomDecompressGuid,
1013         &(((EFI_GUID_DEFINED_SECTION *) InputSection)->SectionDefinitionGuid))) {
1014       return RETURN_INVALID_PARAMETER;
1015     }
1016 
1017     //
1018     // Set Authentication to Zero.
1019     //
1020     *AuthenticationStatus = 0;
1021 
1022     //
1023     // Call Tiano Decompress to get the raw data
1024     //
1025     return UefiTianoDecompress (
1026              (UINT8 *) InputSection + ((EFI_GUID_DEFINED_SECTION *) InputSection)->DataOffset,
1027              *OutputBuffer,
1028              ScratchBuffer,
1029              2
1030            );
1031   }
1032 }
1033 
1034 /**
1035   Registers TianoDecompress and TianoDecompressGetInfo handlers with TianoCustomerDecompressGuid
1036 
1037   @retval  RETURN_SUCCESS            Register successfully.
1038   @retval  RETURN_OUT_OF_RESOURCES   No enough memory to store this handler.
1039 **/
1040 RETURN_STATUS
1041 EFIAPI
TianoDecompressLibConstructor()1042 TianoDecompressLibConstructor (
1043 )
1044 {
1045   return ExtractGuidedSectionRegisterHandlers (
1046           &gTianoCustomDecompressGuid,
1047           TianoDecompressGetInfo,
1048           TianoDecompress
1049           );
1050 }
1051