/** @file
Copyright (c) 2006 - 2008, 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
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
Module Name:
Abstract:
Compression routine. The compression algorithm is a mixture of
LZ77 and Huffman coding. LZ77 transforms the source data into a
sequence of Original Characters and Pointers to repeated strings.
This sequence is further divided into Blocks and Huffman codings
are applied to each Block.
**/
#include "Compress.h"
//
// Macro Definitions
//
#define INIT_CRC 0
#define NIL 0
//
// C: the Char&Len Set; P: the Position Set; T: the exTra Set
//
#else
#endif
//
// Function Prototypes
//
);
);
);
);
Child (
);
);
Split (
);
);
);
);
Encode (
);
);
);
);
EncodeC (
);
EncodeP (
);
);
Output (
);
);
);
);
PutBits (
);
FreadCrc (
);
);
CountLen (
);
MakeLen (
);
DownHeap (
);
MakeCode (
);
MakeTree (
);
//
// Global Variables
//
STATIC UINT16 *mFreq, *mSortPtr, mLenCnt[17], mLeft[2 * NC - 1], mRight[2 * NC - 1], mCrcTable[UINT8_MAX + 1],
//
// functions
//
)
/*++
Routine Description:
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. 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.
--*/
{
//
// Initializations
//
mBufSiz = 0;
mChildCount = NULL;
PutDword (0L);
PutDword (0L);
MakeCrcTable ();
//
// Compress it
//
return EFI_OUT_OF_RESOURCES;
}
//
// Null terminate the compressed data
//
if (mDst < mDstUpperLimit) {
*mDst++ = 0;
}
//
// Fill in compressed size and original size
//
//
// Return
//
return EFI_BUFFER_TOO_SMALL;
} else {
return EFI_SUCCESS;
}
}
PutDword (
)
/*++
Routine Description:
Put a dword to output stream
Arguments:
Data - the dword to put
Returns: (VOID)
--*/
{
if (mDst < mDstUpperLimit) {
}
if (mDst < mDstUpperLimit) {
}
if (mDst < mDstUpperLimit) {
}
if (mDst < mDstUpperLimit) {
}
}
)
/*++
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
--*/
{
}
return EFI_OUT_OF_RESOURCES;
}
}
mBuf[0] = 0;
return EFI_SUCCESS;
}
)
/*++
Routine Description:
Called when compression is completed to free memory previously allocated.
Arguments: (VOID)
Returns: (VOID)
--*/
{
}
}
if (mChildCount != NULL) {
free (mChildCount);
}
}
}
}
}
}
return ;
}
)
/*++
Routine Description:
Initialize String Info Log data structures
Arguments: (VOID)
Returns: (VOID)
--*/
{
}
}
mAvail = 1;
}
}
}
Child (
)
/*++
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)
--*/
{
//
// sentinel
//
}
return NodeR;
}
)
/*++
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)
--*/
{
mChildCount[Parent]++;
}
Split (
)
/*++
Routine Description:
Split a node.
Arguments:
Old - the node to split
Returns: (VOID)
--*/
{
mChildCount[New] = 0;
}
)
/*++
Routine Description:
Insert string info for current position into the String Info Log
Arguments: (VOID)
Returns: (VOID)
--*/
{
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--;
}
}
}
}
} else {
//
// Locate the target tree
//
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 (;;) {
} else {
}
}
return ;
}
mMatchLen++;
t1++;
t2++;
}
break;
}
return ;
}
mMatchLen++;
}
//
// Special usage of 'next'
//
}
)
/*++
Routine Description:
Delete outdated string info. (The Usage of PERC_FLAG
ensures a clean deletion)
Arguments: (VOID)
Returns: (VOID)
--*/
{
return ;
}
return ;
}
mChildCount[NodeR]--;
return ;
}
}
}
}
}
}
}
}
}
)
/*++
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)
--*/
{
mRemainder--;
mPos++;
mRemainder += Number;
}
DeleteNode ();
InsertNode ();
}
Encode (
)
/*++
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
--*/
{
Status = AllocateMemory ();
FreeMemory ();
return Status;
}
InitSlide ();
HufEncodeStart ();
mMatchLen = 0;
InsertNode ();
if (mMatchLen > mRemainder) {
}
while (mRemainder > 0) {
GetNextMatch ();
if (mMatchLen > mRemainder) {
}
//
// Not enough benefits are gained by outputting a pointer,
// so just output the original character
//
} else {
if (LastMatchLen == THRESHOLD) {
continue;
}
}
//
// Outputting a pointer is beneficial enough, do it.
//
Output (
);
LastMatchLen--;
while (LastMatchLen > 0) {
GetNextMatch ();
LastMatchLen--;
}
if (mMatchLen > mRemainder) {
}
}
}
HufEncodeEnd ();
FreeMemory ();
return EFI_SUCCESS;
}
)
/*++
Routine Description:
Count the frequencies for the Extra Set
Arguments: (VOID)
Returns: (VOID)
--*/
{
}
Number--;
}
Index = 0;
if (Index3 == 0) {
Count = 1;
Index++;
Count++;
}
if (Count <= 2) {
} else if (Count <= 18) {
mTFreq[1]++;
} else if (Count == 19) {
mTFreq[0]++;
mTFreq[1]++;
} else {
mTFreq[2]++;
}
} else {
}
}
}
)
/*++
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)
--*/
{
Number--;
}
Index = 0;
if (Index3 <= 6) {
} else {
}
Index++;
}
}
}
}
)
/*++
Routine Description:
Outputs the code length array for Char&Length Set
Arguments: (VOID)
Returns: (VOID)
--*/
{
Number--;
}
Index = 0;
if (Index3 == 0) {
Count = 1;
Index++;
Count++;
}
if (Count <= 2) {
}
} else if (Count <= 18) {
} else if (Count == 19) {
} else {
}
} else {
}
}
}
EncodeC (
)
{
}
EncodeP (
)
{
Index = 0;
while (NodeQ) {
NodeQ >>= 1;
Index++;
}
if (Index > 1) {
}
}
)
/*++
Routine Description:
Huffman code the block and output it.
Arguments:
(VOID)
Returns:
(VOID)
--*/
{
Flags = 0;
CountTFreq ();
} else {
}
WriteCLen ();
} else {
}
} else {
}
Pos = 0;
} else {
Flags <<= 1;
}
}
} else {
}
}
}
}
}
Output (
)
/*++
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)
--*/
{
if ((mOutputMask >>= 1) == 0) {
//
// 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.
//
SendBlock ();
mOutputPos = 0;
}
CPos = mOutputPos++;
}
CharC = 0;
while (Pos) {
Pos >>= 1;
CharC++;
}
}
}
)
{
}
}
mOutputPos = mOutputMask = 0;
InitPutBits ();
return ;
}
)
{
SendBlock ();
//
// Flush remaining bits
//
return ;
}
)
{
if (Temp & 1) {
} else {
Temp >>= 1;
}
}
}
}
PutBits (
)
/*++
Routine Description:
Outputs rightmost n bits of x
Arguments:
Number - the rightmost n bits of the data is used
x - the data
Returns: (VOID)
--*/
{
//
// Number -= mBitCount should never equal to 32
//
if (mDst < mDstUpperLimit) {
}
mCompSize++;
mSubBitBuf = 0;
}
}
FreadCrc (
)
/*++
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
--*/
{
}
Index--;
while (Index >= 0) {
UPDATE_CRC (*Pointer++);
Index--;
}
return Number;
}
)
{
mSubBitBuf = 0;
}
CountLen (
)
/*++
Routine Description:
Count the number of each code length for a Huffman tree.
Arguments:
Index - the top node
Returns: (VOID)
--*/
{
} else {
Depth++;
Depth--;
}
}
MakeLen (
)
/*++
Routine Description:
Create code length array for a Huffman tree
Arguments:
Root - the root of the tree
Returns:
VOID
--*/
{
}
//
// Adjust the length count array so that
// no code will be generated longer than its designated length
//
Cum = 0;
}
mLenCnt[16]--;
break;
}
}
Cum--;
}
Index3--;
while (Index3 >= 0) {
Index3--;
}
}
}
DownHeap (
)
{
//
// priority queue: send Index-th entry down heap
//
Index2++;
}
break;
}
}
}
MakeCode (
)
/*++
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)
--*/
{
Start[1] = 0;
}
}
}
MakeTree (
)
/*++
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.
--*/
{
//
// make tree, calculate len[], return root
//
mHeapSize = 0;
mHeap[1] = 0;
mHeapSize++;
}
}
if (mHeapSize < 2) {
return mHeap[1];
}
//
// make priority queue
//
}
do {
}
DownHeap (1);
}
DownHeap (1);
} while (mHeapSize > 1);
//
// return root
//
return Index3;
}