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