diff options
| author | kx <kx@radix.pro> | 2024-06-04 06:43:08 +0300 |
|---|---|---|
| committer | kx <kx@radix.pro> | 2024-06-04 06:43:08 +0300 |
| commit | 7e2ccccace24636f29ddc210b94606abd4c7e42b (patch) | |
| tree | 545d43ea12671048956cafeb12303e84d601e571 /ShellPkg/Library/UefiShellDebug1CommandsLib/Compress.c | |
| parent | 27b044605cd5f6b33a3d231576003850b3fe305b (diff) | |
| download | edk2-trunk.tar.xz | |
Renormalized end-of-lines from master@27b044605cd5f6b33a3d231576003850b3fe305btrunk
Diffstat (limited to 'ShellPkg/Library/UefiShellDebug1CommandsLib/Compress.c')
| -rw-r--r-- | ShellPkg/Library/UefiShellDebug1CommandsLib/Compress.c | 2782 |
1 files changed, 1391 insertions, 1391 deletions
diff --git a/ShellPkg/Library/UefiShellDebug1CommandsLib/Compress.c b/ShellPkg/Library/UefiShellDebug1CommandsLib/Compress.c index 3dea3c2f2f..5989b3d41e 100644 --- a/ShellPkg/Library/UefiShellDebug1CommandsLib/Compress.c +++ b/ShellPkg/Library/UefiShellDebug1CommandsLib/Compress.c @@ -1,1391 +1,1391 @@ -/** @file
- Main file for compression routine.
-
- 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.
-
- Copyright (c) 2007 - 2018, Intel Corporation. All rights reserved.<BR>
- SPDX-License-Identifier: BSD-2-Clause-Patent
-
-**/
-#include <Uefi.h>
-#include <Library/MemoryAllocationLib.h>
-#include <Library/BaseMemoryLib.h>
-#include <Library/DebugLib.h>
-#include <Library/ShellLib.h>
-
-#include "Compress.h"
-
-//
-// Macro Definitions
-//
-typedef INT16 NODE;
-#define UINT8_MAX 0xff
-#define UINT8_BIT 8
-#define THRESHOLD 3
-#define INIT_CRC 0
-#define WNDBIT 13
-#define WNDSIZ (1U << WNDBIT)
-#define MAXMATCH 256
-#define BLKSIZ (1U << 14) // 16 * 1024U
-#define PERC_FLAG 0x8000U
-#define CODE_BIT 16
-#define NIL 0
-#define MAX_HASH_VAL (3 * WNDSIZ + (WNDSIZ / 512 + 1) * UINT8_MAX)
-#define HASH(LoopVar7, LoopVar5) ((LoopVar7) + ((LoopVar5) << (WNDBIT - 9)) + WNDSIZ * 2)
-#define CRCPOLY 0xA001
-#define UPDATE_CRC(LoopVar5) mCrc = mCrcTable[(mCrc ^ (LoopVar5)) & 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 4
-#define NT (CODE_BIT + 3)
-#define TBIT 5
-#if NT > NP
-#define NPT NT
-#else
-#define NPT NP
-#endif
-//
-// Function Prototypes
-//
-
-/**
- Put a dword to output stream
-
- @param[in] Data The dword to put.
-**/
-VOID
-PutDword (
- IN UINT32 Data
- );
-
-//
-// Global Variables
-//
-STATIC UINT8 *mSrc;
-STATIC UINT8 *mDst;
-STATIC UINT8 *mSrcUpperLimit;
-STATIC UINT8 *mDstUpperLimit;
-
-STATIC UINT8 *mLevel;
-STATIC UINT8 *mText;
-STATIC UINT8 *mChildCount;
-STATIC UINT8 *mBuf;
-STATIC UINT8 mCLen[NC];
-STATIC UINT8 mPTLen[NPT];
-STATIC UINT8 *mLen;
-STATIC INT16 mHeap[NC + 1];
-STATIC INT32 mRemainder;
-STATIC INT32 mMatchLen;
-STATIC INT32 mBitCount;
-STATIC INT32 mHeapSize;
-STATIC INT32 mTempInt32;
-STATIC UINT32 mBufSiz = 0;
-STATIC UINT32 mOutputPos;
-STATIC UINT32 mOutputMask;
-STATIC UINT32 mSubBitBuf;
-STATIC UINT32 mCrc;
-STATIC UINT32 mCompSize;
-STATIC UINT32 mOrigSize;
-
-STATIC UINT16 *mFreq;
-STATIC UINT16 *mSortPtr;
-STATIC UINT16 mLenCnt[17];
-STATIC UINT16 mLeft[2 * NC - 1];
-STATIC UINT16 mRight[2 * NC - 1];
-STATIC UINT16 mCrcTable[UINT8_MAX + 1];
-STATIC UINT16 mCFreq[2 * NC - 1];
-STATIC UINT16 mCCode[NC];
-STATIC UINT16 mPFreq[2 * NP - 1];
-STATIC UINT16 mPTCode[NPT];
-STATIC UINT16 mTFreq[2 * NT - 1];
-
-STATIC NODE mPos;
-STATIC NODE mMatchPos;
-STATIC NODE mAvail;
-STATIC NODE *mPosition;
-STATIC NODE *mParent;
-STATIC NODE *mPrev;
-STATIC NODE *mNext = NULL;
-INT32 mHuffmanDepth = 0;
-
-/**
- Make a CRC table.
-
-**/
-VOID
-MakeCrcTable (
- VOID
- )
-{
- UINT32 LoopVar1;
-
- UINT32 LoopVar2;
-
- UINT32 LoopVar4;
-
- for (LoopVar1 = 0; LoopVar1 <= UINT8_MAX; LoopVar1++) {
- LoopVar4 = LoopVar1;
- for (LoopVar2 = 0; LoopVar2 < UINT8_BIT; LoopVar2++) {
- if ((LoopVar4 & 1) != 0) {
- LoopVar4 = (LoopVar4 >> 1) ^ CRCPOLY;
- } else {
- LoopVar4 >>= 1;
- }
- }
-
- mCrcTable[LoopVar1] = (UINT16)LoopVar4;
- }
-}
-
-/**
- Put a dword to output stream
-
- @param[in] Data The dword to put.
-**/
-VOID
-PutDword (
- IN UINT32 Data
- )
-{
- 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);
- }
-}
-
-/**
- Allocate memory spaces for data structures used in compression process.
-
- @retval EFI_SUCCESS Memory was allocated successfully.
- @retval EFI_OUT_OF_RESOURCES A memory allocation failed.
-**/
-EFI_STATUS
-AllocateMemory (
- VOID
- )
-{
- mText = AllocateZeroPool (WNDSIZ * 2 + MAXMATCH);
- mLevel = AllocateZeroPool ((WNDSIZ + UINT8_MAX + 1) * sizeof (*mLevel));
- mChildCount = AllocateZeroPool ((WNDSIZ + UINT8_MAX + 1) * sizeof (*mChildCount));
- mPosition = AllocateZeroPool ((WNDSIZ + UINT8_MAX + 1) * sizeof (*mPosition));
- mParent = AllocateZeroPool (WNDSIZ * 2 * sizeof (*mParent));
- mPrev = AllocateZeroPool (WNDSIZ * 2 * sizeof (*mPrev));
- mNext = AllocateZeroPool ((MAX_HASH_VAL + 1) * sizeof (*mNext));
-
- mBufSiz = BLKSIZ;
- mBuf = AllocateZeroPool (mBufSiz);
- while (mBuf == NULL) {
- mBufSiz = (mBufSiz / 10U) * 9U;
- if (mBufSiz < 4 * 1024U) {
- return EFI_OUT_OF_RESOURCES;
- }
-
- mBuf = AllocateZeroPool (mBufSiz);
- }
-
- mBuf[0] = 0;
-
- return EFI_SUCCESS;
-}
-
-/**
- Called when compression is completed to free memory previously allocated.
-
-**/
-VOID
-FreeMemory (
- VOID
- )
-{
- SHELL_FREE_NON_NULL (mText);
- SHELL_FREE_NON_NULL (mLevel);
- SHELL_FREE_NON_NULL (mChildCount);
- SHELL_FREE_NON_NULL (mPosition);
- SHELL_FREE_NON_NULL (mParent);
- SHELL_FREE_NON_NULL (mPrev);
- SHELL_FREE_NON_NULL (mNext);
- SHELL_FREE_NON_NULL (mBuf);
-}
-
-/**
- Initialize String Info Log data structures.
-**/
-VOID
-InitSlide (
- VOID
- )
-{
- NODE LoopVar1;
-
- SetMem (mLevel + WNDSIZ, (UINT8_MAX + 1) * sizeof (UINT8), 1);
- SetMem (mPosition + WNDSIZ, (UINT8_MAX + 1) * sizeof (NODE), 0);
-
- SetMem (mParent + WNDSIZ, WNDSIZ * sizeof (NODE), 0);
-
- mAvail = 1;
- for (LoopVar1 = 1; LoopVar1 < WNDSIZ - 1; LoopVar1++) {
- mNext[LoopVar1] = (NODE)(LoopVar1 + 1);
- }
-
- mNext[WNDSIZ - 1] = NIL;
- SetMem (mNext + WNDSIZ * 2, (MAX_HASH_VAL - WNDSIZ * 2 + 1) * sizeof (NODE), 0);
-}
-
-/**
- Find child node given the parent node and the edge character
-
- @param[in] LoopVar6 The parent node.
- @param[in] LoopVar5 The edge character.
-
- @return The child node.
- @retval NIL(Zero) No child could be found.
-
-**/
-NODE
-Child (
- IN NODE LoopVar6,
- IN UINT8 LoopVar5
- )
-{
- NODE LoopVar4;
-
- LoopVar4 = mNext[HASH (LoopVar6, LoopVar5)];
- mParent[NIL] = LoopVar6; /* sentinel */
- while (mParent[LoopVar4] != LoopVar6) {
- LoopVar4 = mNext[LoopVar4];
- }
-
- return LoopVar4;
-}
-
-/**
- Create a new child for a given parent node.
-
- @param[in] LoopVar6 The parent node.
- @param[in] LoopVar5 The edge character.
- @param[in] LoopVar4 The child node.
-**/
-VOID
-MakeChild (
- IN NODE LoopVar6,
- IN UINT8 LoopVar5,
- IN NODE LoopVar4
- )
-{
- NODE LoopVar12;
-
- NODE LoopVar10;
-
- LoopVar12 = (NODE)HASH (LoopVar6, LoopVar5);
- LoopVar10 = mNext[LoopVar12];
- mNext[LoopVar12] = LoopVar4;
- mNext[LoopVar4] = LoopVar10;
- mPrev[LoopVar10] = LoopVar4;
- mPrev[LoopVar4] = LoopVar12;
- mParent[LoopVar4] = LoopVar6;
- mChildCount[LoopVar6]++;
-}
-
-/**
- Split a node.
-
- @param[in] Old The node to split.
-**/
-VOID
-Split (
- IN NODE Old
- )
-{
- NODE New;
-
- NODE LoopVar10;
-
- New = mAvail;
- mAvail = mNext[New];
- mChildCount[New] = 0;
- LoopVar10 = mPrev[Old];
- mPrev[New] = LoopVar10;
- mNext[LoopVar10] = New;
- LoopVar10 = mNext[Old];
- mNext[New] = LoopVar10;
- mPrev[LoopVar10] = New;
- mParent[New] = mParent[Old];
- mLevel[New] = (UINT8)mMatchLen;
- mPosition[New] = mPos;
- MakeChild (New, mText[mMatchPos + mMatchLen], Old);
- MakeChild (New, mText[mPos + mMatchLen], mPos);
-}
-
-/**
- Insert string info for current position into the String Info Log.
-
-**/
-VOID
-InsertNode (
- VOID
- )
-{
- NODE LoopVar6;
-
- NODE LoopVar4;
-
- NODE LoopVar2;
-
- NODE LoopVar10;
- UINT8 LoopVar5;
- UINT8 *TempString3;
- UINT8 *TempString2;
-
- 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--;
- LoopVar4 = (NODE)((mMatchPos + 1) | WNDSIZ);
- LoopVar6 = mParent[LoopVar4];
- while (LoopVar6 == NIL) {
- LoopVar4 = mNext[LoopVar4];
- LoopVar6 = mParent[LoopVar4];
- }
-
- while (mLevel[LoopVar6] >= mMatchLen) {
- LoopVar4 = LoopVar6;
- LoopVar6 = mParent[LoopVar6];
- }
-
- LoopVar10 = LoopVar6;
- while (mPosition[LoopVar10] < 0) {
- mPosition[LoopVar10] = mPos;
- LoopVar10 = mParent[LoopVar10];
- }
-
- if (LoopVar10 < WNDSIZ) {
- mPosition[LoopVar10] = (NODE)(mPos | PERC_FLAG);
- }
- } else {
- //
- // Locate the target tree
- //
- LoopVar6 = (NODE)(mText[mPos] + WNDSIZ);
- LoopVar5 = mText[mPos + 1];
- LoopVar4 = Child (LoopVar6, LoopVar5);
- if (LoopVar4 == NIL) {
- MakeChild (LoopVar6, LoopVar5, 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 (LoopVar4 >= WNDSIZ) {
- LoopVar2 = MAXMATCH;
- mMatchPos = LoopVar4;
- } else {
- LoopVar2 = mLevel[LoopVar4];
- mMatchPos = (NODE)(mPosition[LoopVar4] & ~PERC_FLAG);
- }
-
- if (mMatchPos >= mPos) {
- mMatchPos -= WNDSIZ;
- }
-
- TempString3 = &mText[mPos + mMatchLen];
- TempString2 = &mText[mMatchPos + mMatchLen];
- while (mMatchLen < LoopVar2) {
- if (*TempString3 != *TempString2) {
- Split (LoopVar4);
- return;
- }
-
- mMatchLen++;
- TempString3++;
- TempString2++;
- }
-
- if (mMatchLen >= MAXMATCH) {
- break;
- }
-
- mPosition[LoopVar4] = mPos;
- LoopVar6 = LoopVar4;
- LoopVar4 = Child (LoopVar6, *TempString3);
- if (LoopVar4 == NIL) {
- MakeChild (LoopVar6, *TempString3, mPos);
- return;
- }
-
- mMatchLen++;
- }
-
- LoopVar10 = mPrev[LoopVar4];
- mPrev[mPos] = LoopVar10;
- mNext[LoopVar10] = mPos;
- LoopVar10 = mNext[LoopVar4];
- mNext[mPos] = LoopVar10;
- mPrev[LoopVar10] = mPos;
- mParent[mPos] = LoopVar6;
- mParent[LoopVar4] = NIL;
-
- //
- // Special usage of 'next'
- //
- mNext[LoopVar4] = mPos;
-}
-
-/**
- Delete outdated string info. (The Usage of PERC_FLAG
- ensures a clean deletion).
-
-**/
-VOID
-DeleteNode (
- VOID
- )
-{
- NODE LoopVar6;
-
- NODE LoopVar4;
-
- NODE LoopVar11;
-
- NODE LoopVar10;
-
- NODE LoopVar9;
-
- if (mParent[mPos] == NIL) {
- return;
- }
-
- LoopVar4 = mPrev[mPos];
- LoopVar11 = mNext[mPos];
- mNext[LoopVar4] = LoopVar11;
- mPrev[LoopVar11] = LoopVar4;
- LoopVar4 = mParent[mPos];
- mParent[mPos] = NIL;
- if (LoopVar4 >= WNDSIZ) {
- return;
- }
-
- mChildCount[LoopVar4]--;
- if (mChildCount[LoopVar4] > 1) {
- return;
- }
-
- LoopVar10 = (NODE)(mPosition[LoopVar4] & ~PERC_FLAG);
- if (LoopVar10 >= mPos) {
- LoopVar10 -= WNDSIZ;
- }
-
- LoopVar11 = LoopVar10;
- LoopVar6 = mParent[LoopVar4];
- LoopVar9 = mPosition[LoopVar6];
- while ((LoopVar9 & PERC_FLAG) != 0) {
- LoopVar9 &= ~PERC_FLAG;
- if (LoopVar9 >= mPos) {
- LoopVar9 -= WNDSIZ;
- }
-
- if (LoopVar9 > LoopVar11) {
- LoopVar11 = LoopVar9;
- }
-
- mPosition[LoopVar6] = (NODE)(LoopVar11 | WNDSIZ);
- LoopVar6 = mParent[LoopVar6];
- LoopVar9 = mPosition[LoopVar6];
- }
-
- if (LoopVar6 < WNDSIZ) {
- if (LoopVar9 >= mPos) {
- LoopVar9 -= WNDSIZ;
- }
-
- if (LoopVar9 > LoopVar11) {
- LoopVar11 = LoopVar9;
- }
-
- mPosition[LoopVar6] = (NODE)(LoopVar11 | WNDSIZ | PERC_FLAG);
- }
-
- LoopVar11 = Child (LoopVar4, mText[LoopVar10 + mLevel[LoopVar4]]);
- LoopVar10 = mPrev[LoopVar11];
- LoopVar9 = mNext[LoopVar11];
- mNext[LoopVar10] = LoopVar9;
- mPrev[LoopVar9] = LoopVar10;
- LoopVar10 = mPrev[LoopVar4];
- mNext[LoopVar10] = LoopVar11;
- mPrev[LoopVar11] = LoopVar10;
- LoopVar10 = mNext[LoopVar4];
- mPrev[LoopVar10] = LoopVar11;
- mNext[LoopVar11] = LoopVar10;
- mParent[LoopVar11] = mParent[LoopVar4];
- mParent[LoopVar4] = NIL;
- mNext[LoopVar4] = mAvail;
- mAvail = LoopVar4;
-}
-
-/**
- Read in source data
-
- @param[out] LoopVar7 The buffer to hold the data.
- @param[in] LoopVar8 The number of bytes to read.
-
- @return The number of bytes actually read.
-**/
-INT32
-FreadCrc (
- OUT UINT8 *LoopVar7,
- IN INT32 LoopVar8
- )
-{
- INT32 LoopVar1;
-
- for (LoopVar1 = 0; mSrc < mSrcUpperLimit && LoopVar1 < LoopVar8; LoopVar1++) {
- *LoopVar7++ = *mSrc++;
- }
-
- LoopVar8 = LoopVar1;
-
- LoopVar7 -= LoopVar8;
- mOrigSize += LoopVar8;
- LoopVar1--;
- while (LoopVar1 >= 0) {
- UPDATE_CRC (*LoopVar7++);
- LoopVar1--;
- }
-
- return LoopVar8;
-}
-
-/**
- Advance the current position (read in new data if needed).
- Delete outdated string info. Find a match string for current position.
-
- @retval TRUE The operation was successful.
- @retval FALSE The operation failed due to insufficient memory.
-**/
-BOOLEAN
-GetNextMatch (
- VOID
- )
-{
- INT32 LoopVar8;
- VOID *Temp;
-
- mRemainder--;
- mPos++;
- if (mPos == WNDSIZ * 2) {
- Temp = AllocateZeroPool (WNDSIZ + MAXMATCH);
- if (Temp == NULL) {
- return (FALSE);
- }
-
- CopyMem (Temp, &mText[WNDSIZ], WNDSIZ + MAXMATCH);
- CopyMem (&mText[0], Temp, WNDSIZ + MAXMATCH);
- FreePool (Temp);
- LoopVar8 = FreadCrc (&mText[WNDSIZ + MAXMATCH], WNDSIZ);
- mRemainder += LoopVar8;
- mPos = WNDSIZ;
- }
-
- DeleteNode ();
- InsertNode ();
-
- return (TRUE);
-}
-
-/**
- Send entry LoopVar1 down the queue.
-
- @param[in] LoopVar1 The index of the item to move.
-**/
-VOID
-DownHeap (
- IN INT32 i
- )
-{
- INT32 LoopVar1;
-
- INT32 LoopVar2;
-
- //
- // priority queue: send i-th entry down heap
- //
- LoopVar2 = mHeap[i];
- LoopVar1 = 2 * i;
- while (LoopVar1 <= mHeapSize) {
- if ((LoopVar1 < mHeapSize) && (mFreq[mHeap[LoopVar1]] > mFreq[mHeap[LoopVar1 + 1]])) {
- LoopVar1++;
- }
-
- if (mFreq[LoopVar2] <= mFreq[mHeap[LoopVar1]]) {
- break;
- }
-
- mHeap[i] = mHeap[LoopVar1];
- i = LoopVar1;
- LoopVar1 = 2 * i;
- }
-
- mHeap[i] = (INT16)LoopVar2;
-}
-
-/**
- Count the number of each code length for a Huffman tree.
-
- @param[in] LoopVar1 The top node.
-**/
-VOID
-CountLen (
- IN INT32 LoopVar1
- )
-{
- if (LoopVar1 < mTempInt32) {
- mLenCnt[(mHuffmanDepth < 16) ? mHuffmanDepth : 16]++;
- } else {
- mHuffmanDepth++;
- CountLen (mLeft[LoopVar1]);
- CountLen (mRight[LoopVar1]);
- mHuffmanDepth--;
- }
-}
-
-/**
- Create code length array for a Huffman tree.
-
- @param[in] Root The root of the tree.
-**/
-VOID
-MakeLen (
- IN INT32 Root
- )
-{
- INT32 LoopVar1;
-
- INT32 LoopVar2;
- UINT32 Cum;
-
- for (LoopVar1 = 0; LoopVar1 <= 16; LoopVar1++) {
- mLenCnt[LoopVar1] = 0;
- }
-
- CountLen (Root);
-
- //
- // Adjust the length count array so that
- // no code will be generated longer than its designated length
- //
- Cum = 0;
- for (LoopVar1 = 16; LoopVar1 > 0; LoopVar1--) {
- Cum += mLenCnt[LoopVar1] << (16 - LoopVar1);
- }
-
- while (Cum != (1U << 16)) {
- mLenCnt[16]--;
- for (LoopVar1 = 15; LoopVar1 > 0; LoopVar1--) {
- if (mLenCnt[LoopVar1] != 0) {
- mLenCnt[LoopVar1]--;
- mLenCnt[LoopVar1 + 1] += 2;
- break;
- }
- }
-
- Cum--;
- }
-
- for (LoopVar1 = 16; LoopVar1 > 0; LoopVar1--) {
- LoopVar2 = mLenCnt[LoopVar1];
- LoopVar2--;
- while (LoopVar2 >= 0) {
- mLen[*mSortPtr++] = (UINT8)LoopVar1;
- LoopVar2--;
- }
- }
-}
-
-/**
- Assign code to each symbol based on the code length array.
-
- @param[in] LoopVar8 The number of symbols.
- @param[in] Len The code length array.
- @param[out] Code The stores codes for each symbol.
-**/
-VOID
-MakeCode (
- IN INT32 LoopVar8,
- IN UINT8 Len[],
- OUT UINT16 Code[]
- )
-{
- INT32 LoopVar1;
- UINT16 Start[18];
-
- Start[1] = 0;
- for (LoopVar1 = 1; LoopVar1 <= 16; LoopVar1++) {
- Start[LoopVar1 + 1] = (UINT16)((Start[LoopVar1] + mLenCnt[LoopVar1]) << 1);
- }
-
- for (LoopVar1 = 0; LoopVar1 < LoopVar8; LoopVar1++) {
- Code[LoopVar1] = Start[Len[LoopVar1]]++;
- }
-}
-
-/**
- Generates Huffman codes given a frequency distribution of symbols.
-
- @param[in] NParm The number of symbols.
- @param[in] FreqParm The frequency of each symbol.
- @param[out] LenParm The code length for each symbol.
- @param[out] CodeParm The code for each symbol.
-
- @return The root of the Huffman tree.
-**/
-INT32
-MakeTree (
- IN INT32 NParm,
- IN UINT16 FreqParm[],
- OUT UINT8 LenParm[],
- OUT UINT16 CodeParm[]
- )
-{
- INT32 LoopVar1;
-
- INT32 LoopVar2;
-
- INT32 LoopVar3;
-
- INT32 Avail;
-
- //
- // make tree, calculate len[], return root
- //
- mTempInt32 = NParm;
- mFreq = FreqParm;
- mLen = LenParm;
- Avail = mTempInt32;
- mHeapSize = 0;
- mHeap[1] = 0;
- for (LoopVar1 = 0; LoopVar1 < mTempInt32; LoopVar1++) {
- mLen[LoopVar1] = 0;
- if ((mFreq[LoopVar1]) != 0) {
- mHeapSize++;
- mHeap[mHeapSize] = (INT16)LoopVar1;
- }
- }
-
- if (mHeapSize < 2) {
- CodeParm[mHeap[1]] = 0;
- return mHeap[1];
- }
-
- for (LoopVar1 = mHeapSize / 2; LoopVar1 >= 1; LoopVar1--) {
- //
- // make priority queue
- //
- DownHeap (LoopVar1);
- }
-
- mSortPtr = CodeParm;
- do {
- LoopVar1 = mHeap[1];
- if (LoopVar1 < mTempInt32) {
- *mSortPtr++ = (UINT16)LoopVar1;
- }
-
- mHeap[1] = mHeap[mHeapSize--];
- DownHeap (1);
- LoopVar2 = mHeap[1];
- if (LoopVar2 < mTempInt32) {
- *mSortPtr++ = (UINT16)LoopVar2;
- }
-
- LoopVar3 = Avail++;
- mFreq[LoopVar3] = (UINT16)(mFreq[LoopVar1] + mFreq[LoopVar2]);
- mHeap[1] = (INT16)LoopVar3;
- DownHeap (1);
- mLeft[LoopVar3] = (UINT16)LoopVar1;
- mRight[LoopVar3] = (UINT16)LoopVar2;
- } while (mHeapSize > 1);
-
- mSortPtr = CodeParm;
- MakeLen (LoopVar3);
- MakeCode (NParm, LenParm, CodeParm);
-
- //
- // return root
- //
- return LoopVar3;
-}
-
-/**
- Outputs rightmost LoopVar8 bits of x
-
- @param[in] LoopVar8 The rightmost LoopVar8 bits of the data is used.
- @param[in] x The data.
-**/
-VOID
-PutBits (
- IN INT32 LoopVar8,
- IN UINT32 x
- )
-{
- UINT8 Temp;
-
- if (LoopVar8 < mBitCount) {
- mSubBitBuf |= x << (mBitCount -= LoopVar8);
- } else {
- Temp = (UINT8)(mSubBitBuf | (x >> (LoopVar8 -= mBitCount)));
- if (mDst < mDstUpperLimit) {
- *mDst++ = Temp;
- }
-
- mCompSize++;
-
- if (LoopVar8 < UINT8_BIT) {
- mSubBitBuf = x << (mBitCount = UINT8_BIT - LoopVar8);
- } else {
- Temp = (UINT8)(x >> (LoopVar8 - UINT8_BIT));
- if (mDst < mDstUpperLimit) {
- *mDst++ = Temp;
- }
-
- mCompSize++;
-
- mSubBitBuf = x << (mBitCount = 2 * UINT8_BIT - LoopVar8);
- }
- }
-}
-
-/**
- Encode a signed 32 bit number.
-
- @param[in] LoopVar5 The number to encode.
-**/
-VOID
-EncodeC (
- IN INT32 LoopVar5
- )
-{
- PutBits (mCLen[LoopVar5], mCCode[LoopVar5]);
-}
-
-/**
- Encode a unsigned 32 bit number.
-
- @param[in] LoopVar7 The number to encode.
-**/
-VOID
-EncodeP (
- IN UINT32 LoopVar7
- )
-{
- UINT32 LoopVar5;
-
- UINT32 LoopVar6;
-
- LoopVar5 = 0;
- LoopVar6 = LoopVar7;
- while (LoopVar6 != 0) {
- LoopVar6 >>= 1;
- LoopVar5++;
- }
-
- PutBits (mPTLen[LoopVar5], mPTCode[LoopVar5]);
- if (LoopVar5 > 1) {
- PutBits (LoopVar5 - 1, LoopVar7 & (0xFFFFU >> (17 - LoopVar5)));
- }
-}
-
-/**
- Count the frequencies for the Extra Set.
-
-**/
-VOID
-CountTFreq (
- VOID
- )
-{
- INT32 LoopVar1;
-
- INT32 LoopVar3;
-
- INT32 LoopVar8;
-
- INT32 Count;
-
- for (LoopVar1 = 0; LoopVar1 < NT; LoopVar1++) {
- mTFreq[LoopVar1] = 0;
- }
-
- LoopVar8 = NC;
- while (LoopVar8 > 0 && mCLen[LoopVar8 - 1] == 0) {
- LoopVar8--;
- }
-
- LoopVar1 = 0;
- while (LoopVar1 < LoopVar8) {
- LoopVar3 = mCLen[LoopVar1++];
- if (LoopVar3 == 0) {
- Count = 1;
- while (LoopVar1 < LoopVar8 && mCLen[LoopVar1] == 0) {
- LoopVar1++;
- 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 {
- ASSERT ((LoopVar3+2) < (2 * NT - 1));
- mTFreq[LoopVar3 + 2]++;
- }
- }
-}
-
-/**
- Outputs the code length array for the Extra Set or the Position Set.
-
- @param[in] LoopVar8 The number of symbols.
- @param[in] nbit The number of bits needed to represent 'LoopVar8'.
- @param[in] Special The special symbol that needs to be take care of.
-
-**/
-VOID
-WritePTLen (
- IN INT32 LoopVar8,
- IN INT32 nbit,
- IN INT32 Special
- )
-{
- INT32 LoopVar1;
-
- INT32 LoopVar3;
-
- while (LoopVar8 > 0 && mPTLen[LoopVar8 - 1] == 0) {
- LoopVar8--;
- }
-
- PutBits (nbit, LoopVar8);
- LoopVar1 = 0;
- while (LoopVar1 < LoopVar8) {
- LoopVar3 = mPTLen[LoopVar1++];
- if (LoopVar3 <= 6) {
- PutBits (3, LoopVar3);
- } else {
- PutBits (LoopVar3 - 3, (1U << (LoopVar3 - 3)) - 2);
- }
-
- if (LoopVar1 == Special) {
- while (LoopVar1 < 6 && mPTLen[LoopVar1] == 0) {
- LoopVar1++;
- }
-
- PutBits (2, (LoopVar1 - 3) & 3);
- }
- }
-}
-
-/**
- Outputs the code length array for Char&Length Set.
-**/
-VOID
-WriteCLen (
- VOID
- )
-{
- INT32 LoopVar1;
-
- INT32 LoopVar3;
-
- INT32 LoopVar8;
-
- INT32 Count;
-
- LoopVar8 = NC;
- while (LoopVar8 > 0 && mCLen[LoopVar8 - 1] == 0) {
- LoopVar8--;
- }
-
- PutBits (CBIT, LoopVar8);
- LoopVar1 = 0;
- while (LoopVar1 < LoopVar8) {
- LoopVar3 = mCLen[LoopVar1++];
- if (LoopVar3 == 0) {
- Count = 1;
- while (LoopVar1 < LoopVar8 && mCLen[LoopVar1] == 0) {
- LoopVar1++;
- Count++;
- }
-
- if (Count <= 2) {
- for (LoopVar3 = 0; LoopVar3 < Count; LoopVar3++) {
- 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 {
- ASSERT ((LoopVar3+2) < NPT);
- PutBits (mPTLen[LoopVar3 + 2], mPTCode[LoopVar3 + 2]);
- }
- }
-}
-
-/**
- Huffman code the block and output it.
-
-**/
-VOID
-SendBlock (
- VOID
- )
-{
- UINT32 LoopVar1;
-
- UINT32 LoopVar3;
-
- 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 (LoopVar1 = 0; LoopVar1 < Size; LoopVar1++) {
- if (LoopVar1 % UINT8_BIT == 0) {
- Flags = mBuf[Pos++];
- } else {
- Flags <<= 1;
- }
-
- if ((Flags & (1U << (UINT8_BIT - 1))) != 0) {
- EncodeC (mBuf[Pos++] + (1U << UINT8_BIT));
- LoopVar3 = mBuf[Pos++] << UINT8_BIT;
- LoopVar3 += mBuf[Pos++];
-
- EncodeP (LoopVar3);
- } else {
- EncodeC (mBuf[Pos++]);
- }
- }
-
- SetMem (mCFreq, NC * sizeof (UINT16), 0);
- SetMem (mPFreq, NP * sizeof (UINT16), 0);
-}
-
-/**
- Start the huffman encoding.
-
-**/
-VOID
-HufEncodeStart (
- VOID
- )
-{
- SetMem (mCFreq, NC * sizeof (UINT16), 0);
- SetMem (mPFreq, NP * sizeof (UINT16), 0);
-
- mOutputPos = mOutputMask = 0;
-
- mBitCount = UINT8_BIT;
- mSubBitBuf = 0;
-}
-
-/**
- Outputs an Original Character or a Pointer.
-
- @param[in] LoopVar5 The original character or the 'String Length' element of
- a Pointer.
- @param[in] LoopVar7 The 'Position' field of a Pointer.
-**/
-VOID
-CompressOutput (
- IN UINT32 LoopVar5,
- IN UINT32 LoopVar7
- )
-{
- STATIC UINT32 CPos;
-
- if ((mOutputMask >>= 1) == 0) {
- mOutputMask = 1U << (UINT8_BIT - 1);
- if (mOutputPos >= mBufSiz - 3 * UINT8_BIT) {
- SendBlock ();
- mOutputPos = 0;
- }
-
- CPos = mOutputPos++;
- mBuf[CPos] = 0;
- }
-
- mBuf[mOutputPos++] = (UINT8)LoopVar5;
- mCFreq[LoopVar5]++;
- if (LoopVar5 >= (1U << UINT8_BIT)) {
- mBuf[CPos] = (UINT8)(mBuf[CPos]|mOutputMask);
- mBuf[mOutputPos++] = (UINT8)(LoopVar7 >> UINT8_BIT);
- mBuf[mOutputPos++] = (UINT8)LoopVar7;
- LoopVar5 = 0;
- while (LoopVar7 != 0) {
- LoopVar7 >>= 1;
- LoopVar5++;
- }
-
- mPFreq[LoopVar5]++;
- }
-}
-
-/**
- End the huffman encoding.
-
-**/
-VOID
-HufEncodeEnd (
- VOID
- )
-{
- SendBlock ();
-
- //
- // Flush remaining bits
- //
- PutBits (UINT8_BIT - 1, 0);
-}
-
-/**
- The main controlling routine for compression process.
-
- @retval EFI_SUCCESS The compression is successful.
- @retval EFI_OUT_0F_RESOURCES Not enough memory for compression process.
-**/
-EFI_STATUS
-Encode (
- VOID
- )
-{
- 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;
- if (!GetNextMatch ()) {
- Status = EFI_OUT_OF_RESOURCES;
- }
-
- 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
- //
- CompressOutput (mText[mPos - 1], 0);
- } else {
- //
- // Outputting a pointer is beneficial enough, do it.
- //
-
- CompressOutput (
- LastMatchLen + (UINT8_MAX + 1 - THRESHOLD),
- (mPos - LastMatchPos - 2) & (WNDSIZ - 1)
- );
- LastMatchLen--;
- while (LastMatchLen > 0) {
- if (!GetNextMatch ()) {
- Status = EFI_OUT_OF_RESOURCES;
- }
-
- LastMatchLen--;
- }
-
- if (mMatchLen > mRemainder) {
- mMatchLen = mRemainder;
- }
- }
- }
-
- HufEncodeEnd ();
- FreeMemory ();
- return (Status);
-}
-
-/**
- The compression routine.
-
- @param[in] SrcBuffer The buffer containing the source data.
- @param[in] SrcSize Number of bytes in SrcBuffer.
- @param[in] DstBuffer The buffer to put the compressed image in.
- @param[in, out] DstSize On input the size (in bytes) of DstBuffer, on
- return the number of bytes placed in DstBuffer.
-
- @retval EFI_SUCCESS The compression was successful.
- @retval EFI_BUFFER_TOO_SMALL The buffer was too small. DstSize is required.
-**/
-EFI_STATUS
-Compress (
- IN VOID *SrcBuffer,
- IN UINT64 SrcSize,
- IN VOID *DstBuffer,
- IN OUT UINT64 *DstSize
- )
-{
- 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;
- }
-}
+/** @file + Main file for compression routine. + + 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. + + Copyright (c) 2007 - 2018, Intel Corporation. All rights reserved.<BR> + SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ +#include <Uefi.h> +#include <Library/MemoryAllocationLib.h> +#include <Library/BaseMemoryLib.h> +#include <Library/DebugLib.h> +#include <Library/ShellLib.h> + +#include "Compress.h" + +// +// Macro Definitions +// +typedef INT16 NODE; +#define UINT8_MAX 0xff +#define UINT8_BIT 8 +#define THRESHOLD 3 +#define INIT_CRC 0 +#define WNDBIT 13 +#define WNDSIZ (1U << WNDBIT) +#define MAXMATCH 256 +#define BLKSIZ (1U << 14) // 16 * 1024U +#define PERC_FLAG 0x8000U +#define CODE_BIT 16 +#define NIL 0 +#define MAX_HASH_VAL (3 * WNDSIZ + (WNDSIZ / 512 + 1) * UINT8_MAX) +#define HASH(LoopVar7, LoopVar5) ((LoopVar7) + ((LoopVar5) << (WNDBIT - 9)) + WNDSIZ * 2) +#define CRCPOLY 0xA001 +#define UPDATE_CRC(LoopVar5) mCrc = mCrcTable[(mCrc ^ (LoopVar5)) & 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 4 +#define NT (CODE_BIT + 3) +#define TBIT 5 +#if NT > NP +#define NPT NT +#else +#define NPT NP +#endif +// +// Function Prototypes +// + +/** + Put a dword to output stream + + @param[in] Data The dword to put. +**/ +VOID +PutDword ( + IN UINT32 Data + ); + +// +// Global Variables +// +STATIC UINT8 *mSrc; +STATIC UINT8 *mDst; +STATIC UINT8 *mSrcUpperLimit; +STATIC UINT8 *mDstUpperLimit; + +STATIC UINT8 *mLevel; +STATIC UINT8 *mText; +STATIC UINT8 *mChildCount; +STATIC UINT8 *mBuf; +STATIC UINT8 mCLen[NC]; +STATIC UINT8 mPTLen[NPT]; +STATIC UINT8 *mLen; +STATIC INT16 mHeap[NC + 1]; +STATIC INT32 mRemainder; +STATIC INT32 mMatchLen; +STATIC INT32 mBitCount; +STATIC INT32 mHeapSize; +STATIC INT32 mTempInt32; +STATIC UINT32 mBufSiz = 0; +STATIC UINT32 mOutputPos; +STATIC UINT32 mOutputMask; +STATIC UINT32 mSubBitBuf; +STATIC UINT32 mCrc; +STATIC UINT32 mCompSize; +STATIC UINT32 mOrigSize; + +STATIC UINT16 *mFreq; +STATIC UINT16 *mSortPtr; +STATIC UINT16 mLenCnt[17]; +STATIC UINT16 mLeft[2 * NC - 1]; +STATIC UINT16 mRight[2 * NC - 1]; +STATIC UINT16 mCrcTable[UINT8_MAX + 1]; +STATIC UINT16 mCFreq[2 * NC - 1]; +STATIC UINT16 mCCode[NC]; +STATIC UINT16 mPFreq[2 * NP - 1]; +STATIC UINT16 mPTCode[NPT]; +STATIC UINT16 mTFreq[2 * NT - 1]; + +STATIC NODE mPos; +STATIC NODE mMatchPos; +STATIC NODE mAvail; +STATIC NODE *mPosition; +STATIC NODE *mParent; +STATIC NODE *mPrev; +STATIC NODE *mNext = NULL; +INT32 mHuffmanDepth = 0; + +/** + Make a CRC table. + +**/ +VOID +MakeCrcTable ( + VOID + ) +{ + UINT32 LoopVar1; + + UINT32 LoopVar2; + + UINT32 LoopVar4; + + for (LoopVar1 = 0; LoopVar1 <= UINT8_MAX; LoopVar1++) { + LoopVar4 = LoopVar1; + for (LoopVar2 = 0; LoopVar2 < UINT8_BIT; LoopVar2++) { + if ((LoopVar4 & 1) != 0) { + LoopVar4 = (LoopVar4 >> 1) ^ CRCPOLY; + } else { + LoopVar4 >>= 1; + } + } + + mCrcTable[LoopVar1] = (UINT16)LoopVar4; + } +} + +/** + Put a dword to output stream + + @param[in] Data The dword to put. +**/ +VOID +PutDword ( + IN UINT32 Data + ) +{ + 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); + } +} + +/** + Allocate memory spaces for data structures used in compression process. + + @retval EFI_SUCCESS Memory was allocated successfully. + @retval EFI_OUT_OF_RESOURCES A memory allocation failed. +**/ +EFI_STATUS +AllocateMemory ( + VOID + ) +{ + mText = AllocateZeroPool (WNDSIZ * 2 + MAXMATCH); + mLevel = AllocateZeroPool ((WNDSIZ + UINT8_MAX + 1) * sizeof (*mLevel)); + mChildCount = AllocateZeroPool ((WNDSIZ + UINT8_MAX + 1) * sizeof (*mChildCount)); + mPosition = AllocateZeroPool ((WNDSIZ + UINT8_MAX + 1) * sizeof (*mPosition)); + mParent = AllocateZeroPool (WNDSIZ * 2 * sizeof (*mParent)); + mPrev = AllocateZeroPool (WNDSIZ * 2 * sizeof (*mPrev)); + mNext = AllocateZeroPool ((MAX_HASH_VAL + 1) * sizeof (*mNext)); + + mBufSiz = BLKSIZ; + mBuf = AllocateZeroPool (mBufSiz); + while (mBuf == NULL) { + mBufSiz = (mBufSiz / 10U) * 9U; + if (mBufSiz < 4 * 1024U) { + return EFI_OUT_OF_RESOURCES; + } + + mBuf = AllocateZeroPool (mBufSiz); + } + + mBuf[0] = 0; + + return EFI_SUCCESS; +} + +/** + Called when compression is completed to free memory previously allocated. + +**/ +VOID +FreeMemory ( + VOID + ) +{ + SHELL_FREE_NON_NULL (mText); + SHELL_FREE_NON_NULL (mLevel); + SHELL_FREE_NON_NULL (mChildCount); + SHELL_FREE_NON_NULL (mPosition); + SHELL_FREE_NON_NULL (mParent); + SHELL_FREE_NON_NULL (mPrev); + SHELL_FREE_NON_NULL (mNext); + SHELL_FREE_NON_NULL (mBuf); +} + +/** + Initialize String Info Log data structures. +**/ +VOID +InitSlide ( + VOID + ) +{ + NODE LoopVar1; + + SetMem (mLevel + WNDSIZ, (UINT8_MAX + 1) * sizeof (UINT8), 1); + SetMem (mPosition + WNDSIZ, (UINT8_MAX + 1) * sizeof (NODE), 0); + + SetMem (mParent + WNDSIZ, WNDSIZ * sizeof (NODE), 0); + + mAvail = 1; + for (LoopVar1 = 1; LoopVar1 < WNDSIZ - 1; LoopVar1++) { + mNext[LoopVar1] = (NODE)(LoopVar1 + 1); + } + + mNext[WNDSIZ - 1] = NIL; + SetMem (mNext + WNDSIZ * 2, (MAX_HASH_VAL - WNDSIZ * 2 + 1) * sizeof (NODE), 0); +} + +/** + Find child node given the parent node and the edge character + + @param[in] LoopVar6 The parent node. + @param[in] LoopVar5 The edge character. + + @return The child node. + @retval NIL(Zero) No child could be found. + +**/ +NODE +Child ( + IN NODE LoopVar6, + IN UINT8 LoopVar5 + ) +{ + NODE LoopVar4; + + LoopVar4 = mNext[HASH (LoopVar6, LoopVar5)]; + mParent[NIL] = LoopVar6; /* sentinel */ + while (mParent[LoopVar4] != LoopVar6) { + LoopVar4 = mNext[LoopVar4]; + } + + return LoopVar4; +} + +/** + Create a new child for a given parent node. + + @param[in] LoopVar6 The parent node. + @param[in] LoopVar5 The edge character. + @param[in] LoopVar4 The child node. +**/ +VOID +MakeChild ( + IN NODE LoopVar6, + IN UINT8 LoopVar5, + IN NODE LoopVar4 + ) +{ + NODE LoopVar12; + + NODE LoopVar10; + + LoopVar12 = (NODE)HASH (LoopVar6, LoopVar5); + LoopVar10 = mNext[LoopVar12]; + mNext[LoopVar12] = LoopVar4; + mNext[LoopVar4] = LoopVar10; + mPrev[LoopVar10] = LoopVar4; + mPrev[LoopVar4] = LoopVar12; + mParent[LoopVar4] = LoopVar6; + mChildCount[LoopVar6]++; +} + +/** + Split a node. + + @param[in] Old The node to split. +**/ +VOID +Split ( + IN NODE Old + ) +{ + NODE New; + + NODE LoopVar10; + + New = mAvail; + mAvail = mNext[New]; + mChildCount[New] = 0; + LoopVar10 = mPrev[Old]; + mPrev[New] = LoopVar10; + mNext[LoopVar10] = New; + LoopVar10 = mNext[Old]; + mNext[New] = LoopVar10; + mPrev[LoopVar10] = New; + mParent[New] = mParent[Old]; + mLevel[New] = (UINT8)mMatchLen; + mPosition[New] = mPos; + MakeChild (New, mText[mMatchPos + mMatchLen], Old); + MakeChild (New, mText[mPos + mMatchLen], mPos); +} + +/** + Insert string info for current position into the String Info Log. + +**/ +VOID +InsertNode ( + VOID + ) +{ + NODE LoopVar6; + + NODE LoopVar4; + + NODE LoopVar2; + + NODE LoopVar10; + UINT8 LoopVar5; + UINT8 *TempString3; + UINT8 *TempString2; + + 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--; + LoopVar4 = (NODE)((mMatchPos + 1) | WNDSIZ); + LoopVar6 = mParent[LoopVar4]; + while (LoopVar6 == NIL) { + LoopVar4 = mNext[LoopVar4]; + LoopVar6 = mParent[LoopVar4]; + } + + while (mLevel[LoopVar6] >= mMatchLen) { + LoopVar4 = LoopVar6; + LoopVar6 = mParent[LoopVar6]; + } + + LoopVar10 = LoopVar6; + while (mPosition[LoopVar10] < 0) { + mPosition[LoopVar10] = mPos; + LoopVar10 = mParent[LoopVar10]; + } + + if (LoopVar10 < WNDSIZ) { + mPosition[LoopVar10] = (NODE)(mPos | PERC_FLAG); + } + } else { + // + // Locate the target tree + // + LoopVar6 = (NODE)(mText[mPos] + WNDSIZ); + LoopVar5 = mText[mPos + 1]; + LoopVar4 = Child (LoopVar6, LoopVar5); + if (LoopVar4 == NIL) { + MakeChild (LoopVar6, LoopVar5, 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 (LoopVar4 >= WNDSIZ) { + LoopVar2 = MAXMATCH; + mMatchPos = LoopVar4; + } else { + LoopVar2 = mLevel[LoopVar4]; + mMatchPos = (NODE)(mPosition[LoopVar4] & ~PERC_FLAG); + } + + if (mMatchPos >= mPos) { + mMatchPos -= WNDSIZ; + } + + TempString3 = &mText[mPos + mMatchLen]; + TempString2 = &mText[mMatchPos + mMatchLen]; + while (mMatchLen < LoopVar2) { + if (*TempString3 != *TempString2) { + Split (LoopVar4); + return; + } + + mMatchLen++; + TempString3++; + TempString2++; + } + + if (mMatchLen >= MAXMATCH) { + break; + } + + mPosition[LoopVar4] = mPos; + LoopVar6 = LoopVar4; + LoopVar4 = Child (LoopVar6, *TempString3); + if (LoopVar4 == NIL) { + MakeChild (LoopVar6, *TempString3, mPos); + return; + } + + mMatchLen++; + } + + LoopVar10 = mPrev[LoopVar4]; + mPrev[mPos] = LoopVar10; + mNext[LoopVar10] = mPos; + LoopVar10 = mNext[LoopVar4]; + mNext[mPos] = LoopVar10; + mPrev[LoopVar10] = mPos; + mParent[mPos] = LoopVar6; + mParent[LoopVar4] = NIL; + + // + // Special usage of 'next' + // + mNext[LoopVar4] = mPos; +} + +/** + Delete outdated string info. (The Usage of PERC_FLAG + ensures a clean deletion). + +**/ +VOID +DeleteNode ( + VOID + ) +{ + NODE LoopVar6; + + NODE LoopVar4; + + NODE LoopVar11; + + NODE LoopVar10; + + NODE LoopVar9; + + if (mParent[mPos] == NIL) { + return; + } + + LoopVar4 = mPrev[mPos]; + LoopVar11 = mNext[mPos]; + mNext[LoopVar4] = LoopVar11; + mPrev[LoopVar11] = LoopVar4; + LoopVar4 = mParent[mPos]; + mParent[mPos] = NIL; + if (LoopVar4 >= WNDSIZ) { + return; + } + + mChildCount[LoopVar4]--; + if (mChildCount[LoopVar4] > 1) { + return; + } + + LoopVar10 = (NODE)(mPosition[LoopVar4] & ~PERC_FLAG); + if (LoopVar10 >= mPos) { + LoopVar10 -= WNDSIZ; + } + + LoopVar11 = LoopVar10; + LoopVar6 = mParent[LoopVar4]; + LoopVar9 = mPosition[LoopVar6]; + while ((LoopVar9 & PERC_FLAG) != 0) { + LoopVar9 &= ~PERC_FLAG; + if (LoopVar9 >= mPos) { + LoopVar9 -= WNDSIZ; + } + + if (LoopVar9 > LoopVar11) { + LoopVar11 = LoopVar9; + } + + mPosition[LoopVar6] = (NODE)(LoopVar11 | WNDSIZ); + LoopVar6 = mParent[LoopVar6]; + LoopVar9 = mPosition[LoopVar6]; + } + + if (LoopVar6 < WNDSIZ) { + if (LoopVar9 >= mPos) { + LoopVar9 -= WNDSIZ; + } + + if (LoopVar9 > LoopVar11) { + LoopVar11 = LoopVar9; + } + + mPosition[LoopVar6] = (NODE)(LoopVar11 | WNDSIZ | PERC_FLAG); + } + + LoopVar11 = Child (LoopVar4, mText[LoopVar10 + mLevel[LoopVar4]]); + LoopVar10 = mPrev[LoopVar11]; + LoopVar9 = mNext[LoopVar11]; + mNext[LoopVar10] = LoopVar9; + mPrev[LoopVar9] = LoopVar10; + LoopVar10 = mPrev[LoopVar4]; + mNext[LoopVar10] = LoopVar11; + mPrev[LoopVar11] = LoopVar10; + LoopVar10 = mNext[LoopVar4]; + mPrev[LoopVar10] = LoopVar11; + mNext[LoopVar11] = LoopVar10; + mParent[LoopVar11] = mParent[LoopVar4]; + mParent[LoopVar4] = NIL; + mNext[LoopVar4] = mAvail; + mAvail = LoopVar4; +} + +/** + Read in source data + + @param[out] LoopVar7 The buffer to hold the data. + @param[in] LoopVar8 The number of bytes to read. + + @return The number of bytes actually read. +**/ +INT32 +FreadCrc ( + OUT UINT8 *LoopVar7, + IN INT32 LoopVar8 + ) +{ + INT32 LoopVar1; + + for (LoopVar1 = 0; mSrc < mSrcUpperLimit && LoopVar1 < LoopVar8; LoopVar1++) { + *LoopVar7++ = *mSrc++; + } + + LoopVar8 = LoopVar1; + + LoopVar7 -= LoopVar8; + mOrigSize += LoopVar8; + LoopVar1--; + while (LoopVar1 >= 0) { + UPDATE_CRC (*LoopVar7++); + LoopVar1--; + } + + return LoopVar8; +} + +/** + Advance the current position (read in new data if needed). + Delete outdated string info. Find a match string for current position. + + @retval TRUE The operation was successful. + @retval FALSE The operation failed due to insufficient memory. +**/ +BOOLEAN +GetNextMatch ( + VOID + ) +{ + INT32 LoopVar8; + VOID *Temp; + + mRemainder--; + mPos++; + if (mPos == WNDSIZ * 2) { + Temp = AllocateZeroPool (WNDSIZ + MAXMATCH); + if (Temp == NULL) { + return (FALSE); + } + + CopyMem (Temp, &mText[WNDSIZ], WNDSIZ + MAXMATCH); + CopyMem (&mText[0], Temp, WNDSIZ + MAXMATCH); + FreePool (Temp); + LoopVar8 = FreadCrc (&mText[WNDSIZ + MAXMATCH], WNDSIZ); + mRemainder += LoopVar8; + mPos = WNDSIZ; + } + + DeleteNode (); + InsertNode (); + + return (TRUE); +} + +/** + Send entry LoopVar1 down the queue. + + @param[in] LoopVar1 The index of the item to move. +**/ +VOID +DownHeap ( + IN INT32 i + ) +{ + INT32 LoopVar1; + + INT32 LoopVar2; + + // + // priority queue: send i-th entry down heap + // + LoopVar2 = mHeap[i]; + LoopVar1 = 2 * i; + while (LoopVar1 <= mHeapSize) { + if ((LoopVar1 < mHeapSize) && (mFreq[mHeap[LoopVar1]] > mFreq[mHeap[LoopVar1 + 1]])) { + LoopVar1++; + } + + if (mFreq[LoopVar2] <= mFreq[mHeap[LoopVar1]]) { + break; + } + + mHeap[i] = mHeap[LoopVar1]; + i = LoopVar1; + LoopVar1 = 2 * i; + } + + mHeap[i] = (INT16)LoopVar2; +} + +/** + Count the number of each code length for a Huffman tree. + + @param[in] LoopVar1 The top node. +**/ +VOID +CountLen ( + IN INT32 LoopVar1 + ) +{ + if (LoopVar1 < mTempInt32) { + mLenCnt[(mHuffmanDepth < 16) ? mHuffmanDepth : 16]++; + } else { + mHuffmanDepth++; + CountLen (mLeft[LoopVar1]); + CountLen (mRight[LoopVar1]); + mHuffmanDepth--; + } +} + +/** + Create code length array for a Huffman tree. + + @param[in] Root The root of the tree. +**/ +VOID +MakeLen ( + IN INT32 Root + ) +{ + INT32 LoopVar1; + + INT32 LoopVar2; + UINT32 Cum; + + for (LoopVar1 = 0; LoopVar1 <= 16; LoopVar1++) { + mLenCnt[LoopVar1] = 0; + } + + CountLen (Root); + + // + // Adjust the length count array so that + // no code will be generated longer than its designated length + // + Cum = 0; + for (LoopVar1 = 16; LoopVar1 > 0; LoopVar1--) { + Cum += mLenCnt[LoopVar1] << (16 - LoopVar1); + } + + while (Cum != (1U << 16)) { + mLenCnt[16]--; + for (LoopVar1 = 15; LoopVar1 > 0; LoopVar1--) { + if (mLenCnt[LoopVar1] != 0) { + mLenCnt[LoopVar1]--; + mLenCnt[LoopVar1 + 1] += 2; + break; + } + } + + Cum--; + } + + for (LoopVar1 = 16; LoopVar1 > 0; LoopVar1--) { + LoopVar2 = mLenCnt[LoopVar1]; + LoopVar2--; + while (LoopVar2 >= 0) { + mLen[*mSortPtr++] = (UINT8)LoopVar1; + LoopVar2--; + } + } +} + +/** + Assign code to each symbol based on the code length array. + + @param[in] LoopVar8 The number of symbols. + @param[in] Len The code length array. + @param[out] Code The stores codes for each symbol. +**/ +VOID +MakeCode ( + IN INT32 LoopVar8, + IN UINT8 Len[], + OUT UINT16 Code[] + ) +{ + INT32 LoopVar1; + UINT16 Start[18]; + + Start[1] = 0; + for (LoopVar1 = 1; LoopVar1 <= 16; LoopVar1++) { + Start[LoopVar1 + 1] = (UINT16)((Start[LoopVar1] + mLenCnt[LoopVar1]) << 1); + } + + for (LoopVar1 = 0; LoopVar1 < LoopVar8; LoopVar1++) { + Code[LoopVar1] = Start[Len[LoopVar1]]++; + } +} + +/** + Generates Huffman codes given a frequency distribution of symbols. + + @param[in] NParm The number of symbols. + @param[in] FreqParm The frequency of each symbol. + @param[out] LenParm The code length for each symbol. + @param[out] CodeParm The code for each symbol. + + @return The root of the Huffman tree. +**/ +INT32 +MakeTree ( + IN INT32 NParm, + IN UINT16 FreqParm[], + OUT UINT8 LenParm[], + OUT UINT16 CodeParm[] + ) +{ + INT32 LoopVar1; + + INT32 LoopVar2; + + INT32 LoopVar3; + + INT32 Avail; + + // + // make tree, calculate len[], return root + // + mTempInt32 = NParm; + mFreq = FreqParm; + mLen = LenParm; + Avail = mTempInt32; + mHeapSize = 0; + mHeap[1] = 0; + for (LoopVar1 = 0; LoopVar1 < mTempInt32; LoopVar1++) { + mLen[LoopVar1] = 0; + if ((mFreq[LoopVar1]) != 0) { + mHeapSize++; + mHeap[mHeapSize] = (INT16)LoopVar1; + } + } + + if (mHeapSize < 2) { + CodeParm[mHeap[1]] = 0; + return mHeap[1]; + } + + for (LoopVar1 = mHeapSize / 2; LoopVar1 >= 1; LoopVar1--) { + // + // make priority queue + // + DownHeap (LoopVar1); + } + + mSortPtr = CodeParm; + do { + LoopVar1 = mHeap[1]; + if (LoopVar1 < mTempInt32) { + *mSortPtr++ = (UINT16)LoopVar1; + } + + mHeap[1] = mHeap[mHeapSize--]; + DownHeap (1); + LoopVar2 = mHeap[1]; + if (LoopVar2 < mTempInt32) { + *mSortPtr++ = (UINT16)LoopVar2; + } + + LoopVar3 = Avail++; + mFreq[LoopVar3] = (UINT16)(mFreq[LoopVar1] + mFreq[LoopVar2]); + mHeap[1] = (INT16)LoopVar3; + DownHeap (1); + mLeft[LoopVar3] = (UINT16)LoopVar1; + mRight[LoopVar3] = (UINT16)LoopVar2; + } while (mHeapSize > 1); + + mSortPtr = CodeParm; + MakeLen (LoopVar3); + MakeCode (NParm, LenParm, CodeParm); + + // + // return root + // + return LoopVar3; +} + +/** + Outputs rightmost LoopVar8 bits of x + + @param[in] LoopVar8 The rightmost LoopVar8 bits of the data is used. + @param[in] x The data. +**/ +VOID +PutBits ( + IN INT32 LoopVar8, + IN UINT32 x + ) +{ + UINT8 Temp; + + if (LoopVar8 < mBitCount) { + mSubBitBuf |= x << (mBitCount -= LoopVar8); + } else { + Temp = (UINT8)(mSubBitBuf | (x >> (LoopVar8 -= mBitCount))); + if (mDst < mDstUpperLimit) { + *mDst++ = Temp; + } + + mCompSize++; + + if (LoopVar8 < UINT8_BIT) { + mSubBitBuf = x << (mBitCount = UINT8_BIT - LoopVar8); + } else { + Temp = (UINT8)(x >> (LoopVar8 - UINT8_BIT)); + if (mDst < mDstUpperLimit) { + *mDst++ = Temp; + } + + mCompSize++; + + mSubBitBuf = x << (mBitCount = 2 * UINT8_BIT - LoopVar8); + } + } +} + +/** + Encode a signed 32 bit number. + + @param[in] LoopVar5 The number to encode. +**/ +VOID +EncodeC ( + IN INT32 LoopVar5 + ) +{ + PutBits (mCLen[LoopVar5], mCCode[LoopVar5]); +} + +/** + Encode a unsigned 32 bit number. + + @param[in] LoopVar7 The number to encode. +**/ +VOID +EncodeP ( + IN UINT32 LoopVar7 + ) +{ + UINT32 LoopVar5; + + UINT32 LoopVar6; + + LoopVar5 = 0; + LoopVar6 = LoopVar7; + while (LoopVar6 != 0) { + LoopVar6 >>= 1; + LoopVar5++; + } + + PutBits (mPTLen[LoopVar5], mPTCode[LoopVar5]); + if (LoopVar5 > 1) { + PutBits (LoopVar5 - 1, LoopVar7 & (0xFFFFU >> (17 - LoopVar5))); + } +} + +/** + Count the frequencies for the Extra Set. + +**/ +VOID +CountTFreq ( + VOID + ) +{ + INT32 LoopVar1; + + INT32 LoopVar3; + + INT32 LoopVar8; + + INT32 Count; + + for (LoopVar1 = 0; LoopVar1 < NT; LoopVar1++) { + mTFreq[LoopVar1] = 0; + } + + LoopVar8 = NC; + while (LoopVar8 > 0 && mCLen[LoopVar8 - 1] == 0) { + LoopVar8--; + } + + LoopVar1 = 0; + while (LoopVar1 < LoopVar8) { + LoopVar3 = mCLen[LoopVar1++]; + if (LoopVar3 == 0) { + Count = 1; + while (LoopVar1 < LoopVar8 && mCLen[LoopVar1] == 0) { + LoopVar1++; + 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 { + ASSERT ((LoopVar3+2) < (2 * NT - 1)); + mTFreq[LoopVar3 + 2]++; + } + } +} + +/** + Outputs the code length array for the Extra Set or the Position Set. + + @param[in] LoopVar8 The number of symbols. + @param[in] nbit The number of bits needed to represent 'LoopVar8'. + @param[in] Special The special symbol that needs to be take care of. + +**/ +VOID +WritePTLen ( + IN INT32 LoopVar8, + IN INT32 nbit, + IN INT32 Special + ) +{ + INT32 LoopVar1; + + INT32 LoopVar3; + + while (LoopVar8 > 0 && mPTLen[LoopVar8 - 1] == 0) { + LoopVar8--; + } + + PutBits (nbit, LoopVar8); + LoopVar1 = 0; + while (LoopVar1 < LoopVar8) { + LoopVar3 = mPTLen[LoopVar1++]; + if (LoopVar3 <= 6) { + PutBits (3, LoopVar3); + } else { + PutBits (LoopVar3 - 3, (1U << (LoopVar3 - 3)) - 2); + } + + if (LoopVar1 == Special) { + while (LoopVar1 < 6 && mPTLen[LoopVar1] == 0) { + LoopVar1++; + } + + PutBits (2, (LoopVar1 - 3) & 3); + } + } +} + +/** + Outputs the code length array for Char&Length Set. +**/ +VOID +WriteCLen ( + VOID + ) +{ + INT32 LoopVar1; + + INT32 LoopVar3; + + INT32 LoopVar8; + + INT32 Count; + + LoopVar8 = NC; + while (LoopVar8 > 0 && mCLen[LoopVar8 - 1] == 0) { + LoopVar8--; + } + + PutBits (CBIT, LoopVar8); + LoopVar1 = 0; + while (LoopVar1 < LoopVar8) { + LoopVar3 = mCLen[LoopVar1++]; + if (LoopVar3 == 0) { + Count = 1; + while (LoopVar1 < LoopVar8 && mCLen[LoopVar1] == 0) { + LoopVar1++; + Count++; + } + + if (Count <= 2) { + for (LoopVar3 = 0; LoopVar3 < Count; LoopVar3++) { + 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 { + ASSERT ((LoopVar3+2) < NPT); + PutBits (mPTLen[LoopVar3 + 2], mPTCode[LoopVar3 + 2]); + } + } +} + +/** + Huffman code the block and output it. + +**/ +VOID +SendBlock ( + VOID + ) +{ + UINT32 LoopVar1; + + UINT32 LoopVar3; + + 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 (LoopVar1 = 0; LoopVar1 < Size; LoopVar1++) { + if (LoopVar1 % UINT8_BIT == 0) { + Flags = mBuf[Pos++]; + } else { + Flags <<= 1; + } + + if ((Flags & (1U << (UINT8_BIT - 1))) != 0) { + EncodeC (mBuf[Pos++] + (1U << UINT8_BIT)); + LoopVar3 = mBuf[Pos++] << UINT8_BIT; + LoopVar3 += mBuf[Pos++]; + + EncodeP (LoopVar3); + } else { + EncodeC (mBuf[Pos++]); + } + } + + SetMem (mCFreq, NC * sizeof (UINT16), 0); + SetMem (mPFreq, NP * sizeof (UINT16), 0); +} + +/** + Start the huffman encoding. + +**/ +VOID +HufEncodeStart ( + VOID + ) +{ + SetMem (mCFreq, NC * sizeof (UINT16), 0); + SetMem (mPFreq, NP * sizeof (UINT16), 0); + + mOutputPos = mOutputMask = 0; + + mBitCount = UINT8_BIT; + mSubBitBuf = 0; +} + +/** + Outputs an Original Character or a Pointer. + + @param[in] LoopVar5 The original character or the 'String Length' element of + a Pointer. + @param[in] LoopVar7 The 'Position' field of a Pointer. +**/ +VOID +CompressOutput ( + IN UINT32 LoopVar5, + IN UINT32 LoopVar7 + ) +{ + STATIC UINT32 CPos; + + if ((mOutputMask >>= 1) == 0) { + mOutputMask = 1U << (UINT8_BIT - 1); + if (mOutputPos >= mBufSiz - 3 * UINT8_BIT) { + SendBlock (); + mOutputPos = 0; + } + + CPos = mOutputPos++; + mBuf[CPos] = 0; + } + + mBuf[mOutputPos++] = (UINT8)LoopVar5; + mCFreq[LoopVar5]++; + if (LoopVar5 >= (1U << UINT8_BIT)) { + mBuf[CPos] = (UINT8)(mBuf[CPos]|mOutputMask); + mBuf[mOutputPos++] = (UINT8)(LoopVar7 >> UINT8_BIT); + mBuf[mOutputPos++] = (UINT8)LoopVar7; + LoopVar5 = 0; + while (LoopVar7 != 0) { + LoopVar7 >>= 1; + LoopVar5++; + } + + mPFreq[LoopVar5]++; + } +} + +/** + End the huffman encoding. + +**/ +VOID +HufEncodeEnd ( + VOID + ) +{ + SendBlock (); + + // + // Flush remaining bits + // + PutBits (UINT8_BIT - 1, 0); +} + +/** + The main controlling routine for compression process. + + @retval EFI_SUCCESS The compression is successful. + @retval EFI_OUT_0F_RESOURCES Not enough memory for compression process. +**/ +EFI_STATUS +Encode ( + VOID + ) +{ + 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; + if (!GetNextMatch ()) { + Status = EFI_OUT_OF_RESOURCES; + } + + 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 + // + CompressOutput (mText[mPos - 1], 0); + } else { + // + // Outputting a pointer is beneficial enough, do it. + // + + CompressOutput ( + LastMatchLen + (UINT8_MAX + 1 - THRESHOLD), + (mPos - LastMatchPos - 2) & (WNDSIZ - 1) + ); + LastMatchLen--; + while (LastMatchLen > 0) { + if (!GetNextMatch ()) { + Status = EFI_OUT_OF_RESOURCES; + } + + LastMatchLen--; + } + + if (mMatchLen > mRemainder) { + mMatchLen = mRemainder; + } + } + } + + HufEncodeEnd (); + FreeMemory (); + return (Status); +} + +/** + The compression routine. + + @param[in] SrcBuffer The buffer containing the source data. + @param[in] SrcSize Number of bytes in SrcBuffer. + @param[in] DstBuffer The buffer to put the compressed image in. + @param[in, out] DstSize On input the size (in bytes) of DstBuffer, on + return the number of bytes placed in DstBuffer. + + @retval EFI_SUCCESS The compression was successful. + @retval EFI_BUFFER_TOO_SMALL The buffer was too small. DstSize is required. +**/ +EFI_STATUS +Compress ( + IN VOID *SrcBuffer, + IN UINT64 SrcSize, + IN VOID *DstBuffer, + IN OUT UINT64 *DstSize + ) +{ + 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; + } +} |
