| /** @file | |
| 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 - 2014, Intel Corporation. All rights reserved.<BR> | |
| 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 "Compress.h" | |
| #include "TianoCompress.h" | |
| #include "EfiUtilityMsgs.h" | |
| #include "ParseInf.h" | |
| #include <stdio.h> | |
| #include "assert.h" | |
| // | |
| // Macro Definitions | |
| // | |
| static BOOLEAN VerboseMode = FALSE; | |
| static BOOLEAN QuietMode = FALSE; | |
| #undef UINT8_MAX | |
| #define UINT8_MAX 0xff | |
| #define UINT8_BIT 8 | |
| #define THRESHOLD 3 | |
| #define INIT_CRC 0 | |
| #define WNDBIT 19 | |
| #define WNDSIZ (1U << WNDBIT) | |
| #define MAXMATCH 256 | |
| #define BLKSIZ (1U << 14) // 16 * 1024U | |
| #define PERC_FLAG 0x80000000U | |
| #define CODE_BIT 16 | |
| #define NIL 0 | |
| #define MAX_HASH_VAL (3 * WNDSIZ + (WNDSIZ / 512 + 1) * UINT8_MAX) | |
| #define HASH(p, c) ((p) + ((c) << (WNDBIT - 9)) + WNDSIZ * 2) | |
| #define CRCPOLY 0xA001 | |
| #define UPDATE_CRC(c) mCrc = mCrcTable[(mCrc ^ (c)) & 0xFF] ^ (mCrc >> UINT8_BIT) | |
| // | |
| // C: the Char&Len Set; P: the Position Set; T: the exTra Set | |
| // | |
| //#define NC (UINT8_MAX + MAXMATCH + 2 - THRESHOLD) | |
| #define CBIT 9 | |
| #define NP (WNDBIT + 1) | |
| #define PBIT 5 | |
| //#define NT (CODE_BIT + 3) | |
| //#define TBIT 5 | |
| //#if NT > NP | |
| //#define NPT NT | |
| //#else | |
| //#define NPT NP | |
| //#endif | |
| // | |
| // Global Variables | |
| // | |
| STATIC BOOLEAN ENCODE = FALSE; | |
| STATIC BOOLEAN DECODE = FALSE; | |
| STATIC UINT8 *mSrc, *mDst, *mSrcUpperLimit, *mDstUpperLimit; | |
| STATIC UINT8 *mLevel, *mText, *mChildCount, *mBuf, mCLen[NC], mPTLen[NPT], *mLen; | |
| STATIC INT16 mHeap[NC + 1]; | |
| STATIC INT32 mRemainder, mMatchLen, mBitCount, mHeapSize, mN; | |
| STATIC UINT32 mBufSiz = 0, mOutputPos, mOutputMask, mSubBitBuf, mCrc; | |
| STATIC UINT32 mCompSize, mOrigSize; | |
| STATIC UINT16 *mFreq, *mSortPtr, mLenCnt[17], mLeft[2 * NC - 1], mRight[2 * NC - 1], mCrcTable[UINT8_MAX + 1], | |
| mCFreq[2 * NC - 1], mCCode[NC], mPFreq[2 * NP - 1], mPTCode[NPT], mTFreq[2 * NT - 1]; | |
| STATIC NODE mPos, mMatchPos, mAvail, *mPosition, *mParent, *mPrev, *mNext = NULL; | |
| static UINT64 DebugLevel; | |
| static BOOLEAN DebugMode; | |
| // | |
| // functions | |
| // | |
| EFI_STATUS | |
| TianoCompress ( | |
| IN UINT8 *SrcBuffer, | |
| IN UINT32 SrcSize, | |
| IN UINT8 *DstBuffer, | |
| IN OUT UINT32 *DstSize | |
| ) | |
| /*++ | |
| Routine Description: | |
| The internal implementation of [Efi/Tiano]Compress(). | |
| Arguments: | |
| SrcBuffer - The buffer storing the source data | |
| SrcSize - The size of source data | |
| DstBuffer - The buffer to store the compressed data | |
| Version - The version of de/compression algorithm. | |
| Version 1 for EFI 1.1 de/compression algorithm. | |
| Version 2 for Tiano de/compression algorithm. | |
| Returns: | |
| EFI_BUFFER_TOO_SMALL - The DstBuffer is too small. In this case, | |
| DstSize contains the size needed. | |
| EFI_SUCCESS - Compression is successful. | |
| EFI_OUT_OF_RESOURCES - No resource to complete function. | |
| EFI_INVALID_PARAMETER - Parameter supplied is wrong. | |
| --*/ | |
| { | |
| EFI_STATUS Status; | |
| // | |
| // Initializations | |
| // | |
| mBufSiz = 0; | |
| mBuf = NULL; | |
| mText = NULL; | |
| mLevel = NULL; | |
| mChildCount = NULL; | |
| mPosition = NULL; | |
| mParent = NULL; | |
| mPrev = NULL; | |
| mNext = NULL; | |
| mSrc = SrcBuffer; | |
| mSrcUpperLimit = mSrc + SrcSize; | |
| mDst = DstBuffer; | |
| mDstUpperLimit = mDst +*DstSize; | |
| PutDword (0L); | |
| PutDword (0L); | |
| MakeCrcTable (); | |
| mOrigSize = mCompSize = 0; | |
| mCrc = INIT_CRC; | |
| // | |
| // Compress it | |
| // | |
| Status = Encode (); | |
| if (EFI_ERROR (Status)) { | |
| return EFI_OUT_OF_RESOURCES; | |
| } | |
| // | |
| // Null terminate the compressed data | |
| // | |
| if (mDst < mDstUpperLimit) { | |
| *mDst++ = 0; | |
| } | |
| // | |
| // Fill in compressed size and original size | |
| // | |
| mDst = DstBuffer; | |
| PutDword (mCompSize + 1); | |
| PutDword (mOrigSize); | |
| // | |
| // Return | |
| // | |
| if (mCompSize + 1 + 8 > *DstSize) { | |
| *DstSize = mCompSize + 1 + 8; | |
| return EFI_BUFFER_TOO_SMALL; | |
| } else { | |
| *DstSize = mCompSize + 1 + 8; | |
| return EFI_SUCCESS; | |
| } | |
| } | |
| STATIC | |
| VOID | |
| PutDword ( | |
| IN UINT32 Data | |
| ) | |
| /*++ | |
| Routine Description: | |
| Put a dword to output stream | |
| Arguments: | |
| Data - the dword to put | |
| Returns: (VOID) | |
| --*/ | |
| { | |
| if (mDst < mDstUpperLimit) { | |
| *mDst++ = (UINT8) (((UINT8) (Data)) & 0xff); | |
| } | |
| if (mDst < mDstUpperLimit) { | |
| *mDst++ = (UINT8) (((UINT8) (Data >> 0x08)) & 0xff); | |
| } | |
| if (mDst < mDstUpperLimit) { | |
| *mDst++ = (UINT8) (((UINT8) (Data >> 0x10)) & 0xff); | |
| } | |
| if (mDst < mDstUpperLimit) { | |
| *mDst++ = (UINT8) (((UINT8) (Data >> 0x18)) & 0xff); | |
| } | |
| } | |
| STATIC | |
| EFI_STATUS | |
| AllocateMemory ( | |
| VOID | |
| ) | |
| /*++ | |
| Routine Description: | |
| Allocate memory spaces for data structures used in compression process | |
| Argements: | |
| VOID | |
| Returns: | |
| EFI_SUCCESS - Memory is allocated successfully | |
| EFI_OUT_OF_RESOURCES - Allocation fails | |
| --*/ | |
| { | |
| UINT32 Index; | |
| mText = malloc (WNDSIZ * 2 + MAXMATCH); | |
| for (Index = 0; Index < WNDSIZ * 2 + MAXMATCH; Index++) { | |
| mText[Index] = 0; | |
| } | |
| mLevel = malloc ((WNDSIZ + UINT8_MAX + 1) * sizeof (*mLevel)); | |
| mChildCount = malloc ((WNDSIZ + UINT8_MAX + 1) * sizeof (*mChildCount)); | |
| mPosition = malloc ((WNDSIZ + UINT8_MAX + 1) * sizeof (*mPosition)); | |
| mParent = malloc (WNDSIZ * 2 * sizeof (*mParent)); | |
| mPrev = malloc (WNDSIZ * 2 * sizeof (*mPrev)); | |
| mNext = malloc ((MAX_HASH_VAL + 1) * sizeof (*mNext)); | |
| mBufSiz = BLKSIZ; | |
| mBuf = malloc (mBufSiz); | |
| while (mBuf == NULL) { | |
| mBufSiz = (mBufSiz / 10U) * 9U; | |
| if (mBufSiz < 4 * 1024U) { | |
| return EFI_OUT_OF_RESOURCES; | |
| } | |
| mBuf = malloc (mBufSiz); | |
| } | |
| mBuf[0] = 0; | |
| return EFI_SUCCESS; | |
| } | |
| VOID | |
| FreeMemory ( | |
| VOID | |
| ) | |
| /*++ | |
| Routine Description: | |
| Called when compression is completed to free memory previously allocated. | |
| Arguments: (VOID) | |
| Returns: (VOID) | |
| --*/ | |
| { | |
| if (mText != NULL) { | |
| free (mText); | |
| } | |
| if (mLevel != NULL) { | |
| free (mLevel); | |
| } | |
| if (mChildCount != NULL) { | |
| free (mChildCount); | |
| } | |
| if (mPosition != NULL) { | |
| free (mPosition); | |
| } | |
| if (mParent != NULL) { | |
| free (mParent); | |
| } | |
| if (mPrev != NULL) { | |
| free (mPrev); | |
| } | |
| if (mNext != NULL) { | |
| free (mNext); | |
| } | |
| if (mBuf != NULL) { | |
| free (mBuf); | |
| } | |
| return ; | |
| } | |
| STATIC | |
| VOID | |
| InitSlide ( | |
| VOID | |
| ) | |
| /*++ | |
| Routine Description: | |
| Initialize String Info Log data structures | |
| Arguments: (VOID) | |
| Returns: (VOID) | |
| --*/ | |
| { | |
| NODE Index; | |
| for (Index = WNDSIZ; Index <= WNDSIZ + UINT8_MAX; Index++) { | |
| mLevel[Index] = 1; | |
| mPosition[Index] = NIL; // sentinel | |
| } | |
| for (Index = WNDSIZ; Index < WNDSIZ * 2; Index++) { | |
| mParent[Index] = NIL; | |
| } | |
| mAvail = 1; | |
| for (Index = 1; Index < WNDSIZ - 1; Index++) { | |
| mNext[Index] = (NODE) (Index + 1); | |
| } | |
| mNext[WNDSIZ - 1] = NIL; | |
| for (Index = WNDSIZ * 2; Index <= MAX_HASH_VAL; Index++) { | |
| mNext[Index] = NIL; | |
| } | |
| } | |
| STATIC | |
| NODE | |
| Child ( | |
| IN NODE NodeQ, | |
| IN UINT8 CharC | |
| ) | |
| /*++ | |
| Routine Description: | |
| Find child node given the parent node and the edge character | |
| Arguments: | |
| NodeQ - the parent node | |
| CharC - the edge character | |
| Returns: | |
| The child node (NIL if not found) | |
| --*/ | |
| { | |
| NODE NodeR; | |
| NodeR = mNext[HASH (NodeQ, CharC)]; | |
| // | |
| // sentinel | |
| // | |
| mParent[NIL] = NodeQ; | |
| while (mParent[NodeR] != NodeQ) { | |
| NodeR = mNext[NodeR]; | |
| } | |
| return NodeR; | |
| } | |
| STATIC | |
| VOID | |
| MakeChild ( | |
| IN NODE Parent, | |
| IN UINT8 CharC, | |
| IN NODE Child | |
| ) | |
| /*++ | |
| Routine Description: | |
| Create a new child for a given parent node. | |
| Arguments: | |
| Parent - the parent node | |
| CharC - the edge character | |
| Child - the child node | |
| Returns: (VOID) | |
| --*/ | |
| { | |
| NODE Node1; | |
| NODE Node2; | |
| Node1 = (NODE) HASH (Parent, CharC); | |
| Node2 = mNext[Node1]; | |
| mNext[Node1] = Child; | |
| mNext[Child] = Node2; | |
| mPrev[Node2] = Child; | |
| mPrev[Child] = Node1; | |
| mParent[Child] = Parent; | |
| mChildCount[Parent]++; | |
| } | |
| STATIC | |
| VOID | |
| Split ( | |
| NODE Old | |
| ) | |
| /*++ | |
| Routine Description: | |
| Split a node. | |
| Arguments: | |
| Old - the node to split | |
| Returns: (VOID) | |
| --*/ | |
| { | |
| NODE New; | |
| NODE TempNode; | |
| New = mAvail; | |
| mAvail = mNext[New]; | |
| mChildCount[New] = 0; | |
| TempNode = mPrev[Old]; | |
| mPrev[New] = TempNode; | |
| mNext[TempNode] = New; | |
| TempNode = mNext[Old]; | |
| mNext[New] = TempNode; | |
| mPrev[TempNode] = New; | |
| mParent[New] = mParent[Old]; | |
| mLevel[New] = (UINT8) mMatchLen; | |
| mPosition[New] = mPos; | |
| MakeChild (New, mText[mMatchPos + mMatchLen], Old); | |
| MakeChild (New, mText[mPos + mMatchLen], mPos); | |
| } | |
| STATIC | |
| VOID | |
| InsertNode ( | |
| VOID | |
| ) | |
| /*++ | |
| Routine Description: | |
| Insert string info for current position into the String Info Log | |
| Arguments: (VOID) | |
| Returns: (VOID) | |
| --*/ | |
| { | |
| NODE NodeQ; | |
| NODE NodeR; | |
| NODE Index2; | |
| NODE NodeT; | |
| UINT8 CharC; | |
| UINT8 *t1; | |
| UINT8 *t2; | |
| if (mMatchLen >= 4) { | |
| // | |
| // We have just got a long match, the target tree | |
| // can be located by MatchPos + 1. Travese the tree | |
| // from bottom up to get to a proper starting point. | |
| // The usage of PERC_FLAG ensures proper node deletion | |
| // in DeleteNode() later. | |
| // | |
| mMatchLen--; | |
| NodeR = (NODE) ((mMatchPos + 1) | WNDSIZ); | |
| NodeQ = mParent[NodeR]; | |
| while (NodeQ == NIL) { | |
| NodeR = mNext[NodeR]; | |
| NodeQ = mParent[NodeR]; | |
| } | |
| while (mLevel[NodeQ] >= mMatchLen) { | |
| NodeR = NodeQ; | |
| NodeQ = mParent[NodeQ]; | |
| } | |
| NodeT = NodeQ; | |
| while (mPosition[NodeT] < 0) { | |
| mPosition[NodeT] = mPos; | |
| NodeT = mParent[NodeT]; | |
| } | |
| if (NodeT < WNDSIZ) { | |
| mPosition[NodeT] = (NODE) (mPos | (UINT32) PERC_FLAG); | |
| } | |
| } else { | |
| // | |
| // Locate the target tree | |
| // | |
| NodeQ = (NODE) (mText[mPos] + WNDSIZ); | |
| CharC = mText[mPos + 1]; | |
| NodeR = Child (NodeQ, CharC); | |
| if (NodeR == NIL) { | |
| MakeChild (NodeQ, CharC, mPos); | |
| mMatchLen = 1; | |
| return ; | |
| } | |
| mMatchLen = 2; | |
| } | |
| // | |
| // Traverse down the tree to find a match. | |
| // Update Position value along the route. | |
| // Node split or creation is involved. | |
| // | |
| for (;;) { | |
| if (NodeR >= WNDSIZ) { | |
| Index2 = MAXMATCH; | |
| mMatchPos = NodeR; | |
| } else { | |
| Index2 = mLevel[NodeR]; | |
| mMatchPos = (NODE) (mPosition[NodeR] & (UINT32)~PERC_FLAG); | |
| } | |
| if (mMatchPos >= mPos) { | |
| mMatchPos -= WNDSIZ; | |
| } | |
| t1 = &mText[mPos + mMatchLen]; | |
| t2 = &mText[mMatchPos + mMatchLen]; | |
| while (mMatchLen < Index2) { | |
| if (*t1 != *t2) { | |
| Split (NodeR); | |
| return ; | |
| } | |
| mMatchLen++; | |
| t1++; | |
| t2++; | |
| } | |
| if (mMatchLen >= MAXMATCH) { | |
| break; | |
| } | |
| mPosition[NodeR] = mPos; | |
| NodeQ = NodeR; | |
| NodeR = Child (NodeQ, *t1); | |
| if (NodeR == NIL) { | |
| MakeChild (NodeQ, *t1, mPos); | |
| return ; | |
| } | |
| mMatchLen++; | |
| } | |
| NodeT = mPrev[NodeR]; | |
| mPrev[mPos] = NodeT; | |
| mNext[NodeT] = mPos; | |
| NodeT = mNext[NodeR]; | |
| mNext[mPos] = NodeT; | |
| mPrev[NodeT] = mPos; | |
| mParent[mPos] = NodeQ; | |
| mParent[NodeR] = NIL; | |
| // | |
| // Special usage of 'next' | |
| // | |
| mNext[NodeR] = mPos; | |
| } | |
| STATIC | |
| VOID | |
| DeleteNode ( | |
| VOID | |
| ) | |
| /*++ | |
| Routine Description: | |
| Delete outdated string info. (The Usage of PERC_FLAG | |
| ensures a clean deletion) | |
| Arguments: (VOID) | |
| Returns: (VOID) | |
| --*/ | |
| { | |
| NODE NodeQ; | |
| NODE NodeR; | |
| NODE NodeS; | |
| NODE NodeT; | |
| NODE NodeU; | |
| if (mParent[mPos] == NIL) { | |
| return ; | |
| } | |
| NodeR = mPrev[mPos]; | |
| NodeS = mNext[mPos]; | |
| mNext[NodeR] = NodeS; | |
| mPrev[NodeS] = NodeR; | |
| NodeR = mParent[mPos]; | |
| mParent[mPos] = NIL; | |
| if (NodeR >= WNDSIZ) { | |
| return ; | |
| } | |
| mChildCount[NodeR]--; | |
| if (mChildCount[NodeR] > 1) { | |
| return ; | |
| } | |
| NodeT = (NODE) (mPosition[NodeR] & (UINT32)~PERC_FLAG); | |
| if (NodeT >= mPos) { | |
| NodeT -= WNDSIZ; | |
| } | |
| NodeS = NodeT; | |
| NodeQ = mParent[NodeR]; | |
| NodeU = mPosition[NodeQ]; | |
| while (NodeU & (UINT32) PERC_FLAG) { | |
| NodeU &= (UINT32)~PERC_FLAG; | |
| if (NodeU >= mPos) { | |
| NodeU -= WNDSIZ; | |
| } | |
| if (NodeU > NodeS) { | |
| NodeS = NodeU; | |
| } | |
| mPosition[NodeQ] = (NODE) (NodeS | WNDSIZ); | |
| NodeQ = mParent[NodeQ]; | |
| NodeU = mPosition[NodeQ]; | |
| } | |
| if (NodeQ < WNDSIZ) { | |
| if (NodeU >= mPos) { | |
| NodeU -= WNDSIZ; | |
| } | |
| if (NodeU > NodeS) { | |
| NodeS = NodeU; | |
| } | |
| mPosition[NodeQ] = (NODE) (NodeS | WNDSIZ | (UINT32) PERC_FLAG); | |
| } | |
| NodeS = Child (NodeR, mText[NodeT + mLevel[NodeR]]); | |
| NodeT = mPrev[NodeS]; | |
| NodeU = mNext[NodeS]; | |
| mNext[NodeT] = NodeU; | |
| mPrev[NodeU] = NodeT; | |
| NodeT = mPrev[NodeR]; | |
| mNext[NodeT] = NodeS; | |
| mPrev[NodeS] = NodeT; | |
| NodeT = mNext[NodeR]; | |
| mPrev[NodeT] = NodeS; | |
| mNext[NodeS] = NodeT; | |
| mParent[NodeS] = mParent[NodeR]; | |
| mParent[NodeR] = NIL; | |
| mNext[NodeR] = mAvail; | |
| mAvail = NodeR; | |
| } | |
| STATIC | |
| VOID | |
| GetNextMatch ( | |
| VOID | |
| ) | |
| /*++ | |
| Routine Description: | |
| Advance the current position (read in new data if needed). | |
| Delete outdated string info. Find a match string for current position. | |
| Arguments: (VOID) | |
| Returns: (VOID) | |
| --*/ | |
| { | |
| INT32 Number; | |
| mRemainder--; | |
| mPos++; | |
| if (mPos == WNDSIZ * 2) { | |
| memmove (&mText[0], &mText[WNDSIZ], WNDSIZ + MAXMATCH); | |
| Number = FreadCrc (&mText[WNDSIZ + MAXMATCH], WNDSIZ); | |
| mRemainder += Number; | |
| mPos = WNDSIZ; | |
| } | |
| DeleteNode (); | |
| InsertNode (); | |
| } | |
| STATIC | |
| EFI_STATUS | |
| Encode ( | |
| VOID | |
| ) | |
| /*++ | |
| Routine Description: | |
| The main controlling routine for compression process. | |
| Arguments: (VOID) | |
| Returns: | |
| EFI_SUCCESS - The compression is successful | |
| EFI_OUT_0F_RESOURCES - Not enough memory for compression process | |
| --*/ | |
| { | |
| EFI_STATUS Status; | |
| INT32 LastMatchLen; | |
| NODE LastMatchPos; | |
| Status = AllocateMemory (); | |
| if (EFI_ERROR (Status)) { | |
| FreeMemory (); | |
| return Status; | |
| } | |
| InitSlide (); | |
| HufEncodeStart (); | |
| mRemainder = FreadCrc (&mText[WNDSIZ], WNDSIZ + MAXMATCH); | |
| mMatchLen = 0; | |
| mPos = WNDSIZ; | |
| InsertNode (); | |
| if (mMatchLen > mRemainder) { | |
| mMatchLen = mRemainder; | |
| } | |
| while (mRemainder > 0) { | |
| LastMatchLen = mMatchLen; | |
| LastMatchPos = mMatchPos; | |
| GetNextMatch (); | |
| if (mMatchLen > mRemainder) { | |
| mMatchLen = mRemainder; | |
| } | |
| if (mMatchLen > LastMatchLen || LastMatchLen < THRESHOLD) { | |
| // | |
| // Not enough benefits are gained by outputting a pointer, | |
| // so just output the original character | |
| // | |
| Output (mText[mPos - 1], 0); | |
| } else { | |
| if (LastMatchLen == THRESHOLD) { | |
| if (((mPos - LastMatchPos - 2) & (WNDSIZ - 1)) > (1U << 11)) { | |
| Output (mText[mPos - 1], 0); | |
| continue; | |
| } | |
| } | |
| // | |
| // Outputting a pointer is beneficial enough, do it. | |
| // | |
| Output ( | |
| LastMatchLen + (UINT8_MAX + 1 - THRESHOLD), | |
| (mPos - LastMatchPos - 2) & (WNDSIZ - 1) | |
| ); | |
| LastMatchLen--; | |
| while (LastMatchLen > 0) { | |
| GetNextMatch (); | |
| LastMatchLen--; | |
| } | |
| if (mMatchLen > mRemainder) { | |
| mMatchLen = mRemainder; | |
| } | |
| } | |
| } | |
| HufEncodeEnd (); | |
| FreeMemory (); | |
| return EFI_SUCCESS; | |
| } | |
| STATIC | |
| VOID | |
| CountTFreq ( | |
| VOID | |
| ) | |
| /*++ | |
| Routine Description: | |
| Count the frequencies for the Extra Set | |
| Arguments: (VOID) | |
| Returns: (VOID) | |
| --*/ | |
| { | |
| INT32 Index; | |
| INT32 Index3; | |
| INT32 Number; | |
| INT32 Count; | |
| for (Index = 0; Index < NT; Index++) { | |
| mTFreq[Index] = 0; | |
| } | |
| Number = NC; | |
| while (Number > 0 && mCLen[Number - 1] == 0) { | |
| Number--; | |
| } | |
| Index = 0; | |
| while (Index < Number) { | |
| Index3 = mCLen[Index++]; | |
| if (Index3 == 0) { | |
| Count = 1; | |
| while (Index < Number && mCLen[Index] == 0) { | |
| Index++; | |
| Count++; | |
| } | |
| if (Count <= 2) { | |
| mTFreq[0] = (UINT16) (mTFreq[0] + Count); | |
| } else if (Count <= 18) { | |
| mTFreq[1]++; | |
| } else if (Count == 19) { | |
| mTFreq[0]++; | |
| mTFreq[1]++; | |
| } else { | |
| mTFreq[2]++; | |
| } | |
| } else { | |
| mTFreq[Index3 + 2]++; | |
| } | |
| } | |
| } | |
| STATIC | |
| VOID | |
| WritePTLen ( | |
| IN INT32 Number, | |
| IN INT32 nbit, | |
| IN INT32 Special | |
| ) | |
| /*++ | |
| Routine Description: | |
| Outputs the code length array for the Extra Set or the Position Set. | |
| Arguments: | |
| Number - the number of symbols | |
| nbit - the number of bits needed to represent 'n' | |
| Special - the special symbol that needs to be take care of | |
| Returns: (VOID) | |
| --*/ | |
| { | |
| INT32 Index; | |
| INT32 Index3; | |
| while (Number > 0 && mPTLen[Number - 1] == 0) { | |
| Number--; | |
| } | |
| PutBits (nbit, Number); | |
| Index = 0; | |
| while (Index < Number) { | |
| Index3 = mPTLen[Index++]; | |
| if (Index3 <= 6) { | |
| PutBits (3, Index3); | |
| } else { | |
| PutBits (Index3 - 3, (1U << (Index3 - 3)) - 2); | |
| } | |
| if (Index == Special) { | |
| while (Index < 6 && mPTLen[Index] == 0) { | |
| Index++; | |
| } | |
| PutBits (2, (Index - 3) & 3); | |
| } | |
| } | |
| } | |
| STATIC | |
| VOID | |
| WriteCLen ( | |
| VOID | |
| ) | |
| /*++ | |
| Routine Description: | |
| Outputs the code length array for Char&Length Set | |
| Arguments: (VOID) | |
| Returns: (VOID) | |
| --*/ | |
| { | |
| INT32 Index; | |
| INT32 Index3; | |
| INT32 Number; | |
| INT32 Count; | |
| Number = NC; | |
| while (Number > 0 && mCLen[Number - 1] == 0) { | |
| Number--; | |
| } | |
| PutBits (CBIT, Number); | |
| Index = 0; | |
| while (Index < Number) { | |
| Index3 = mCLen[Index++]; | |
| if (Index3 == 0) { | |
| Count = 1; | |
| while (Index < Number && mCLen[Index] == 0) { | |
| Index++; | |
| Count++; | |
| } | |
| if (Count <= 2) { | |
| for (Index3 = 0; Index3 < Count; Index3++) { | |
| PutBits (mPTLen[0], mPTCode[0]); | |
| } | |
| } else if (Count <= 18) { | |
| PutBits (mPTLen[1], mPTCode[1]); | |
| PutBits (4, Count - 3); | |
| } else if (Count == 19) { | |
| PutBits (mPTLen[0], mPTCode[0]); | |
| PutBits (mPTLen[1], mPTCode[1]); | |
| PutBits (4, 15); | |
| } else { | |
| PutBits (mPTLen[2], mPTCode[2]); | |
| PutBits (CBIT, Count - 20); | |
| } | |
| } else { | |
| PutBits (mPTLen[Index3 + 2], mPTCode[Index3 + 2]); | |
| } | |
| } | |
| } | |
| STATIC | |
| VOID | |
| EncodeC ( | |
| IN INT32 Value | |
| ) | |
| { | |
| PutBits (mCLen[Value], mCCode[Value]); | |
| } | |
| STATIC | |
| VOID | |
| EncodeP ( | |
| IN UINT32 Value | |
| ) | |
| { | |
| UINT32 Index; | |
| UINT32 NodeQ; | |
| Index = 0; | |
| NodeQ = Value; | |
| while (NodeQ) { | |
| NodeQ >>= 1; | |
| Index++; | |
| } | |
| PutBits (mPTLen[Index], mPTCode[Index]); | |
| if (Index > 1) { | |
| PutBits (Index - 1, Value & (0xFFFFFFFFU >> (32 - Index + 1))); | |
| } | |
| } | |
| STATIC | |
| VOID | |
| SendBlock ( | |
| VOID | |
| ) | |
| /*++ | |
| Routine Description: | |
| Huffman code the block and output it. | |
| Arguments: | |
| (VOID) | |
| Returns: | |
| (VOID) | |
| --*/ | |
| { | |
| UINT32 Index; | |
| UINT32 Index2; | |
| UINT32 Index3; | |
| UINT32 Flags; | |
| UINT32 Root; | |
| UINT32 Pos; | |
| UINT32 Size; | |
| Flags = 0; | |
| Root = MakeTree (NC, mCFreq, mCLen, mCCode); | |
| Size = mCFreq[Root]; | |
| PutBits (16, Size); | |
| if (Root >= NC) { | |
| CountTFreq (); | |
| Root = MakeTree (NT, mTFreq, mPTLen, mPTCode); | |
| if (Root >= NT) { | |
| WritePTLen (NT, TBIT, 3); | |
| } else { | |
| PutBits (TBIT, 0); | |
| PutBits (TBIT, Root); | |
| } | |
| WriteCLen (); | |
| } else { | |
| PutBits (TBIT, 0); | |
| PutBits (TBIT, 0); | |
| PutBits (CBIT, 0); | |
| PutBits (CBIT, Root); | |
| } | |
| Root = MakeTree (NP, mPFreq, mPTLen, mPTCode); | |
| if (Root >= NP) { | |
| WritePTLen (NP, PBIT, -1); | |
| } else { | |
| PutBits (PBIT, 0); | |
| PutBits (PBIT, Root); | |
| } | |
| Pos = 0; | |
| for (Index = 0; Index < Size; Index++) { | |
| if (Index % UINT8_BIT == 0) { | |
| Flags = mBuf[Pos++]; | |
| } else { | |
| Flags <<= 1; | |
| } | |
| if (Flags & (1U << (UINT8_BIT - 1))) { | |
| EncodeC (mBuf[Pos++] + (1U << UINT8_BIT)); | |
| Index3 = mBuf[Pos++]; | |
| for (Index2 = 0; Index2 < 3; Index2++) { | |
| Index3 <<= UINT8_BIT; | |
| Index3 += mBuf[Pos++]; | |
| } | |
| EncodeP (Index3); | |
| } else { | |
| EncodeC (mBuf[Pos++]); | |
| } | |
| } | |
| for (Index = 0; Index < NC; Index++) { | |
| mCFreq[Index] = 0; | |
| } | |
| for (Index = 0; Index < NP; Index++) { | |
| mPFreq[Index] = 0; | |
| } | |
| } | |
| STATIC | |
| VOID | |
| Output ( | |
| IN UINT32 CharC, | |
| IN UINT32 Pos | |
| ) | |
| /*++ | |
| Routine Description: | |
| Outputs an Original Character or a Pointer | |
| Arguments: | |
| CharC - The original character or the 'String Length' element of a Pointer | |
| Pos - The 'Position' field of a Pointer | |
| Returns: (VOID) | |
| --*/ | |
| { | |
| STATIC UINT32 CPos; | |
| if ((mOutputMask >>= 1) == 0) { | |
| mOutputMask = 1U << (UINT8_BIT - 1); | |
| // | |
| // Check the buffer overflow per outputing UINT8_BIT symbols | |
| // which is an Original Character or a Pointer. The biggest | |
| // symbol is a Pointer which occupies 5 bytes. | |
| // | |
| if (mOutputPos >= mBufSiz - 5 * UINT8_BIT) { | |
| SendBlock (); | |
| mOutputPos = 0; | |
| } | |
| CPos = mOutputPos++; | |
| mBuf[CPos] = 0; | |
| } | |
| mBuf[mOutputPos++] = (UINT8) CharC; | |
| mCFreq[CharC]++; | |
| if (CharC >= (1U << UINT8_BIT)) { | |
| mBuf[CPos] |= mOutputMask; | |
| mBuf[mOutputPos++] = (UINT8) (Pos >> 24); | |
| mBuf[mOutputPos++] = (UINT8) (Pos >> 16); | |
| mBuf[mOutputPos++] = (UINT8) (Pos >> (UINT8_BIT)); | |
| mBuf[mOutputPos++] = (UINT8) Pos; | |
| CharC = 0; | |
| while (Pos) { | |
| Pos >>= 1; | |
| CharC++; | |
| } | |
| mPFreq[CharC]++; | |
| } | |
| } | |
| STATIC | |
| VOID | |
| HufEncodeStart ( | |
| VOID | |
| ) | |
| { | |
| INT32 Index; | |
| for (Index = 0; Index < NC; Index++) { | |
| mCFreq[Index] = 0; | |
| } | |
| for (Index = 0; Index < NP; Index++) { | |
| mPFreq[Index] = 0; | |
| } | |
| mOutputPos = mOutputMask = 0; | |
| InitPutBits (); | |
| return ; | |
| } | |
| STATIC | |
| VOID | |
| HufEncodeEnd ( | |
| VOID | |
| ) | |
| { | |
| SendBlock (); | |
| // | |
| // Flush remaining bits | |
| // | |
| PutBits (UINT8_BIT - 1, 0); | |
| return ; | |
| } | |
| STATIC | |
| VOID | |
| MakeCrcTable ( | |
| VOID | |
| ) | |
| { | |
| UINT32 Index; | |
| UINT32 Index2; | |
| UINT32 Temp; | |
| for (Index = 0; Index <= UINT8_MAX; Index++) { | |
| Temp = Index; | |
| for (Index2 = 0; Index2 < UINT8_BIT; Index2++) { | |
| if (Temp & 1) { | |
| Temp = (Temp >> 1) ^ CRCPOLY; | |
| } else { | |
| Temp >>= 1; | |
| } | |
| } | |
| mCrcTable[Index] = (UINT16) Temp; | |
| } | |
| } | |
| STATIC | |
| VOID | |
| PutBits ( | |
| IN INT32 Number, | |
| IN UINT32 Value | |
| ) | |
| /*++ | |
| Routine Description: | |
| Outputs rightmost n bits of x | |
| Arguments: | |
| Number - the rightmost n bits of the data is used | |
| x - the data | |
| Returns: (VOID) | |
| --*/ | |
| { | |
| UINT8 Temp; | |
| while (Number >= mBitCount) { | |
| // | |
| // Number -= mBitCount should never equal to 32 | |
| // | |
| Temp = (UINT8) (mSubBitBuf | (Value >> (Number -= mBitCount))); | |
| if (mDst < mDstUpperLimit) { | |
| *mDst++ = Temp; | |
| } | |
| mCompSize++; | |
| mSubBitBuf = 0; | |
| mBitCount = UINT8_BIT; | |
| } | |
| mSubBitBuf |= Value << (mBitCount -= Number); | |
| } | |
| STATIC | |
| INT32 | |
| FreadCrc ( | |
| OUT UINT8 *Pointer, | |
| IN INT32 Number | |
| ) | |
| /*++ | |
| Routine Description: | |
| Read in source data | |
| Arguments: | |
| Pointer - the buffer to hold the data | |
| Number - number of bytes to read | |
| Returns: | |
| number of bytes actually read | |
| --*/ | |
| { | |
| INT32 Index; | |
| for (Index = 0; mSrc < mSrcUpperLimit && Index < Number; Index++) { | |
| *Pointer++ = *mSrc++; | |
| } | |
| Number = Index; | |
| Pointer -= Number; | |
| mOrigSize += Number; | |
| Index--; | |
| while (Index >= 0) { | |
| UPDATE_CRC (*Pointer++); | |
| Index--; | |
| } | |
| return Number; | |
| } | |
| STATIC | |
| VOID | |
| InitPutBits ( | |
| VOID | |
| ) | |
| { | |
| mBitCount = UINT8_BIT; | |
| mSubBitBuf = 0; | |
| } | |
| STATIC | |
| VOID | |
| CountLen ( | |
| IN INT32 Index | |
| ) | |
| /*++ | |
| Routine Description: | |
| Count the number of each code length for a Huffman tree. | |
| Arguments: | |
| Index - the top node | |
| Returns: (VOID) | |
| --*/ | |
| { | |
| STATIC INT32 Depth = 0; | |
| if (Index < mN) { | |
| mLenCnt[(Depth < 16) ? Depth : 16]++; | |
| } else { | |
| Depth++; | |
| CountLen (mLeft[Index]); | |
| CountLen (mRight[Index]); | |
| Depth--; | |
| } | |
| } | |
| STATIC | |
| VOID | |
| MakeLen ( | |
| IN INT32 Root | |
| ) | |
| /*++ | |
| Routine Description: | |
| Create code length array for a Huffman tree | |
| Arguments: | |
| Root - the root of the tree | |
| Returns: | |
| VOID | |
| --*/ | |
| { | |
| INT32 Index; | |
| INT32 Index3; | |
| UINT32 Cum; | |
| for (Index = 0; Index <= 16; Index++) { | |
| mLenCnt[Index] = 0; | |
| } | |
| CountLen (Root); | |
| // | |
| // Adjust the length count array so that | |
| // no code will be generated longer than its designated length | |
| // | |
| Cum = 0; | |
| for (Index = 16; Index > 0; Index--) { | |
| Cum += mLenCnt[Index] << (16 - Index); | |
| } | |
| while (Cum != (1U << 16)) { | |
| mLenCnt[16]--; | |
| for (Index = 15; Index > 0; Index--) { | |
| if (mLenCnt[Index] != 0) { | |
| mLenCnt[Index]--; | |
| mLenCnt[Index + 1] += 2; | |
| break; | |
| } | |
| } | |
| Cum--; | |
| } | |
| for (Index = 16; Index > 0; Index--) { | |
| Index3 = mLenCnt[Index]; | |
| Index3--; | |
| while (Index3 >= 0) { | |
| mLen[*mSortPtr++] = (UINT8) Index; | |
| Index3--; | |
| } | |
| } | |
| } | |
| STATIC | |
| VOID | |
| DownHeap ( | |
| IN INT32 Index | |
| ) | |
| { | |
| INT32 Index2; | |
| INT32 Index3; | |
| // | |
| // priority queue: send Index-th entry down heap | |
| // | |
| Index3 = mHeap[Index]; | |
| Index2 = 2 * Index; | |
| while (Index2 <= mHeapSize) { | |
| if (Index2 < mHeapSize && mFreq[mHeap[Index2]] > mFreq[mHeap[Index2 + 1]]) { | |
| Index2++; | |
| } | |
| if (mFreq[Index3] <= mFreq[mHeap[Index2]]) { | |
| break; | |
| } | |
| mHeap[Index] = mHeap[Index2]; | |
| Index = Index2; | |
| Index2 = 2 * Index; | |
| } | |
| mHeap[Index] = (INT16) Index3; | |
| } | |
| STATIC | |
| VOID | |
| MakeCode ( | |
| IN INT32 Number, | |
| IN UINT8 Len[ ], | |
| OUT UINT16 Code[] | |
| ) | |
| /*++ | |
| Routine Description: | |
| Assign code to each symbol based on the code length array | |
| Arguments: | |
| Number - number of symbols | |
| Len - the code length array | |
| Code - stores codes for each symbol | |
| Returns: (VOID) | |
| --*/ | |
| { | |
| INT32 Index; | |
| UINT16 Start[18]; | |
| Start[1] = 0; | |
| for (Index = 1; Index <= 16; Index++) { | |
| Start[Index + 1] = (UINT16) ((Start[Index] + mLenCnt[Index]) << 1); | |
| } | |
| for (Index = 0; Index < Number; Index++) { | |
| Code[Index] = Start[Len[Index]]++; | |
| } | |
| } | |
| STATIC | |
| INT32 | |
| MakeTree ( | |
| IN INT32 NParm, | |
| IN UINT16 FreqParm[], | |
| OUT UINT8 LenParm[ ], | |
| OUT UINT16 CodeParm[] | |
| ) | |
| /*++ | |
| Routine Description: | |
| Generates Huffman codes given a frequency distribution of symbols | |
| Arguments: | |
| NParm - number of symbols | |
| FreqParm - frequency of each symbol | |
| LenParm - code length for each symbol | |
| CodeParm - code for each symbol | |
| Returns: | |
| Root of the Huffman tree. | |
| --*/ | |
| { | |
| INT32 Index; | |
| INT32 Index2; | |
| INT32 Index3; | |
| INT32 Avail; | |
| // | |
| // make tree, calculate len[], return root | |
| // | |
| mN = NParm; | |
| mFreq = FreqParm; | |
| mLen = LenParm; | |
| Avail = mN; | |
| mHeapSize = 0; | |
| mHeap[1] = 0; | |
| for (Index = 0; Index < mN; Index++) { | |
| mLen[Index] = 0; | |
| if (mFreq[Index]) { | |
| mHeapSize++; | |
| mHeap[mHeapSize] = (INT16) Index; | |
| } | |
| } | |
| if (mHeapSize < 2) { | |
| CodeParm[mHeap[1]] = 0; | |
| return mHeap[1]; | |
| } | |
| for (Index = mHeapSize / 2; Index >= 1; Index--) { | |
| // | |
| // make priority queue | |
| // | |
| DownHeap (Index); | |
| } | |
| mSortPtr = CodeParm; | |
| do { | |
| Index = mHeap[1]; | |
| if (Index < mN) { | |
| *mSortPtr++ = (UINT16) Index; | |
| } | |
| mHeap[1] = mHeap[mHeapSize--]; | |
| DownHeap (1); | |
| Index2 = mHeap[1]; | |
| if (Index2 < mN) { | |
| *mSortPtr++ = (UINT16) Index2; | |
| } | |
| Index3 = Avail++; | |
| mFreq[Index3] = (UINT16) (mFreq[Index] + mFreq[Index2]); | |
| mHeap[1] = (INT16) Index3; | |
| DownHeap (1); | |
| mLeft[Index3] = (UINT16) Index; | |
| mRight[Index3] = (UINT16) Index2; | |
| } while (mHeapSize > 1); | |
| mSortPtr = CodeParm; | |
| MakeLen (Index3); | |
| MakeCode (NParm, LenParm, CodeParm); | |
| // | |
| // return root | |
| // | |
| return Index3; | |
| } | |
| EFI_STATUS | |
| GetFileContents ( | |
| IN char *InputFileName, | |
| OUT UINT8 *FileBuffer, | |
| OUT UINT32 *BufferLength | |
| ) | |
| /*++ | |
| Routine Description: | |
| Get the contents of file specified in InputFileName | |
| into FileBuffer. | |
| Arguments: | |
| InputFileName - Name of the input file. | |
| FileBuffer - Output buffer to contain data | |
| BufferLength - Actual length of the data | |
| Returns: | |
| EFI_SUCCESS on successful return | |
| EFI_ABORTED if unable to open input file. | |
| --*/ | |
| { | |
| UINTN Size; | |
| UINTN FileSize; | |
| FILE *InputFile; | |
| Size = 0; | |
| // | |
| // Copy the file contents to the output buffer. | |
| // | |
| InputFile = fopen (LongFilePath (InputFileName), "rb"); | |
| if (InputFile == NULL) { | |
| Error (NULL, 0, 0001, "Error opening file: %s", InputFileName); | |
| return EFI_ABORTED; | |
| } | |
| fseek (InputFile, 0, SEEK_END); | |
| FileSize = ftell (InputFile); | |
| fseek (InputFile, 0, SEEK_SET); | |
| // | |
| // Now read the contents of the file into the buffer | |
| // | |
| if (FileSize > 0 && FileBuffer != NULL) { | |
| if (fread (FileBuffer, FileSize, 1, InputFile) != 1) { | |
| Error (NULL, 0, 0004, "Error reading contents of input file: %s", InputFileName); | |
| fclose (InputFile); | |
| return EFI_ABORTED; | |
| } | |
| } | |
| fclose (InputFile); | |
| Size += (UINTN) FileSize; | |
| *BufferLength = Size; | |
| if (FileBuffer != NULL) { | |
| return EFI_SUCCESS; | |
| } else { | |
| return EFI_BUFFER_TOO_SMALL; | |
| } | |
| } | |
| VOID | |
| Version ( | |
| VOID | |
| ) | |
| /*++ | |
| Routine Description: | |
| Displays the standard utility information to SDTOUT | |
| Arguments: | |
| None | |
| Returns: | |
| None | |
| --*/ | |
| { | |
| fprintf (stdout, "%s Version %d.%d %s \n", UTILITY_NAME, UTILITY_MAJOR_VERSION, UTILITY_MINOR_VERSION, __BUILD_VERSION); | |
| } | |
| VOID | |
| Usage ( | |
| VOID | |
| ) | |
| /*++ | |
| Routine Description: | |
| Displays the utility usage syntax to STDOUT | |
| Arguments: | |
| None | |
| Returns: | |
| None | |
| --*/ | |
| { | |
| // | |
| // Summary usage | |
| // | |
| fprintf (stdout, "Usage: %s -e|-d [options] <input_file>\n\n", UTILITY_NAME); | |
| // | |
| // Copyright declaration | |
| // | |
| fprintf (stdout, "Copyright (c) 2007 - 2014, Intel Corporation. All rights reserved.\n\n"); | |
| // | |
| // Details Option | |
| // | |
| fprintf (stdout, "Options:\n"); | |
| fprintf (stdout, " -o FileName, --output FileName\n\ | |
| File will be created to store the ouput content.\n"); | |
| fprintf (stdout, " -v, --verbose\n\ | |
| Turn on verbose output with informational messages.\n"); | |
| fprintf (stdout, " -q, --quiet\n\ | |
| Disable all messages except key message and fatal error\n"); | |
| fprintf (stdout, " --debug [0-9]\n\ | |
| Enable debug messages, at input debug level.\n"); | |
| fprintf (stdout, " --version\n\ | |
| Show program's version number and exit.\n"); | |
| fprintf (stdout, " -h, --help\n\ | |
| Show this help message and exit.\n"); | |
| } | |
| int | |
| main ( | |
| int argc, | |
| char *argv[] | |
| ) | |
| /*++ | |
| Routine Description: | |
| Main | |
| Arguments: | |
| command line parameters | |
| Returns: | |
| EFI_SUCCESS Section header successfully generated and section concatenated. | |
| EFI_ABORTED Could not generate the section | |
| EFI_OUT_OF_RESOURCES No resource to complete the operation. | |
| --*/ | |
| { | |
| FILE *OutputFile; | |
| char *OutputFileName; | |
| char *InputFileName; | |
| FILE *InputFile; | |
| EFI_STATUS Status; | |
| UINT8 *FileBuffer; | |
| UINT8 *OutBuffer; | |
| UINT32 InputLength; | |
| UINT32 DstSize; | |
| SCRATCH_DATA *Scratch; | |
| UINT8 *Src; | |
| UINT32 OrigSize; | |
| SetUtilityName(UTILITY_NAME); | |
| FileBuffer = NULL; | |
| Src = NULL; | |
| OutBuffer = NULL; | |
| Scratch = NULL; | |
| OrigSize = 0; | |
| InputLength = 0; | |
| InputFileName = NULL; | |
| OutputFileName = NULL; | |
| DstSize=0; | |
| DebugLevel = 0; | |
| DebugMode = FALSE; | |
| // | |
| // Verify the correct number of arguments | |
| // | |
| if (argc == 1) { | |
| Error (NULL, 0, 1001, "Missing options", "No input options specified."); | |
| Usage(); | |
| return 0; | |
| } | |
| if ((strcmp(argv[1], "-h") == 0) || (strcmp(argv[1], "--help") == 0)) { | |
| Usage(); | |
| return 0; | |
| } | |
| if ((strcmp(argv[1], "--version") == 0)) { | |
| Version(); | |
| return 0; | |
| } | |
| argc--; | |
| argv++; | |
| if (strcmp(argv[0],"-e") == 0) { | |
| // | |
| // encode the input file | |
| // | |
| ENCODE = TRUE; | |
| argc--; | |
| argv++; | |
| } else if (strcmp(argv[0], "-d") == 0) { | |
| // | |
| // decode the input file | |
| // | |
| DECODE = TRUE; | |
| argc--; | |
| argv++; | |
| } else { | |
| // | |
| // Error command line | |
| // | |
| Error (NULL, 0, 1003, "Invalid option value", "the options specified are not recognized."); | |
| Usage(); | |
| return 1; | |
| } | |
| while (argc > 0) { | |
| if ((strcmp(argv[0], "-v") == 0) || (stricmp(argv[0], "--verbose") == 0)) { | |
| VerboseMode = TRUE; | |
| argc--; | |
| argv++; | |
| continue; | |
| } | |
| if (stricmp (argv[0], "--debug") == 0) { | |
| argc-=2; | |
| argv++; | |
| Status = AsciiStringToUint64(argv[0], FALSE, &DebugLevel); | |
| if (DebugLevel > 9) { | |
| Error (NULL, 0 ,2000, "Invalid parameter", "Unrecognized argument %s", argv[0]); | |
| goto ERROR; | |
| } | |
| if (DebugLevel>=5 && DebugLevel <=9){ | |
| DebugMode = TRUE; | |
| } else { | |
| DebugMode = FALSE; | |
| } | |
| argv++; | |
| continue; | |
| } | |
| if ((strcmp(argv[0], "-q") == 0) || (stricmp (argv[0], "--quiet") == 0)) { | |
| QuietMode = TRUE; | |
| argc--; | |
| argv++; | |
| continue; | |
| } | |
| if ((strcmp(argv[0], "-o") == 0) || (stricmp (argv[0], "--output") == 0)) { | |
| if (argv[1] == NULL || argv[1][0] == '-') { | |
| Error (NULL, 0, 1003, "Invalid option value", "Output File name is missing for -o option"); | |
| goto ERROR; | |
| } | |
| OutputFileName = argv[1]; | |
| argc -=2; | |
| argv +=2; | |
| continue; | |
| } | |
| if (argv[0][0]!='-') { | |
| InputFileName = argv[0]; | |
| argc--; | |
| argv++; | |
| continue; | |
| } | |
| Error (NULL, 0, 1000, "Unknown option", argv[0]); | |
| goto ERROR; | |
| } | |
| if (InputFileName == NULL) { | |
| Error (NULL, 0, 1001, "Missing options", "No input files specified."); | |
| goto ERROR; | |
| } | |
| // | |
| // All Parameters has been parsed, now set the message print level | |
| // | |
| if (QuietMode) { | |
| SetPrintLevel(40); | |
| } else if (VerboseMode) { | |
| SetPrintLevel(15); | |
| } else if (DebugMode) { | |
| SetPrintLevel(DebugLevel); | |
| } | |
| if (VerboseMode) { | |
| VerboseMsg("%s tool start.\n", UTILITY_NAME); | |
| } | |
| Scratch = (SCRATCH_DATA *)malloc(sizeof(SCRATCH_DATA)); | |
| if (Scratch == NULL) { | |
| Error (NULL, 0, 4001, "Resource:", "Memory cannot be allocated!"); | |
| goto ERROR; | |
| } | |
| InputFile = fopen (LongFilePath (InputFileName), "rb"); | |
| if (InputFile == NULL) { | |
| Error (NULL, 0, 0001, "Error opening input file", InputFileName); | |
| goto ERROR; | |
| } | |
| Status = GetFileContents( | |
| InputFileName, | |
| FileBuffer, | |
| &InputLength); | |
| if (Status == EFI_BUFFER_TOO_SMALL) { | |
| FileBuffer = (UINT8 *) malloc (InputLength); | |
| if (FileBuffer == NULL) { | |
| Error (NULL, 0, 4001, "Resource:", "Memory cannot be allocated!"); | |
| return 1; | |
| } | |
| Status = GetFileContents ( | |
| InputFileName, | |
| FileBuffer, | |
| &InputLength | |
| ); | |
| } | |
| if (EFI_ERROR(Status)) { | |
| free(FileBuffer); | |
| return 1; | |
| } | |
| if (OutputFileName != NULL) { | |
| OutputFile = fopen (LongFilePath (OutputFileName), "wb"); | |
| if (OutputFile == NULL) { | |
| Error (NULL, 0, 0001, "Error opening output file for writing", OutputFileName); | |
| if (InputFile != NULL) { | |
| fclose (InputFile); | |
| } | |
| goto ERROR; | |
| } | |
| } else { | |
| OutputFileName = DEFAULT_OUTPUT_FILE; | |
| OutputFile = fopen (LongFilePath (OutputFileName), "wb"); | |
| } | |
| if (ENCODE) { | |
| // | |
| // First call TianoCompress to get DstSize | |
| // | |
| if (DebugMode) { | |
| DebugMsg(UTILITY_NAME, 0, DebugLevel, "Encoding", NULL); | |
| } | |
| Status = TianoCompress ((UINT8 *)FileBuffer, InputLength, OutBuffer, &DstSize); | |
| if (Status == EFI_BUFFER_TOO_SMALL) { | |
| OutBuffer = (UINT8 *) malloc (DstSize); | |
| if (OutBuffer == NULL) { | |
| Error (NULL, 0, 4001, "Resource:", "Memory cannot be allocated!"); | |
| goto ERROR; | |
| } | |
| } | |
| Status = TianoCompress ((UINT8 *)FileBuffer, InputLength, OutBuffer, &DstSize); | |
| if (Status != EFI_SUCCESS) { | |
| Error (NULL, 0, 0007, "Error compressing file", NULL); | |
| goto ERROR; | |
| } | |
| fwrite(OutBuffer,(size_t)DstSize, 1, OutputFile); | |
| free(Scratch); | |
| free(FileBuffer); | |
| free(OutBuffer); | |
| if (DebugMode) { | |
| DebugMsg(UTILITY_NAME, 0, DebugLevel, "Encoding Successful!\n", NULL); | |
| } | |
| if (VerboseMode) { | |
| VerboseMsg("Encoding successful\n"); | |
| } | |
| return 0; | |
| } | |
| else if (DECODE) { | |
| if (DebugMode) { | |
| DebugMsg(UTILITY_NAME, 0, DebugLevel, "Decoding\n", NULL); | |
| } | |
| // | |
| // Get Compressed file original size | |
| // | |
| Src = (UINT8 *)FileBuffer; | |
| OrigSize = Src[4] + (Src[5] << 8) + (Src[6] << 16) + (Src[7] << 24); | |
| // | |
| // Allocate OutputBuffer | |
| // | |
| OutBuffer = (UINT8 *)malloc(OrigSize); | |
| if (OutBuffer == NULL) { | |
| Error (NULL, 0, 4001, "Resource:", "Memory cannot be allocated!"); | |
| goto ERROR; | |
| } | |
| Status = Decompress((VOID *)FileBuffer, (VOID *)OutBuffer, (VOID *)Scratch, 2); | |
| if (Status != EFI_SUCCESS) { | |
| goto ERROR; | |
| } | |
| fwrite(OutBuffer, (size_t)(Scratch->mOrigSize), 1, OutputFile); | |
| free(Scratch); | |
| free(FileBuffer); | |
| free(OutBuffer); | |
| if (DebugMode) { | |
| DebugMsg(UTILITY_NAME, 0, DebugLevel, "Encoding successful!\n", NULL); | |
| } | |
| if (VerboseMode) { | |
| VerboseMsg("Decoding successful\n"); | |
| } | |
| return 0; | |
| } | |
| ERROR: | |
| if (DebugMode) { | |
| if (ENCODE) { | |
| DebugMsg(UTILITY_NAME, 0, DebugLevel, "Encoding Error\n", NULL); | |
| } else if (DECODE) { | |
| DebugMsg(UTILITY_NAME, 0, DebugLevel, "Decoding Error\n", NULL); | |
| } | |
| } | |
| if (Scratch != NULL) { | |
| free(Scratch); | |
| } | |
| if (FileBuffer != NULL) { | |
| free(FileBuffer); | |
| } | |
| if (OutBuffer != NULL) { | |
| free(OutBuffer); | |
| } | |
| if (VerboseMode) { | |
| VerboseMsg("%s tool done with return code is 0x%x.\n", UTILITY_NAME, GetUtilityStatus ()); | |
| } | |
| return GetUtilityStatus (); | |
| } | |
| VOID | |
| FillBuf ( | |
| IN SCRATCH_DATA *Sd, | |
| IN UINT16 NumOfBits | |
| ) | |
| /*++ | |
| Routine Description: | |
| Shift mBitBuf NumOfBits left. Read in NumOfBits of bits from source. | |
| Arguments: | |
| Sd - The global scratch data | |
| NumOfBits - The number of bits to shift and read. | |
| Returns: (VOID) | |
| --*/ | |
| { | |
| Sd->mBitBuf = (UINT32) (Sd->mBitBuf << NumOfBits); | |
| while (NumOfBits > Sd->mBitCount) { | |
| Sd->mBitBuf |= (UINT32) (Sd->mSubBitBuf << (NumOfBits = (UINT16) (NumOfBits - Sd->mBitCount))); | |
| if (Sd->mCompSize > 0) { | |
| // | |
| // Get 1 byte into SubBitBuf | |
| // | |
| Sd->mCompSize--; | |
| Sd->mSubBitBuf = 0; | |
| Sd->mSubBitBuf = Sd->mSrcBase[Sd->mInBuf++]; | |
| Sd->mBitCount = 8; | |
| } else { | |
| // | |
| // No more bits from the source, just pad zero bit. | |
| // | |
| Sd->mSubBitBuf = 0; | |
| Sd->mBitCount = 8; | |
| } | |
| } | |
| Sd->mBitCount = (UINT16) (Sd->mBitCount - NumOfBits); | |
| Sd->mBitBuf |= Sd->mSubBitBuf >> Sd->mBitCount; | |
| } | |
| UINT32 | |
| GetBits ( | |
| IN SCRATCH_DATA *Sd, | |
| IN UINT16 NumOfBits | |
| ) | |
| /*++ | |
| Routine Description: | |
| Get NumOfBits of bits out from mBitBuf. Fill mBitBuf with subsequent | |
| NumOfBits of bits from source. Returns NumOfBits of bits that are | |
| popped out. | |
| Arguments: | |
| Sd - The global scratch data. | |
| NumOfBits - The number of bits to pop and read. | |
| Returns: | |
| The bits that are popped out. | |
| --*/ | |
| { | |
| UINT32 OutBits; | |
| OutBits = (UINT32) (Sd->mBitBuf >> (BITBUFSIZ - NumOfBits)); | |
| FillBuf (Sd, NumOfBits); | |
| return OutBits; | |
| } | |
| UINT16 | |
| MakeTable ( | |
| IN SCRATCH_DATA *Sd, | |
| IN UINT16 NumOfChar, | |
| IN UINT8 *BitLen, | |
| IN UINT16 TableBits, | |
| OUT UINT16 *Table | |
| ) | |
| /*++ | |
| Routine Description: | |
| Creates Huffman Code mapping table according to code length array. | |
| Arguments: | |
| Sd - The global scratch data | |
| NumOfChar - Number of symbols in the symbol set | |
| BitLen - Code length array | |
| TableBits - The width of the mapping table | |
| Table - The table | |
| Returns: | |
| 0 - OK. | |
| BAD_TABLE - The table is corrupted. | |
| --*/ | |
| { | |
| UINT16 Count[17]; | |
| UINT16 Weight[17]; | |
| UINT16 Start[18]; | |
| UINT16 *Pointer; | |
| UINT16 Index3; | |
| volatile UINT16 Index; | |
| UINT16 Len; | |
| UINT16 Char; | |
| UINT16 JuBits; | |
| UINT16 Avail; | |
| UINT16 NextCode; | |
| UINT16 Mask; | |
| UINT16 WordOfStart; | |
| UINT16 WordOfCount; | |
| for (Index = 1; Index <= 16; Index++) { | |
| Count[Index] = 0; | |
| } | |
| for (Index = 0; Index < NumOfChar; Index++) { | |
| Count[BitLen[Index]]++; | |
| } | |
| Start[1] = 0; | |
| for (Index = 1; Index <= 16; Index++) { | |
| WordOfStart = Start[Index]; | |
| WordOfCount = Count[Index]; | |
| Start[Index + 1] = (UINT16) (WordOfStart + (WordOfCount << (16 - Index))); | |
| } | |
| if (Start[17] != 0) { | |
| // | |
| //(1U << 16) | |
| // | |
| return (UINT16) BAD_TABLE; | |
| } | |
| JuBits = (UINT16) (16 - TableBits); | |
| for (Index = 1; Index <= TableBits; Index++) { | |
| Start[Index] >>= JuBits; | |
| Weight[Index] = (UINT16) (1U << (TableBits - Index)); | |
| } | |
| while (Index <= 16) { | |
| Weight[Index] = (UINT16) (1U << (16 - Index)); | |
| Index++; | |
| } | |
| Index = (UINT16) (Start[TableBits + 1] >> JuBits); | |
| if (Index != 0) { | |
| Index3 = (UINT16) (1U << TableBits); | |
| while (Index != Index3) { | |
| Table[Index++] = 0; | |
| } | |
| } | |
| Avail = NumOfChar; | |
| Mask = (UINT16) (1U << (15 - TableBits)); | |
| for (Char = 0; Char < NumOfChar; Char++) { | |
| Len = BitLen[Char]; | |
| if (Len == 0) { | |
| continue; | |
| } | |
| NextCode = (UINT16) (Start[Len] + Weight[Len]); | |
| if (Len <= TableBits) { | |
| for (Index = Start[Len]; Index < NextCode; Index++) { | |
| Table[Index] = Char; | |
| } | |
| } else { | |
| Index3 = Start[Len]; | |
| Pointer = &Table[Index3 >> JuBits]; | |
| Index = (UINT16) (Len - TableBits); | |
| while (Index != 0) { | |
| if (*Pointer == 0) { | |
| Sd->mRight[Avail] = Sd->mLeft[Avail] = 0; | |
| *Pointer = Avail++; | |
| } | |
| if (Index3 & Mask) { | |
| Pointer = &Sd->mRight[*Pointer]; | |
| } else { | |
| Pointer = &Sd->mLeft[*Pointer]; | |
| } | |
| Index3 <<= 1; | |
| Index--; | |
| } | |
| *Pointer = Char; | |
| } | |
| Start[Len] = NextCode; | |
| } | |
| // | |
| // Succeeds | |
| // | |
| return 0; | |
| } | |
| UINT32 | |
| DecodeP ( | |
| IN SCRATCH_DATA *Sd | |
| ) | |
| /*++ | |
| Routine Description: | |
| Decodes a position value. | |
| Arguments: | |
| Sd - the global scratch data | |
| Returns: | |
| The position value decoded. | |
| --*/ | |
| { | |
| UINT16 Val; | |
| UINT32 Mask; | |
| UINT32 Pos; | |
| Val = Sd->mPTTable[Sd->mBitBuf >> (BITBUFSIZ - 8)]; | |
| if (Val >= MAXNP) { | |
| Mask = 1U << (BITBUFSIZ - 1 - 8); | |
| do { | |
| if (Sd->mBitBuf & Mask) { | |
| Val = Sd->mRight[Val]; | |
| } else { | |
| Val = Sd->mLeft[Val]; | |
| } | |
| Mask >>= 1; | |
| } while (Val >= MAXNP); | |
| } | |
| // | |
| // Advance what we have read | |
| // | |
| FillBuf (Sd, Sd->mPTLen[Val]); | |
| Pos = Val; | |
| if (Val > 1) { | |
| Pos = (UINT32) ((1U << (Val - 1)) + GetBits (Sd, (UINT16) (Val - 1))); | |
| } | |
| return Pos; | |
| } | |
| UINT16 | |
| ReadPTLen ( | |
| IN SCRATCH_DATA *Sd, | |
| IN UINT16 nn, | |
| IN UINT16 nbit, | |
| IN UINT16 Special | |
| ) | |
| /*++ | |
| Routine Description: | |
| Reads code lengths for the Extra Set or the Position Set | |
| Arguments: | |
| Sd - The global scratch data | |
| nn - Number of symbols | |
| nbit - Number of bits needed to represent nn | |
| Special - The special symbol that needs to be taken care of | |
| Returns: | |
| 0 - OK. | |
| BAD_TABLE - Table is corrupted. | |
| --*/ | |
| { | |
| UINT16 Number; | |
| UINT16 CharC; | |
| volatile UINT16 Index; | |
| UINT32 Mask; | |
| Number = (UINT16) GetBits (Sd, nbit); | |
| if (Number == 0) { | |
| CharC = (UINT16) GetBits (Sd, nbit); | |
| for (Index = 0; Index < 256; Index++) { | |
| Sd->mPTTable[Index] = CharC; | |
| } | |
| for (Index = 0; Index < nn; Index++) { | |
| Sd->mPTLen[Index] = 0; | |
| } | |
| return 0; | |
| } | |
| Index = 0; | |
| while (Index < Number) { | |
| CharC = (UINT16) (Sd->mBitBuf >> (BITBUFSIZ - 3)); | |
| if (CharC == 7) { | |
| Mask = 1U << (BITBUFSIZ - 1 - 3); | |
| while (Mask & Sd->mBitBuf) { | |
| Mask >>= 1; | |
| CharC += 1; | |
| } | |
| } | |
| FillBuf (Sd, (UINT16) ((CharC < 7) ? 3 : CharC - 3)); | |
| Sd->mPTLen[Index++] = (UINT8) CharC; | |
| if (Index == Special) { | |
| CharC = (UINT16) GetBits (Sd, 2); | |
| while ((INT16) (--CharC) >= 0) { | |
| Sd->mPTLen[Index++] = 0; | |
| } | |
| } | |
| } | |
| while (Index < nn) { | |
| Sd->mPTLen[Index++] = 0; | |
| } | |
| return MakeTable (Sd, nn, Sd->mPTLen, 8, Sd->mPTTable); | |
| } | |
| VOID | |
| ReadCLen ( | |
| SCRATCH_DATA *Sd | |
| ) | |
| /*++ | |
| Routine Description: | |
| Reads code lengths for Char&Len Set. | |
| Arguments: | |
| Sd - the global scratch data | |
| Returns: (VOID) | |
| --*/ | |
| { | |
| UINT16 Number; | |
| UINT16 CharC; | |
| volatile UINT16 Index; | |
| UINT32 Mask; | |
| Number = (UINT16) GetBits (Sd, CBIT); | |
| if (Number == 0) { | |
| CharC = (UINT16) GetBits (Sd, CBIT); | |
| for (Index = 0; Index < NC; Index++) { | |
| Sd->mCLen[Index] = 0; | |
| } | |
| for (Index = 0; Index < 4096; Index++) { | |
| Sd->mCTable[Index] = CharC; | |
| } | |
| return ; | |
| } | |
| Index = 0; | |
| while (Index < Number) { | |
| CharC = Sd->mPTTable[Sd->mBitBuf >> (BITBUFSIZ - 8)]; | |
| if (CharC >= NT) { | |
| Mask = 1U << (BITBUFSIZ - 1 - 8); | |
| do { | |
| if (Mask & Sd->mBitBuf) { | |
| CharC = Sd->mRight[CharC]; | |
| } else { | |
| CharC = Sd->mLeft[CharC]; | |
| } | |
| Mask >>= 1; | |
| } while (CharC >= NT); | |
| } | |
| // | |
| // Advance what we have read | |
| // | |
| FillBuf (Sd, Sd->mPTLen[CharC]); | |
| if (CharC <= 2) { | |
| if (CharC == 0) { | |
| CharC = 1; | |
| } else if (CharC == 1) { | |
| CharC = (UINT16) (GetBits (Sd, 4) + 3); | |
| } else if (CharC == 2) { | |
| CharC = (UINT16) (GetBits (Sd, CBIT) + 20); | |
| } | |
| while ((INT16) (--CharC) >= 0) { | |
| Sd->mCLen[Index++] = 0; | |
| } | |
| } else { | |
| Sd->mCLen[Index++] = (UINT8) (CharC - 2); | |
| } | |
| } | |
| while (Index < NC) { | |
| Sd->mCLen[Index++] = 0; | |
| } | |
| MakeTable (Sd, NC, Sd->mCLen, 12, Sd->mCTable); | |
| return ; | |
| } | |
| UINT16 | |
| DecodeC ( | |
| SCRATCH_DATA *Sd | |
| ) | |
| /*++ | |
| Routine Description: | |
| Decode a character/length value. | |
| Arguments: | |
| Sd - The global scratch data. | |
| Returns: | |
| The value decoded. | |
| --*/ | |
| { | |
| UINT16 Index2; | |
| UINT32 Mask; | |
| if (Sd->mBlockSize == 0) { | |
| // | |
| // Starting a new block | |
| // | |
| Sd->mBlockSize = (UINT16) GetBits (Sd, 16); | |
| Sd->mBadTableFlag = ReadPTLen (Sd, NT, TBIT, 3); | |
| if (Sd->mBadTableFlag != 0) { | |
| return 0; | |
| } | |
| ReadCLen (Sd); | |
| Sd->mBadTableFlag = ReadPTLen (Sd, MAXNP, Sd->mPBit, (UINT16) (-1)); | |
| if (Sd->mBadTableFlag != 0) { | |
| return 0; | |
| } | |
| } | |
| Sd->mBlockSize--; | |
| Index2 = Sd->mCTable[Sd->mBitBuf >> (BITBUFSIZ - 12)]; | |
| if (Index2 >= NC) { | |
| Mask = 1U << (BITBUFSIZ - 1 - 12); | |
| do { | |
| if (Sd->mBitBuf & Mask) { | |
| Index2 = Sd->mRight[Index2]; | |
| } else { | |
| Index2 = Sd->mLeft[Index2]; | |
| } | |
| Mask >>= 1; | |
| } while (Index2 >= NC); | |
| } | |
| // | |
| // Advance what we have read | |
| // | |
| FillBuf (Sd, Sd->mCLen[Index2]); | |
| return Index2; | |
| } | |
| VOID | |
| Decode ( | |
| SCRATCH_DATA *Sd | |
| ) | |
| /*++ | |
| Routine Description: | |
| Decode the source data and put the resulting data into the destination buffer. | |
| Arguments: | |
| Sd - The global scratch data | |
| Returns: (VOID) | |
| --*/ | |
| { | |
| UINT16 BytesRemain; | |
| UINT32 DataIdx; | |
| UINT16 CharC; | |
| BytesRemain = (UINT16) (-1); | |
| DataIdx = 0; | |
| for (;;) { | |
| CharC = DecodeC (Sd); | |
| if (Sd->mBadTableFlag != 0) { | |
| goto Done ; | |
| } | |
| if (CharC < 256) { | |
| // | |
| // Process an Original character | |
| // | |
| if (Sd->mOutBuf >= Sd->mOrigSize) { | |
| goto Done ; | |
| } else { | |
| Sd->mDstBase[Sd->mOutBuf++] = (UINT8) CharC; | |
| } | |
| } else { | |
| // | |
| // Process a Pointer | |
| // | |
| CharC = (UINT16) (CharC - (UINT8_MAX + 1 - THRESHOLD)); | |
| BytesRemain = CharC; | |
| DataIdx = Sd->mOutBuf - DecodeP (Sd) - 1; | |
| BytesRemain--; | |
| while ((INT16) (BytesRemain) >= 0) { | |
| Sd->mDstBase[Sd->mOutBuf++] = Sd->mDstBase[DataIdx++]; | |
| if (Sd->mOutBuf >= Sd->mOrigSize) { | |
| goto Done ; | |
| } | |
| BytesRemain--; | |
| } | |
| } | |
| } | |
| Done: | |
| return ; | |
| } | |
| RETURN_STATUS | |
| EFIAPI | |
| Decompress ( | |
| IN VOID *Source, | |
| IN OUT VOID *Destination, | |
| IN OUT VOID *Scratch, | |
| IN UINT32 Version | |
| ) | |
| /*++ | |
| Routine Description: | |
| The internal implementation of Decompress(). | |
| Arguments: | |
| Source - The source buffer containing the compressed data. | |
| Destination - The destination buffer to store the decompressed data | |
| Scratch - The buffer used internally by the decompress routine. This buffer is needed to store intermediate data. | |
| Version - 1 for EFI1.1 Decompress algoruthm, 2 for Tiano Decompress algorithm | |
| Returns: | |
| RETURN_SUCCESS - Decompression is successfull | |
| RETURN_INVALID_PARAMETER - The source data is corrupted | |
| --*/ | |
| { | |
| volatile UINT32 Index; | |
| UINT32 CompSize; | |
| UINT32 OrigSize; | |
| SCRATCH_DATA *Sd; | |
| CONST UINT8 *Src; | |
| UINT8 *Dst; | |
| // | |
| // Verify input is not NULL | |
| // | |
| assert(Source); | |
| // assert(Destination); | |
| assert(Scratch); | |
| Src = (UINT8 *)Source; | |
| Dst = (UINT8 *)Destination; | |
| Sd = (SCRATCH_DATA *) Scratch; | |
| CompSize = Src[0] + (Src[1] << 8) + (Src[2] << 16) + (Src[3] << 24); | |
| OrigSize = Src[4] + (Src[5] << 8) + (Src[6] << 16) + (Src[7] << 24); | |
| // | |
| // If compressed file size is 0, return | |
| // | |
| if (OrigSize == 0) { | |
| return RETURN_SUCCESS; | |
| } | |
| Src = Src + 8; | |
| for (Index = 0; Index < sizeof (SCRATCH_DATA); Index++) { | |
| ((UINT8 *) Sd)[Index] = 0; | |
| } | |
| // | |
| // The length of the field 'Position Set Code Length Array Size' in Block Header. | |
| // For EFI 1.1 de/compression algorithm(Version 1), mPBit = 4 | |
| // For Tiano de/compression algorithm(Version 2), mPBit = 5 | |
| // | |
| switch (Version) { | |
| case 1 : | |
| Sd->mPBit = 4; | |
| break; | |
| case 2 : | |
| Sd->mPBit = 5; | |
| break; | |
| default: | |
| assert(FALSE); | |
| } | |
| Sd->mSrcBase = (UINT8 *)Src; | |
| Sd->mDstBase = Dst; | |
| Sd->mCompSize = CompSize; | |
| Sd->mOrigSize = OrigSize; | |
| // | |
| // Fill the first BITBUFSIZ bits | |
| // | |
| FillBuf (Sd, BITBUFSIZ); | |
| // | |
| // Decompress it | |
| // | |
| Decode (Sd); | |
| if (Sd->mBadTableFlag != 0) { | |
| // | |
| // Something wrong with the source | |
| // | |
| return RETURN_INVALID_PARAMETER; | |
| } | |
| return RETURN_SUCCESS; | |
| } | |