Home | History | Annotate | Download | only in BaseUefiTianoCustomDecompressLib
      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
     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
     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
    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
    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 Pointion Set Length Arrary, 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
    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
    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
    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 Arrary,
    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 Arrary,
    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 Arrary,
    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
    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
    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
    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
    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
    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
    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
   1042 TianoDecompressLibConstructor (
   1043 )
   1044 {
   1045   return ExtractGuidedSectionRegisterHandlers (
   1046           &gTianoCustomDecompressGuid,
   1047           TianoDecompressGetInfo,
   1048           TianoDecompress
   1049           );
   1050 }
   1051