Home | History | Annotate | Download | only in Common
      1 /*
      2 
      3 Copyright (c) 2006, Intel Corporation. All rights reserved.<BR>
      4 This program and the accompanying materials
      5 are licensed and made available under the terms and conditions of the BSD License
      6 which accompanies this distribution.  The full text of the license may be found at
      7 http://opensource.org/licenses/bsd-license.php
      8 
      9 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
     10 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
     11 
     12 Module Name:
     13 
     14   EfiCompress.c
     15 
     16 Abstract:
     17 
     18   Compression routine. The compression algorithm is a mixture of
     19   LZ77 and Huffman coding. LZ77 transforms the source data into a
     20   sequence of Original Characters and Pointers to repeated strings.
     21   This sequence is further divided into Blocks and Huffman codings
     22   are applied to each Block.
     23 
     24 --*/
     25 
     26 #include <stdlib.h>
     27 #include <string.h>
     28 #include "TianoCommon.h"
     29 #include "Compress.h"
     30 
     31 
     32 //
     33 // Macro Definitions
     34 //
     35 
     36 typedef INT16             NODE;
     37 #define UINT8_MAX         0xff
     38 #define UINT8_BIT         8
     39 #define THRESHOLD         3
     40 #define INIT_CRC          0
     41 #define WNDBIT            13
     42 #define WNDSIZ            (1U << WNDBIT)
     43 #define MAXMATCH          256
     44 #define PERC_FLAG         0x8000U
     45 #define CODE_BIT          16
     46 #define NIL               0
     47 #define MAX_HASH_VAL      (3 * WNDSIZ + (WNDSIZ / 512 + 1) * UINT8_MAX)
     48 #define HASH(p, c)        ((p) + ((c) << (WNDBIT - 9)) + WNDSIZ * 2)
     49 #define CRCPOLY           0xA001
     50 #define UPDATE_CRC(c)     mCrc = mCrcTable[(mCrc ^ (c)) & 0xFF] ^ (mCrc >> UINT8_BIT)
     51 
     52 //
     53 // C: the Char&Len Set; P: the Position Set; T: the exTra Set
     54 //
     55 
     56 #define NC                (UINT8_MAX + MAXMATCH + 2 - THRESHOLD)
     57 #define CBIT              9
     58 #define NP                (WNDBIT + 1)
     59 #define PBIT              4
     60 #define NT                (CODE_BIT + 3)
     61 #define TBIT              5
     62 #if NT > NP
     63   #define                 NPT NT
     64 #else
     65   #define                 NPT NP
     66 #endif
     67 
     68 //
     69 // Function Prototypes
     70 //
     71 
     72 STATIC
     73 VOID
     74 PutDword(
     75   IN UINT32 Data
     76   );
     77 
     78 STATIC
     79 EFI_STATUS
     80 AllocateMemory (
     81   );
     82 
     83 STATIC
     84 VOID
     85 FreeMemory (
     86   );
     87 
     88 STATIC
     89 VOID
     90 InitSlide (
     91   );
     92 
     93 STATIC
     94 NODE
     95 Child (
     96   IN NODE q,
     97   IN UINT8 c
     98   );
     99 
    100 STATIC
    101 VOID
    102 MakeChild (
    103   IN NODE q,
    104   IN UINT8 c,
    105   IN NODE r
    106   );
    107 
    108 STATIC
    109 VOID
    110 Split (
    111   IN NODE Old
    112   );
    113 
    114 STATIC
    115 VOID
    116 InsertNode (
    117   );
    118 
    119 STATIC
    120 VOID
    121 DeleteNode (
    122   );
    123 
    124 STATIC
    125 VOID
    126 GetNextMatch (
    127   );
    128 
    129 STATIC
    130 EFI_STATUS
    131 Encode (
    132   );
    133 
    134 STATIC
    135 VOID
    136 CountTFreq (
    137   );
    138 
    139 STATIC
    140 VOID
    141 WritePTLen (
    142   IN INT32 n,
    143   IN INT32 nbit,
    144   IN INT32 Special
    145   );
    146 
    147 STATIC
    148 VOID
    149 WriteCLen (
    150   );
    151 
    152 STATIC
    153 VOID
    154 EncodeC (
    155   IN INT32 c
    156   );
    157 
    158 STATIC
    159 VOID
    160 EncodeP (
    161   IN UINT32 p
    162   );
    163 
    164 STATIC
    165 VOID
    166 SendBlock (
    167   );
    168 
    169 STATIC
    170 VOID
    171 Output (
    172   IN UINT32 c,
    173   IN UINT32 p
    174   );
    175 
    176 STATIC
    177 VOID
    178 HufEncodeStart (
    179   );
    180 
    181 STATIC
    182 VOID
    183 HufEncodeEnd (
    184   );
    185 
    186 STATIC
    187 VOID
    188 MakeCrcTable (
    189   );
    190 
    191 STATIC
    192 VOID
    193 PutBits (
    194   IN INT32 n,
    195   IN UINT32 x
    196   );
    197 
    198 STATIC
    199 INT32
    200 FreadCrc (
    201   OUT UINT8 *p,
    202   IN  INT32 n
    203   );
    204 
    205 STATIC
    206 VOID
    207 InitPutBits (
    208   );
    209 
    210 STATIC
    211 VOID
    212 CountLen (
    213   IN INT32 i
    214   );
    215 
    216 STATIC
    217 VOID
    218 MakeLen (
    219   IN INT32 Root
    220   );
    221 
    222 STATIC
    223 VOID
    224 DownHeap (
    225   IN INT32 i
    226   );
    227 
    228 STATIC
    229 VOID
    230 MakeCode (
    231   IN  INT32 n,
    232   IN  UINT8 Len[],
    233   OUT UINT16 Code[]
    234   );
    235 
    236 STATIC
    237 INT32
    238 MakeTree (
    239   IN  INT32   NParm,
    240   IN  UINT16  FreqParm[],
    241   OUT UINT8   LenParm[],
    242   OUT UINT16  CodeParm[]
    243   );
    244 
    245 
    246 //
    247 //  Global Variables
    248 //
    249 
    250 STATIC UINT8  *mSrc, *mDst, *mSrcUpperLimit, *mDstUpperLimit;
    251 
    252 STATIC UINT8  *mLevel, *mText, *mChildCount, *mBuf, mCLen[NC], mPTLen[NPT], *mLen;
    253 STATIC INT16  mHeap[NC + 1];
    254 STATIC INT32  mRemainder, mMatchLen, mBitCount, mHeapSize, mN;
    255 STATIC UINT32 mBufSiz = 0, mOutputPos, mOutputMask, mSubBitBuf, mCrc;
    256 STATIC UINT32 mCompSize, mOrigSize;
    257 
    258 STATIC UINT16 *mFreq, *mSortPtr, mLenCnt[17], mLeft[2 * NC - 1], mRight[2 * NC - 1],
    259               mCrcTable[UINT8_MAX + 1], mCFreq[2 * NC - 1], mCTable[4096], mCCode[NC],
    260               mPFreq[2 * NP - 1], mPTCode[NPT], mTFreq[2 * NT - 1];
    261 
    262 STATIC NODE   mPos, mMatchPos, mAvail, *mPosition, *mParent, *mPrev, *mNext = NULL;
    263 
    264 
    265 //
    266 // functions
    267 //
    268 
    269 EFI_STATUS
    270 EfiCompress (
    271   IN      UINT8   *SrcBuffer,
    272   IN      UINT32  SrcSize,
    273   IN      UINT8   *DstBuffer,
    274   IN OUT  UINT32  *DstSize
    275   )
    276 /*++
    277 
    278 Routine Description:
    279 
    280   The main compression routine.
    281 
    282 Arguments:
    283 
    284   SrcBuffer   - The buffer storing the source data
    285   SrcSize     - The size of source data
    286   DstBuffer   - The buffer to store the compressed data
    287   DstSize     - On input, the size of DstBuffer; On output,
    288                 the size of the actual compressed data.
    289 
    290 Returns:
    291 
    292   EFI_BUFFER_TOO_SMALL  - The DstBuffer is too small. In this case,
    293                 DstSize contains the size needed.
    294   EFI_SUCCESS           - Compression is successful.
    295 
    296 --*/
    297 {
    298   EFI_STATUS Status = EFI_SUCCESS;
    299 
    300   //
    301   // Initializations
    302   //
    303   mBufSiz = 0;
    304   mBuf = NULL;
    305   mText       = NULL;
    306   mLevel      = NULL;
    307   mChildCount = NULL;
    308   mPosition   = NULL;
    309   mParent     = NULL;
    310   mPrev       = NULL;
    311   mNext       = NULL;
    312 
    313 
    314   mSrc = SrcBuffer;
    315   mSrcUpperLimit = mSrc + SrcSize;
    316   mDst = DstBuffer;
    317   mDstUpperLimit = mDst + *DstSize;
    318 
    319   PutDword(0L);
    320   PutDword(0L);
    321 
    322   MakeCrcTable ();
    323 
    324   mOrigSize = mCompSize = 0;
    325   mCrc = INIT_CRC;
    326 
    327   //
    328   // Compress it
    329   //
    330 
    331   Status = Encode();
    332   if (EFI_ERROR (Status)) {
    333     return EFI_OUT_OF_RESOURCES;
    334   }
    335 
    336   //
    337   // Null terminate the compressed data
    338   //
    339   if (mDst < mDstUpperLimit) {
    340     *mDst++ = 0;
    341   }
    342 
    343   //
    344   // Fill in compressed size and original size
    345   //
    346   mDst = DstBuffer;
    347   PutDword(mCompSize+1);
    348   PutDword(mOrigSize);
    349 
    350   //
    351   // Return
    352   //
    353 
    354   if (mCompSize + 1 + 8 > *DstSize) {
    355     *DstSize = mCompSize + 1 + 8;
    356     return EFI_BUFFER_TOO_SMALL;
    357   } else {
    358     *DstSize = mCompSize + 1 + 8;
    359     return EFI_SUCCESS;
    360   }
    361 
    362 }
    363 
    364 STATIC
    365 VOID
    366 PutDword(
    367   IN UINT32 Data
    368   )
    369 /*++
    370 
    371 Routine Description:
    372 
    373   Put a dword to output stream
    374 
    375 Arguments:
    376 
    377   Data    - the dword to put
    378 
    379 Returns: (VOID)
    380 
    381 --*/
    382 {
    383   if (mDst < mDstUpperLimit) {
    384     *mDst++ = (UINT8)(((UINT8)(Data        )) & 0xff);
    385   }
    386 
    387   if (mDst < mDstUpperLimit) {
    388     *mDst++ = (UINT8)(((UINT8)(Data >> 0x08)) & 0xff);
    389   }
    390 
    391   if (mDst < mDstUpperLimit) {
    392     *mDst++ = (UINT8)(((UINT8)(Data >> 0x10)) & 0xff);
    393   }
    394 
    395   if (mDst < mDstUpperLimit) {
    396     *mDst++ = (UINT8)(((UINT8)(Data >> 0x18)) & 0xff);
    397   }
    398 }
    399 
    400 STATIC
    401 EFI_STATUS
    402 AllocateMemory ()
    403 /*++
    404 
    405 Routine Description:
    406 
    407   Allocate memory spaces for data structures used in compression process
    408 
    409 Argements: (VOID)
    410 
    411 Returns:
    412 
    413   EFI_SUCCESS           - Memory is allocated successfully
    414   EFI_OUT_OF_RESOURCES  - Allocation fails
    415 
    416 --*/
    417 {
    418   UINT32      i;
    419 
    420   mText       = malloc (WNDSIZ * 2 + MAXMATCH);
    421   for (i = 0 ; i < WNDSIZ * 2 + MAXMATCH; i ++) {
    422     mText[i] = 0;
    423   }
    424 
    425   mLevel      = malloc ((WNDSIZ + UINT8_MAX + 1) * sizeof(*mLevel));
    426   mChildCount = malloc ((WNDSIZ + UINT8_MAX + 1) * sizeof(*mChildCount));
    427   mPosition   = malloc ((WNDSIZ + UINT8_MAX + 1) * sizeof(*mPosition));
    428   mParent     = malloc (WNDSIZ * 2 * sizeof(*mParent));
    429   mPrev       = malloc (WNDSIZ * 2 * sizeof(*mPrev));
    430   mNext       = malloc ((MAX_HASH_VAL + 1) * sizeof(*mNext));
    431 
    432   mBufSiz = 16 * 1024U;
    433   while ((mBuf = malloc(mBufSiz)) == NULL) {
    434     mBufSiz = (mBufSiz / 10U) * 9U;
    435     if (mBufSiz < 4 * 1024U) {
    436       return EFI_OUT_OF_RESOURCES;
    437     }
    438   }
    439   mBuf[0] = 0;
    440 
    441   return EFI_SUCCESS;
    442 }
    443 
    444 VOID
    445 FreeMemory ()
    446 /*++
    447 
    448 Routine Description:
    449 
    450   Called when compression is completed to free memory previously allocated.
    451 
    452 Arguments: (VOID)
    453 
    454 Returns: (VOID)
    455 
    456 --*/
    457 {
    458   if (mText) {
    459     free (mText);
    460   }
    461 
    462   if (mLevel) {
    463     free (mLevel);
    464   }
    465 
    466   if (mChildCount) {
    467     free (mChildCount);
    468   }
    469 
    470   if (mPosition) {
    471     free (mPosition);
    472   }
    473 
    474   if (mParent) {
    475     free (mParent);
    476   }
    477 
    478   if (mPrev) {
    479     free (mPrev);
    480   }
    481 
    482   if (mNext) {
    483     free (mNext);
    484   }
    485 
    486   if (mBuf) {
    487     free (mBuf);
    488   }
    489 
    490   return;
    491 }
    492 
    493 
    494 STATIC
    495 VOID
    496 InitSlide ()
    497 /*++
    498 
    499 Routine Description:
    500 
    501   Initialize String Info Log data structures
    502 
    503 Arguments: (VOID)
    504 
    505 Returns: (VOID)
    506 
    507 --*/
    508 {
    509   NODE i;
    510 
    511   for (i = WNDSIZ; i <= WNDSIZ + UINT8_MAX; i++) {
    512     mLevel[i] = 1;
    513     mPosition[i] = NIL;  /* sentinel */
    514   }
    515   for (i = WNDSIZ; i < WNDSIZ * 2; i++) {
    516     mParent[i] = NIL;
    517   }
    518   mAvail = 1;
    519   for (i = 1; i < WNDSIZ - 1; i++) {
    520     mNext[i] = (NODE)(i + 1);
    521   }
    522 
    523   mNext[WNDSIZ - 1] = NIL;
    524   for (i = WNDSIZ * 2; i <= MAX_HASH_VAL; i++) {
    525     mNext[i] = NIL;
    526   }
    527 }
    528 
    529 
    530 STATIC
    531 NODE
    532 Child (
    533   IN NODE q,
    534   IN UINT8 c
    535   )
    536 /*++
    537 
    538 Routine Description:
    539 
    540   Find child node given the parent node and the edge character
    541 
    542 Arguments:
    543 
    544   q       - the parent node
    545   c       - the edge character
    546 
    547 Returns:
    548 
    549   The child node (NIL if not found)
    550 
    551 --*/
    552 {
    553   NODE r;
    554 
    555   r = mNext[HASH(q, c)];
    556   mParent[NIL] = q;  /* sentinel */
    557   while (mParent[r] != q) {
    558     r = mNext[r];
    559   }
    560 
    561   return r;
    562 }
    563 
    564 STATIC
    565 VOID
    566 MakeChild (
    567   IN NODE q,
    568   IN UINT8 c,
    569   IN NODE r
    570   )
    571 /*++
    572 
    573 Routine Description:
    574 
    575   Create a new child for a given parent node.
    576 
    577 Arguments:
    578 
    579   q       - the parent node
    580   c       - the edge character
    581   r       - the child node
    582 
    583 Returns: (VOID)
    584 
    585 --*/
    586 {
    587   NODE h, t;
    588 
    589   h = (NODE)HASH(q, c);
    590   t = mNext[h];
    591   mNext[h] = r;
    592   mNext[r] = t;
    593   mPrev[t] = r;
    594   mPrev[r] = h;
    595   mParent[r] = q;
    596   mChildCount[q]++;
    597 }
    598 
    599 STATIC
    600 VOID
    601 Split (
    602   NODE Old
    603   )
    604 /*++
    605 
    606 Routine Description:
    607 
    608   Split a node.
    609 
    610 Arguments:
    611 
    612   Old     - the node to split
    613 
    614 Returns: (VOID)
    615 
    616 --*/
    617 {
    618   NODE New, t;
    619 
    620   New = mAvail;
    621   mAvail = mNext[New];
    622   mChildCount[New] = 0;
    623   t = mPrev[Old];
    624   mPrev[New] = t;
    625   mNext[t] = New;
    626   t = mNext[Old];
    627   mNext[New] = t;
    628   mPrev[t] = New;
    629   mParent[New] = mParent[Old];
    630   mLevel[New] = (UINT8)mMatchLen;
    631   mPosition[New] = mPos;
    632   MakeChild(New, mText[mMatchPos + mMatchLen], Old);
    633   MakeChild(New, mText[mPos + mMatchLen], mPos);
    634 }
    635 
    636 STATIC
    637 VOID
    638 InsertNode ()
    639 /*++
    640 
    641 Routine Description:
    642 
    643   Insert string info for current position into the String Info Log
    644 
    645 Arguments: (VOID)
    646 
    647 Returns: (VOID)
    648 
    649 --*/
    650 {
    651   NODE q, r, j, t;
    652   UINT8 c, *t1, *t2;
    653 
    654   if (mMatchLen >= 4) {
    655 
    656     //
    657     // We have just got a long match, the target tree
    658     // can be located by MatchPos + 1. Travese the tree
    659     // from bottom up to get to a proper starting point.
    660     // The usage of PERC_FLAG ensures proper node deletion
    661     // in DeleteNode() later.
    662     //
    663 
    664     mMatchLen--;
    665     r = (INT16)((mMatchPos + 1) | WNDSIZ);
    666     while ((q = mParent[r]) == NIL) {
    667       r = mNext[r];
    668     }
    669     while (mLevel[q] >= mMatchLen) {
    670       r = q;  q = mParent[q];
    671     }
    672     t = q;
    673     while (mPosition[t] < 0) {
    674       mPosition[t] = mPos;
    675       t = mParent[t];
    676     }
    677     if (t < WNDSIZ) {
    678       mPosition[t] = (NODE)(mPos | PERC_FLAG);
    679     }
    680   } else {
    681 
    682     //
    683     // Locate the target tree
    684     //
    685 
    686     q = (INT16)(mText[mPos] + WNDSIZ);
    687     c = mText[mPos + 1];
    688     if ((r = Child(q, c)) == NIL) {
    689       MakeChild(q, c, mPos);
    690       mMatchLen = 1;
    691       return;
    692     }
    693     mMatchLen = 2;
    694   }
    695 
    696   //
    697   // Traverse down the tree to find a match.
    698   // Update Position value along the route.
    699   // Node split or creation is involved.
    700   //
    701 
    702   for ( ; ; ) {
    703     if (r >= WNDSIZ) {
    704       j = MAXMATCH;
    705       mMatchPos = r;
    706     } else {
    707       j = mLevel[r];
    708       mMatchPos = (NODE)(mPosition[r] & ~PERC_FLAG);
    709     }
    710     if (mMatchPos >= mPos) {
    711       mMatchPos -= WNDSIZ;
    712     }
    713     t1 = &mText[mPos + mMatchLen];
    714     t2 = &mText[mMatchPos + mMatchLen];
    715     while (mMatchLen < j) {
    716       if (*t1 != *t2) {
    717         Split(r);
    718         return;
    719       }
    720       mMatchLen++;
    721       t1++;
    722       t2++;
    723     }
    724     if (mMatchLen >= MAXMATCH) {
    725       break;
    726     }
    727     mPosition[r] = mPos;
    728     q = r;
    729     if ((r = Child(q, *t1)) == NIL) {
    730       MakeChild(q, *t1, mPos);
    731       return;
    732     }
    733     mMatchLen++;
    734   }
    735   t = mPrev[r];
    736   mPrev[mPos] = t;
    737   mNext[t] = mPos;
    738   t = mNext[r];
    739   mNext[mPos] = t;
    740   mPrev[t] = mPos;
    741   mParent[mPos] = q;
    742   mParent[r] = NIL;
    743 
    744   //
    745   // Special usage of 'next'
    746   //
    747   mNext[r] = mPos;
    748 
    749 }
    750 
    751 STATIC
    752 VOID
    753 DeleteNode ()
    754 /*++
    755 
    756 Routine Description:
    757 
    758   Delete outdated string info. (The Usage of PERC_FLAG
    759   ensures a clean deletion)
    760 
    761 Arguments: (VOID)
    762 
    763 Returns: (VOID)
    764 
    765 --*/
    766 {
    767   NODE q, r, s, t, u;
    768 
    769   if (mParent[mPos] == NIL) {
    770     return;
    771   }
    772 
    773   r = mPrev[mPos];
    774   s = mNext[mPos];
    775   mNext[r] = s;
    776   mPrev[s] = r;
    777   r = mParent[mPos];
    778   mParent[mPos] = NIL;
    779   if (r >= WNDSIZ || --mChildCount[r] > 1) {
    780     return;
    781   }
    782   t = (NODE)(mPosition[r] & ~PERC_FLAG);
    783   if (t >= mPos) {
    784     t -= WNDSIZ;
    785   }
    786   s = t;
    787   q = mParent[r];
    788   while ((u = mPosition[q]) & PERC_FLAG) {
    789     u &= ~PERC_FLAG;
    790     if (u >= mPos) {
    791       u -= WNDSIZ;
    792     }
    793     if (u > s) {
    794       s = u;
    795     }
    796     mPosition[q] = (INT16)(s | WNDSIZ);
    797     q = mParent[q];
    798   }
    799   if (q < WNDSIZ) {
    800     if (u >= mPos) {
    801       u -= WNDSIZ;
    802     }
    803     if (u > s) {
    804       s = u;
    805     }
    806     mPosition[q] = (INT16)(s | WNDSIZ | PERC_FLAG);
    807   }
    808   s = Child(r, mText[t + mLevel[r]]);
    809   t = mPrev[s];
    810   u = mNext[s];
    811   mNext[t] = u;
    812   mPrev[u] = t;
    813   t = mPrev[r];
    814   mNext[t] = s;
    815   mPrev[s] = t;
    816   t = mNext[r];
    817   mPrev[t] = s;
    818   mNext[s] = t;
    819   mParent[s] = mParent[r];
    820   mParent[r] = NIL;
    821   mNext[r] = mAvail;
    822   mAvail = r;
    823 }
    824 
    825 STATIC
    826 VOID
    827 GetNextMatch ()
    828 /*++
    829 
    830 Routine Description:
    831 
    832   Advance the current position (read in new data if needed).
    833   Delete outdated string info. Find a match string for current position.
    834 
    835 Arguments: (VOID)
    836 
    837 Returns: (VOID)
    838 
    839 --*/
    840 {
    841   INT32 n;
    842 
    843   mRemainder--;
    844   if (++mPos == WNDSIZ * 2) {
    845     memmove(&mText[0], &mText[WNDSIZ], WNDSIZ + MAXMATCH);
    846     n = FreadCrc(&mText[WNDSIZ + MAXMATCH], WNDSIZ);
    847     mRemainder += n;
    848     mPos = WNDSIZ;
    849   }
    850   DeleteNode();
    851   InsertNode();
    852 }
    853 
    854 STATIC
    855 EFI_STATUS
    856 Encode ()
    857 /*++
    858 
    859 Routine Description:
    860 
    861   The main controlling routine for compression process.
    862 
    863 Arguments: (VOID)
    864 
    865 Returns:
    866 
    867   EFI_SUCCESS           - The compression is successful
    868   EFI_OUT_0F_RESOURCES  - Not enough memory for compression process
    869 
    870 --*/
    871 {
    872   EFI_STATUS  Status;
    873   INT32       LastMatchLen;
    874   NODE        LastMatchPos;
    875 
    876   Status = AllocateMemory();
    877   if (EFI_ERROR(Status)) {
    878     FreeMemory();
    879     return Status;
    880   }
    881 
    882   InitSlide();
    883 
    884   HufEncodeStart();
    885 
    886   mRemainder = FreadCrc(&mText[WNDSIZ], WNDSIZ + MAXMATCH);
    887 
    888   mMatchLen = 0;
    889   mPos = WNDSIZ;
    890   InsertNode();
    891   if (mMatchLen > mRemainder) {
    892     mMatchLen = mRemainder;
    893   }
    894   while (mRemainder > 0) {
    895     LastMatchLen = mMatchLen;
    896     LastMatchPos = mMatchPos;
    897     GetNextMatch();
    898     if (mMatchLen > mRemainder) {
    899       mMatchLen = mRemainder;
    900     }
    901 
    902     if (mMatchLen > LastMatchLen || LastMatchLen < THRESHOLD) {
    903 
    904       //
    905       // Not enough benefits are gained by outputting a pointer,
    906       // so just output the original character
    907       //
    908 
    909       Output(mText[mPos - 1], 0);
    910     } else {
    911 
    912       //
    913       // Outputting a pointer is beneficial enough, do it.
    914       //
    915 
    916       Output(LastMatchLen + (UINT8_MAX + 1 - THRESHOLD),
    917              (mPos - LastMatchPos - 2) & (WNDSIZ - 1));
    918       while (--LastMatchLen > 0) {
    919         GetNextMatch();
    920       }
    921       if (mMatchLen > mRemainder) {
    922         mMatchLen = mRemainder;
    923       }
    924     }
    925   }
    926 
    927   HufEncodeEnd();
    928   FreeMemory();
    929   return EFI_SUCCESS;
    930 }
    931 
    932 STATIC
    933 VOID
    934 CountTFreq ()
    935 /*++
    936 
    937 Routine Description:
    938 
    939   Count the frequencies for the Extra Set
    940 
    941 Arguments: (VOID)
    942 
    943 Returns: (VOID)
    944 
    945 --*/
    946 {
    947   INT32 i, k, n, Count;
    948 
    949   for (i = 0; i < NT; i++) {
    950     mTFreq[i] = 0;
    951   }
    952   n = NC;
    953   while (n > 0 && mCLen[n - 1] == 0) {
    954     n--;
    955   }
    956   i = 0;
    957   while (i < n) {
    958     k = mCLen[i++];
    959     if (k == 0) {
    960       Count = 1;
    961       while (i < n && mCLen[i] == 0) {
    962         i++;
    963         Count++;
    964       }
    965       if (Count <= 2) {
    966         mTFreq[0] = (UINT16)(mTFreq[0] + Count);
    967       } else if (Count <= 18) {
    968         mTFreq[1]++;
    969       } else if (Count == 19) {
    970         mTFreq[0]++;
    971         mTFreq[1]++;
    972       } else {
    973         mTFreq[2]++;
    974       }
    975     } else {
    976       mTFreq[k + 2]++;
    977     }
    978   }
    979 }
    980 
    981 STATIC
    982 VOID
    983 WritePTLen (
    984   IN INT32 n,
    985   IN INT32 nbit,
    986   IN INT32 Special
    987   )
    988 /*++
    989 
    990 Routine Description:
    991 
    992   Outputs the code length array for the Extra Set or the Position Set.
    993 
    994 Arguments:
    995 
    996   n       - the number of symbols
    997   nbit    - the number of bits needed to represent 'n'
    998   Special - the special symbol that needs to be take care of
    999 
   1000 Returns: (VOID)
   1001 
   1002 --*/
   1003 {
   1004   INT32 i, k;
   1005 
   1006   while (n > 0 && mPTLen[n - 1] == 0) {
   1007     n--;
   1008   }
   1009   PutBits(nbit, n);
   1010   i = 0;
   1011   while (i < n) {
   1012     k = mPTLen[i++];
   1013     if (k <= 6) {
   1014       PutBits(3, k);
   1015     } else {
   1016       PutBits(k - 3, (1U << (k - 3)) - 2);
   1017     }
   1018     if (i == Special) {
   1019       while (i < 6 && mPTLen[i] == 0) {
   1020         i++;
   1021       }
   1022       PutBits(2, (i - 3) & 3);
   1023     }
   1024   }
   1025 }
   1026 
   1027 STATIC
   1028 VOID
   1029 WriteCLen ()
   1030 /*++
   1031 
   1032 Routine Description:
   1033 
   1034   Outputs the code length array for Char&Length Set
   1035 
   1036 Arguments: (VOID)
   1037 
   1038 Returns: (VOID)
   1039 
   1040 --*/
   1041 {
   1042   INT32 i, k, n, Count;
   1043 
   1044   n = NC;
   1045   while (n > 0 && mCLen[n - 1] == 0) {
   1046     n--;
   1047   }
   1048   PutBits(CBIT, n);
   1049   i = 0;
   1050   while (i < n) {
   1051     k = mCLen[i++];
   1052     if (k == 0) {
   1053       Count = 1;
   1054       while (i < n && mCLen[i] == 0) {
   1055         i++;
   1056         Count++;
   1057       }
   1058       if (Count <= 2) {
   1059         for (k = 0; k < Count; k++) {
   1060           PutBits(mPTLen[0], mPTCode[0]);
   1061         }
   1062       } else if (Count <= 18) {
   1063         PutBits(mPTLen[1], mPTCode[1]);
   1064         PutBits(4, Count - 3);
   1065       } else if (Count == 19) {
   1066         PutBits(mPTLen[0], mPTCode[0]);
   1067         PutBits(mPTLen[1], mPTCode[1]);
   1068         PutBits(4, 15);
   1069       } else {
   1070         PutBits(mPTLen[2], mPTCode[2]);
   1071         PutBits(CBIT, Count - 20);
   1072       }
   1073     } else {
   1074       PutBits(mPTLen[k + 2], mPTCode[k + 2]);
   1075     }
   1076   }
   1077 }
   1078 
   1079 STATIC
   1080 VOID
   1081 EncodeC (
   1082   IN INT32 c
   1083   )
   1084 {
   1085   PutBits(mCLen[c], mCCode[c]);
   1086 }
   1087 
   1088 STATIC
   1089 VOID
   1090 EncodeP (
   1091   IN UINT32 p
   1092   )
   1093 {
   1094   UINT32 c, q;
   1095 
   1096   c = 0;
   1097   q = p;
   1098   while (q) {
   1099     q >>= 1;
   1100     c++;
   1101   }
   1102   PutBits(mPTLen[c], mPTCode[c]);
   1103   if (c > 1) {
   1104     PutBits(c - 1, p & (0xFFFFU >> (17 - c)));
   1105   }
   1106 }
   1107 
   1108 STATIC
   1109 VOID
   1110 SendBlock ()
   1111 /*++
   1112 
   1113 Routine Description:
   1114 
   1115   Huffman code the block and output it.
   1116 
   1117 Argument: (VOID)
   1118 
   1119 Returns: (VOID)
   1120 
   1121 --*/
   1122 {
   1123   UINT32 i, k, Flags, Root, Pos, Size;
   1124   Flags = 0;
   1125 
   1126   Root = MakeTree(NC, mCFreq, mCLen, mCCode);
   1127   Size = mCFreq[Root];
   1128   PutBits(16, Size);
   1129   if (Root >= NC) {
   1130     CountTFreq();
   1131     Root = MakeTree(NT, mTFreq, mPTLen, mPTCode);
   1132     if (Root >= NT) {
   1133       WritePTLen(NT, TBIT, 3);
   1134     } else {
   1135       PutBits(TBIT, 0);
   1136       PutBits(TBIT, Root);
   1137     }
   1138     WriteCLen();
   1139   } else {
   1140     PutBits(TBIT, 0);
   1141     PutBits(TBIT, 0);
   1142     PutBits(CBIT, 0);
   1143     PutBits(CBIT, Root);
   1144   }
   1145   Root = MakeTree(NP, mPFreq, mPTLen, mPTCode);
   1146   if (Root >= NP) {
   1147     WritePTLen(NP, PBIT, -1);
   1148   } else {
   1149     PutBits(PBIT, 0);
   1150     PutBits(PBIT, Root);
   1151   }
   1152   Pos = 0;
   1153   for (i = 0; i < Size; i++) {
   1154     if (i % UINT8_BIT == 0) {
   1155       Flags = mBuf[Pos++];
   1156     } else {
   1157       Flags <<= 1;
   1158     }
   1159     if (Flags & (1U << (UINT8_BIT - 1))) {
   1160       EncodeC(mBuf[Pos++] + (1U << UINT8_BIT));
   1161       k = mBuf[Pos++] << UINT8_BIT;
   1162       k += mBuf[Pos++];
   1163       EncodeP(k);
   1164     } else {
   1165       EncodeC(mBuf[Pos++]);
   1166     }
   1167   }
   1168   for (i = 0; i < NC; i++) {
   1169     mCFreq[i] = 0;
   1170   }
   1171   for (i = 0; i < NP; i++) {
   1172     mPFreq[i] = 0;
   1173   }
   1174 }
   1175 
   1176 
   1177 STATIC
   1178 VOID
   1179 Output (
   1180   IN UINT32 c,
   1181   IN UINT32 p
   1182   )
   1183 /*++
   1184 
   1185 Routine Description:
   1186 
   1187   Outputs an Original Character or a Pointer
   1188 
   1189 Arguments:
   1190 
   1191   c     - The original character or the 'String Length' element of a Pointer
   1192   p     - The 'Position' field of a Pointer
   1193 
   1194 Returns: (VOID)
   1195 
   1196 --*/
   1197 {
   1198   STATIC UINT32 CPos;
   1199 
   1200   if ((mOutputMask >>= 1) == 0) {
   1201     mOutputMask = 1U << (UINT8_BIT - 1);
   1202     if (mOutputPos >= mBufSiz - 3 * UINT8_BIT) {
   1203       SendBlock();
   1204       mOutputPos = 0;
   1205     }
   1206     CPos = mOutputPos++;
   1207     mBuf[CPos] = 0;
   1208   }
   1209   mBuf[mOutputPos++] = (UINT8) c;
   1210   mCFreq[c]++;
   1211   if (c >= (1U << UINT8_BIT)) {
   1212     mBuf[CPos] |= mOutputMask;
   1213     mBuf[mOutputPos++] = (UINT8)(p >> UINT8_BIT);
   1214     mBuf[mOutputPos++] = (UINT8) p;
   1215     c = 0;
   1216     while (p) {
   1217       p >>= 1;
   1218       c++;
   1219     }
   1220     mPFreq[c]++;
   1221   }
   1222 }
   1223 
   1224 STATIC
   1225 VOID
   1226 HufEncodeStart ()
   1227 {
   1228   INT32 i;
   1229 
   1230   for (i = 0; i < NC; i++) {
   1231     mCFreq[i] = 0;
   1232   }
   1233   for (i = 0; i < NP; i++) {
   1234     mPFreq[i] = 0;
   1235   }
   1236   mOutputPos = mOutputMask = 0;
   1237   InitPutBits();
   1238   return;
   1239 }
   1240 
   1241 STATIC
   1242 VOID
   1243 HufEncodeEnd ()
   1244 {
   1245   SendBlock();
   1246 
   1247   //
   1248   // Flush remaining bits
   1249   //
   1250   PutBits(UINT8_BIT - 1, 0);
   1251 
   1252   return;
   1253 }
   1254 
   1255 
   1256 STATIC
   1257 VOID
   1258 MakeCrcTable ()
   1259 {
   1260   UINT32 i, j, r;
   1261 
   1262   for (i = 0; i <= UINT8_MAX; i++) {
   1263     r = i;
   1264     for (j = 0; j < UINT8_BIT; j++) {
   1265       if (r & 1) {
   1266         r = (r >> 1) ^ CRCPOLY;
   1267       } else {
   1268         r >>= 1;
   1269       }
   1270     }
   1271     mCrcTable[i] = (UINT16)r;
   1272   }
   1273 }
   1274 
   1275 STATIC
   1276 VOID
   1277 PutBits (
   1278   IN INT32 n,
   1279   IN UINT32 x
   1280   )
   1281 /*++
   1282 
   1283 Routine Description:
   1284 
   1285   Outputs rightmost n bits of x
   1286 
   1287 Argments:
   1288 
   1289   n   - the rightmost n bits of the data is used
   1290   x   - the data
   1291 
   1292 Returns: (VOID)
   1293 
   1294 --*/
   1295 {
   1296   UINT8 Temp;
   1297 
   1298   if (n < mBitCount) {
   1299     mSubBitBuf |= x << (mBitCount -= n);
   1300   } else {
   1301 
   1302     Temp = (UINT8)(mSubBitBuf | (x >> (n -= mBitCount)));
   1303     if (mDst < mDstUpperLimit) {
   1304       *mDst++ = Temp;
   1305     }
   1306     mCompSize++;
   1307 
   1308     if (n < UINT8_BIT) {
   1309       mSubBitBuf = x << (mBitCount = UINT8_BIT - n);
   1310     } else {
   1311 
   1312       Temp = (UINT8)(x >> (n - UINT8_BIT));
   1313       if (mDst < mDstUpperLimit) {
   1314         *mDst++ = Temp;
   1315       }
   1316       mCompSize++;
   1317 
   1318       mSubBitBuf = x << (mBitCount = 2 * UINT8_BIT - n);
   1319     }
   1320   }
   1321 }
   1322 
   1323 STATIC
   1324 INT32
   1325 FreadCrc (
   1326   OUT UINT8 *p,
   1327   IN  INT32 n
   1328   )
   1329 /*++
   1330 
   1331 Routine Description:
   1332 
   1333   Read in source data
   1334 
   1335 Arguments:
   1336 
   1337   p   - the buffer to hold the data
   1338   n   - number of bytes to read
   1339 
   1340 Returns:
   1341 
   1342   number of bytes actually read
   1343 
   1344 --*/
   1345 {
   1346   INT32 i;
   1347 
   1348   for (i = 0; mSrc < mSrcUpperLimit && i < n; i++) {
   1349     *p++ = *mSrc++;
   1350   }
   1351   n = i;
   1352 
   1353   p -= n;
   1354   mOrigSize += n;
   1355   while (--i >= 0) {
   1356     UPDATE_CRC(*p++);
   1357   }
   1358   return n;
   1359 }
   1360 
   1361 
   1362 STATIC
   1363 VOID
   1364 InitPutBits ()
   1365 {
   1366   mBitCount = UINT8_BIT;
   1367   mSubBitBuf = 0;
   1368 }
   1369 
   1370 STATIC
   1371 VOID
   1372 CountLen (
   1373   IN INT32 i
   1374   )
   1375 /*++
   1376 
   1377 Routine Description:
   1378 
   1379   Count the number of each code length for a Huffman tree.
   1380 
   1381 Arguments:
   1382 
   1383   i   - the top node
   1384 
   1385 Returns: (VOID)
   1386 
   1387 --*/
   1388 {
   1389   STATIC INT32 Depth = 0;
   1390 
   1391   if (i < mN) {
   1392     mLenCnt[(Depth < 16) ? Depth : 16]++;
   1393   } else {
   1394     Depth++;
   1395     CountLen(mLeft [i]);
   1396     CountLen(mRight[i]);
   1397     Depth--;
   1398   }
   1399 }
   1400 
   1401 STATIC
   1402 VOID
   1403 MakeLen (
   1404   IN INT32 Root
   1405   )
   1406 /*++
   1407 
   1408 Routine Description:
   1409 
   1410   Create code length array for a Huffman tree
   1411 
   1412 Arguments:
   1413 
   1414   Root   - the root of the tree
   1415 
   1416 --*/
   1417 {
   1418   INT32 i, k;
   1419   UINT32 Cum;
   1420 
   1421   for (i = 0; i <= 16; i++) {
   1422     mLenCnt[i] = 0;
   1423   }
   1424   CountLen(Root);
   1425 
   1426   //
   1427   // Adjust the length count array so that
   1428   // no code will be generated longer than its designated length
   1429   //
   1430 
   1431   Cum = 0;
   1432   for (i = 16; i > 0; i--) {
   1433     Cum += mLenCnt[i] << (16 - i);
   1434   }
   1435   while (Cum != (1U << 16)) {
   1436     mLenCnt[16]--;
   1437     for (i = 15; i > 0; i--) {
   1438       if (mLenCnt[i] != 0) {
   1439         mLenCnt[i]--;
   1440         mLenCnt[i+1] += 2;
   1441         break;
   1442       }
   1443     }
   1444     Cum--;
   1445   }
   1446   for (i = 16; i > 0; i--) {
   1447     k = mLenCnt[i];
   1448     while (--k >= 0) {
   1449       mLen[*mSortPtr++] = (UINT8)i;
   1450     }
   1451   }
   1452 }
   1453 
   1454 STATIC
   1455 VOID
   1456 DownHeap (
   1457   IN INT32 i
   1458   )
   1459 {
   1460   INT32 j, k;
   1461 
   1462   //
   1463   // priority queue: send i-th entry down heap
   1464   //
   1465 
   1466   k = mHeap[i];
   1467   while ((j = 2 * i) <= mHeapSize) {
   1468     if (j < mHeapSize && mFreq[mHeap[j]] > mFreq[mHeap[j + 1]]) {
   1469       j++;
   1470     }
   1471     if (mFreq[k] <= mFreq[mHeap[j]]) {
   1472       break;
   1473     }
   1474     mHeap[i] = mHeap[j];
   1475     i = j;
   1476   }
   1477   mHeap[i] = (INT16)k;
   1478 }
   1479 
   1480 STATIC
   1481 VOID
   1482 MakeCode (
   1483   IN  INT32 n,
   1484   IN  UINT8 Len[],
   1485   OUT UINT16 Code[]
   1486   )
   1487 /*++
   1488 
   1489 Routine Description:
   1490 
   1491   Assign code to each symbol based on the code length array
   1492 
   1493 Arguments:
   1494 
   1495   n     - number of symbols
   1496   Len   - the code length array
   1497   Code  - stores codes for each symbol
   1498 
   1499 Returns: (VOID)
   1500 
   1501 --*/
   1502 {
   1503   INT32    i;
   1504   UINT16   Start[18];
   1505 
   1506   Start[1] = 0;
   1507   for (i = 1; i <= 16; i++) {
   1508     Start[i + 1] = (UINT16)((Start[i] + mLenCnt[i]) << 1);
   1509   }
   1510   for (i = 0; i < n; i++) {
   1511     Code[i] = Start[Len[i]]++;
   1512   }
   1513 }
   1514 
   1515 STATIC
   1516 INT32
   1517 MakeTree (
   1518   IN  INT32   NParm,
   1519   IN  UINT16  FreqParm[],
   1520   OUT UINT8   LenParm[],
   1521   OUT UINT16  CodeParm[]
   1522   )
   1523 /*++
   1524 
   1525 Routine Description:
   1526 
   1527   Generates Huffman codes given a frequency distribution of symbols
   1528 
   1529 Arguments:
   1530 
   1531   NParm    - number of symbols
   1532   FreqParm - frequency of each symbol
   1533   LenParm  - code length for each symbol
   1534   CodeParm - code for each symbol
   1535 
   1536 Returns:
   1537 
   1538   Root of the Huffman tree.
   1539 
   1540 --*/
   1541 {
   1542   INT32 i, j, k, Avail;
   1543 
   1544   //
   1545   // make tree, calculate len[], return root
   1546   //
   1547 
   1548   mN = NParm;
   1549   mFreq = FreqParm;
   1550   mLen = LenParm;
   1551   Avail = mN;
   1552   mHeapSize = 0;
   1553   mHeap[1] = 0;
   1554   for (i = 0; i < mN; i++) {
   1555     mLen[i] = 0;
   1556     if (mFreq[i]) {
   1557       mHeap[++mHeapSize] = (INT16)i;
   1558     }
   1559   }
   1560   if (mHeapSize < 2) {
   1561     CodeParm[mHeap[1]] = 0;
   1562     return mHeap[1];
   1563   }
   1564   for (i = mHeapSize / 2; i >= 1; i--) {
   1565 
   1566     //
   1567     // make priority queue
   1568     //
   1569     DownHeap(i);
   1570   }
   1571   mSortPtr = CodeParm;
   1572   do {
   1573     i = mHeap[1];
   1574     if (i < mN) {
   1575       *mSortPtr++ = (UINT16)i;
   1576     }
   1577     mHeap[1] = mHeap[mHeapSize--];
   1578     DownHeap(1);
   1579     j = mHeap[1];
   1580     if (j < mN) {
   1581       *mSortPtr++ = (UINT16)j;
   1582     }
   1583     k = Avail++;
   1584     mFreq[k] = (UINT16)(mFreq[i] + mFreq[j]);
   1585     mHeap[1] = (INT16)k;
   1586     DownHeap(1);
   1587     mLeft[k] = (UINT16)i;
   1588     mRight[k] = (UINT16)j;
   1589   } while (mHeapSize > 1);
   1590 
   1591   mSortPtr = CodeParm;
   1592   MakeLen(k);
   1593   MakeCode(NParm, LenParm, CodeParm);
   1594 
   1595   //
   1596   // return root
   1597   //
   1598   return k;
   1599 }
   1600 
   1601