Home | History | Annotate | Download | only in TianoCompress
      1 /** @file
      2 Compression routine. The compression algorithm is a mixture of LZ77 and Huffman
      3 coding. LZ77 transforms the source data into a sequence of Original Characters
      4 and Pointers to repeated strings.
      5 This sequence is further divided into Blocks and Huffman codings are applied to
      6 each Block.
      7 
      8 Copyright (c) 2007 - 2014, Intel Corporation. All rights reserved.<BR>
      9 This program and the accompanying materials
     10 are licensed and made available under the terms and conditions of the BSD License
     11 which accompanies this distribution.  The full text of the license may be found at
     12 http://opensource.org/licenses/bsd-license.php
     13 
     14 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
     15 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
     16 
     17 **/
     18 
     19 #include "Compress.h"
     20 #include "TianoCompress.h"
     21 #include "EfiUtilityMsgs.h"
     22 #include "ParseInf.h"
     23 #include <stdio.h>
     24 #include "assert.h"
     25 
     26 //
     27 // Macro Definitions
     28 //
     29 static BOOLEAN VerboseMode = FALSE;
     30 static BOOLEAN QuietMode = FALSE;
     31 #undef UINT8_MAX
     32 #define UINT8_MAX     0xff
     33 #define UINT8_BIT     8
     34 #define THRESHOLD     3
     35 #define INIT_CRC      0
     36 #define WNDBIT        19
     37 #define WNDSIZ        (1U << WNDBIT)
     38 #define MAXMATCH      256
     39 #define BLKSIZ        (1U << 14)  // 16 * 1024U
     40 #define PERC_FLAG     0x80000000U
     41 #define CODE_BIT      16
     42 #define NIL           0
     43 #define MAX_HASH_VAL  (3 * WNDSIZ + (WNDSIZ / 512 + 1) * UINT8_MAX)
     44 #define HASH(p, c)    ((p) + ((c) << (WNDBIT - 9)) + WNDSIZ * 2)
     45 #define CRCPOLY       0xA001
     46 #define UPDATE_CRC(c) mCrc = mCrcTable[(mCrc ^ (c)) & 0xFF] ^ (mCrc >> UINT8_BIT)
     47 
     48 //
     49 // C: the Char&Len Set; P: the Position Set; T: the exTra Set
     50 //
     51 //#define NC    (UINT8_MAX + MAXMATCH + 2 - THRESHOLD)
     52 #define CBIT  9
     53 #define NP    (WNDBIT + 1)
     54 #define PBIT  5
     55 //#define NT    (CODE_BIT + 3)
     56 //#define TBIT  5
     57 //#if NT > NP
     58 //#define NPT NT
     59 //#else
     60 //#define NPT NP
     61 //#endif
     62 
     63 //
     64 //  Global Variables
     65 //
     66 STATIC BOOLEAN ENCODE = FALSE;
     67 STATIC BOOLEAN DECODE = FALSE;
     68 STATIC UINT8  *mSrc, *mDst, *mSrcUpperLimit, *mDstUpperLimit;
     69 STATIC UINT8  *mLevel, *mText, *mChildCount, *mBuf, mCLen[NC], mPTLen[NPT], *mLen;
     70 STATIC INT16  mHeap[NC + 1];
     71 STATIC INT32  mRemainder, mMatchLen, mBitCount, mHeapSize, mN;
     72 STATIC UINT32 mBufSiz = 0, mOutputPos, mOutputMask, mSubBitBuf, mCrc;
     73 STATIC UINT32 mCompSize, mOrigSize;
     74 
     75 STATIC UINT16 *mFreq, *mSortPtr, mLenCnt[17], mLeft[2 * NC - 1], mRight[2 * NC - 1], mCrcTable[UINT8_MAX + 1],
     76   mCFreq[2 * NC - 1], mCCode[NC], mPFreq[2 * NP - 1], mPTCode[NPT], mTFreq[2 * NT - 1];
     77 
     78 STATIC NODE   mPos, mMatchPos, mAvail, *mPosition, *mParent, *mPrev, *mNext = NULL;
     79 
     80 static  UINT64     DebugLevel;
     81 static  BOOLEAN    DebugMode;
     82 //
     83 // functions
     84 //
     85 EFI_STATUS
     86 TianoCompress (
     87   IN      UINT8   *SrcBuffer,
     88   IN      UINT32  SrcSize,
     89   IN      UINT8   *DstBuffer,
     90   IN OUT  UINT32  *DstSize
     91   )
     92 /*++
     93 
     94 Routine Description:
     95 
     96   The internal implementation of [Efi/Tiano]Compress().
     97 
     98 Arguments:
     99 
    100   SrcBuffer   - The buffer storing the source data
    101   SrcSize     - The size of source data
    102   DstBuffer   - The buffer to store the compressed data
    103 
    104   Version     - The version of de/compression algorithm.
    105                 Version 1 for EFI 1.1 de/compression algorithm.
    106                 Version 2 for Tiano de/compression algorithm.
    107 
    108 Returns:
    109 
    110   EFI_BUFFER_TOO_SMALL  - The DstBuffer is too small. In this case,
    111                 DstSize contains the size needed.
    112   EFI_SUCCESS           - Compression is successful.
    113   EFI_OUT_OF_RESOURCES  - No resource to complete function.
    114   EFI_INVALID_PARAMETER - Parameter supplied is wrong.
    115 
    116 --*/
    117 {
    118   EFI_STATUS  Status;
    119 
    120   //
    121   // Initializations
    122   //
    123   mBufSiz         = 0;
    124   mBuf            = NULL;
    125   mText           = NULL;
    126   mLevel          = NULL;
    127   mChildCount     = NULL;
    128   mPosition       = NULL;
    129   mParent         = NULL;
    130   mPrev           = NULL;
    131   mNext           = NULL;
    132 
    133 
    134   mSrc            = SrcBuffer;
    135   mSrcUpperLimit  = mSrc + SrcSize;
    136   mDst            = DstBuffer;
    137   mDstUpperLimit  = mDst +*DstSize;
    138 
    139   PutDword (0L);
    140   PutDword (0L);
    141 
    142   MakeCrcTable ();
    143 
    144   mOrigSize             = mCompSize = 0;
    145   mCrc                  = INIT_CRC;
    146 
    147   //
    148   // Compress it
    149   //
    150   Status = Encode ();
    151   if (EFI_ERROR (Status)) {
    152     return EFI_OUT_OF_RESOURCES;
    153   }
    154 
    155   //
    156   // Null terminate the compressed data
    157   //
    158 
    159   if (mDst < mDstUpperLimit) {
    160     *mDst++ = 0;
    161   }
    162 
    163   //
    164   // Fill in compressed size and original size
    165   //
    166   mDst = DstBuffer;
    167 
    168   PutDword (mCompSize + 1);
    169   PutDword (mOrigSize);
    170   //
    171   // Return
    172   //
    173 
    174   if (mCompSize + 1 + 8 > *DstSize) {
    175     *DstSize = mCompSize + 1 + 8;
    176     return EFI_BUFFER_TOO_SMALL;
    177   } else {
    178     *DstSize = mCompSize + 1 + 8;
    179     return EFI_SUCCESS;
    180   }
    181 }
    182 
    183 STATIC
    184 VOID
    185 PutDword (
    186   IN UINT32 Data
    187   )
    188 /*++
    189 
    190 Routine Description:
    191 
    192   Put a dword to output stream
    193 
    194 Arguments:
    195 
    196   Data    - the dword to put
    197 
    198 Returns: (VOID)
    199 
    200 --*/
    201 {
    202   if (mDst < mDstUpperLimit) {
    203     *mDst++ = (UINT8) (((UINT8) (Data)) & 0xff);
    204   }
    205 
    206   if (mDst < mDstUpperLimit) {
    207     *mDst++ = (UINT8) (((UINT8) (Data >> 0x08)) & 0xff);
    208   }
    209 
    210   if (mDst < mDstUpperLimit) {
    211     *mDst++ = (UINT8) (((UINT8) (Data >> 0x10)) & 0xff);
    212   }
    213 
    214   if (mDst < mDstUpperLimit) {
    215     *mDst++ = (UINT8) (((UINT8) (Data >> 0x18)) & 0xff);
    216   }
    217 }
    218 
    219 STATIC
    220 EFI_STATUS
    221 AllocateMemory (
    222   VOID
    223   )
    224 /*++
    225 
    226 Routine Description:
    227 
    228   Allocate memory spaces for data structures used in compression process
    229 
    230 Argements:
    231   VOID
    232 
    233 Returns:
    234 
    235   EFI_SUCCESS           - Memory is allocated successfully
    236   EFI_OUT_OF_RESOURCES  - Allocation fails
    237 
    238 --*/
    239 {
    240   UINT32  Index;
    241 
    242   mText = malloc (WNDSIZ * 2 + MAXMATCH);
    243   for (Index = 0; Index < WNDSIZ * 2 + MAXMATCH; Index++) {
    244     mText[Index] = 0;
    245   }
    246 
    247   mLevel      = malloc ((WNDSIZ + UINT8_MAX + 1) * sizeof (*mLevel));
    248   mChildCount = malloc ((WNDSIZ + UINT8_MAX + 1) * sizeof (*mChildCount));
    249   mPosition   = malloc ((WNDSIZ + UINT8_MAX + 1) * sizeof (*mPosition));
    250   mParent     = malloc (WNDSIZ * 2 * sizeof (*mParent));
    251   mPrev       = malloc (WNDSIZ * 2 * sizeof (*mPrev));
    252   mNext       = malloc ((MAX_HASH_VAL + 1) * sizeof (*mNext));
    253 
    254   mBufSiz     = BLKSIZ;
    255   mBuf        = malloc (mBufSiz);
    256   while (mBuf == NULL) {
    257     mBufSiz = (mBufSiz / 10U) * 9U;
    258     if (mBufSiz < 4 * 1024U) {
    259       return EFI_OUT_OF_RESOURCES;
    260     }
    261 
    262     mBuf = malloc (mBufSiz);
    263   }
    264 
    265   mBuf[0] = 0;
    266 
    267   return EFI_SUCCESS;
    268 }
    269 
    270 VOID
    271 FreeMemory (
    272   VOID
    273   )
    274 /*++
    275 
    276 Routine Description:
    277 
    278   Called when compression is completed to free memory previously allocated.
    279 
    280 Arguments: (VOID)
    281 
    282 Returns: (VOID)
    283 
    284 --*/
    285 {
    286   if (mText != NULL) {
    287     free (mText);
    288   }
    289 
    290   if (mLevel != NULL) {
    291     free (mLevel);
    292   }
    293 
    294   if (mChildCount != NULL) {
    295     free (mChildCount);
    296   }
    297 
    298   if (mPosition != NULL) {
    299     free (mPosition);
    300   }
    301 
    302   if (mParent != NULL) {
    303     free (mParent);
    304   }
    305 
    306   if (mPrev != NULL) {
    307     free (mPrev);
    308   }
    309 
    310   if (mNext != NULL) {
    311     free (mNext);
    312   }
    313 
    314   if (mBuf != NULL) {
    315     free (mBuf);
    316   }
    317 
    318   return ;
    319 }
    320 
    321 STATIC
    322 VOID
    323 InitSlide (
    324   VOID
    325   )
    326 /*++
    327 
    328 Routine Description:
    329 
    330   Initialize String Info Log data structures
    331 
    332 Arguments: (VOID)
    333 
    334 Returns: (VOID)
    335 
    336 --*/
    337 {
    338   NODE  Index;
    339 
    340   for (Index = WNDSIZ; Index <= WNDSIZ + UINT8_MAX; Index++) {
    341     mLevel[Index]     = 1;
    342     mPosition[Index]  = NIL;  // sentinel
    343   }
    344 
    345   for (Index = WNDSIZ; Index < WNDSIZ * 2; Index++) {
    346     mParent[Index] = NIL;
    347   }
    348 
    349   mAvail = 1;
    350   for (Index = 1; Index < WNDSIZ - 1; Index++) {
    351     mNext[Index] = (NODE) (Index + 1);
    352   }
    353 
    354   mNext[WNDSIZ - 1] = NIL;
    355   for (Index = WNDSIZ * 2; Index <= MAX_HASH_VAL; Index++) {
    356     mNext[Index] = NIL;
    357   }
    358 }
    359 
    360 STATIC
    361 NODE
    362 Child (
    363   IN NODE  NodeQ,
    364   IN UINT8 CharC
    365   )
    366 /*++
    367 
    368 Routine Description:
    369 
    370   Find child node given the parent node and the edge character
    371 
    372 Arguments:
    373 
    374   NodeQ       - the parent node
    375   CharC       - the edge character
    376 
    377 Returns:
    378 
    379   The child node (NIL if not found)
    380 
    381 --*/
    382 {
    383   NODE  NodeR;
    384 
    385   NodeR = mNext[HASH (NodeQ, CharC)];
    386   //
    387   // sentinel
    388   //
    389   mParent[NIL] = NodeQ;
    390   while (mParent[NodeR] != NodeQ) {
    391     NodeR = mNext[NodeR];
    392   }
    393 
    394   return NodeR;
    395 }
    396 
    397 STATIC
    398 VOID
    399 MakeChild (
    400   IN NODE  Parent,
    401   IN UINT8 CharC,
    402   IN NODE  Child
    403   )
    404 /*++
    405 
    406 Routine Description:
    407 
    408   Create a new child for a given parent node.
    409 
    410 Arguments:
    411 
    412   Parent       - the parent node
    413   CharC   - the edge character
    414   Child       - the child node
    415 
    416 Returns: (VOID)
    417 
    418 --*/
    419 {
    420   NODE  Node1;
    421   NODE  Node2;
    422 
    423   Node1           = (NODE) HASH (Parent, CharC);
    424   Node2           = mNext[Node1];
    425   mNext[Node1]    = Child;
    426   mNext[Child]    = Node2;
    427   mPrev[Node2]    = Child;
    428   mPrev[Child]    = Node1;
    429   mParent[Child]  = Parent;
    430   mChildCount[Parent]++;
    431 }
    432 
    433 STATIC
    434 VOID
    435 Split (
    436   NODE Old
    437   )
    438 /*++
    439 
    440 Routine Description:
    441 
    442   Split a node.
    443 
    444 Arguments:
    445 
    446   Old     - the node to split
    447 
    448 Returns: (VOID)
    449 
    450 --*/
    451 {
    452   NODE  New;
    453   NODE  TempNode;
    454 
    455   New               = mAvail;
    456   mAvail            = mNext[New];
    457   mChildCount[New]  = 0;
    458   TempNode          = mPrev[Old];
    459   mPrev[New]        = TempNode;
    460   mNext[TempNode]   = New;
    461   TempNode          = mNext[Old];
    462   mNext[New]        = TempNode;
    463   mPrev[TempNode]   = New;
    464   mParent[New]      = mParent[Old];
    465   mLevel[New]       = (UINT8) mMatchLen;
    466   mPosition[New]    = mPos;
    467   MakeChild (New, mText[mMatchPos + mMatchLen], Old);
    468   MakeChild (New, mText[mPos + mMatchLen], mPos);
    469 }
    470 
    471 STATIC
    472 VOID
    473 InsertNode (
    474   VOID
    475   )
    476 /*++
    477 
    478 Routine Description:
    479 
    480   Insert string info for current position into the String Info Log
    481 
    482 Arguments: (VOID)
    483 
    484 Returns: (VOID)
    485 
    486 --*/
    487 {
    488   NODE  NodeQ;
    489   NODE  NodeR;
    490   NODE  Index2;
    491   NODE  NodeT;
    492   UINT8 CharC;
    493   UINT8 *t1;
    494   UINT8 *t2;
    495 
    496   if (mMatchLen >= 4) {
    497     //
    498     // We have just got a long match, the target tree
    499     // can be located by MatchPos + 1. Travese the tree
    500     // from bottom up to get to a proper starting point.
    501     // The usage of PERC_FLAG ensures proper node deletion
    502     // in DeleteNode() later.
    503     //
    504     mMatchLen--;
    505     NodeR = (NODE) ((mMatchPos + 1) | WNDSIZ);
    506     NodeQ = mParent[NodeR];
    507     while (NodeQ == NIL) {
    508       NodeR = mNext[NodeR];
    509       NodeQ = mParent[NodeR];
    510     }
    511 
    512     while (mLevel[NodeQ] >= mMatchLen) {
    513       NodeR = NodeQ;
    514       NodeQ = mParent[NodeQ];
    515     }
    516 
    517     NodeT = NodeQ;
    518     while (mPosition[NodeT] < 0) {
    519       mPosition[NodeT]  = mPos;
    520       NodeT             = mParent[NodeT];
    521     }
    522 
    523     if (NodeT < WNDSIZ) {
    524       mPosition[NodeT] = (NODE) (mPos | (UINT32) PERC_FLAG);
    525     }
    526   } else {
    527     //
    528     // Locate the target tree
    529     //
    530     NodeQ = (NODE) (mText[mPos] + WNDSIZ);
    531     CharC = mText[mPos + 1];
    532     NodeR = Child (NodeQ, CharC);
    533     if (NodeR == NIL) {
    534       MakeChild (NodeQ, CharC, mPos);
    535       mMatchLen = 1;
    536       return ;
    537     }
    538 
    539     mMatchLen = 2;
    540   }
    541   //
    542   // Traverse down the tree to find a match.
    543   // Update Position value along the route.
    544   // Node split or creation is involved.
    545   //
    546   for (;;) {
    547     if (NodeR >= WNDSIZ) {
    548       Index2    = MAXMATCH;
    549       mMatchPos = NodeR;
    550     } else {
    551       Index2    = mLevel[NodeR];
    552       mMatchPos = (NODE) (mPosition[NodeR] & (UINT32)~PERC_FLAG);
    553     }
    554 
    555     if (mMatchPos >= mPos) {
    556       mMatchPos -= WNDSIZ;
    557     }
    558 
    559     t1  = &mText[mPos + mMatchLen];
    560     t2  = &mText[mMatchPos + mMatchLen];
    561     while (mMatchLen < Index2) {
    562       if (*t1 != *t2) {
    563         Split (NodeR);
    564         return ;
    565       }
    566 
    567       mMatchLen++;
    568       t1++;
    569       t2++;
    570     }
    571 
    572     if (mMatchLen >= MAXMATCH) {
    573       break;
    574     }
    575 
    576     mPosition[NodeR]  = mPos;
    577     NodeQ             = NodeR;
    578     NodeR             = Child (NodeQ, *t1);
    579     if (NodeR == NIL) {
    580       MakeChild (NodeQ, *t1, mPos);
    581       return ;
    582     }
    583 
    584     mMatchLen++;
    585   }
    586 
    587   NodeT           = mPrev[NodeR];
    588   mPrev[mPos]     = NodeT;
    589   mNext[NodeT]    = mPos;
    590   NodeT           = mNext[NodeR];
    591   mNext[mPos]     = NodeT;
    592   mPrev[NodeT]    = mPos;
    593   mParent[mPos]   = NodeQ;
    594   mParent[NodeR]  = NIL;
    595 
    596   //
    597   // Special usage of 'next'
    598   //
    599   mNext[NodeR] = mPos;
    600 
    601 }
    602 
    603 STATIC
    604 VOID
    605 DeleteNode (
    606   VOID
    607   )
    608 /*++
    609 
    610 Routine Description:
    611 
    612   Delete outdated string info. (The Usage of PERC_FLAG
    613   ensures a clean deletion)
    614 
    615 Arguments: (VOID)
    616 
    617 Returns: (VOID)
    618 
    619 --*/
    620 {
    621   NODE  NodeQ;
    622   NODE  NodeR;
    623   NODE  NodeS;
    624   NODE  NodeT;
    625   NODE  NodeU;
    626 
    627   if (mParent[mPos] == NIL) {
    628     return ;
    629   }
    630 
    631   NodeR         = mPrev[mPos];
    632   NodeS         = mNext[mPos];
    633   mNext[NodeR]  = NodeS;
    634   mPrev[NodeS]  = NodeR;
    635   NodeR         = mParent[mPos];
    636   mParent[mPos] = NIL;
    637   if (NodeR >= WNDSIZ) {
    638     return ;
    639   }
    640 
    641   mChildCount[NodeR]--;
    642   if (mChildCount[NodeR] > 1) {
    643     return ;
    644   }
    645 
    646   NodeT = (NODE) (mPosition[NodeR] & (UINT32)~PERC_FLAG);
    647   if (NodeT >= mPos) {
    648     NodeT -= WNDSIZ;
    649   }
    650 
    651   NodeS = NodeT;
    652   NodeQ = mParent[NodeR];
    653   NodeU = mPosition[NodeQ];
    654   while (NodeU & (UINT32) PERC_FLAG) {
    655     NodeU &= (UINT32)~PERC_FLAG;
    656     if (NodeU >= mPos) {
    657       NodeU -= WNDSIZ;
    658     }
    659 
    660     if (NodeU > NodeS) {
    661       NodeS = NodeU;
    662     }
    663 
    664     mPosition[NodeQ]  = (NODE) (NodeS | WNDSIZ);
    665     NodeQ             = mParent[NodeQ];
    666     NodeU             = mPosition[NodeQ];
    667   }
    668 
    669   if (NodeQ < WNDSIZ) {
    670     if (NodeU >= mPos) {
    671       NodeU -= WNDSIZ;
    672     }
    673 
    674     if (NodeU > NodeS) {
    675       NodeS = NodeU;
    676     }
    677 
    678     mPosition[NodeQ] = (NODE) (NodeS | WNDSIZ | (UINT32) PERC_FLAG);
    679   }
    680 
    681   NodeS           = Child (NodeR, mText[NodeT + mLevel[NodeR]]);
    682   NodeT           = mPrev[NodeS];
    683   NodeU           = mNext[NodeS];
    684   mNext[NodeT]    = NodeU;
    685   mPrev[NodeU]    = NodeT;
    686   NodeT           = mPrev[NodeR];
    687   mNext[NodeT]    = NodeS;
    688   mPrev[NodeS]    = NodeT;
    689   NodeT           = mNext[NodeR];
    690   mPrev[NodeT]    = NodeS;
    691   mNext[NodeS]    = NodeT;
    692   mParent[NodeS]  = mParent[NodeR];
    693   mParent[NodeR]  = NIL;
    694   mNext[NodeR]    = mAvail;
    695   mAvail          = NodeR;
    696 }
    697 
    698 STATIC
    699 VOID
    700 GetNextMatch (
    701   VOID
    702   )
    703 /*++
    704 
    705 Routine Description:
    706 
    707   Advance the current position (read in new data if needed).
    708   Delete outdated string info. Find a match string for current position.
    709 
    710 Arguments: (VOID)
    711 
    712 Returns: (VOID)
    713 
    714 --*/
    715 {
    716   INT32 Number;
    717 
    718   mRemainder--;
    719   mPos++;
    720   if (mPos == WNDSIZ * 2) {
    721     memmove (&mText[0], &mText[WNDSIZ], WNDSIZ + MAXMATCH);
    722     Number = FreadCrc (&mText[WNDSIZ + MAXMATCH], WNDSIZ);
    723     mRemainder += Number;
    724     mPos = WNDSIZ;
    725   }
    726 
    727   DeleteNode ();
    728   InsertNode ();
    729 }
    730 
    731 STATIC
    732 EFI_STATUS
    733 Encode (
    734   VOID
    735   )
    736 /*++
    737 
    738 Routine Description:
    739 
    740   The main controlling routine for compression process.
    741 
    742 Arguments: (VOID)
    743 
    744 Returns:
    745 
    746   EFI_SUCCESS           - The compression is successful
    747   EFI_OUT_0F_RESOURCES  - Not enough memory for compression process
    748 
    749 --*/
    750 {
    751   EFI_STATUS  Status;
    752   INT32       LastMatchLen;
    753   NODE        LastMatchPos;
    754 
    755   Status = AllocateMemory ();
    756   if (EFI_ERROR (Status)) {
    757     FreeMemory ();
    758     return Status;
    759   }
    760 
    761   InitSlide ();
    762 
    763   HufEncodeStart ();
    764 
    765   mRemainder  = FreadCrc (&mText[WNDSIZ], WNDSIZ + MAXMATCH);
    766 
    767   mMatchLen   = 0;
    768   mPos        = WNDSIZ;
    769   InsertNode ();
    770   if (mMatchLen > mRemainder) {
    771     mMatchLen = mRemainder;
    772   }
    773 
    774   while (mRemainder > 0) {
    775     LastMatchLen  = mMatchLen;
    776     LastMatchPos  = mMatchPos;
    777     GetNextMatch ();
    778     if (mMatchLen > mRemainder) {
    779       mMatchLen = mRemainder;
    780     }
    781 
    782     if (mMatchLen > LastMatchLen || LastMatchLen < THRESHOLD) {
    783       //
    784       // Not enough benefits are gained by outputting a pointer,
    785       // so just output the original character
    786       //
    787       Output (mText[mPos - 1], 0);
    788 
    789     } else {
    790 
    791       if (LastMatchLen == THRESHOLD) {
    792         if (((mPos - LastMatchPos - 2) & (WNDSIZ - 1)) > (1U << 11)) {
    793           Output (mText[mPos - 1], 0);
    794           continue;
    795         }
    796       }
    797       //
    798       // Outputting a pointer is beneficial enough, do it.
    799       //
    800       Output (
    801         LastMatchLen + (UINT8_MAX + 1 - THRESHOLD),
    802         (mPos - LastMatchPos - 2) & (WNDSIZ - 1)
    803         );
    804       LastMatchLen--;
    805       while (LastMatchLen > 0) {
    806         GetNextMatch ();
    807         LastMatchLen--;
    808       }
    809 
    810       if (mMatchLen > mRemainder) {
    811         mMatchLen = mRemainder;
    812       }
    813     }
    814   }
    815 
    816   HufEncodeEnd ();
    817   FreeMemory ();
    818   return EFI_SUCCESS;
    819 }
    820 
    821 STATIC
    822 VOID
    823 CountTFreq (
    824   VOID
    825   )
    826 /*++
    827 
    828 Routine Description:
    829 
    830   Count the frequencies for the Extra Set
    831 
    832 Arguments: (VOID)
    833 
    834 Returns: (VOID)
    835 
    836 --*/
    837 {
    838   INT32 Index;
    839   INT32 Index3;
    840   INT32 Number;
    841   INT32 Count;
    842 
    843   for (Index = 0; Index < NT; Index++) {
    844     mTFreq[Index] = 0;
    845   }
    846 
    847   Number = NC;
    848   while (Number > 0 && mCLen[Number - 1] == 0) {
    849     Number--;
    850   }
    851 
    852   Index = 0;
    853   while (Index < Number) {
    854     Index3 = mCLen[Index++];
    855     if (Index3 == 0) {
    856       Count = 1;
    857       while (Index < Number && mCLen[Index] == 0) {
    858         Index++;
    859         Count++;
    860       }
    861 
    862       if (Count <= 2) {
    863         mTFreq[0] = (UINT16) (mTFreq[0] + Count);
    864       } else if (Count <= 18) {
    865         mTFreq[1]++;
    866       } else if (Count == 19) {
    867         mTFreq[0]++;
    868         mTFreq[1]++;
    869       } else {
    870         mTFreq[2]++;
    871       }
    872     } else {
    873       mTFreq[Index3 + 2]++;
    874     }
    875   }
    876 }
    877 
    878 STATIC
    879 VOID
    880 WritePTLen (
    881   IN INT32 Number,
    882   IN INT32 nbit,
    883   IN INT32 Special
    884   )
    885 /*++
    886 
    887 Routine Description:
    888 
    889   Outputs the code length array for the Extra Set or the Position Set.
    890 
    891 Arguments:
    892 
    893   Number       - the number of symbols
    894   nbit    - the number of bits needed to represent 'n'
    895   Special - the special symbol that needs to be take care of
    896 
    897 Returns: (VOID)
    898 
    899 --*/
    900 {
    901   INT32 Index;
    902   INT32 Index3;
    903 
    904   while (Number > 0 && mPTLen[Number - 1] == 0) {
    905     Number--;
    906   }
    907 
    908   PutBits (nbit, Number);
    909   Index = 0;
    910   while (Index < Number) {
    911     Index3 = mPTLen[Index++];
    912     if (Index3 <= 6) {
    913       PutBits (3, Index3);
    914     } else {
    915       PutBits (Index3 - 3, (1U << (Index3 - 3)) - 2);
    916     }
    917 
    918     if (Index == Special) {
    919       while (Index < 6 && mPTLen[Index] == 0) {
    920         Index++;
    921       }
    922 
    923       PutBits (2, (Index - 3) & 3);
    924     }
    925   }
    926 }
    927 
    928 STATIC
    929 VOID
    930 WriteCLen (
    931   VOID
    932   )
    933 /*++
    934 
    935 Routine Description:
    936 
    937   Outputs the code length array for Char&Length Set
    938 
    939 Arguments: (VOID)
    940 
    941 Returns: (VOID)
    942 
    943 --*/
    944 {
    945   INT32 Index;
    946   INT32 Index3;
    947   INT32 Number;
    948   INT32 Count;
    949 
    950   Number = NC;
    951   while (Number > 0 && mCLen[Number - 1] == 0) {
    952     Number--;
    953   }
    954 
    955   PutBits (CBIT, Number);
    956   Index = 0;
    957   while (Index < Number) {
    958     Index3 = mCLen[Index++];
    959     if (Index3 == 0) {
    960       Count = 1;
    961       while (Index < Number && mCLen[Index] == 0) {
    962         Index++;
    963         Count++;
    964       }
    965 
    966       if (Count <= 2) {
    967         for (Index3 = 0; Index3 < Count; Index3++) {
    968           PutBits (mPTLen[0], mPTCode[0]);
    969         }
    970       } else if (Count <= 18) {
    971         PutBits (mPTLen[1], mPTCode[1]);
    972         PutBits (4, Count - 3);
    973       } else if (Count == 19) {
    974         PutBits (mPTLen[0], mPTCode[0]);
    975         PutBits (mPTLen[1], mPTCode[1]);
    976         PutBits (4, 15);
    977       } else {
    978         PutBits (mPTLen[2], mPTCode[2]);
    979         PutBits (CBIT, Count - 20);
    980       }
    981     } else {
    982       PutBits (mPTLen[Index3 + 2], mPTCode[Index3 + 2]);
    983     }
    984   }
    985 }
    986 
    987 STATIC
    988 VOID
    989 EncodeC (
    990   IN INT32 Value
    991   )
    992 {
    993   PutBits (mCLen[Value], mCCode[Value]);
    994 }
    995 
    996 STATIC
    997 VOID
    998 EncodeP (
    999   IN UINT32 Value
   1000   )
   1001 {
   1002   UINT32  Index;
   1003   UINT32  NodeQ;
   1004 
   1005   Index = 0;
   1006   NodeQ = Value;
   1007   while (NodeQ) {
   1008     NodeQ >>= 1;
   1009     Index++;
   1010   }
   1011 
   1012   PutBits (mPTLen[Index], mPTCode[Index]);
   1013   if (Index > 1) {
   1014     PutBits (Index - 1, Value & (0xFFFFFFFFU >> (32 - Index + 1)));
   1015   }
   1016 }
   1017 
   1018 STATIC
   1019 VOID
   1020 SendBlock (
   1021   VOID
   1022   )
   1023 /*++
   1024 
   1025 Routine Description:
   1026 
   1027   Huffman code the block and output it.
   1028 
   1029 Arguments:
   1030   (VOID)
   1031 
   1032 Returns:
   1033   (VOID)
   1034 
   1035 --*/
   1036 {
   1037   UINT32  Index;
   1038   UINT32  Index2;
   1039   UINT32  Index3;
   1040   UINT32  Flags;
   1041   UINT32  Root;
   1042   UINT32  Pos;
   1043   UINT32  Size;
   1044   Flags = 0;
   1045 
   1046   Root  = MakeTree (NC, mCFreq, mCLen, mCCode);
   1047   Size  = mCFreq[Root];
   1048 
   1049   PutBits (16, Size);
   1050   if (Root >= NC) {
   1051     CountTFreq ();
   1052     Root = MakeTree (NT, mTFreq, mPTLen, mPTCode);
   1053     if (Root >= NT) {
   1054       WritePTLen (NT, TBIT, 3);
   1055     } else {
   1056       PutBits (TBIT, 0);
   1057       PutBits (TBIT, Root);
   1058     }
   1059 
   1060     WriteCLen ();
   1061   } else {
   1062     PutBits (TBIT, 0);
   1063     PutBits (TBIT, 0);
   1064     PutBits (CBIT, 0);
   1065     PutBits (CBIT, Root);
   1066   }
   1067 
   1068   Root = MakeTree (NP, mPFreq, mPTLen, mPTCode);
   1069   if (Root >= NP) {
   1070     WritePTLen (NP, PBIT, -1);
   1071   } else {
   1072     PutBits (PBIT, 0);
   1073     PutBits (PBIT, Root);
   1074   }
   1075 
   1076   Pos = 0;
   1077   for (Index = 0; Index < Size; Index++) {
   1078     if (Index % UINT8_BIT == 0) {
   1079       Flags = mBuf[Pos++];
   1080     } else {
   1081       Flags <<= 1;
   1082     }
   1083 
   1084     if (Flags & (1U << (UINT8_BIT - 1))) {
   1085       EncodeC (mBuf[Pos++] + (1U << UINT8_BIT));
   1086       Index3 = mBuf[Pos++];
   1087       for (Index2 = 0; Index2 < 3; Index2++) {
   1088         Index3 <<= UINT8_BIT;
   1089         Index3 += mBuf[Pos++];
   1090       }
   1091 
   1092       EncodeP (Index3);
   1093     } else {
   1094       EncodeC (mBuf[Pos++]);
   1095     }
   1096   }
   1097 
   1098   for (Index = 0; Index < NC; Index++) {
   1099     mCFreq[Index] = 0;
   1100   }
   1101 
   1102   for (Index = 0; Index < NP; Index++) {
   1103     mPFreq[Index] = 0;
   1104   }
   1105 }
   1106 
   1107 STATIC
   1108 VOID
   1109 Output (
   1110   IN UINT32 CharC,
   1111   IN UINT32 Pos
   1112   )
   1113 /*++
   1114 
   1115 Routine Description:
   1116 
   1117   Outputs an Original Character or a Pointer
   1118 
   1119 Arguments:
   1120 
   1121   CharC     - The original character or the 'String Length' element of a Pointer
   1122   Pos     - The 'Position' field of a Pointer
   1123 
   1124 Returns: (VOID)
   1125 
   1126 --*/
   1127 {
   1128   STATIC UINT32 CPos;
   1129 
   1130   if ((mOutputMask >>= 1) == 0) {
   1131     mOutputMask = 1U << (UINT8_BIT - 1);
   1132     //
   1133     // Check the buffer overflow per outputing UINT8_BIT symbols
   1134     // which is an Original Character or a Pointer. The biggest
   1135     // symbol is a Pointer which occupies 5 bytes.
   1136     //
   1137     if (mOutputPos >= mBufSiz - 5 * UINT8_BIT) {
   1138       SendBlock ();
   1139       mOutputPos = 0;
   1140     }
   1141 
   1142     CPos        = mOutputPos++;
   1143     mBuf[CPos]  = 0;
   1144   }
   1145 
   1146   mBuf[mOutputPos++] = (UINT8) CharC;
   1147   mCFreq[CharC]++;
   1148   if (CharC >= (1U << UINT8_BIT)) {
   1149     mBuf[CPos] |= mOutputMask;
   1150     mBuf[mOutputPos++]  = (UINT8) (Pos >> 24);
   1151     mBuf[mOutputPos++]  = (UINT8) (Pos >> 16);
   1152     mBuf[mOutputPos++]  = (UINT8) (Pos >> (UINT8_BIT));
   1153     mBuf[mOutputPos++]  = (UINT8) Pos;
   1154     CharC               = 0;
   1155     while (Pos) {
   1156       Pos >>= 1;
   1157       CharC++;
   1158     }
   1159 
   1160     mPFreq[CharC]++;
   1161   }
   1162 }
   1163 
   1164 STATIC
   1165 VOID
   1166 HufEncodeStart (
   1167   VOID
   1168   )
   1169 {
   1170   INT32 Index;
   1171 
   1172   for (Index = 0; Index < NC; Index++) {
   1173     mCFreq[Index] = 0;
   1174   }
   1175 
   1176   for (Index = 0; Index < NP; Index++) {
   1177     mPFreq[Index] = 0;
   1178   }
   1179 
   1180   mOutputPos = mOutputMask = 0;
   1181   InitPutBits ();
   1182   return ;
   1183 }
   1184 
   1185 STATIC
   1186 VOID
   1187 HufEncodeEnd (
   1188   VOID
   1189   )
   1190 {
   1191   SendBlock ();
   1192 
   1193   //
   1194   // Flush remaining bits
   1195   //
   1196   PutBits (UINT8_BIT - 1, 0);
   1197 
   1198   return ;
   1199 }
   1200 
   1201 STATIC
   1202 VOID
   1203 MakeCrcTable (
   1204   VOID
   1205   )
   1206 {
   1207   UINT32  Index;
   1208   UINT32  Index2;
   1209   UINT32  Temp;
   1210 
   1211   for (Index = 0; Index <= UINT8_MAX; Index++) {
   1212     Temp = Index;
   1213     for (Index2 = 0; Index2 < UINT8_BIT; Index2++) {
   1214       if (Temp & 1) {
   1215         Temp = (Temp >> 1) ^ CRCPOLY;
   1216       } else {
   1217         Temp >>= 1;
   1218       }
   1219     }
   1220 
   1221     mCrcTable[Index] = (UINT16) Temp;
   1222   }
   1223 }
   1224 
   1225 STATIC
   1226 VOID
   1227 PutBits (
   1228   IN INT32  Number,
   1229   IN UINT32 Value
   1230   )
   1231 /*++
   1232 
   1233 Routine Description:
   1234 
   1235   Outputs rightmost n bits of x
   1236 
   1237 Arguments:
   1238 
   1239   Number   - the rightmost n bits of the data is used
   1240   x   - the data
   1241 
   1242 Returns: (VOID)
   1243 
   1244 --*/
   1245 {
   1246   UINT8 Temp;
   1247 
   1248   while (Number >= mBitCount) {
   1249     //
   1250     // Number -= mBitCount should never equal to 32
   1251     //
   1252     Temp = (UINT8) (mSubBitBuf | (Value >> (Number -= mBitCount)));
   1253 
   1254     if (mDst < mDstUpperLimit) {
   1255       *mDst++ = Temp;
   1256     }
   1257 
   1258     mCompSize++;
   1259     mSubBitBuf  = 0;
   1260     mBitCount   = UINT8_BIT;
   1261   }
   1262 
   1263   mSubBitBuf |= Value << (mBitCount -= Number);
   1264 }
   1265 
   1266 STATIC
   1267 INT32
   1268 FreadCrc (
   1269   OUT UINT8 *Pointer,
   1270   IN  INT32 Number
   1271   )
   1272 /*++
   1273 
   1274 Routine Description:
   1275 
   1276   Read in source data
   1277 
   1278 Arguments:
   1279 
   1280   Pointer   - the buffer to hold the data
   1281   Number   - number of bytes to read
   1282 
   1283 Returns:
   1284 
   1285   number of bytes actually read
   1286 
   1287 --*/
   1288 {
   1289   INT32 Index;
   1290 
   1291   for (Index = 0; mSrc < mSrcUpperLimit && Index < Number; Index++) {
   1292     *Pointer++ = *mSrc++;
   1293   }
   1294 
   1295   Number = Index;
   1296 
   1297   Pointer -= Number;
   1298   mOrigSize += Number;
   1299 
   1300   Index--;
   1301   while (Index >= 0) {
   1302     UPDATE_CRC (*Pointer++);
   1303     Index--;
   1304   }
   1305 
   1306   return Number;
   1307 }
   1308 
   1309 STATIC
   1310 VOID
   1311 InitPutBits (
   1312   VOID
   1313   )
   1314 {
   1315   mBitCount   = UINT8_BIT;
   1316   mSubBitBuf  = 0;
   1317 }
   1318 
   1319 STATIC
   1320 VOID
   1321 CountLen (
   1322   IN INT32 Index
   1323   )
   1324 /*++
   1325 
   1326 Routine Description:
   1327 
   1328   Count the number of each code length for a Huffman tree.
   1329 
   1330 Arguments:
   1331 
   1332   Index   - the top node
   1333 
   1334 Returns: (VOID)
   1335 
   1336 --*/
   1337 {
   1338   STATIC INT32  Depth = 0;
   1339 
   1340   if (Index < mN) {
   1341     mLenCnt[(Depth < 16) ? Depth : 16]++;
   1342   } else {
   1343     Depth++;
   1344     CountLen (mLeft[Index]);
   1345     CountLen (mRight[Index]);
   1346     Depth--;
   1347   }
   1348 }
   1349 
   1350 STATIC
   1351 VOID
   1352 MakeLen (
   1353   IN INT32 Root
   1354   )
   1355 /*++
   1356 
   1357 Routine Description:
   1358 
   1359   Create code length array for a Huffman tree
   1360 
   1361 Arguments:
   1362 
   1363   Root   - the root of the tree
   1364 
   1365 Returns:
   1366 
   1367   VOID
   1368 
   1369 --*/
   1370 {
   1371   INT32   Index;
   1372   INT32   Index3;
   1373   UINT32  Cum;
   1374 
   1375   for (Index = 0; Index <= 16; Index++) {
   1376     mLenCnt[Index] = 0;
   1377   }
   1378 
   1379   CountLen (Root);
   1380 
   1381   //
   1382   // Adjust the length count array so that
   1383   // no code will be generated longer than its designated length
   1384   //
   1385   Cum = 0;
   1386   for (Index = 16; Index > 0; Index--) {
   1387     Cum += mLenCnt[Index] << (16 - Index);
   1388   }
   1389 
   1390   while (Cum != (1U << 16)) {
   1391     mLenCnt[16]--;
   1392     for (Index = 15; Index > 0; Index--) {
   1393       if (mLenCnt[Index] != 0) {
   1394         mLenCnt[Index]--;
   1395         mLenCnt[Index + 1] += 2;
   1396         break;
   1397       }
   1398     }
   1399 
   1400     Cum--;
   1401   }
   1402 
   1403   for (Index = 16; Index > 0; Index--) {
   1404     Index3 = mLenCnt[Index];
   1405     Index3--;
   1406     while (Index3 >= 0) {
   1407       mLen[*mSortPtr++] = (UINT8) Index;
   1408       Index3--;
   1409     }
   1410   }
   1411 }
   1412 
   1413 STATIC
   1414 VOID
   1415 DownHeap (
   1416   IN INT32 Index
   1417   )
   1418 {
   1419   INT32 Index2;
   1420   INT32 Index3;
   1421 
   1422   //
   1423   // priority queue: send Index-th entry down heap
   1424   //
   1425   Index3  = mHeap[Index];
   1426   Index2  = 2 * Index;
   1427   while (Index2 <= mHeapSize) {
   1428     if (Index2 < mHeapSize && mFreq[mHeap[Index2]] > mFreq[mHeap[Index2 + 1]]) {
   1429       Index2++;
   1430     }
   1431 
   1432     if (mFreq[Index3] <= mFreq[mHeap[Index2]]) {
   1433       break;
   1434     }
   1435 
   1436     mHeap[Index]  = mHeap[Index2];
   1437     Index         = Index2;
   1438     Index2        = 2 * Index;
   1439   }
   1440 
   1441   mHeap[Index] = (INT16) Index3;
   1442 }
   1443 
   1444 STATIC
   1445 VOID
   1446 MakeCode (
   1447   IN  INT32       Number,
   1448   IN  UINT8 Len[  ],
   1449   OUT UINT16 Code[]
   1450   )
   1451 /*++
   1452 
   1453 Routine Description:
   1454 
   1455   Assign code to each symbol based on the code length array
   1456 
   1457 Arguments:
   1458 
   1459   Number     - number of symbols
   1460   Len   - the code length array
   1461   Code  - stores codes for each symbol
   1462 
   1463 Returns: (VOID)
   1464 
   1465 --*/
   1466 {
   1467   INT32   Index;
   1468   UINT16  Start[18];
   1469 
   1470   Start[1] = 0;
   1471   for (Index = 1; Index <= 16; Index++) {
   1472     Start[Index + 1] = (UINT16) ((Start[Index] + mLenCnt[Index]) << 1);
   1473   }
   1474 
   1475   for (Index = 0; Index < Number; Index++) {
   1476     Code[Index] = Start[Len[Index]]++;
   1477   }
   1478 }
   1479 
   1480 STATIC
   1481 INT32
   1482 MakeTree (
   1483   IN  INT32            NParm,
   1484   IN  UINT16  FreqParm[],
   1485   OUT UINT8   LenParm[ ],
   1486   OUT UINT16  CodeParm[]
   1487   )
   1488 /*++
   1489 
   1490 Routine Description:
   1491 
   1492   Generates Huffman codes given a frequency distribution of symbols
   1493 
   1494 Arguments:
   1495 
   1496   NParm    - number of symbols
   1497   FreqParm - frequency of each symbol
   1498   LenParm  - code length for each symbol
   1499   CodeParm - code for each symbol
   1500 
   1501 Returns:
   1502 
   1503   Root of the Huffman tree.
   1504 
   1505 --*/
   1506 {
   1507   INT32 Index;
   1508   INT32 Index2;
   1509   INT32 Index3;
   1510   INT32 Avail;
   1511 
   1512   //
   1513   // make tree, calculate len[], return root
   1514   //
   1515   mN        = NParm;
   1516   mFreq     = FreqParm;
   1517   mLen      = LenParm;
   1518   Avail     = mN;
   1519   mHeapSize = 0;
   1520   mHeap[1]  = 0;
   1521   for (Index = 0; Index < mN; Index++) {
   1522     mLen[Index] = 0;
   1523     if (mFreq[Index]) {
   1524       mHeapSize++;
   1525       mHeap[mHeapSize] = (INT16) Index;
   1526     }
   1527   }
   1528 
   1529   if (mHeapSize < 2) {
   1530     CodeParm[mHeap[1]] = 0;
   1531     return mHeap[1];
   1532   }
   1533 
   1534   for (Index = mHeapSize / 2; Index >= 1; Index--) {
   1535     //
   1536     // make priority queue
   1537     //
   1538     DownHeap (Index);
   1539   }
   1540 
   1541   mSortPtr = CodeParm;
   1542   do {
   1543     Index = mHeap[1];
   1544     if (Index < mN) {
   1545       *mSortPtr++ = (UINT16) Index;
   1546     }
   1547 
   1548     mHeap[1] = mHeap[mHeapSize--];
   1549     DownHeap (1);
   1550     Index2 = mHeap[1];
   1551     if (Index2 < mN) {
   1552       *mSortPtr++ = (UINT16) Index2;
   1553     }
   1554 
   1555     Index3        = Avail++;
   1556     mFreq[Index3] = (UINT16) (mFreq[Index] + mFreq[Index2]);
   1557     mHeap[1]      = (INT16) Index3;
   1558     DownHeap (1);
   1559     mLeft[Index3]   = (UINT16) Index;
   1560     mRight[Index3]  = (UINT16) Index2;
   1561   } while (mHeapSize > 1);
   1562 
   1563   mSortPtr = CodeParm;
   1564   MakeLen (Index3);
   1565   MakeCode (NParm, LenParm, CodeParm);
   1566 
   1567   //
   1568   // return root
   1569   //
   1570   return Index3;
   1571 }
   1572 
   1573 EFI_STATUS
   1574 GetFileContents (
   1575   IN char    *InputFileName,
   1576   OUT UINT8   *FileBuffer,
   1577   OUT UINT32  *BufferLength
   1578   )
   1579 /*++
   1580 
   1581 Routine Description:
   1582 
   1583   Get the contents of file specified in InputFileName
   1584   into FileBuffer.
   1585 
   1586 Arguments:
   1587 
   1588   InputFileName  - Name of the input file.
   1589 
   1590   FileBuffer     - Output buffer to contain data
   1591 
   1592   BufferLength   - Actual length of the data
   1593 
   1594 Returns:
   1595 
   1596   EFI_SUCCESS on successful return
   1597   EFI_ABORTED if unable to open input file.
   1598 
   1599 --*/
   1600 {
   1601   UINTN   Size;
   1602   UINTN   FileSize;
   1603   FILE    *InputFile;
   1604 
   1605   Size = 0;
   1606   //
   1607   // Copy the file contents to the output buffer.
   1608   //
   1609   InputFile = fopen (LongFilePath (InputFileName), "rb");
   1610     if (InputFile == NULL) {
   1611       Error (NULL, 0, 0001, "Error opening file: %s", InputFileName);
   1612       return EFI_ABORTED;
   1613     }
   1614 
   1615   fseek (InputFile, 0, SEEK_END);
   1616   FileSize = ftell (InputFile);
   1617   fseek (InputFile, 0, SEEK_SET);
   1618     //
   1619     // Now read the contents of the file into the buffer
   1620     //
   1621     if (FileSize > 0 && FileBuffer != NULL) {
   1622       if (fread (FileBuffer, FileSize, 1, InputFile) != 1) {
   1623         Error (NULL, 0, 0004, "Error reading contents of input file: %s", InputFileName);
   1624         fclose (InputFile);
   1625         return EFI_ABORTED;
   1626       }
   1627     }
   1628 
   1629   fclose (InputFile);
   1630   Size += (UINTN) FileSize;
   1631   *BufferLength = Size;
   1632 
   1633   if (FileBuffer != NULL) {
   1634     return EFI_SUCCESS;
   1635   } else {
   1636     return EFI_BUFFER_TOO_SMALL;
   1637   }
   1638 }
   1639 
   1640 VOID
   1641 Version (
   1642   VOID
   1643   )
   1644 /*++
   1645 
   1646 Routine Description:
   1647 
   1648   Displays the standard utility information to SDTOUT
   1649 
   1650 Arguments:
   1651 
   1652   None
   1653 
   1654 Returns:
   1655 
   1656   None
   1657 
   1658 --*/
   1659 {
   1660   fprintf (stdout, "%s Version %d.%d %s \n", UTILITY_NAME, UTILITY_MAJOR_VERSION, UTILITY_MINOR_VERSION, __BUILD_VERSION);
   1661 }
   1662 
   1663 VOID
   1664 Usage (
   1665   VOID
   1666   )
   1667 /*++
   1668 
   1669 Routine Description:
   1670 
   1671   Displays the utility usage syntax to STDOUT
   1672 
   1673 Arguments:
   1674 
   1675   None
   1676 
   1677 Returns:
   1678 
   1679   None
   1680 
   1681 --*/
   1682 {
   1683   //
   1684   // Summary usage
   1685   //
   1686   fprintf (stdout, "Usage: %s -e|-d [options] <input_file>\n\n", UTILITY_NAME);
   1687 
   1688   //
   1689   // Copyright declaration
   1690   //
   1691   fprintf (stdout, "Copyright (c) 2007 - 2014, Intel Corporation. All rights reserved.\n\n");
   1692 
   1693   //
   1694   // Details Option
   1695   //
   1696   fprintf (stdout, "Options:\n");
   1697   fprintf (stdout, "  -o FileName, --output FileName\n\
   1698             File will be created to store the ouput content.\n");
   1699   fprintf (stdout, "  -v, --verbose\n\
   1700            Turn on verbose output with informational messages.\n");
   1701   fprintf (stdout, "  -q, --quiet\n\
   1702            Disable all messages except key message and fatal error\n");
   1703   fprintf (stdout, "  --debug [0-9]\n\
   1704            Enable debug messages, at input debug level.\n");
   1705   fprintf (stdout, "  --version\n\
   1706            Show program's version number and exit.\n");
   1707   fprintf (stdout, "  -h, --help\n\
   1708            Show this help message and exit.\n");
   1709 }
   1710 
   1711 
   1712 int
   1713 main (
   1714   int  argc,
   1715   char *argv[]
   1716   )
   1717 /*++
   1718 
   1719 Routine Description:
   1720 
   1721   Main
   1722 
   1723 Arguments:
   1724 
   1725   command line parameters
   1726 
   1727 Returns:
   1728 
   1729   EFI_SUCCESS    Section header successfully generated and section concatenated.
   1730   EFI_ABORTED    Could not generate the section
   1731   EFI_OUT_OF_RESOURCES  No resource to complete the operation.
   1732 
   1733 --*/
   1734 {
   1735   FILE       *OutputFile;
   1736   char       *OutputFileName;
   1737   char       *InputFileName;
   1738   FILE       *InputFile;
   1739   EFI_STATUS Status;
   1740   UINT8      *FileBuffer;
   1741   UINT8      *OutBuffer;
   1742   UINT32     InputLength;
   1743   UINT32     DstSize;
   1744   SCRATCH_DATA      *Scratch;
   1745   UINT8      *Src;
   1746   UINT32     OrigSize;
   1747 
   1748   SetUtilityName(UTILITY_NAME);
   1749 
   1750   FileBuffer = NULL;
   1751   Src = NULL;
   1752   OutBuffer = NULL;
   1753   Scratch   = NULL;
   1754   OrigSize = 0;
   1755   InputLength = 0;
   1756   InputFileName = NULL;
   1757   OutputFileName = NULL;
   1758   DstSize=0;
   1759   DebugLevel = 0;
   1760   DebugMode = FALSE;
   1761 
   1762   //
   1763   // Verify the correct number of arguments
   1764   //
   1765   if (argc == 1) {
   1766     Error (NULL, 0, 1001, "Missing options", "No input options specified.");
   1767     Usage();
   1768     return 0;
   1769   }
   1770 
   1771   if ((strcmp(argv[1], "-h") == 0) || (strcmp(argv[1], "--help") == 0)) {
   1772     Usage();
   1773     return 0;
   1774   }
   1775 
   1776   if ((strcmp(argv[1], "--version") == 0)) {
   1777     Version();
   1778     return 0;
   1779   }
   1780 
   1781   argc--;
   1782   argv++;
   1783   if (strcmp(argv[0],"-e") == 0) {
   1784     //
   1785     // encode the input file
   1786     //
   1787     ENCODE = TRUE;
   1788     argc--;
   1789     argv++;
   1790   } else if (strcmp(argv[0], "-d") == 0) {
   1791     //
   1792     // decode the input file
   1793     //
   1794     DECODE = TRUE;
   1795     argc--;
   1796     argv++;
   1797   } else {
   1798     //
   1799     // Error command line
   1800     //
   1801     Error (NULL, 0, 1003, "Invalid option value", "the options specified are not recognized.");
   1802     Usage();
   1803     return 1;
   1804   }
   1805 
   1806   while (argc > 0) {
   1807     if ((strcmp(argv[0], "-v") == 0) || (stricmp(argv[0], "--verbose") == 0)) {
   1808       VerboseMode = TRUE;
   1809       argc--;
   1810       argv++;
   1811       continue;
   1812     }
   1813 
   1814     if (stricmp (argv[0], "--debug") == 0) {
   1815       argc-=2;
   1816       argv++;
   1817       Status = AsciiStringToUint64(argv[0], FALSE, &DebugLevel);
   1818       if (DebugLevel > 9) {
   1819         Error (NULL, 0 ,2000, "Invalid parameter", "Unrecognized argument %s", argv[0]);
   1820         goto ERROR;
   1821       }
   1822       if (DebugLevel>=5 && DebugLevel <=9){
   1823         DebugMode = TRUE;
   1824       } else {
   1825         DebugMode = FALSE;
   1826       }
   1827       argv++;
   1828       continue;
   1829     }
   1830 
   1831     if ((strcmp(argv[0], "-q") == 0) || (stricmp (argv[0], "--quiet") == 0)) {
   1832       QuietMode = TRUE;
   1833       argc--;
   1834       argv++;
   1835       continue;
   1836     }
   1837 
   1838     if ((strcmp(argv[0], "-o") == 0) || (stricmp (argv[0], "--output") == 0)) {
   1839       if (argv[1] == NULL || argv[1][0] == '-') {
   1840         Error (NULL, 0, 1003, "Invalid option value", "Output File name is missing for -o option");
   1841         goto ERROR;
   1842       }
   1843       OutputFileName = argv[1];
   1844       argc -=2;
   1845       argv +=2;
   1846       continue;
   1847     }
   1848 
   1849     if (argv[0][0]!='-') {
   1850       InputFileName = argv[0];
   1851       argc--;
   1852       argv++;
   1853       continue;
   1854     }
   1855 
   1856     Error (NULL, 0, 1000, "Unknown option", argv[0]);
   1857     goto ERROR;
   1858   }
   1859 
   1860   if (InputFileName == NULL) {
   1861     Error (NULL, 0, 1001, "Missing options", "No input files specified.");
   1862     goto ERROR;
   1863   }
   1864 
   1865 //
   1866 // All Parameters has been parsed, now set the message print level
   1867 //
   1868   if (QuietMode) {
   1869     SetPrintLevel(40);
   1870   } else if (VerboseMode) {
   1871     SetPrintLevel(15);
   1872   } else if (DebugMode) {
   1873     SetPrintLevel(DebugLevel);
   1874   }
   1875 
   1876   if (VerboseMode) {
   1877     VerboseMsg("%s tool start.\n", UTILITY_NAME);
   1878    }
   1879   Scratch = (SCRATCH_DATA *)malloc(sizeof(SCRATCH_DATA));
   1880   if (Scratch == NULL) {
   1881     Error (NULL, 0, 4001, "Resource:", "Memory cannot be allocated!");
   1882     goto ERROR;
   1883   }
   1884 
   1885   InputFile = fopen (LongFilePath (InputFileName), "rb");
   1886   if (InputFile == NULL) {
   1887     Error (NULL, 0, 0001, "Error opening input file", InputFileName);
   1888     goto ERROR;
   1889   }
   1890 
   1891   Status = GetFileContents(
   1892             InputFileName,
   1893             FileBuffer,
   1894             &InputLength);
   1895 
   1896   if (Status == EFI_BUFFER_TOO_SMALL) {
   1897     FileBuffer = (UINT8 *) malloc (InputLength);
   1898     if (FileBuffer == NULL) {
   1899       Error (NULL, 0, 4001, "Resource:", "Memory cannot be allocated!");
   1900       return 1;
   1901     }
   1902 
   1903     Status = GetFileContents (
   1904               InputFileName,
   1905               FileBuffer,
   1906               &InputLength
   1907               );
   1908   }
   1909 
   1910   if (EFI_ERROR(Status)) {
   1911     free(FileBuffer);
   1912     return 1;
   1913   }
   1914 
   1915   if (OutputFileName != NULL) {
   1916     OutputFile = fopen (LongFilePath (OutputFileName), "wb");
   1917     if (OutputFile == NULL) {
   1918       Error (NULL, 0, 0001, "Error opening output file for writing", OutputFileName);
   1919     if (InputFile != NULL) {
   1920       fclose (InputFile);
   1921       }
   1922       goto ERROR;
   1923       }
   1924     } else {
   1925       OutputFileName = DEFAULT_OUTPUT_FILE;
   1926       OutputFile = fopen (LongFilePath (OutputFileName), "wb");
   1927     }
   1928 
   1929   if (ENCODE) {
   1930   //
   1931   // First call TianoCompress to get DstSize
   1932   //
   1933   if (DebugMode) {
   1934     DebugMsg(UTILITY_NAME, 0, DebugLevel, "Encoding", NULL);
   1935   }
   1936   Status = TianoCompress ((UINT8 *)FileBuffer, InputLength, OutBuffer, &DstSize);
   1937 
   1938   if (Status == EFI_BUFFER_TOO_SMALL) {
   1939     OutBuffer = (UINT8 *) malloc (DstSize);
   1940     if (OutBuffer == NULL) {
   1941       Error (NULL, 0, 4001, "Resource:", "Memory cannot be allocated!");
   1942       goto ERROR;
   1943     }
   1944   }
   1945   Status = TianoCompress ((UINT8 *)FileBuffer, InputLength, OutBuffer, &DstSize);
   1946   if (Status != EFI_SUCCESS) {
   1947     Error (NULL, 0, 0007, "Error compressing file", NULL);
   1948     goto ERROR;
   1949   }
   1950 
   1951   fwrite(OutBuffer,(size_t)DstSize, 1, OutputFile);
   1952   free(Scratch);
   1953   free(FileBuffer);
   1954   free(OutBuffer);
   1955 
   1956   if (DebugMode) {
   1957     DebugMsg(UTILITY_NAME, 0, DebugLevel, "Encoding Successful!\n", NULL);
   1958   }
   1959   if (VerboseMode) {
   1960     VerboseMsg("Encoding successful\n");
   1961   }
   1962   return 0;
   1963   }
   1964   else if (DECODE) {
   1965   if (DebugMode) {
   1966     DebugMsg(UTILITY_NAME, 0, DebugLevel, "Decoding\n", NULL);
   1967   }
   1968   //
   1969   // Get Compressed file original size
   1970   //
   1971   Src     = (UINT8 *)FileBuffer;
   1972   OrigSize  = Src[4] + (Src[5] << 8) + (Src[6] << 16) + (Src[7] << 24);
   1973 
   1974   //
   1975   // Allocate OutputBuffer
   1976   //
   1977   OutBuffer = (UINT8 *)malloc(OrigSize);
   1978   if (OutBuffer == NULL) {
   1979     Error (NULL, 0, 4001, "Resource:", "Memory cannot be allocated!");
   1980     goto ERROR;
   1981    }
   1982 
   1983   Status = Decompress((VOID *)FileBuffer, (VOID *)OutBuffer, (VOID *)Scratch, 2);
   1984   if (Status != EFI_SUCCESS) {
   1985    goto ERROR;
   1986   }
   1987 
   1988   fwrite(OutBuffer, (size_t)(Scratch->mOrigSize), 1, OutputFile);
   1989   free(Scratch);
   1990   free(FileBuffer);
   1991   free(OutBuffer);
   1992 
   1993   if (DebugMode) {
   1994     DebugMsg(UTILITY_NAME, 0, DebugLevel, "Encoding successful!\n", NULL);
   1995   }
   1996 
   1997   if (VerboseMode) {
   1998     VerboseMsg("Decoding successful\n");
   1999   }
   2000   return 0;
   2001   }
   2002 
   2003 ERROR:
   2004   if (DebugMode) {
   2005     if (ENCODE) {
   2006       DebugMsg(UTILITY_NAME, 0, DebugLevel, "Encoding Error\n", NULL);
   2007     } else if (DECODE) {
   2008       DebugMsg(UTILITY_NAME, 0, DebugLevel, "Decoding Error\n", NULL);
   2009     }
   2010   }
   2011   if (Scratch != NULL) {
   2012     free(Scratch);
   2013   }
   2014   if (FileBuffer != NULL) {
   2015     free(FileBuffer);
   2016   }
   2017   if (OutBuffer != NULL) {
   2018     free(OutBuffer);
   2019   }
   2020 
   2021   if (VerboseMode) {
   2022     VerboseMsg("%s tool done with return code is 0x%x.\n", UTILITY_NAME, GetUtilityStatus ());
   2023   }
   2024   return GetUtilityStatus ();
   2025 }
   2026 
   2027 VOID
   2028 FillBuf (
   2029   IN  SCRATCH_DATA  *Sd,
   2030   IN  UINT16        NumOfBits
   2031   )
   2032 /*++
   2033 
   2034 Routine Description:
   2035 
   2036   Shift mBitBuf NumOfBits left. Read in NumOfBits of bits from source.
   2037 
   2038 Arguments:
   2039 
   2040   Sd        - The global scratch data
   2041   NumOfBits  - The number of bits to shift and read.
   2042 
   2043 Returns: (VOID)
   2044 
   2045 --*/
   2046 {
   2047   Sd->mBitBuf = (UINT32) (Sd->mBitBuf << NumOfBits);
   2048 
   2049   while (NumOfBits > Sd->mBitCount) {
   2050 
   2051     Sd->mBitBuf |= (UINT32) (Sd->mSubBitBuf << (NumOfBits = (UINT16) (NumOfBits - Sd->mBitCount)));
   2052 
   2053     if (Sd->mCompSize > 0) {
   2054       //
   2055       // Get 1 byte into SubBitBuf
   2056       //
   2057       Sd->mCompSize--;
   2058       Sd->mSubBitBuf  = 0;
   2059       Sd->mSubBitBuf  = Sd->mSrcBase[Sd->mInBuf++];
   2060       Sd->mBitCount   = 8;
   2061 
   2062     } else {
   2063       //
   2064       // No more bits from the source, just pad zero bit.
   2065       //
   2066       Sd->mSubBitBuf  = 0;
   2067       Sd->mBitCount   = 8;
   2068 
   2069     }
   2070   }
   2071 
   2072   Sd->mBitCount = (UINT16) (Sd->mBitCount - NumOfBits);
   2073   Sd->mBitBuf |= Sd->mSubBitBuf >> Sd->mBitCount;
   2074 }
   2075 
   2076 UINT32
   2077 GetBits (
   2078   IN  SCRATCH_DATA  *Sd,
   2079   IN  UINT16        NumOfBits
   2080   )
   2081 /*++
   2082 
   2083 Routine Description:
   2084 
   2085   Get NumOfBits of bits out from mBitBuf. Fill mBitBuf with subsequent
   2086   NumOfBits of bits from source. Returns NumOfBits of bits that are
   2087   popped out.
   2088 
   2089 Arguments:
   2090 
   2091   Sd            - The global scratch data.
   2092   NumOfBits     - The number of bits to pop and read.
   2093 
   2094 Returns:
   2095 
   2096   The bits that are popped out.
   2097 
   2098 --*/
   2099 {
   2100   UINT32  OutBits;
   2101 
   2102   OutBits = (UINT32) (Sd->mBitBuf >> (BITBUFSIZ - NumOfBits));
   2103 
   2104   FillBuf (Sd, NumOfBits);
   2105 
   2106   return OutBits;
   2107 }
   2108 
   2109 UINT16
   2110 MakeTable (
   2111   IN  SCRATCH_DATA  *Sd,
   2112   IN  UINT16        NumOfChar,
   2113   IN  UINT8         *BitLen,
   2114   IN  UINT16        TableBits,
   2115   OUT UINT16        *Table
   2116   )
   2117 /*++
   2118 
   2119 Routine Description:
   2120 
   2121   Creates Huffman Code mapping table according to code length array.
   2122 
   2123 Arguments:
   2124 
   2125   Sd        - The global scratch data
   2126   NumOfChar - Number of symbols in the symbol set
   2127   BitLen    - Code length array
   2128   TableBits - The width of the mapping table
   2129   Table     - The table
   2130 
   2131 Returns:
   2132 
   2133   0         - OK.
   2134   BAD_TABLE - The table is corrupted.
   2135 
   2136 --*/
   2137 {
   2138   UINT16  Count[17];
   2139   UINT16  Weight[17];
   2140   UINT16  Start[18];
   2141   UINT16  *Pointer;
   2142   UINT16  Index3;
   2143   volatile UINT16  Index;
   2144   UINT16  Len;
   2145   UINT16  Char;
   2146   UINT16  JuBits;
   2147   UINT16  Avail;
   2148   UINT16  NextCode;
   2149   UINT16  Mask;
   2150   UINT16  WordOfStart;
   2151   UINT16  WordOfCount;
   2152 
   2153   for (Index = 1; Index <= 16; Index++) {
   2154     Count[Index] = 0;
   2155   }
   2156 
   2157   for (Index = 0; Index < NumOfChar; Index++) {
   2158     Count[BitLen[Index]]++;
   2159   }
   2160 
   2161   Start[1] = 0;
   2162 
   2163   for (Index = 1; Index <= 16; Index++) {
   2164     WordOfStart = Start[Index];
   2165     WordOfCount = Count[Index];
   2166     Start[Index + 1] = (UINT16) (WordOfStart + (WordOfCount << (16 - Index)));
   2167   }
   2168 
   2169   if (Start[17] != 0) {
   2170     //
   2171     //(1U << 16)
   2172     //
   2173     return (UINT16) BAD_TABLE;
   2174   }
   2175 
   2176   JuBits = (UINT16) (16 - TableBits);
   2177 
   2178   for (Index = 1; Index <= TableBits; Index++) {
   2179     Start[Index] >>= JuBits;
   2180     Weight[Index] = (UINT16) (1U << (TableBits - Index));
   2181   }
   2182 
   2183   while (Index <= 16) {
   2184     Weight[Index] = (UINT16) (1U << (16 - Index));
   2185     Index++;
   2186   }
   2187 
   2188   Index = (UINT16) (Start[TableBits + 1] >> JuBits);
   2189 
   2190   if (Index != 0) {
   2191     Index3 = (UINT16) (1U << TableBits);
   2192     while (Index != Index3) {
   2193       Table[Index++] = 0;
   2194     }
   2195   }
   2196 
   2197   Avail = NumOfChar;
   2198   Mask  = (UINT16) (1U << (15 - TableBits));
   2199 
   2200   for (Char = 0; Char < NumOfChar; Char++) {
   2201 
   2202     Len = BitLen[Char];
   2203     if (Len == 0) {
   2204       continue;
   2205     }
   2206 
   2207     NextCode = (UINT16) (Start[Len] + Weight[Len]);
   2208 
   2209     if (Len <= TableBits) {
   2210 
   2211       for (Index = Start[Len]; Index < NextCode; Index++) {
   2212         Table[Index] = Char;
   2213       }
   2214 
   2215     } else {
   2216 
   2217       Index3  = Start[Len];
   2218       Pointer = &Table[Index3 >> JuBits];
   2219       Index   = (UINT16) (Len - TableBits);
   2220 
   2221       while (Index != 0) {
   2222         if (*Pointer == 0) {
   2223           Sd->mRight[Avail]                     = Sd->mLeft[Avail] = 0;
   2224           *Pointer = Avail++;
   2225         }
   2226 
   2227         if (Index3 & Mask) {
   2228           Pointer = &Sd->mRight[*Pointer];
   2229         } else {
   2230           Pointer = &Sd->mLeft[*Pointer];
   2231         }
   2232 
   2233         Index3 <<= 1;
   2234         Index--;
   2235       }
   2236 
   2237       *Pointer = Char;
   2238 
   2239     }
   2240 
   2241     Start[Len] = NextCode;
   2242   }
   2243   //
   2244   // Succeeds
   2245   //
   2246   return 0;
   2247 }
   2248 
   2249 UINT32
   2250 DecodeP (
   2251   IN  SCRATCH_DATA  *Sd
   2252   )
   2253 /*++
   2254 
   2255 Routine Description:
   2256 
   2257   Decodes a position value.
   2258 
   2259 Arguments:
   2260 
   2261   Sd      - the global scratch data
   2262 
   2263 Returns:
   2264 
   2265   The position value decoded.
   2266 
   2267 --*/
   2268 {
   2269   UINT16  Val;
   2270   UINT32  Mask;
   2271   UINT32  Pos;
   2272 
   2273   Val = Sd->mPTTable[Sd->mBitBuf >> (BITBUFSIZ - 8)];
   2274 
   2275   if (Val >= MAXNP) {
   2276     Mask = 1U << (BITBUFSIZ - 1 - 8);
   2277 
   2278     do {
   2279 
   2280       if (Sd->mBitBuf & Mask) {
   2281         Val = Sd->mRight[Val];
   2282       } else {
   2283         Val = Sd->mLeft[Val];
   2284       }
   2285 
   2286       Mask >>= 1;
   2287     } while (Val >= MAXNP);
   2288   }
   2289   //
   2290   // Advance what we have read
   2291   //
   2292   FillBuf (Sd, Sd->mPTLen[Val]);
   2293 
   2294   Pos = Val;
   2295   if (Val > 1) {
   2296     Pos = (UINT32) ((1U << (Val - 1)) + GetBits (Sd, (UINT16) (Val - 1)));
   2297   }
   2298 
   2299   return Pos;
   2300 }
   2301 
   2302 UINT16
   2303 ReadPTLen (
   2304   IN  SCRATCH_DATA  *Sd,
   2305   IN  UINT16        nn,
   2306   IN  UINT16        nbit,
   2307   IN  UINT16        Special
   2308   )
   2309 /*++
   2310 
   2311 Routine Description:
   2312 
   2313   Reads code lengths for the Extra Set or the Position Set
   2314 
   2315 Arguments:
   2316 
   2317   Sd        - The global scratch data
   2318   nn        - Number of symbols
   2319   nbit      - Number of bits needed to represent nn
   2320   Special   - The special symbol that needs to be taken care of
   2321 
   2322 Returns:
   2323 
   2324   0         - OK.
   2325   BAD_TABLE - Table is corrupted.
   2326 
   2327 --*/
   2328 {
   2329   UINT16  Number;
   2330   UINT16  CharC;
   2331   volatile UINT16  Index;
   2332   UINT32  Mask;
   2333 
   2334   Number = (UINT16) GetBits (Sd, nbit);
   2335 
   2336   if (Number == 0) {
   2337     CharC = (UINT16) GetBits (Sd, nbit);
   2338 
   2339     for (Index = 0; Index < 256; Index++) {
   2340       Sd->mPTTable[Index] = CharC;
   2341     }
   2342 
   2343     for (Index = 0; Index < nn; Index++) {
   2344       Sd->mPTLen[Index] = 0;
   2345     }
   2346 
   2347     return 0;
   2348   }
   2349 
   2350   Index = 0;
   2351 
   2352   while (Index < Number) {
   2353 
   2354     CharC = (UINT16) (Sd->mBitBuf >> (BITBUFSIZ - 3));
   2355 
   2356     if (CharC == 7) {
   2357       Mask = 1U << (BITBUFSIZ - 1 - 3);
   2358       while (Mask & Sd->mBitBuf) {
   2359         Mask >>= 1;
   2360         CharC += 1;
   2361       }
   2362     }
   2363 
   2364     FillBuf (Sd, (UINT16) ((CharC < 7) ? 3 : CharC - 3));
   2365 
   2366     Sd->mPTLen[Index++] = (UINT8) CharC;
   2367 
   2368     if (Index == Special) {
   2369       CharC = (UINT16) GetBits (Sd, 2);
   2370       while ((INT16) (--CharC) >= 0) {
   2371         Sd->mPTLen[Index++] = 0;
   2372       }
   2373     }
   2374   }
   2375 
   2376   while (Index < nn) {
   2377     Sd->mPTLen[Index++] = 0;
   2378   }
   2379 
   2380   return MakeTable (Sd, nn, Sd->mPTLen, 8, Sd->mPTTable);
   2381 }
   2382 
   2383 VOID
   2384 ReadCLen (
   2385   SCRATCH_DATA  *Sd
   2386   )
   2387 /*++
   2388 
   2389 Routine Description:
   2390 
   2391   Reads code lengths for Char&Len Set.
   2392 
   2393 Arguments:
   2394 
   2395   Sd    - the global scratch data
   2396 
   2397 Returns: (VOID)
   2398 
   2399 --*/
   2400 {
   2401   UINT16  Number;
   2402   UINT16  CharC;
   2403   volatile UINT16  Index;
   2404   UINT32  Mask;
   2405 
   2406   Number = (UINT16) GetBits (Sd, CBIT);
   2407 
   2408   if (Number == 0) {
   2409     CharC = (UINT16) GetBits (Sd, CBIT);
   2410 
   2411     for (Index = 0; Index < NC; Index++) {
   2412       Sd->mCLen[Index] = 0;
   2413     }
   2414 
   2415     for (Index = 0; Index < 4096; Index++) {
   2416       Sd->mCTable[Index] = CharC;
   2417     }
   2418 
   2419     return ;
   2420   }
   2421 
   2422   Index = 0;
   2423   while (Index < Number) {
   2424 
   2425     CharC = Sd->mPTTable[Sd->mBitBuf >> (BITBUFSIZ - 8)];
   2426     if (CharC >= NT) {
   2427       Mask = 1U << (BITBUFSIZ - 1 - 8);
   2428 
   2429       do {
   2430 
   2431         if (Mask & Sd->mBitBuf) {
   2432           CharC = Sd->mRight[CharC];
   2433         } else {
   2434           CharC = Sd->mLeft[CharC];
   2435         }
   2436 
   2437         Mask >>= 1;
   2438 
   2439       } while (CharC >= NT);
   2440     }
   2441     //
   2442     // Advance what we have read
   2443     //
   2444     FillBuf (Sd, Sd->mPTLen[CharC]);
   2445 
   2446     if (CharC <= 2) {
   2447 
   2448       if (CharC == 0) {
   2449         CharC = 1;
   2450       } else if (CharC == 1) {
   2451         CharC = (UINT16) (GetBits (Sd, 4) + 3);
   2452       } else if (CharC == 2) {
   2453         CharC = (UINT16) (GetBits (Sd, CBIT) + 20);
   2454       }
   2455 
   2456       while ((INT16) (--CharC) >= 0) {
   2457         Sd->mCLen[Index++] = 0;
   2458       }
   2459 
   2460     } else {
   2461 
   2462       Sd->mCLen[Index++] = (UINT8) (CharC - 2);
   2463 
   2464     }
   2465   }
   2466 
   2467   while (Index < NC) {
   2468     Sd->mCLen[Index++] = 0;
   2469   }
   2470 
   2471   MakeTable (Sd, NC, Sd->mCLen, 12, Sd->mCTable);
   2472 
   2473   return ;
   2474 }
   2475 
   2476 UINT16
   2477 DecodeC (
   2478   SCRATCH_DATA  *Sd
   2479   )
   2480 /*++
   2481 
   2482 Routine Description:
   2483 
   2484   Decode a character/length value.
   2485 
   2486 Arguments:
   2487 
   2488   Sd    - The global scratch data.
   2489 
   2490 Returns:
   2491 
   2492   The value decoded.
   2493 
   2494 --*/
   2495 {
   2496   UINT16  Index2;
   2497   UINT32  Mask;
   2498 
   2499   if (Sd->mBlockSize == 0) {
   2500     //
   2501     // Starting a new block
   2502     //
   2503     Sd->mBlockSize    = (UINT16) GetBits (Sd, 16);
   2504     Sd->mBadTableFlag = ReadPTLen (Sd, NT, TBIT, 3);
   2505     if (Sd->mBadTableFlag != 0) {
   2506       return 0;
   2507     }
   2508 
   2509     ReadCLen (Sd);
   2510 
   2511     Sd->mBadTableFlag = ReadPTLen (Sd, MAXNP, Sd->mPBit, (UINT16) (-1));
   2512     if (Sd->mBadTableFlag != 0) {
   2513       return 0;
   2514     }
   2515   }
   2516 
   2517   Sd->mBlockSize--;
   2518   Index2 = Sd->mCTable[Sd->mBitBuf >> (BITBUFSIZ - 12)];
   2519 
   2520   if (Index2 >= NC) {
   2521     Mask = 1U << (BITBUFSIZ - 1 - 12);
   2522 
   2523     do {
   2524       if (Sd->mBitBuf & Mask) {
   2525         Index2 = Sd->mRight[Index2];
   2526       } else {
   2527         Index2 = Sd->mLeft[Index2];
   2528       }
   2529 
   2530       Mask >>= 1;
   2531     } while (Index2 >= NC);
   2532   }
   2533   //
   2534   // Advance what we have read
   2535   //
   2536   FillBuf (Sd, Sd->mCLen[Index2]);
   2537 
   2538   return Index2;
   2539 }
   2540 
   2541 VOID
   2542 Decode (
   2543   SCRATCH_DATA  *Sd
   2544   )
   2545 /*++
   2546 
   2547 Routine Description:
   2548 
   2549   Decode the source data and put the resulting data into the destination buffer.
   2550 
   2551 Arguments:
   2552 
   2553   Sd            - The global scratch data
   2554 
   2555 Returns: (VOID)
   2556 
   2557  --*/
   2558 {
   2559   UINT16  BytesRemain;
   2560   UINT32  DataIdx;
   2561   UINT16  CharC;
   2562 
   2563   BytesRemain = (UINT16) (-1);
   2564 
   2565   DataIdx     = 0;
   2566 
   2567   for (;;) {
   2568     CharC = DecodeC (Sd);
   2569     if (Sd->mBadTableFlag != 0) {
   2570       goto Done ;
   2571     }
   2572 
   2573     if (CharC < 256) {
   2574       //
   2575       // Process an Original character
   2576       //
   2577       if (Sd->mOutBuf >= Sd->mOrigSize) {
   2578         goto Done ;
   2579       } else {
   2580         Sd->mDstBase[Sd->mOutBuf++] = (UINT8) CharC;
   2581       }
   2582 
   2583     } else {
   2584       //
   2585       // Process a Pointer
   2586       //
   2587       CharC       = (UINT16) (CharC - (UINT8_MAX + 1 - THRESHOLD));
   2588 
   2589       BytesRemain = CharC;
   2590 
   2591       DataIdx     = Sd->mOutBuf - DecodeP (Sd) - 1;
   2592 
   2593       BytesRemain--;
   2594       while ((INT16) (BytesRemain) >= 0) {
   2595         Sd->mDstBase[Sd->mOutBuf++] = Sd->mDstBase[DataIdx++];
   2596         if (Sd->mOutBuf >= Sd->mOrigSize) {
   2597           goto Done ;
   2598         }
   2599 
   2600         BytesRemain--;
   2601       }
   2602     }
   2603   }
   2604 
   2605 Done:
   2606   return ;
   2607 }
   2608 
   2609 RETURN_STATUS
   2610 EFIAPI
   2611 Decompress (
   2612   IN VOID  *Source,
   2613   IN OUT VOID    *Destination,
   2614   IN OUT VOID    *Scratch,
   2615   IN UINT32      Version
   2616   )
   2617 /*++
   2618 
   2619 Routine Description:
   2620 
   2621   The internal implementation of Decompress().
   2622 
   2623 Arguments:
   2624 
   2625   Source          - The source buffer containing the compressed data.
   2626   Destination     - The destination buffer to store the decompressed data
   2627   Scratch         - The buffer used internally by the decompress routine. This  buffer is needed to store intermediate data.
   2628   Version         - 1 for EFI1.1 Decompress algoruthm, 2 for Tiano Decompress algorithm
   2629 
   2630 Returns:
   2631 
   2632   RETURN_SUCCESS           - Decompression is successfull
   2633   RETURN_INVALID_PARAMETER - The source data is corrupted
   2634 
   2635 --*/
   2636 {
   2637   volatile UINT32  Index;
   2638   UINT32           CompSize;
   2639   UINT32           OrigSize;
   2640   SCRATCH_DATA     *Sd;
   2641   CONST UINT8      *Src;
   2642   UINT8            *Dst;
   2643 
   2644   //
   2645   // Verify input is not NULL
   2646   //
   2647   assert(Source);
   2648 //  assert(Destination);
   2649   assert(Scratch);
   2650 
   2651   Src     = (UINT8 *)Source;
   2652   Dst     = (UINT8 *)Destination;
   2653 
   2654   Sd      = (SCRATCH_DATA *) Scratch;
   2655   CompSize  = Src[0] + (Src[1] << 8) + (Src[2] << 16) + (Src[3] << 24);
   2656   OrigSize  = Src[4] + (Src[5] << 8) + (Src[6] << 16) + (Src[7] << 24);
   2657 
   2658   //
   2659   // If compressed file size is 0, return
   2660   //
   2661   if (OrigSize == 0) {
   2662     return RETURN_SUCCESS;
   2663   }
   2664 
   2665   Src = Src + 8;
   2666 
   2667   for (Index = 0; Index < sizeof (SCRATCH_DATA); Index++) {
   2668     ((UINT8 *) Sd)[Index] = 0;
   2669   }
   2670   //
   2671   // The length of the field 'Position Set Code Length Array Size' in Block Header.
   2672   // For EFI 1.1 de/compression algorithm(Version 1), mPBit = 4
   2673   // For Tiano de/compression algorithm(Version 2), mPBit = 5
   2674   //
   2675   switch (Version) {
   2676     case 1 :
   2677       Sd->mPBit = 4;
   2678       break;
   2679     case 2 :
   2680       Sd->mPBit = 5;
   2681       break;
   2682     default:
   2683       assert(FALSE);
   2684   }
   2685   Sd->mSrcBase  = (UINT8 *)Src;
   2686   Sd->mDstBase  = Dst;
   2687   Sd->mCompSize = CompSize;
   2688   Sd->mOrigSize = OrigSize;
   2689 
   2690   //
   2691   // Fill the first BITBUFSIZ bits
   2692   //
   2693   FillBuf (Sd, BITBUFSIZ);
   2694 
   2695   //
   2696   // Decompress it
   2697   //
   2698 
   2699   Decode (Sd);
   2700 
   2701   if (Sd->mBadTableFlag != 0) {
   2702     //
   2703     // Something wrong with the source
   2704     //
   2705     return RETURN_INVALID_PARAMETER;
   2706   }
   2707 
   2708   return RETURN_SUCCESS;
   2709 }
   2710 
   2711 
   2712