diff --git a/Tiano/EfiTianoCompress.c b/Tiano/EfiTianoCompress.c index 0e64f5b..d13864c 100644 --- a/Tiano/EfiTianoCompress.c +++ b/Tiano/EfiTianoCompress.c @@ -1,4 +1,20 @@ -/* EfiTianoCompress.c +/* EFI11/Tiano Compress Implementation + +Copyright (c) 2014, Nikolaj Schlej +Copyright (c) 2006 - 2008, Intel Corporation +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, +WITHWARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +Module Name: + +EfiTianoCompress.c + +Abstract: Compression routine. The compression algorithm is a mixture of LZ77 and Huffman coding. LZ77 transforms the source data into a @@ -6,1400 +22,295 @@ 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) 2014, Nikolaj Schlej. All rights reserved.
-Copyright (c) 2007 - 2011, 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. - -**/ +*/ #include "EfiTianoCompress.h" // // Macro Definitions // -typedef INT16 NODE; -#ifndef UINT8_MAX -#define UINT8_MAX 0xff -#endif -#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) +#undef UINT8_MAX +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 4 -#define NT (CODE_BIT + 3) -#define TBIT 5 +#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 +#define NPT NT #else -#define NPT NP +#define NPT NP #endif // // Function Prototypes // -/** -Put a dword to output stream +STATIC + VOID + PutDword( + UINT32 Data + ); -@param[in] Data The dword to put. -**/ -VOID -EFIAPI -PutDword( -IN UINT32 Data +STATIC + INT32 + AllocateMemory ( + VOID + ); + +STATIC + VOID + FreeMemory ( + VOID + ); + +STATIC + VOID + InitSlide ( + VOID + ); + +STATIC + NODE + Child ( + NODE NodeQ, + UINT8 CharC + ); + +STATIC + VOID + MakeChild ( + NODE NodeQ, + UINT8 CharC, + NODE NodeR + ); + +STATIC + VOID + Split ( + NODE Old + ); + +STATIC + VOID + InsertNode ( + VOID + ); + +STATIC + VOID + DeleteNode ( + VOID + ); + +STATIC + VOID + GetNextMatch ( + VOID + ); + +STATIC + INT32 + Encode ( + VOID + ); + +STATIC + VOID + CountTFreq ( + VOID + ); + +STATIC + VOID + WritePTLen ( + INT32 Number, + INT32 nbit, + INT32 Special + ); + +STATIC + VOID + WriteCLen ( + VOID + ); + +STATIC + VOID + EncodeC ( + INT32 Value + ); + +STATIC + VOID + EncodeP ( + UINT32 Value + ); + +STATIC + VOID + SendBlock ( + VOID + ); + +STATIC + VOID + Output ( + UINT32 c, + UINT32 p + ); + +STATIC + VOID + HufEncodeStart ( + VOID + ); + +STATIC + VOID + HufEncodeEnd ( + VOID + ); + +STATIC + VOID + MakeCrcTable ( + VOID + ); + +STATIC + VOID + PutBits ( + INT32 Number, + UINT32 Value + ); + +STATIC + INT32 + FreadCrc ( + UINT8 *Pointer, + INT32 Number + ); + +STATIC + VOID + InitPutBits ( + VOID + ); + +STATIC + VOID + CountLen ( + INT32 Index + ); + +STATIC + VOID + MakeLen ( + INT32 Root + ); + +STATIC + VOID + DownHeap ( + INT32 Index + ); + +STATIC + VOID + MakeCode ( + INT32 Number, + UINT8 Len[ ], + UINT16 Code[] +); + +STATIC + INT32 + MakeTree ( + INT32 NParm, + UINT16 FreqParm[], + UINT8 LenParm[ ], + UINT16 CodeParm[] ); // // Global Variables // -STATIC UINT8 *mSrc; -STATIC UINT8 *mDst; -STATIC UINT8 *mSrcUpperLimit; -STATIC UINT8 *mDstUpperLimit; +STATIC UINT8 *mSrc, *mDst, *mSrcUpperLimit, *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 UINT8 *mLevel, *mText, *mChildCount, *mBuf, mCLen[NC], mPTLen[NPT], *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 INT32 mRemainder, mMatchLen, mBitCount, mHeapSize, mN; +STATIC UINT32 mBufSiz = 0, mOutputPos, mOutputMask, mSubBitBuf, mCrc; +STATIC UINT32 mCompSize, 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 UINT16 *mFreq, *mSortPtr, mLenCnt[17], mLeft[2 * NC - 1], mRight[2 * NC - 1], mCrcTable[UINT8_MAX + 1], + mCFreq[2 * NC - 1], mCCode[NC], mPFreq[2 * NP - 1], mPTCode[NPT], 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; +STATIC UINT8 mPbit; -STATIC UINT8 mPBit; +STATIC NODE mPos, mMatchPos, mAvail, *mPosition, *mParent, *mPrev, *mNext = NULL; -VOID* SetMem(VOID* dst, size_t size, UINT8 value) { - return memset(dst, value, size); -} - -VOID* CopyMem(VOID* dst, CONST VOID* src, size_t size) { - return memcpy(dst, src, size); -} - -VOID* AllocateZeroPool(size_t size) { - VOID* pool; - if (!size) - return NULL; - - pool = malloc(size); - memset(pool, 0x00, size); - return pool; -} - -VOID FreePool(VOID* pool) { - if (pool != NULL) - free(pool); -} - -/** -Make a CRC table. - -**/ -VOID -EFIAPI -MakeCrcTable( -VOID +// +// functions +// +UINT8 +EfiCompress( +CONST VOID *SrcBuffer, +CONST UINT64 SrcSize, +VOID *DstBuffer, +UINT64 *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. + +Returns: + +EFI_BUFFER_TOO_SMALL - The DstBuffer is too small. 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. + +--*/ { - 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 -EFIAPI -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 -EFIAPI -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 -EFIAPI -FreeMemory( -VOID -) -{ - FreePool(mText); - FreePool(mLevel); - FreePool(mChildCount); - FreePool(mPosition); - FreePool(mParent); - FreePool(mPrev); - FreePool(mNext); - FreePool(mBuf); -} - -/** -Initialize String Info Log data structures. -**/ -VOID -EFIAPI -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 -EFIAPI -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 -EFIAPI -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 -EFIAPI -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 -EFIAPI -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 -EFIAPI -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 -EFIAPI -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 -EFIAPI -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 -EFIAPI -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 -EFIAPI -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 -EFIAPI -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 -EFIAPI -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 -EFIAPI -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 -EFIAPI -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 -EFIAPI -EncodeC( -IN INT32 LoopVar5 -) -{ - PutBits(mCLen[LoopVar5], mCCode[LoopVar5]); -} - -/** -Encode a unsigned 32 bit number. - -@param[in] LoopVar7 The number to encode. -**/ -VOID -EFIAPI -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 -EFIAPI -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 -EFIAPI -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 -EFIAPI -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 -EFIAPI -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, mPBit, -1); - } - else { - PutBits(mPBit, 0); - PutBits(mPBit, 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 -EFIAPI -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 -EFIAPI -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 -EFIAPI -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 -EFIAPI -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 The 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 -EFIAPI -Compress( -IN VOID *SrcBuffer, -IN UINT64 SrcSize, -IN VOID *DstBuffer, -IN OUT UINT64 *DstSize -) -{ - EFI_STATUS Status; + INT32 Status; // // Initializations // + mPbit = 4; + mBufSiz = 0; mBuf = NULL; mText = NULL; @@ -1410,7 +321,7 @@ IN OUT UINT64 *DstSize mPrev = NULL; mNext = NULL; - mSrc = SrcBuffer; + mSrc = (UINT8*) SrcBuffer; mSrcUpperLimit = mSrc + SrcSize; mDst = DstBuffer; mDstUpperLimit = mDst + *DstSize; @@ -1427,7 +338,7 @@ IN OUT UINT64 *DstSize // Compress it // Status = Encode(); - if (EFI_ERROR(Status)) { + if (Status) { return EFI_OUT_OF_RESOURCES; } // @@ -1437,7 +348,7 @@ IN OUT UINT64 *DstSize *mDst++ = 0; } // - // Fill in compressed size and original size + // Fill compressed size and original size // mDst = DstBuffer; PutDword(mCompSize + 1); @@ -1454,20 +365,1489 @@ IN OUT UINT64 *DstSize *DstSize = mCompSize + 1 + 8; return EFI_SUCCESS; } + } -UINT8 EfiCompress(CONST VOID* SrcBuffer, CONST UINT64 SrcSize, VOID* DstBuffer, UINT64* DstSize) +UINT8 +TianoCompress ( +CONST VOID *SrcBuffer, +CONST UINT64 SrcSize, +VOID *DstBuffer, +UINT64 *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 UEFI 2.0 de/compression algorithm. + Version 2 for Tiano de/compression algorithm. + + Returns: + + EFI_BUFFER_TOO_SMALL - The DstBuffer is too small. 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. + + --*/ { - VOID* buffer = (VOID*)SrcBuffer; - UINT64 size = SrcSize; - mPBit = 4; - return Compress(buffer, size, DstBuffer, DstSize); + INT32 Status; + + // + // Initializations + // + mPbit = 5; + + mBufSiz = 0; + mBuf = NULL; + mText = NULL; + mLevel = NULL; + mChildCount = NULL; + mPosition = NULL; + mParent = NULL; + mPrev = NULL; + mNext = NULL; + + mSrc = (UINT8*) 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 (Status) { + return EFI_OUT_OF_RESOURCES; + } + // + // Null terminate the compressed data + // + if (mDst < mDstUpperLimit) { + *mDst++ = 0; + } + // + // Fill 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; + } + } -UINT8 TianoCompress(CONST VOID* SrcBuffer, CONST UINT64 SrcSize, VOID* DstBuffer, UINT64* DstSize) +STATIC + VOID + PutDword ( + UINT32 Data + ) + /*++ + + Routine Description: + + Put a DWORD to output stream + + Arguments: + + Data - the DWORD to put + + Returns: (VOID) + + --*/ { - VOID* buffer = (VOID*)SrcBuffer; - UINT64 size = SrcSize; - mPBit = 5; - return Compress(buffer, size, DstBuffer, DstSize); -} \ No newline at end of file + 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 + INT32 + AllocateMemory ( + VOID + ) + /*++ + + Routine Description: + + Allocate memory spaces for data structures used compression process + + Arguments: + 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 = (NODE) WNDSIZ; Index <= (NODE) WNDSIZ + UINT8_MAX; Index++) { + mLevel[Index] = 1; + mPosition[Index] = NIL; // sentinel + } + + for (Index = (NODE) WNDSIZ; Index < (NODE) WNDSIZ * 2; Index++) { + mParent[Index] = NIL; + } + + mAvail = 1; + for (Index = 1; Index < (NODE) WNDSIZ - 1; Index++) { + mNext[Index] = (NODE) (Index + 1); + } + + mNext[WNDSIZ - 1] = NIL; + for (Index = (NODE) WNDSIZ * 2; Index <= (NODE) MAX_HASH_VAL; Index++) { + mNext[Index] = NIL; + } +} + +STATIC + NODE + Child ( + NODE NodeQ, + 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 ( + NODE Parent, + UINT8 CharC, + 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. Traverse the tree + // from bottom up to get to a proper starting point. + // The usage of PERC_FLAG ensures proper node deletion + // 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 < (NODE) 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 >= (NODE) 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 >= (NODE) 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 < (NODE) 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 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 + INT32 + Encode ( + VOID + ) + /*++ + + Routine Description: + + The mac controlling routine for compression process. + + Arguments: (VOID) + + Returns: + + EFI_SUCCESS - The compression is successful + EFI_OUT_0F_RESOURCES - Not enough memory for compression process + + --*/ +{ + INT32 Status; + INT32 LastMatchLen; + NODE LastMatchPos; + + Status = AllocateMemory (); + if (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 ( + INT32 Number, + INT32 nbit, + 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 ( + INT32 Value + ) +{ + PutBits (mCLen[Value], mCCode[Value]); +} + +STATIC + VOID + EncodeP ( + 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, mPbit, -1); + } else { + PutBits (mPbit, 0); + PutBits (mPbit, 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 ( + UINT32 CharC, + 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 outputting 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 ( + INT32 Number, + 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 ( + UINT8 *Pointer, + INT32 Number + ) + /*++ + + Routine Description: + + Read 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 ( + 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 ( + 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 ( + 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 ( + INT32 Number, + UINT8 Len[ ], + 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 ( + INT32 NParm, + UINT16 FreqParm[], + UINT8 LenParm[ ], + 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; +} diff --git a/guidlineedit.cpp b/guidlineedit.cpp new file mode 100644 index 0000000..a441e0c --- /dev/null +++ b/guidlineedit.cpp @@ -0,0 +1,61 @@ +/* guidlineedit.cpp + + Copyright (c) 2014, Nikolaj Schlej. 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. + + */ + +#include "guidlineedit.h" + +GuidLineEdit::GuidLineEdit(QWidget * parent) + :QLineEdit(parent) +{ +} + +GuidLineEdit::GuidLineEdit(const QString & contents, QWidget * parent) + :QLineEdit(contents, parent) +{ +} + +GuidLineEdit::~GuidLineEdit() +{ +} + +void GuidLineEdit::keyPressEvent(QKeyEvent * event) +{ + if (event == QKeySequence::Delete || event->key() == Qt::Key_Backspace) + { + int pos = cursorPosition(); + if (event->key() == Qt::Key_Backspace && pos > 0) { + cursorBackward(false); + pos = cursorPosition(); + } + + QString txt = text(); + QString selected = selectedText(); + + if (!selected.isEmpty()) { + pos = QLineEdit::selectionStart(); + for (int i = pos; i < pos + selected.count(); i++) + if (txt[i] != QChar('-')) + txt[i] = QChar('.'); + } + else + txt[pos] = QChar('.'); + + setCursorPosition(0); + insert(txt); + setCursorPosition(pos); + + return; + } + + // Call original event handler + QLineEdit::keyPressEvent(event); +} \ No newline at end of file diff --git a/guidlineedit.h b/guidlineedit.h new file mode 100644 index 0000000..5324b7b --- /dev/null +++ b/guidlineedit.h @@ -0,0 +1,36 @@ +/* guidlineedit.h + + Copyright (c) 2014, Nikolaj Schlej. 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. + + */ + +#ifndef __GUIDLINEEDIT_H__ +#define __GUIDLINEEDIT_H__ + +#include +#include +#include +#include + +#include "basetypes.h" + +class GuidLineEdit : public QLineEdit +{ +public: + GuidLineEdit(QWidget * parent = 0); + GuidLineEdit(const QString & contents, QWidget * parent = 0); + ~GuidLineEdit(); + +protected: + void keyPressEvent(QKeyEvent * event); + +}; + +#endif diff --git a/searchdialog.ui b/searchdialog.ui index 4bcc006..c1e2f56 100644 --- a/searchdialog.ui +++ b/searchdialog.ui @@ -101,7 +101,7 @@ - + Consolas @@ -217,6 +217,13 @@ + + + GuidLineEdit + QLineEdit +
guidlineedit.h
+
+
tabWidget hexEdit diff --git a/uefitool.cpp b/uefitool.cpp index 58e8f69..1332648 100644 --- a/uefitool.cpp +++ b/uefitool.cpp @@ -17,7 +17,7 @@ UEFITool::UEFITool(QWidget *parent) : QMainWindow(parent), ui(new Ui::UEFITool), -version(tr("0.18.6")) +version(tr("0.18.7")) { clipboard = QApplication::clipboard(); diff --git a/uefitool.pro b/uefitool.pro index 7ce3ed9..73e258c 100644 --- a/uefitool.pro +++ b/uefitool.pro @@ -14,6 +14,7 @@ SOURCES += uefitool_main.cpp \ treeitem.cpp \ treemodel.cpp \ messagelistitem.cpp \ + guidlineedit.cpp \ LZMA/LzmaCompress.c \ LZMA/LzmaDecompress.c \ LZMA/SDK/C/LzFind.c \ @@ -35,6 +36,7 @@ HEADERS += uefitool.h \ treeitem.h \ treemodel.h \ messagelistitem.h \ + guidlineedit.h \ LZMA/LzmaCompress.h \ LZMA/LzmaDecompress.h \ Tiano/EfiTianoDecompress.h \ diff --git a/uefitool.ui b/uefitool.ui index 3bcb6bc..3e92815 100644 --- a/uefitool.ui +++ b/uefitool.ui @@ -497,7 +497,7 @@ - C&opy All + C&opy all Ctrl+Alt+C