From 30f80dd8dedf2c333be4616442daf5d1b412e23e Mon Sep 17 00:00:00 2001
From: klu2 <klu2@6f19259b-4bc3-4df7-8a09-765794883524>
Date: Thu, 7 Dec 2006 05:29:07 +0000
Subject: =?UTF-8?q?The=20main=20issue=20want=20to=20be=20resolve=20is=20th?=
 =?UTF-8?q?at=20some=20tools=20need=20EfiCompress=20and=20other=20tools=20?=
 =?UTF-8?q?need=20TianoCompress,=20but=20only=20common=20Compress(indeed?=
 =?UTF-8?q?=20is=20TianoCompress)=20is=20provided=20in=20tool/CCode/Common?=
 =?UTF-8?q?.=20=09EfiCompress=20and=20TianoCompress=20are=20all=20originat?=
 =?UTF-8?q?ed=20from=20LZ77=20algorithms=20and=20they=20have=20very=20litt?=
 =?UTF-8?q?le=20different,=20that=20different=20position=20set=20for=20Huf?=
 =?UTF-8?q?fman=20code.=20=09EfiCompress=20is=20defined=20in=20EFI=201.1?=
 =?UTF-8?q?=20spec=20and=20EfiRom=20tool=20need=20it=20to=20create=20a=20r?=
 =?UTF-8?q?ecognized=20compressed=20EFI=20driver.=20=09TianoCompress=20is?=
 =?UTF-8?q?=20for=20pursuer=20more=20size=20saving=20and=20it=20used=20be?=
 =?UTF-8?q?=20GenFfs=20and=20GenSection=20tools.=20=09So=20this=20patch:?=
 =?UTF-8?q?=20=091)=20Split=20EfiComress=20and=20TianoCompress=20in=20edkI?=
 =?UTF-8?q?I=E2=80=99s=20tools=20=092)=20Change=20EfiRom=20tool=20use=20Ef?=
 =?UTF-8?q?iCompress=20and=20GenFfs/GenSection=20use=20TianoCompress?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

git-svn-id: https://edk2.svn.sourceforge.net/svnroot/edk2/trunk/edk2@2064 6f19259b-4bc3-4df7-8a09-765794883524
---
 Tools/CCode/Source/Common/TianoCompress.c | 1752 +++++++++++++++++++++++++++++
 1 file changed, 1752 insertions(+)
 create mode 100644 Tools/CCode/Source/Common/TianoCompress.c

(limited to 'Tools/CCode/Source/Common/TianoCompress.c')

diff --git a/Tools/CCode/Source/Common/TianoCompress.c b/Tools/CCode/Source/Common/TianoCompress.c
new file mode 100644
index 0000000000..dc78e7ad85
--- /dev/null
+++ b/Tools/CCode/Source/Common/TianoCompress.c
@@ -0,0 +1,1752 @@
+/*++
+
+Copyright (c) 2006, Intel Corporation                                              
+All rights reserved. This program and the accompanying materials                          
+are licensed and made available under the terms and conditions of the BSD License         
+which accompanies this distribution.  The full text of the license may be found at        
+http://opensource.org/licenses/bsd-license.php                                            
+                                                                                          
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,                     
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.             
+
+Module Name:
+
+  TianoCompress.c
+
+Abstract:
+
+  Compression routine. The compression algorithm is a mixture of
+  LZ77 and Huffman coding. LZ77 transforms the source data into a
+  sequence of Original Characters and Pointers to repeated strings.
+  This sequence is further divided into Blocks and Huffman codings
+  are applied to each Block.
+
+--*/
+
+#include "Compress.h"
+
+//
+// Macro Definitions
+//
+typedef INT32 NODE;
+#define UINT8_MAX     0xff
+#define UINT8_BIT     8
+#define THRESHOLD     3
+#define INIT_CRC      0
+#define WNDBIT        19
+#define WNDSIZ        (1U << WNDBIT)
+#define MAXMATCH      256
+#define BLKSIZ        (1U << 14)  // 16 * 1024U
+#define PERC_FLAG     0x80000000U
+#define CODE_BIT      16
+#define NIL           0
+#define MAX_HASH_VAL  (3 * WNDSIZ + (WNDSIZ / 512 + 1) * UINT8_MAX)
+#define HASH(p, c)    ((p) + ((c) << (WNDBIT - 9)) + WNDSIZ * 2)
+#define CRCPOLY       0xA001
+#define UPDATE_CRC(c) mCrc = mCrcTable[(mCrc ^ (c)) & 0xFF] ^ (mCrc >> UINT8_BIT)
+
+//
+// C: the Char&Len Set; P: the Position Set; T: the exTra Set
+//
+#define NC    (UINT8_MAX + MAXMATCH + 2 - THRESHOLD)
+#define CBIT  9
+#define NP    (WNDBIT + 1)
+#define PBIT  5
+#define NT    (CODE_BIT + 3)
+#define TBIT  5
+#if NT > NP
+#define NPT NT
+#else
+#define NPT NP
+#endif
+//
+// Function Prototypes
+//
+
+STATIC
+VOID
+PutDword(
+  IN UINT32 Data
+  );
+
+STATIC
+EFI_STATUS
+AllocateMemory (
+  VOID
+  );
+
+STATIC
+VOID
+FreeMemory (
+  VOID
+  );
+
+STATIC
+VOID
+InitSlide (
+  VOID
+  );
+
+STATIC
+NODE
+Child (
+  IN NODE   NodeQ,
+  IN UINT8  CharC
+  );
+
+STATIC
+VOID
+MakeChild (
+  IN NODE  NodeQ,
+  IN UINT8 CharC,
+  IN NODE  NodeR
+  );
+
+STATIC
+VOID
+Split (
+  IN NODE Old
+  );
+
+STATIC
+VOID
+InsertNode (
+  VOID
+  );
+
+STATIC
+VOID
+DeleteNode (
+  VOID
+  );
+
+STATIC
+VOID
+GetNextMatch (
+  VOID
+  );
+
+STATIC
+EFI_STATUS
+Encode (
+  VOID
+  );
+
+STATIC
+VOID
+CountTFreq (
+  VOID
+  );
+
+STATIC
+VOID
+WritePTLen (
+  IN INT32 Number,
+  IN INT32 nbit,
+  IN INT32 Special
+  );
+
+STATIC
+VOID
+WriteCLen (
+  VOID
+  );
+
+STATIC
+VOID
+EncodeC (
+  IN INT32 Value
+  );
+
+STATIC
+VOID
+EncodeP (
+  IN UINT32 Value
+  );
+
+STATIC
+VOID
+SendBlock (
+  VOID
+  );
+
+STATIC
+VOID
+Output (
+  IN UINT32 c,
+  IN UINT32 p
+  );
+
+STATIC
+VOID
+HufEncodeStart (
+  VOID
+  );
+
+STATIC
+VOID
+HufEncodeEnd (
+  VOID
+  );
+
+STATIC
+VOID
+MakeCrcTable (
+  VOID
+  );
+
+STATIC
+VOID
+PutBits (
+  IN INT32  Number,
+  IN UINT32 Value
+  );
+
+STATIC
+INT32
+FreadCrc (
+  OUT UINT8 *Pointer,
+  IN  INT32 Number
+  );
+
+STATIC
+VOID
+InitPutBits (
+  VOID
+  );
+
+STATIC
+VOID
+CountLen (
+  IN INT32 Index
+  );
+
+STATIC
+VOID
+MakeLen (
+  IN INT32 Root
+  );
+
+STATIC
+VOID
+DownHeap (
+  IN INT32 Index
+  );
+
+STATIC
+VOID
+MakeCode (
+  IN  INT32       Number,
+  IN  UINT8 Len[  ],
+  OUT UINT16 Code[]
+  );
+
+STATIC
+INT32
+MakeTree (
+  IN  INT32            NParm,
+  IN  UINT16  FreqParm[],
+  OUT UINT8   LenParm[ ],
+  OUT UINT16  CodeParm[]
+  );
+
+//
+//  Global Variables
+//
+STATIC UINT8  *mSrc, *mDst, *mSrcUpperLimit, *mDstUpperLimit;
+
+STATIC UINT8  *mLevel, *mText, *mChildCount, *mBuf, mCLen[NC], mPTLen[NPT], *mLen;
+STATIC INT16  mHeap[NC + 1];
+STATIC INT32  mRemainder, mMatchLen, mBitCount, mHeapSize, mN;
+STATIC UINT32 mBufSiz = 0, mOutputPos, mOutputMask, mSubBitBuf, mCrc;
+STATIC UINT32 mCompSize, mOrigSize;
+
+STATIC UINT16 *mFreq, *mSortPtr, mLenCnt[17], mLeft[2 * NC - 1], mRight[2 * NC - 1], mCrcTable[UINT8_MAX + 1],
+  mCFreq[2 * NC - 1], mCTable[4096], mCCode[NC], mPFreq[2 * NP - 1], mPTCode[NPT], mTFreq[2 * NT - 1];
+
+STATIC NODE   mPos, mMatchPos, mAvail, *mPosition, *mParent, *mPrev, *mNext = NULL;
+
+//
+// functions
+//
+EFI_STATUS
+TianoCompress (
+  IN      UINT8   *SrcBuffer,
+  IN      UINT32  SrcSize,
+  IN      UINT8   *DstBuffer,
+  IN OUT  UINT32  *DstSize
+  )
+/*++
+
+Routine Description:
+
+  The internal implementation of [Efi/Tiano]Compress().
+
+Arguments:
+
+  SrcBuffer   - The buffer storing the source data
+  SrcSize     - The size of source data
+  DstBuffer   - The buffer to store the compressed data
+  DstSize     - On input, the size of DstBuffer; On output,
+                the size of the actual compressed data.
+  Version     - The version of de/compression algorithm.
+                Version 1 for EFI 1.1 de/compression algorithm.
+                Version 2 for Tiano de/compression algorithm.
+
+Returns:
+
+  EFI_BUFFER_TOO_SMALL  - The DstBuffer is too small. In this case,
+                DstSize contains the size needed.
+  EFI_SUCCESS           - Compression is successful.
+  EFI_OUT_OF_RESOURCES  - No resource to complete function.
+  EFI_INVALID_PARAMETER - Parameter supplied is wrong.
+
+--*/
+{
+  EFI_STATUS  Status;
+
+  //
+  // Initializations
+  //
+  mBufSiz         = 0;
+  mBuf            = NULL;
+  mText           = NULL;
+  mLevel          = NULL;
+  mChildCount     = NULL;
+  mPosition       = NULL;
+  mParent         = NULL;
+  mPrev           = NULL;
+  mNext           = NULL;
+
+  mSrc            = SrcBuffer;
+  mSrcUpperLimit  = mSrc + SrcSize;
+  mDst            = DstBuffer;
+  mDstUpperLimit  = mDst +*DstSize;
+
+  PutDword (0L);
+  PutDword (0L);
+
+  MakeCrcTable ();
+
+  mOrigSize             = mCompSize = 0;
+  mCrc                  = INIT_CRC;
+
+  //
+  // Compress it
+  //
+  Status = Encode ();
+  if (EFI_ERROR (Status)) {
+    return EFI_OUT_OF_RESOURCES;
+  }
+  //
+  // Null terminate the compressed data
+  //
+  if (mDst < mDstUpperLimit) {
+    *mDst++ = 0;
+  }
+  //
+  // Fill in compressed size and original size
+  //
+  mDst = DstBuffer;
+  PutDword (mCompSize + 1);
+  PutDword (mOrigSize);
+
+  //
+  // Return
+  //
+  if (mCompSize + 1 + 8 > *DstSize) {
+    *DstSize = mCompSize + 1 + 8;
+    return EFI_BUFFER_TOO_SMALL;
+  } else {
+    *DstSize = mCompSize + 1 + 8;
+    return EFI_SUCCESS;
+  }
+
+}
+
+STATIC
+VOID
+PutDword (
+  IN UINT32 Data
+  )
+/*++
+
+Routine Description:
+
+  Put a dword to output stream
+  
+Arguments:
+
+  Data    - the dword to put
+  
+Returns: (VOID)
+  
+--*/
+{
+  if (mDst < mDstUpperLimit) {
+    *mDst++ = (UINT8) (((UINT8) (Data)) & 0xff);
+  }
+
+  if (mDst < mDstUpperLimit) {
+    *mDst++ = (UINT8) (((UINT8) (Data >> 0x08)) & 0xff);
+  }
+
+  if (mDst < mDstUpperLimit) {
+    *mDst++ = (UINT8) (((UINT8) (Data >> 0x10)) & 0xff);
+  }
+
+  if (mDst < mDstUpperLimit) {
+    *mDst++ = (UINT8) (((UINT8) (Data >> 0x18)) & 0xff);
+  }
+}
+
+STATIC
+EFI_STATUS
+AllocateMemory (
+  VOID
+  )
+/*++
+
+Routine Description:
+
+  Allocate memory spaces for data structures used in compression process
+  
+Argements: 
+  VOID
+
+Returns:
+
+  EFI_SUCCESS           - Memory is allocated successfully
+  EFI_OUT_OF_RESOURCES  - Allocation fails
+
+--*/
+{
+  UINT32  Index;
+
+  mText = malloc (WNDSIZ * 2 + MAXMATCH);
+  for (Index = 0; Index < WNDSIZ * 2 + MAXMATCH; Index++) {
+    mText[Index] = 0;
+  }
+
+  mLevel      = malloc ((WNDSIZ + UINT8_MAX + 1) * sizeof (*mLevel));
+  mChildCount = malloc ((WNDSIZ + UINT8_MAX + 1) * sizeof (*mChildCount));
+  mPosition   = malloc ((WNDSIZ + UINT8_MAX + 1) * sizeof (*mPosition));
+  mParent     = malloc (WNDSIZ * 2 * sizeof (*mParent));
+  mPrev       = malloc (WNDSIZ * 2 * sizeof (*mPrev));
+  mNext       = malloc ((MAX_HASH_VAL + 1) * sizeof (*mNext));
+
+  mBufSiz     = BLKSIZ;
+  mBuf        = malloc (mBufSiz);
+  while (mBuf == NULL) {
+    mBufSiz = (mBufSiz / 10U) * 9U;
+    if (mBufSiz < 4 * 1024U) {
+      return EFI_OUT_OF_RESOURCES;
+    }
+
+    mBuf = malloc (mBufSiz);
+  }
+
+  mBuf[0] = 0;
+
+  return EFI_SUCCESS;
+}
+
+VOID
+FreeMemory (
+  VOID
+  )
+/*++
+
+Routine Description:
+
+  Called when compression is completed to free memory previously allocated.
+  
+Arguments: (VOID)
+
+Returns: (VOID)
+
+--*/
+{
+  if (mText != NULL) {
+    free (mText);
+  }
+
+  if (mLevel != NULL) {
+    free (mLevel);
+  }
+
+  if (mChildCount != NULL) {
+    free (mChildCount);
+  }
+
+  if (mPosition != NULL) {
+    free (mPosition);
+  }
+
+  if (mParent != NULL) {
+    free (mParent);
+  }
+
+  if (mPrev != NULL) {
+    free (mPrev);
+  }
+
+  if (mNext != NULL) {
+    free (mNext);
+  }
+
+  if (mBuf != NULL) {
+    free (mBuf);
+  }
+
+  return ;
+}
+
+STATIC
+VOID
+InitSlide (
+  VOID
+  )
+/*++
+
+Routine Description:
+
+  Initialize String Info Log data structures
+  
+Arguments: (VOID)
+
+Returns: (VOID)
+
+--*/
+{
+  NODE  Index;
+
+  for (Index = WNDSIZ; Index <= WNDSIZ + UINT8_MAX; Index++) {
+    mLevel[Index]     = 1;
+    mPosition[Index]  = NIL;  /* sentinel */
+  }
+
+  for (Index = WNDSIZ; Index < WNDSIZ * 2; Index++) {
+    mParent[Index] = NIL;
+  }
+
+  mAvail = 1;
+  for (Index = 1; Index < WNDSIZ - 1; Index++) {
+    mNext[Index] = (NODE) (Index + 1);
+  }
+
+  mNext[WNDSIZ - 1] = NIL;
+  for (Index = WNDSIZ * 2; Index <= MAX_HASH_VAL; Index++) {
+    mNext[Index] = NIL;
+  }
+}
+
+STATIC
+NODE
+Child (
+  IN NODE  NodeQ,
+  IN UINT8 CharC
+  )
+/*++
+
+Routine Description:
+
+  Find child node given the parent node and the edge character
+  
+Arguments:
+
+  NodeQ       - the parent node
+  CharC       - the edge character
+  
+Returns:
+
+  The child node (NIL if not found)  
+  
+--*/
+{
+  NODE  NodeR;
+
+  NodeR = mNext[HASH (NodeQ, CharC)];
+  //
+  // sentinel
+  //
+  mParent[NIL] = NodeQ;
+  while (mParent[NodeR] != NodeQ) {
+    NodeR = mNext[NodeR];
+  }
+
+  return NodeR;
+}
+
+STATIC
+VOID
+MakeChild (
+  IN NODE  Parent,
+  IN UINT8 CharC,
+  IN NODE  Child
+  )
+/*++
+
+Routine Description:
+
+  Create a new child for a given parent node.
+  
+Arguments:
+
+  Parent       - the parent node
+  CharC   - the edge character
+  Child       - the child node
+  
+Returns: (VOID)
+
+--*/
+{
+  NODE  Node1;
+  NODE  Node2;
+
+  Node1           = (NODE) HASH (Parent, CharC);
+  Node2           = mNext[Node1];
+  mNext[Node1]    = Child;
+  mNext[Child]    = Node2;
+  mPrev[Node2]    = Child;
+  mPrev[Child]    = Node1;
+  mParent[Child]  = Parent;
+  mChildCount[Parent]++;
+}
+
+STATIC
+VOID
+Split (
+  NODE Old
+  )
+/*++
+
+Routine Description:
+
+  Split a node.
+  
+Arguments:
+
+  Old     - the node to split
+  
+Returns: (VOID)
+
+--*/
+{
+  NODE  New;
+  NODE  TempNode;
+
+  New               = mAvail;
+  mAvail            = mNext[New];
+  mChildCount[New]  = 0;
+  TempNode          = mPrev[Old];
+  mPrev[New]        = TempNode;
+  mNext[TempNode]   = New;
+  TempNode          = mNext[Old];
+  mNext[New]        = TempNode;
+  mPrev[TempNode]   = New;
+  mParent[New]      = mParent[Old];
+  mLevel[New]       = (UINT8) mMatchLen;
+  mPosition[New]    = mPos;
+  MakeChild (New, mText[mMatchPos + mMatchLen], Old);
+  MakeChild (New, mText[mPos + mMatchLen], mPos);
+}
+
+STATIC
+VOID
+InsertNode (
+  VOID
+  )
+/*++
+
+Routine Description:
+
+  Insert string info for current position into the String Info Log
+  
+Arguments: (VOID)
+
+Returns: (VOID)
+
+--*/
+{
+  NODE  NodeQ;
+  NODE  NodeR;
+  NODE  Index2;
+  NODE  NodeT;
+  UINT8 CharC;
+  UINT8 *t1;
+  UINT8 *t2;
+
+  if (mMatchLen >= 4) {
+    //
+    // We have just got a long match, the target tree
+    // can be located by MatchPos + 1. Travese the tree
+    // from bottom up to get to a proper starting point.
+    // The usage of PERC_FLAG ensures proper node deletion
+    // in DeleteNode() later.
+    //
+    mMatchLen--;
+    NodeR = (NODE) ((mMatchPos + 1) | WNDSIZ);
+    NodeQ = mParent[NodeR];
+    while (NodeQ == NIL) {
+      NodeR = mNext[NodeR];
+      NodeQ = mParent[NodeR];
+    }
+
+    while (mLevel[NodeQ] >= mMatchLen) {
+      NodeR = NodeQ;
+      NodeQ = mParent[NodeQ];
+    }
+
+    NodeT = NodeQ;
+    while (mPosition[NodeT] < 0) {
+      mPosition[NodeT]  = mPos;
+      NodeT             = mParent[NodeT];
+    }
+
+    if (NodeT < WNDSIZ) {
+      mPosition[NodeT] = (NODE) (mPos | (UINT32) PERC_FLAG);
+    }
+  } else {
+    //
+    // Locate the target tree
+    //
+    NodeQ = (NODE) (mText[mPos] + WNDSIZ);
+    CharC = mText[mPos + 1];
+    NodeR = Child (NodeQ, CharC);
+    if (NodeR == NIL) {
+      MakeChild (NodeQ, CharC, mPos);
+      mMatchLen = 1;
+      return ;
+    }
+
+    mMatchLen = 2;
+  }
+  //
+  // Traverse down the tree to find a match.
+  // Update Position value along the route.
+  // Node split or creation is involved.
+  //
+  for (;;) {
+    if (NodeR >= WNDSIZ) {
+      Index2    = MAXMATCH;
+      mMatchPos = NodeR;
+    } else {
+      Index2    = mLevel[NodeR];
+      mMatchPos = (NODE) (mPosition[NodeR] & (UINT32)~PERC_FLAG);
+    }
+
+    if (mMatchPos >= mPos) {
+      mMatchPos -= WNDSIZ;
+    }
+
+    t1  = &mText[mPos + mMatchLen];
+    t2  = &mText[mMatchPos + mMatchLen];
+    while (mMatchLen < Index2) {
+      if (*t1 != *t2) {
+        Split (NodeR);
+        return ;
+      }
+
+      mMatchLen++;
+      t1++;
+      t2++;
+    }
+
+    if (mMatchLen >= MAXMATCH) {
+      break;
+    }
+
+    mPosition[NodeR]  = mPos;
+    NodeQ             = NodeR;
+    NodeR             = Child (NodeQ, *t1);
+    if (NodeR == NIL) {
+      MakeChild (NodeQ, *t1, mPos);
+      return ;
+    }
+
+    mMatchLen++;
+  }
+
+  NodeT           = mPrev[NodeR];
+  mPrev[mPos]     = NodeT;
+  mNext[NodeT]    = mPos;
+  NodeT           = mNext[NodeR];
+  mNext[mPos]     = NodeT;
+  mPrev[NodeT]    = mPos;
+  mParent[mPos]   = NodeQ;
+  mParent[NodeR]  = NIL;
+
+  //
+  // Special usage of 'next'
+  //
+  mNext[NodeR] = mPos;
+
+}
+
+STATIC
+VOID
+DeleteNode (
+  VOID
+  )
+/*++
+
+Routine Description:
+
+  Delete outdated string info. (The Usage of PERC_FLAG
+  ensures a clean deletion)
+  
+Arguments: (VOID)
+
+Returns: (VOID)
+
+--*/
+{
+  NODE  NodeQ;
+  NODE  NodeR;
+  NODE  NodeS;
+  NODE  NodeT;
+  NODE  NodeU;
+
+  if (mParent[mPos] == NIL) {
+    return ;
+  }
+
+  NodeR         = mPrev[mPos];
+  NodeS         = mNext[mPos];
+  mNext[NodeR]  = NodeS;
+  mPrev[NodeS]  = NodeR;
+  NodeR         = mParent[mPos];
+  mParent[mPos] = NIL;
+  if (NodeR >= WNDSIZ) {
+    return ;
+  }
+
+  mChildCount[NodeR]--;
+  if (mChildCount[NodeR] > 1) {
+    return ;
+  }
+
+  NodeT = (NODE) (mPosition[NodeR] & (UINT32)~PERC_FLAG);
+  if (NodeT >= mPos) {
+    NodeT -= WNDSIZ;
+  }
+
+  NodeS = NodeT;
+  NodeQ = mParent[NodeR];
+  NodeU = mPosition[NodeQ];
+  while (NodeU & (UINT32) PERC_FLAG) {
+    NodeU &= (UINT32)~PERC_FLAG;
+    if (NodeU >= mPos) {
+      NodeU -= WNDSIZ;
+    }
+
+    if (NodeU > NodeS) {
+      NodeS = NodeU;
+    }
+
+    mPosition[NodeQ]  = (NODE) (NodeS | WNDSIZ);
+    NodeQ             = mParent[NodeQ];
+    NodeU             = mPosition[NodeQ];
+  }
+
+  if (NodeQ < WNDSIZ) {
+    if (NodeU >= mPos) {
+      NodeU -= WNDSIZ;
+    }
+
+    if (NodeU > NodeS) {
+      NodeS = NodeU;
+    }
+
+    mPosition[NodeQ] = (NODE) (NodeS | WNDSIZ | (UINT32) PERC_FLAG);
+  }
+
+  NodeS           = Child (NodeR, mText[NodeT + mLevel[NodeR]]);
+  NodeT           = mPrev[NodeS];
+  NodeU           = mNext[NodeS];
+  mNext[NodeT]    = NodeU;
+  mPrev[NodeU]    = NodeT;
+  NodeT           = mPrev[NodeR];
+  mNext[NodeT]    = NodeS;
+  mPrev[NodeS]    = NodeT;
+  NodeT           = mNext[NodeR];
+  mPrev[NodeT]    = NodeS;
+  mNext[NodeS]    = NodeT;
+  mParent[NodeS]  = mParent[NodeR];
+  mParent[NodeR]  = NIL;
+  mNext[NodeR]    = mAvail;
+  mAvail          = NodeR;
+}
+
+STATIC
+VOID
+GetNextMatch (
+  VOID
+  )
+/*++
+
+Routine Description:
+
+  Advance the current position (read in new data if needed).
+  Delete outdated string info. Find a match string for current position.
+
+Arguments: (VOID)
+
+Returns: (VOID)
+
+--*/
+{
+  INT32 Number;
+
+  mRemainder--;
+  mPos++;
+  if (mPos == WNDSIZ * 2) {
+    memmove (&mText[0], &mText[WNDSIZ], WNDSIZ + MAXMATCH);
+    Number = FreadCrc (&mText[WNDSIZ + MAXMATCH], WNDSIZ);
+    mRemainder += Number;
+    mPos = WNDSIZ;
+  }
+
+  DeleteNode ();
+  InsertNode ();
+}
+
+STATIC
+EFI_STATUS
+Encode (
+  VOID
+  )
+/*++
+
+Routine Description:
+
+  The main controlling routine for compression process.
+
+Arguments: (VOID)
+
+Returns:
+  
+  EFI_SUCCESS           - The compression is successful
+  EFI_OUT_0F_RESOURCES  - Not enough memory for compression process
+
+--*/
+{
+  EFI_STATUS  Status;
+  INT32       LastMatchLen;
+  NODE        LastMatchPos;
+
+  Status = AllocateMemory ();
+  if (EFI_ERROR (Status)) {
+    FreeMemory ();
+    return Status;
+  }
+
+  InitSlide ();
+
+  HufEncodeStart ();
+
+  mRemainder  = FreadCrc (&mText[WNDSIZ], WNDSIZ + MAXMATCH);
+
+  mMatchLen   = 0;
+  mPos        = WNDSIZ;
+  InsertNode ();
+  if (mMatchLen > mRemainder) {
+    mMatchLen = mRemainder;
+  }
+
+  while (mRemainder > 0) {
+    LastMatchLen  = mMatchLen;
+    LastMatchPos  = mMatchPos;
+    GetNextMatch ();
+    if (mMatchLen > mRemainder) {
+      mMatchLen = mRemainder;
+    }
+
+    if (mMatchLen > LastMatchLen || LastMatchLen < THRESHOLD) {
+      //
+      // Not enough benefits are gained by outputting a pointer,
+      // so just output the original character
+      //
+      Output (mText[mPos - 1], 0);
+
+    } else {
+
+      if (LastMatchLen == THRESHOLD) {
+        if (((mPos - LastMatchPos - 2) & (WNDSIZ - 1)) > (1U << 11)) {
+          Output (mText[mPos - 1], 0);
+          continue;
+        }
+      }
+      //
+      // Outputting a pointer is beneficial enough, do it.
+      //
+      Output (
+        LastMatchLen + (UINT8_MAX + 1 - THRESHOLD),
+        (mPos - LastMatchPos - 2) & (WNDSIZ - 1)
+        );
+      LastMatchLen--;
+      while (LastMatchLen > 0) {
+        GetNextMatch ();
+        LastMatchLen--;
+      }
+
+      if (mMatchLen > mRemainder) {
+        mMatchLen = mRemainder;
+      }
+    }
+  }
+
+  HufEncodeEnd ();
+  FreeMemory ();
+  return EFI_SUCCESS;
+}
+
+STATIC
+VOID
+CountTFreq (
+  VOID
+  )
+/*++
+
+Routine Description:
+
+  Count the frequencies for the Extra Set
+  
+Arguments: (VOID)
+
+Returns: (VOID)
+
+--*/
+{
+  INT32 Index;
+  INT32 Index3;
+  INT32 Number;
+  INT32 Count;
+
+  for (Index = 0; Index < NT; Index++) {
+    mTFreq[Index] = 0;
+  }
+
+  Number = NC;
+  while (Number > 0 && mCLen[Number - 1] == 0) {
+    Number--;
+  }
+
+  Index = 0;
+  while (Index < Number) {
+    Index3 = mCLen[Index++];
+    if (Index3 == 0) {
+      Count = 1;
+      while (Index < Number && mCLen[Index] == 0) {
+        Index++;
+        Count++;
+      }
+
+      if (Count <= 2) {
+        mTFreq[0] = (UINT16) (mTFreq[0] + Count);
+      } else if (Count <= 18) {
+        mTFreq[1]++;
+      } else if (Count == 19) {
+        mTFreq[0]++;
+        mTFreq[1]++;
+      } else {
+        mTFreq[2]++;
+      }
+    } else {
+      mTFreq[Index3 + 2]++;
+    }
+  }
+}
+
+STATIC
+VOID
+WritePTLen (
+  IN INT32 Number,
+  IN INT32 nbit,
+  IN INT32 Special
+  )
+/*++
+
+Routine Description:
+
+  Outputs the code length array for the Extra Set or the Position Set.
+  
+Arguments:
+
+  Number       - the number of symbols
+  nbit    - the number of bits needed to represent 'n'
+  Special - the special symbol that needs to be take care of
+  
+Returns: (VOID)
+
+--*/
+{
+  INT32 Index;
+  INT32 Index3;
+
+  while (Number > 0 && mPTLen[Number - 1] == 0) {
+    Number--;
+  }
+
+  PutBits (nbit, Number);
+  Index = 0;
+  while (Index < Number) {
+    Index3 = mPTLen[Index++];
+    if (Index3 <= 6) {
+      PutBits (3, Index3);
+    } else {
+      PutBits (Index3 - 3, (1U << (Index3 - 3)) - 2);
+    }
+
+    if (Index == Special) {
+      while (Index < 6 && mPTLen[Index] == 0) {
+        Index++;
+      }
+
+      PutBits (2, (Index - 3) & 3);
+    }
+  }
+}
+
+STATIC
+VOID
+WriteCLen (
+  VOID
+  )
+/*++
+
+Routine Description:
+
+  Outputs the code length array for Char&Length Set
+  
+Arguments: (VOID)
+
+Returns: (VOID)
+
+--*/
+{
+  INT32 Index;
+  INT32 Index3;
+  INT32 Number;
+  INT32 Count;
+
+  Number = NC;
+  while (Number > 0 && mCLen[Number - 1] == 0) {
+    Number--;
+  }
+
+  PutBits (CBIT, Number);
+  Index = 0;
+  while (Index < Number) {
+    Index3 = mCLen[Index++];
+    if (Index3 == 0) {
+      Count = 1;
+      while (Index < Number && mCLen[Index] == 0) {
+        Index++;
+        Count++;
+      }
+
+      if (Count <= 2) {
+        for (Index3 = 0; Index3 < Count; Index3++) {
+          PutBits (mPTLen[0], mPTCode[0]);
+        }
+      } else if (Count <= 18) {
+        PutBits (mPTLen[1], mPTCode[1]);
+        PutBits (4, Count - 3);
+      } else if (Count == 19) {
+        PutBits (mPTLen[0], mPTCode[0]);
+        PutBits (mPTLen[1], mPTCode[1]);
+        PutBits (4, 15);
+      } else {
+        PutBits (mPTLen[2], mPTCode[2]);
+        PutBits (CBIT, Count - 20);
+      }
+    } else {
+      PutBits (mPTLen[Index3 + 2], mPTCode[Index3 + 2]);
+    }
+  }
+}
+
+STATIC
+VOID
+EncodeC (
+  IN INT32 Value
+  )
+{
+  PutBits (mCLen[Value], mCCode[Value]);
+}
+
+STATIC
+VOID
+EncodeP (
+  IN UINT32 Value
+  )
+{
+  UINT32  Index;
+  UINT32  NodeQ;
+
+  Index = 0;
+  NodeQ = Value;
+  while (NodeQ) {
+    NodeQ >>= 1;
+    Index++;
+  }
+
+  PutBits (mPTLen[Index], mPTCode[Index]);
+  if (Index > 1) {
+    PutBits (Index - 1, Value & (0xFFFFFFFFU >> (32 - Index + 1)));
+  }
+}
+
+STATIC
+VOID
+SendBlock (
+  VOID
+  )
+/*++
+
+Routine Description:
+
+  Huffman code the block and output it.
+  
+Arguments: 
+  (VOID)
+
+Returns: 
+  (VOID)
+
+--*/
+{
+  UINT32  Index;
+  UINT32  Index2;
+  UINT32  Index3;
+  UINT32  Flags;
+  UINT32  Root;
+  UINT32  Pos;
+  UINT32  Size;
+  Flags = 0;
+
+  Root  = MakeTree (NC, mCFreq, mCLen, mCCode);
+  Size  = mCFreq[Root];
+  PutBits (16, Size);
+  if (Root >= NC) {
+    CountTFreq ();
+    Root = MakeTree (NT, mTFreq, mPTLen, mPTCode);
+    if (Root >= NT) {
+      WritePTLen (NT, TBIT, 3);
+    } else {
+      PutBits (TBIT, 0);
+      PutBits (TBIT, Root);
+    }
+
+    WriteCLen ();
+  } else {
+    PutBits (TBIT, 0);
+    PutBits (TBIT, 0);
+    PutBits (CBIT, 0);
+    PutBits (CBIT, Root);
+  }
+
+  Root = MakeTree (NP, mPFreq, mPTLen, mPTCode);
+  if (Root >= NP) {
+    WritePTLen (NP, PBIT, -1);
+  } else {
+    PutBits (PBIT, 0);
+    PutBits (PBIT, Root);
+  }
+
+  Pos = 0;
+  for (Index = 0; Index < Size; Index++) {
+    if (Index % UINT8_BIT == 0) {
+      Flags = mBuf[Pos++];
+    } else {
+      Flags <<= 1;
+    }
+
+    if (Flags & (1U << (UINT8_BIT - 1))) {
+      EncodeC (mBuf[Pos++] + (1U << UINT8_BIT));
+      Index3 = mBuf[Pos++];
+      for (Index2 = 0; Index2 < 3; Index2++) {
+        Index3 <<= UINT8_BIT;
+        Index3 += mBuf[Pos++];
+      }
+
+      EncodeP (Index3);
+    } else {
+      EncodeC (mBuf[Pos++]);
+    }
+  }
+
+  for (Index = 0; Index < NC; Index++) {
+    mCFreq[Index] = 0;
+  }
+
+  for (Index = 0; Index < NP; Index++) {
+    mPFreq[Index] = 0;
+  }
+}
+
+STATIC
+VOID
+Output (
+  IN UINT32 CharC,
+  IN UINT32 Pos
+  )
+/*++
+
+Routine Description:
+
+  Outputs an Original Character or a Pointer
+
+Arguments:
+
+  CharC     - The original character or the 'String Length' element of a Pointer
+  Pos     - The 'Position' field of a Pointer
+
+Returns: (VOID)
+
+--*/
+{
+  STATIC UINT32 CPos;
+
+  if ((mOutputMask >>= 1) == 0) {
+    mOutputMask = 1U << (UINT8_BIT - 1);
+    //
+    // Check the buffer overflow per outputing UINT8_BIT symbols
+    // which is an Original Character or a Pointer. The biggest
+    // symbol is a Pointer which occupies 5 bytes.
+    //
+    if (mOutputPos >= mBufSiz - 5 * UINT8_BIT) {
+      SendBlock ();
+      mOutputPos = 0;
+    }
+
+    CPos        = mOutputPos++;
+    mBuf[CPos]  = 0;
+  }
+
+  mBuf[mOutputPos++] = (UINT8) CharC;
+  mCFreq[CharC]++;
+  if (CharC >= (1U << UINT8_BIT)) {
+    mBuf[CPos] |= mOutputMask;
+    mBuf[mOutputPos++]  = (UINT8) (Pos >> 24);
+    mBuf[mOutputPos++]  = (UINT8) (Pos >> 16);
+    mBuf[mOutputPos++]  = (UINT8) (Pos >> (UINT8_BIT));
+    mBuf[mOutputPos++]  = (UINT8) Pos;
+    CharC               = 0;
+    while (Pos) {
+      Pos >>= 1;
+      CharC++;
+    }
+
+    mPFreq[CharC]++;
+  }
+}
+
+STATIC
+VOID
+HufEncodeStart (
+  VOID
+  )
+{
+  INT32 Index;
+
+  for (Index = 0; Index < NC; Index++) {
+    mCFreq[Index] = 0;
+  }
+
+  for (Index = 0; Index < NP; Index++) {
+    mPFreq[Index] = 0;
+  }
+
+  mOutputPos = mOutputMask = 0;
+  InitPutBits ();
+  return ;
+}
+
+STATIC
+VOID
+HufEncodeEnd (
+  VOID
+  )
+{
+  SendBlock ();
+
+  //
+  // Flush remaining bits
+  //
+  PutBits (UINT8_BIT - 1, 0);
+
+  return ;
+}
+
+STATIC
+VOID
+MakeCrcTable (
+  VOID
+  )
+{
+  UINT32  Index;
+  UINT32  Index2;
+  UINT32  Temp;
+
+  for (Index = 0; Index <= UINT8_MAX; Index++) {
+    Temp = Index;
+    for (Index2 = 0; Index2 < UINT8_BIT; Index2++) {
+      if (Temp & 1) {
+        Temp = (Temp >> 1) ^ CRCPOLY;
+      } else {
+        Temp >>= 1;
+      }
+    }
+
+    mCrcTable[Index] = (UINT16) Temp;
+  }
+}
+
+STATIC
+VOID
+PutBits (
+  IN INT32  Number,
+  IN UINT32 Value
+  )
+/*++
+
+Routine Description:
+
+  Outputs rightmost n bits of x
+
+Arguments:
+
+  Number   - the rightmost n bits of the data is used
+  x   - the data 
+
+Returns: (VOID)
+
+--*/
+{
+  UINT8 Temp;
+
+  while (Number >= mBitCount) {
+    //
+    // Number -= mBitCount should never equal to 32
+    //
+    Temp = (UINT8) (mSubBitBuf | (Value >> (Number -= mBitCount)));
+    if (mDst < mDstUpperLimit) {
+      *mDst++ = Temp;
+    }
+
+    mCompSize++;
+    mSubBitBuf  = 0;
+    mBitCount   = UINT8_BIT;
+  }
+
+  mSubBitBuf |= Value << (mBitCount -= Number);
+}
+
+STATIC
+INT32
+FreadCrc (
+  OUT UINT8 *Pointer,
+  IN  INT32 Number
+  )
+/*++
+
+Routine Description:
+
+  Read in source data
+  
+Arguments:
+
+  Pointer   - the buffer to hold the data
+  Number   - number of bytes to read
+
+Returns:
+
+  number of bytes actually read
+  
+--*/
+{
+  INT32 Index;
+
+  for (Index = 0; mSrc < mSrcUpperLimit && Index < Number; Index++) {
+    *Pointer++ = *mSrc++;
+  }
+
+  Number = Index;
+
+  Pointer -= Number;
+  mOrigSize += Number;
+  Index--;
+  while (Index >= 0) {
+    UPDATE_CRC (*Pointer++);
+    Index--;
+  }
+
+  return Number;
+}
+
+STATIC
+VOID
+InitPutBits (
+  VOID
+  )
+{
+  mBitCount   = UINT8_BIT;
+  mSubBitBuf  = 0;
+}
+
+STATIC
+VOID
+CountLen (
+  IN INT32 Index
+  )
+/*++
+
+Routine Description:
+
+  Count the number of each code length for a Huffman tree.
+  
+Arguments:
+
+  Index   - the top node
+  
+Returns: (VOID)
+
+--*/
+{
+  STATIC INT32  Depth = 0;
+
+  if (Index < mN) {
+    mLenCnt[(Depth < 16) ? Depth : 16]++;
+  } else {
+    Depth++;
+    CountLen (mLeft[Index]);
+    CountLen (mRight[Index]);
+    Depth--;
+  }
+}
+
+STATIC
+VOID
+MakeLen (
+  IN INT32 Root
+  )
+/*++
+
+Routine Description:
+
+  Create code length array for a Huffman tree
+  
+Arguments:
+
+  Root   - the root of the tree
+  
+Returns:
+
+  VOID
+
+--*/
+{
+  INT32   Index;
+  INT32   Index3;
+  UINT32  Cum;
+
+  for (Index = 0; Index <= 16; Index++) {
+    mLenCnt[Index] = 0;
+  }
+
+  CountLen (Root);
+
+  //
+  // Adjust the length count array so that
+  // no code will be generated longer than its designated length
+  //
+  Cum = 0;
+  for (Index = 16; Index > 0; Index--) {
+    Cum += mLenCnt[Index] << (16 - Index);
+  }
+
+  while (Cum != (1U << 16)) {
+    mLenCnt[16]--;
+    for (Index = 15; Index > 0; Index--) {
+      if (mLenCnt[Index] != 0) {
+        mLenCnt[Index]--;
+        mLenCnt[Index + 1] += 2;
+        break;
+      }
+    }
+
+    Cum--;
+  }
+
+  for (Index = 16; Index > 0; Index--) {
+    Index3 = mLenCnt[Index];
+    Index3--;
+    while (Index3 >= 0) {
+      mLen[*mSortPtr++] = (UINT8) Index;
+      Index3--;
+    }
+  }
+}
+
+STATIC
+VOID
+DownHeap (
+  IN INT32 Index
+  )
+{
+  INT32 Index2;
+  INT32 Index3;
+
+  //
+  // priority queue: send Index-th entry down heap
+  //
+  Index3  = mHeap[Index];
+  Index2  = 2 * Index;
+  while (Index2 <= mHeapSize) {
+    if (Index2 < mHeapSize && mFreq[mHeap[Index2]] > mFreq[mHeap[Index2 + 1]]) {
+      Index2++;
+    }
+
+    if (mFreq[Index3] <= mFreq[mHeap[Index2]]) {
+      break;
+    }
+
+    mHeap[Index]  = mHeap[Index2];
+    Index         = Index2;
+    Index2        = 2 * Index;
+  }
+
+  mHeap[Index] = (INT16) Index3;
+}
+
+STATIC
+VOID
+MakeCode (
+  IN  INT32       Number,
+  IN  UINT8 Len[  ],
+  OUT UINT16 Code[]
+  )
+/*++
+
+Routine Description:
+
+  Assign code to each symbol based on the code length array
+  
+Arguments:
+
+  Number     - number of symbols
+  Len   - the code length array
+  Code  - stores codes for each symbol
+
+Returns: (VOID)
+
+--*/
+{
+  INT32   Index;
+  UINT16  Start[18];
+
+  Start[1] = 0;
+  for (Index = 1; Index <= 16; Index++) {
+    Start[Index + 1] = (UINT16) ((Start[Index] + mLenCnt[Index]) << 1);
+  }
+
+  for (Index = 0; Index < Number; Index++) {
+    Code[Index] = Start[Len[Index]]++;
+  }
+}
+
+STATIC
+INT32
+MakeTree (
+  IN  INT32            NParm,
+  IN  UINT16  FreqParm[],
+  OUT UINT8   LenParm[ ],
+  OUT UINT16  CodeParm[]
+  )
+/*++
+
+Routine Description:
+
+  Generates Huffman codes given a frequency distribution of symbols
+  
+Arguments:
+
+  NParm    - number of symbols
+  FreqParm - frequency of each symbol
+  LenParm  - code length for each symbol
+  CodeParm - code for each symbol
+  
+Returns:
+
+  Root of the Huffman tree.
+  
+--*/
+{
+  INT32 Index;
+  INT32 Index2;
+  INT32 Index3;
+  INT32 Avail;
+
+  //
+  // make tree, calculate len[], return root
+  //
+  mN        = NParm;
+  mFreq     = FreqParm;
+  mLen      = LenParm;
+  Avail     = mN;
+  mHeapSize = 0;
+  mHeap[1]  = 0;
+  for (Index = 0; Index < mN; Index++) {
+    mLen[Index] = 0;
+    if (mFreq[Index]) {
+      mHeapSize++;
+      mHeap[mHeapSize] = (INT16) Index;
+    }
+  }
+
+  if (mHeapSize < 2) {
+    CodeParm[mHeap[1]] = 0;
+    return mHeap[1];
+  }
+
+  for (Index = mHeapSize / 2; Index >= 1; Index--) {
+    //
+    // make priority queue
+    //
+    DownHeap (Index);
+  }
+
+  mSortPtr = CodeParm;
+  do {
+    Index = mHeap[1];
+    if (Index < mN) {
+      *mSortPtr++ = (UINT16) Index;
+    }
+
+    mHeap[1] = mHeap[mHeapSize--];
+    DownHeap (1);
+    Index2 = mHeap[1];
+    if (Index2 < mN) {
+      *mSortPtr++ = (UINT16) Index2;
+    }
+
+    Index3        = Avail++;
+    mFreq[Index3] = (UINT16) (mFreq[Index] + mFreq[Index2]);
+    mHeap[1]      = (INT16) Index3;
+    DownHeap (1);
+    mLeft[Index3]   = (UINT16) Index;
+    mRight[Index3]  = (UINT16) Index2;
+  } while (mHeapSize > 1);
+
+  mSortPtr = CodeParm;
+  MakeLen (Index3);
+  MakeCode (NParm, LenParm, CodeParm);
+
+  //
+  // return root
+  //
+  return Index3;
+}
-- 
cgit v1.2.3