tianocompress.c
来自「EFI BIOS是Intel提出的下一代的BIOS标准。这里上传的Edk源代码是」· C语言 代码 · 共 1,766 行 · 第 1/3 页
C
1,766 行
/*++
Copyright (c) 2006, 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.
Module Name:
TianoCompress.c
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 <string.h>
#include <stdlib.h>
#include "TianoCommon.h"
#include "Compress.h"
//
// Macro Definitions
//
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 5
#define NT (CODE_BIT + 3)
#define TBIT 5
#if NT > NP
#define NPT NT
#else
#define NPT NP
#endif
//
// Function Prototypes
//
STATIC
EFI_STATUS
Compress (
IN UINT8 *SrcBuffer,
IN UINT32 SrcSize,
IN UINT8 *DstBuffer,
IN OUT UINT32 *DstSize,
IN UINT8 Version
);
STATIC
VOID
PutDword(
IN UINT32 Data
);
STATIC
EFI_STATUS
AllocateMemory (
VOID
);
STATIC
VOID
FreeMemory (
VOID
);
STATIC
VOID
InitSlide (
VOID
);
STATIC
NODE
Child (
IN NODE NodeQ,
IN UINT8 CharC
);
STATIC
VOID
MakeChild (
IN NODE NodeQ,
IN UINT8 CharC,
IN NODE NodeR
);
STATIC
VOID
Split (
IN NODE Old
);
STATIC
VOID
InsertNode (
VOID
);
STATIC
VOID
DeleteNode (
VOID
);
STATIC
VOID
GetNextMatch (
VOID
);
STATIC
EFI_STATUS
Encode (
VOID
);
STATIC
VOID
CountTFreq (
VOID
);
STATIC
VOID
WritePTLen (
IN INT32 Number,
IN INT32 nbit,
IN INT32 Special
);
STATIC
VOID
WriteCLen (
VOID
);
STATIC
VOID
EncodeC (
IN INT32 Value
);
STATIC
VOID
EncodeP (
IN UINT32 Value
);
STATIC
VOID
SendBlock (
VOID
);
STATIC
VOID
Output (
IN UINT32 c,
IN UINT32 p
);
STATIC
VOID
HufEncodeStart (
VOID
);
STATIC
VOID
HufEncodeEnd (
VOID
);
STATIC
VOID
MakeCrcTable (
VOID
);
STATIC
VOID
PutBits (
IN INT32 Number,
IN UINT32 Value
);
STATIC
INT32
FreadCrc (
OUT UINT8 *Pointer,
IN INT32 Number
);
STATIC
VOID
InitPutBits (
VOID
);
STATIC
VOID
CountLen (
IN INT32 Index
);
STATIC
VOID
MakeLen (
IN INT32 Root
);
STATIC
VOID
DownHeap (
IN INT32 Index
);
STATIC
VOID
MakeCode (
IN INT32 Number,
IN UINT8 Len[ ],
OUT UINT16 Code[]
);
STATIC
INT32
MakeTree (
IN INT32 NParm,
IN UINT16 FreqParm[],
OUT UINT8 LenParm[ ],
OUT UINT16 CodeParm[]
);
//
// Global Variables
//
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], mCTable[4096], mCCode[NC], mPFreq[2 * NP - 1], mPTCode[NPT], mTFreq[2 * NT - 1];
STATIC NODE mPos, mMatchPos, mAvail, *mPosition, *mParent, *mPrev, *mNext = NULL;
//
// 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
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 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];
}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?