/** @file
Copyright (c) 2007 - 2010, 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"
#include "TianoCompress.h"
#include "EfiUtilityMsgs.h"
#include "ParseInf.h"
#include <stdio.h>
#include "assert.h"
//
// Macro Definitions
//
#define INIT_CRC 0
#define NIL 0
//
// C: the Char&Len Set; P: the Position Set; T: the exTra Set
//
//#define NC (UINT8_MAX + MAXMATCH + 2 - THRESHOLD)
//#define NT (CODE_BIT + 3)
//#define TBIT 5
//#if NT > NP
//#define NPT NT
//#else
//#define NPT NP
//#endif
//
// 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
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.
--*/
{
//
// 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;
}
IN char *InputFileName,
)
/*++
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.
--*/
{
Size = 0;
//
// Copy the file contents to the output buffer.
//
return EFI_ABORTED;
}
//
// Now read the contents of the file into the buffer
//
return EFI_ABORTED;
}
}
*BufferLength = Size;
if (FileBuffer != NULL) {
return EFI_SUCCESS;
} else {
return EFI_BUFFER_TOO_SMALL;
}
}
Version (
)
/*++
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);
}
Usage (
)
/*++
Routine Description:
Displays the utility usage syntax to STDOUT
Arguments:
None
Returns:
None
--*/
{
//
// Summary usage
//
//
// Copyright declaration
//
//
// Details Option
//
File will be created to store the ouput content.\n");
Turn on verbose output with informational messages.\n");
Disable all messages except key message and fatal error\n");
Enable debug messages, at input debug level.\n");
Show program's version number and exit.\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.
--*/
{
char *OutputFileName;
char *InputFileName;
FileBuffer = NULL;
OrigSize = 0;
InputLength = 0;
DstSize=0;
DebugLevel = 0;
//
// Verify the correct number of arguments
//
if (argc == 1) {
Usage();
return 0;
}
Usage();
return 0;
}
Version();
return 0;
}
argc--;
argv++;
//
// encode the input file
//
argc--;
argv++;
//
// decode the input file
//
argc--;
argv++;
} else {
//
// Error command line
//
Usage();
return 1;
}
while (argc > 0) {
VerboseMode = TRUE;
argc--;
argv++;
continue;
}
argc-=2;
argv++;
if (DebugLevel > 9) {
goto ERROR;
}
} else {
}
argv++;
continue;
}
argc--;
argv++;
continue;
}
goto ERROR;
}
argc -=2;
argv +=2;
continue;
}
if (argv[0][0]!='-') {
InputFileName = argv[0];
argc--;
argv++;
continue;
}
goto ERROR;
}
if (InputFileName == NULL) {
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) {
}
if (VerboseMode) {
}
goto ERROR;
}
goto ERROR;
}
&InputLength);
if (Status == EFI_BUFFER_TOO_SMALL) {
if (FileBuffer == NULL) {
return 1;
}
);
}
return 1;
}
if (OutputFileName != NULL) {
if (OutputFile == NULL) {
}
goto ERROR;
}
} else {
}
if (ENCODE) {
//
// First call TianoCompress to get DstSize
//
if (DebugMode) {
}
if (Status == EFI_BUFFER_TOO_SMALL) {
goto ERROR;
}
}
if (Status != EFI_SUCCESS) {
goto ERROR;
}
if (DebugMode) {
}
if (VerboseMode) {
VerboseMsg("Encoding successful\n");
}
return 0;
}
else if (DECODE) {
if (DebugMode) {
}
//
// Get Compressed file original size
//
//
// Allocate OutputBuffer
//
goto ERROR;
}
if (Status != EFI_SUCCESS) {
goto ERROR;
}
if (DebugMode) {
}
if (VerboseMode) {
VerboseMsg("Decoding successful\n");
}
return 0;
}
if (DebugMode) {
if (ENCODE) {
} else if (DECODE) {
}
}
}
if (FileBuffer != NULL) {
}
}
if (VerboseMode) {
}
return GetUtilityStatus ();
}
FillBuf (
)
/*++
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)
--*/
{
//
// Get 1 byte into SubBitBuf
//
Sd->mSubBitBuf = 0;
} else {
//
// No more bits from the source, just pad zero bit.
//
Sd->mSubBitBuf = 0;
}
}
}
GetBits (
)
/*++
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.
--*/
{
return OutBits;
}
)
/*++
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.
--*/
{
}
}
Start[1] = 0;
}
if (Start[17] != 0) {
//
//(1U << 16)
//
}
}
while (Index <= 16) {
Index++;
}
if (Index != 0) {
}
}
if (Len == 0) {
continue;
}
}
} else {
while (Index != 0) {
if (*Pointer == 0) {
}
} else {
}
Index3 <<= 1;
Index--;
}
}
}
//
// Succeeds
//
return 0;
}
DecodeP (
)
/*++
Routine Description:
Decodes a position value.
Arguments:
Sd - the global scratch data
Returns:
The position value decoded.
--*/
{
do {
} else {
}
Mask >>= 1;
}
//
// Advance what we have read
//
if (Val > 1) {
}
return Pos;
}
)
/*++
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.
--*/
{
if (Number == 0) {
}
}
return 0;
}
Index = 0;
if (CharC == 7) {
Mask >>= 1;
CharC += 1;
}
}
}
}
}
}
}
ReadCLen (
)
/*++
Routine Description:
Reads code lengths for Char&Len Set.
Arguments:
Sd - the global scratch data
Returns: (VOID)
--*/
{
if (Number == 0) {
}
}
return ;
}
Index = 0;
do {
} else {
}
Mask >>= 1;
}
//
// Advance what we have read
//
if (CharC <= 2) {
if (CharC == 0) {
CharC = 1;
} else if (CharC == 1) {
} else if (CharC == 2) {
}
}
} else {
}
}
}
return ;
}
DecodeC (
)
/*++
Routine Description:
Arguments:
Sd - The global scratch data.
Returns:
The value decoded.
--*/
{
if (Sd->mBlockSize == 0) {
//
// Starting a new block
//
if (Sd->mBadTableFlag != 0) {
return 0;
}
if (Sd->mBadTableFlag != 0) {
return 0;
}
}
Sd->mBlockSize--;
do {
} else {
}
Mask >>= 1;
}
//
// Advance what we have read
//
return Index2;
}
Decode (
)
/*++
Routine Description:
Decode the source data and put the resulting data into the destination buffer.
Arguments:
Sd - The global scratch data
Returns: (VOID)
--*/
{
DataIdx = 0;
for (;;) {
if (Sd->mBadTableFlag != 0) {
goto Done ;
}
if (CharC < 256) {
//
// Process an Original character
//
goto Done ;
} else {
}
} else {
//
// Process a Pointer
//
BytesRemain = CharC;
BytesRemain--;
while ((INT16) (BytesRemain) >= 0) {
goto Done ;
}
BytesRemain--;
}
}
}
Done:
return ;
}
)
/*++
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
--*/
{
//
// Verify input is not NULL
//
// assert(Destination);
//
// If compressed file size is 0, return
//
if (OrigSize == 0) {
return RETURN_SUCCESS;
}
}
//
// 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 :
break;
case 2 :
break;
default:
}
//
// Fill the first BITBUFSIZ bits
//
//
// Decompress it
//
if (Sd->mBadTableFlag != 0) {
//
// Something wrong with the source
//
return RETURN_INVALID_PARAMETER;
}
return RETURN_SUCCESS;
}