123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731 |
- /* Copyright (c) 2010 The Chromium OS Authors. All rights reserved.
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
- /*++
- 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:
- EfiCompress.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 <errno.h>
- #include <stdint.h>
- #include <stdio.h>
- #include <stdlib.h>
- #include <string.h>
- #include <sys/types.h>
- #include <sys/stat.h>
- #include <unistd.h>
- #include "eficompress.h"
- //
- // Macro Definitions
- //
- typedef INT16 NODE;
- #define UINT8_BIT 8
- #define THRESHOLD 3
- #define INIT_CRC 0
- #define WNDBIT 13
- #define WNDSIZ (1U << WNDBIT)
- #define MAXMATCH 256
- #define PERC_FLAG 0x8000U
- #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
- #if NT > NP
- #define NPT NT
- #else
- #define NPT NP
- #endif
- //
- // Function Prototypes
- //
- STATIC
- VOID
- PutDword(
- IN UINT32 Data
- );
- STATIC
- EFI_STATUS
- AllocateMemory (
- );
- STATIC
- VOID
- FreeMemory (
- );
- STATIC
- VOID
- InitSlide (
- );
- STATIC
- NODE
- Child (
- IN NODE q,
- IN UINT8 c
- );
- STATIC
- VOID
- MakeChild (
- IN NODE q,
- IN UINT8 c,
- IN NODE r
- );
- STATIC
- VOID
- Split (
- IN NODE Old
- );
- STATIC
- VOID
- InsertNode (
- );
- STATIC
- VOID
- DeleteNode (
- );
- STATIC
- VOID
- GetNextMatch (
- );
- STATIC
- EFI_STATUS
- Encode (
- );
- STATIC
- VOID
- CountTFreq (
- );
- STATIC
- VOID
- WritePTLen (
- IN INT32 n,
- IN INT32 nbit,
- IN INT32 Special
- );
- STATIC
- VOID
- WriteCLen (
- );
- STATIC
- VOID
- EncodeC (
- IN INT32 c
- );
- STATIC
- VOID
- EncodeP (
- IN UINT32 p
- );
- STATIC
- VOID
- SendBlock (
- );
- STATIC
- VOID
- Output (
- IN UINT32 c,
- IN UINT32 p
- );
- STATIC
- VOID
- HufEncodeStart (
- );
- STATIC
- VOID
- HufEncodeEnd (
- );
- STATIC
- VOID
- MakeCrcTable (
- );
- STATIC
- VOID
- PutBits (
- IN INT32 n,
- IN UINT32 x
- );
- STATIC
- INT32
- FreadCrc (
- OUT UINT8 *p,
- IN INT32 n
- );
- STATIC
- VOID
- InitPutBits (
- );
- STATIC
- VOID
- CountLen (
- IN INT32 i
- );
- STATIC
- VOID
- MakeLen (
- IN INT32 Root
- );
- STATIC
- VOID
- DownHeap (
- IN INT32 i
- );
- STATIC
- VOID
- MakeCode (
- IN INT32 n,
- 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], 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
- EfiCompress (
- IN UINT8 *SrcBuffer,
- IN UINT32 SrcSize,
- IN UINT8 *DstBuffer,
- IN OUT UINT32 *DstSize
- )
- /*++
- Routine Description:
- The main compression routine.
- 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. In this case,
- DstSize contains the size needed.
- EFI_SUCCESS - Compression is successful.
- --*/
- {
- EFI_STATUS Status = EFI_SUCCESS;
- //
- // 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 ()
- /*++
- 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 i;
- mText = malloc (WNDSIZ * 2 + MAXMATCH);
- for (i = 0 ; i < WNDSIZ * 2 + MAXMATCH; i ++) {
- mText[i] = 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 = 16 * 1024U;
- while ((mBuf = malloc(mBufSiz)) == NULL) {
- mBufSiz = (mBufSiz / 10U) * 9U;
- if (mBufSiz < 4 * 1024U) {
- return EFI_OUT_OF_RESOURCES;
- }
- }
- mBuf[0] = 0;
- return EFI_SUCCESS;
- }
- VOID
- FreeMemory ()
- /*++
- Routine Description:
- Called when compression is completed to free memory previously allocated.
- Arguments: (VOID)
- Returns: (VOID)
- --*/
- {
- if (mText) {
- free (mText);
- }
- if (mLevel) {
- free (mLevel);
- }
- if (mChildCount) {
- free (mChildCount);
- }
- if (mPosition) {
- free (mPosition);
- }
- if (mParent) {
- free (mParent);
- }
- if (mPrev) {
- free (mPrev);
- }
- if (mNext) {
- free (mNext);
- }
- if (mBuf) {
- free (mBuf);
- }
- return;
- }
- STATIC
- VOID
- InitSlide ()
- /*++
- Routine Description:
- Initialize String Info Log data structures
- Arguments: (VOID)
- Returns: (VOID)
- --*/
- {
- NODE i;
- for (i = WNDSIZ; i <= WNDSIZ + UINT8_MAX; i++) {
- mLevel[i] = 1;
- mPosition[i] = NIL; /* sentinel */
- }
- for (i = WNDSIZ; i < WNDSIZ * 2; i++) {
- mParent[i] = NIL;
- }
- mAvail = 1;
- for (i = 1; i < WNDSIZ - 1; i++) {
- mNext[i] = (NODE)(i + 1);
- }
- mNext[WNDSIZ - 1] = NIL;
- for (i = WNDSIZ * 2; i <= MAX_HASH_VAL; i++) {
- mNext[i] = NIL;
- }
- }
- STATIC
- NODE
- Child (
- IN NODE q,
- IN UINT8 c
- )
- /*++
- Routine Description:
- Find child node given the parent node and the edge character
- Arguments:
- q - the parent node
- c - the edge character
- Returns:
- The child node (NIL if not found)
- --*/
- {
- NODE r;
- r = mNext[HASH(q, c)];
- mParent[NIL] = q; /* sentinel */
- while (mParent[r] != q) {
- r = mNext[r];
- }
- return r;
- }
- STATIC
- VOID
- MakeChild (
- IN NODE q,
- IN UINT8 c,
- IN NODE r
- )
- /*++
- Routine Description:
- Create a new child for a given parent node.
- Arguments:
- q - the parent node
- c - the edge character
- r - the child node
- Returns: (VOID)
- --*/
- {
- NODE h, t;
- h = (NODE)HASH(q, c);
- t = mNext[h];
- mNext[h] = r;
- mNext[r] = t;
- mPrev[t] = r;
- mPrev[r] = h;
- mParent[r] = q;
- mChildCount[q]++;
- }
- STATIC
- VOID
- Split (
- NODE Old
- )
- /*++
- Routine Description:
- Split a node.
- Arguments:
- Old - the node to split
- Returns: (VOID)
- --*/
- {
- NODE New, t;
- New = mAvail;
- mAvail = mNext[New];
- mChildCount[New] = 0;
- t = mPrev[Old];
- mPrev[New] = t;
- mNext[t] = New;
- t = mNext[Old];
- mNext[New] = t;
- mPrev[t] = 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 ()
- /*++
- Routine Description:
- Insert string info for current position into the String Info Log
- Arguments: (VOID)
- Returns: (VOID)
- --*/
- {
- NODE q, r, j, t;
- UINT8 c, *t1, *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--;
- r = (INT16)((mMatchPos + 1) | WNDSIZ);
- while ((q = mParent[r]) == NIL) {
- r = mNext[r];
- }
- while (mLevel[q] >= mMatchLen) {
- r = q; q = mParent[q];
- }
- t = q;
- while (mPosition[t] < 0) {
- mPosition[t] = mPos;
- t = mParent[t];
- }
- if (t < WNDSIZ) {
- mPosition[t] = (NODE)(mPos | PERC_FLAG);
- }
- } else {
- //
- // Locate the target tree
- //
- q = (INT16)(mText[mPos] + WNDSIZ);
- c = mText[mPos + 1];
- if ((r = Child(q, c)) == NIL) {
- MakeChild(q, c, 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 (r >= WNDSIZ) {
- j = MAXMATCH;
- mMatchPos = r;
- } else {
- j = mLevel[r];
- mMatchPos = (NODE)(mPosition[r] & ~PERC_FLAG);
- }
- if (mMatchPos >= mPos) {
- mMatchPos -= WNDSIZ;
- }
- t1 = &mText[mPos + mMatchLen];
- t2 = &mText[mMatchPos + mMatchLen];
- while (mMatchLen < j) {
- if (*t1 != *t2) {
- Split(r);
- return;
- }
- mMatchLen++;
- t1++;
- t2++;
- }
- if (mMatchLen >= MAXMATCH) {
- break;
- }
- mPosition[r] = mPos;
- q = r;
- if ((r = Child(q, *t1)) == NIL) {
- MakeChild(q, *t1, mPos);
- return;
- }
- mMatchLen++;
- }
- t = mPrev[r];
- mPrev[mPos] = t;
- mNext[t] = mPos;
- t = mNext[r];
- mNext[mPos] = t;
- mPrev[t] = mPos;
- mParent[mPos] = q;
- mParent[r] = NIL;
- //
- // Special usage of 'next'
- //
- mNext[r] = mPos;
- }
- STATIC
- VOID
- DeleteNode ()
- /*++
- Routine Description:
- Delete outdated string info. (The Usage of PERC_FLAG
- ensures a clean deletion)
- Arguments: (VOID)
- Returns: (VOID)
- --*/
- {
- NODE q, r, s, t, u;
- if (mParent[mPos] == NIL) {
- return;
- }
- r = mPrev[mPos];
- s = mNext[mPos];
- mNext[r] = s;
- mPrev[s] = r;
- r = mParent[mPos];
- mParent[mPos] = NIL;
- if (r >= WNDSIZ || --mChildCount[r] > 1) {
- return;
- }
- t = (NODE)(mPosition[r] & ~PERC_FLAG);
- if (t >= mPos) {
- t -= WNDSIZ;
- }
- s = t;
- q = mParent[r];
- while ((u = mPosition[q]) & PERC_FLAG) {
- u &= ~PERC_FLAG;
- if (u >= mPos) {
- u -= WNDSIZ;
- }
- if (u > s) {
- s = u;
- }
- mPosition[q] = (INT16)(s | WNDSIZ);
- q = mParent[q];
- }
- if (q < WNDSIZ) {
- if (u >= mPos) {
- u -= WNDSIZ;
- }
- if (u > s) {
- s = u;
- }
- mPosition[q] = (INT16)(s | WNDSIZ | PERC_FLAG);
- }
- s = Child(r, mText[t + mLevel[r]]);
- t = mPrev[s];
- u = mNext[s];
- mNext[t] = u;
- mPrev[u] = t;
- t = mPrev[r];
- mNext[t] = s;
- mPrev[s] = t;
- t = mNext[r];
- mPrev[t] = s;
- mNext[s] = t;
- mParent[s] = mParent[r];
- mParent[r] = NIL;
- mNext[r] = mAvail;
- mAvail = r;
- }
- STATIC
- VOID
- GetNextMatch ()
- /*++
- 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 n;
- mRemainder--;
- if (++mPos == WNDSIZ * 2) {
- memmove(&mText[0], &mText[WNDSIZ], WNDSIZ + MAXMATCH);
- n = FreadCrc(&mText[WNDSIZ + MAXMATCH], WNDSIZ);
- mRemainder += n;
- mPos = WNDSIZ;
- }
- DeleteNode();
- InsertNode();
- }
- STATIC
- EFI_STATUS
- 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
- --*/
- {
- 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 {
- //
- // Outputting a pointer is beneficial enough, do it.
- //
- Output(LastMatchLen + (UINT8_MAX + 1 - THRESHOLD),
- (mPos - LastMatchPos - 2) & (WNDSIZ - 1));
- while (--LastMatchLen > 0) {
- GetNextMatch();
- }
- if (mMatchLen > mRemainder) {
- mMatchLen = mRemainder;
- }
- }
- }
- HufEncodeEnd();
- FreeMemory();
- return EFI_SUCCESS;
- }
- STATIC
- VOID
- CountTFreq ()
- /*++
- Routine Description:
- Count the frequencies for the Extra Set
- Arguments: (VOID)
- Returns: (VOID)
- --*/
- {
- INT32 i, k, n, Count;
- for (i = 0; i < NT; i++) {
- mTFreq[i] = 0;
- }
- n = NC;
- while (n > 0 && mCLen[n - 1] == 0) {
- n--;
- }
- i = 0;
- while (i < n) {
- k = mCLen[i++];
- if (k == 0) {
- Count = 1;
- while (i < n && mCLen[i] == 0) {
- i++;
- 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[k + 2]++;
- }
- }
- }
- STATIC
- VOID
- WritePTLen (
- IN INT32 n,
- IN INT32 nbit,
- IN INT32 Special
- )
- /*++
- Routine Description:
- Outputs the code length array for the Extra Set or the Position Set.
- Arguments:
- n - 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 i, k;
- while (n > 0 && mPTLen[n - 1] == 0) {
- n--;
- }
- PutBits(nbit, n);
- i = 0;
- while (i < n) {
- k = mPTLen[i++];
- if (k <= 6) {
- PutBits(3, k);
- } else {
- PutBits(k - 3, (1U << (k - 3)) - 2);
- }
- if (i == Special) {
- while (i < 6 && mPTLen[i] == 0) {
- i++;
- }
- PutBits(2, (i - 3) & 3);
- }
- }
- }
- STATIC
- VOID
- WriteCLen ()
- /*++
- Routine Description:
- Outputs the code length array for Char&Length Set
- Arguments: (VOID)
- Returns: (VOID)
- --*/
- {
- INT32 i, k, n, Count;
- n = NC;
- while (n > 0 && mCLen[n - 1] == 0) {
- n--;
- }
- PutBits(CBIT, n);
- i = 0;
- while (i < n) {
- k = mCLen[i++];
- if (k == 0) {
- Count = 1;
- while (i < n && mCLen[i] == 0) {
- i++;
- Count++;
- }
- if (Count <= 2) {
- for (k = 0; k < Count; k++) {
- 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[k + 2], mPTCode[k + 2]);
- }
- }
- }
- STATIC
- VOID
- EncodeC (
- IN INT32 c
- )
- {
- PutBits(mCLen[c], mCCode[c]);
- }
- STATIC
- VOID
- EncodeP (
- IN UINT32 p
- )
- {
- UINT32 c, q;
- c = 0;
- q = p;
- while (q) {
- q >>= 1;
- c++;
- }
- PutBits(mPTLen[c], mPTCode[c]);
- if (c > 1) {
- PutBits(c - 1, p & (0xFFFFU >> (17 - c)));
- }
- }
- STATIC
- VOID
- SendBlock ()
- /*++
- Routine Description:
- Huffman code the block and output it.
- Argument: (VOID)
- Returns: (VOID)
- --*/
- {
- UINT32 i, k, Flags, Root, Pos, 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 (i = 0; i < Size; i++) {
- if (i % UINT8_BIT == 0) {
- Flags = mBuf[Pos++];
- } else {
- Flags <<= 1;
- }
- if (Flags & (1U << (UINT8_BIT - 1))) {
- EncodeC(mBuf[Pos++] + (1U << UINT8_BIT));
- k = mBuf[Pos++] << UINT8_BIT;
- k += mBuf[Pos++];
- EncodeP(k);
- } else {
- EncodeC(mBuf[Pos++]);
- }
- }
- for (i = 0; i < NC; i++) {
- mCFreq[i] = 0;
- }
- for (i = 0; i < NP; i++) {
- mPFreq[i] = 0;
- }
- }
- STATIC
- VOID
- Output (
- IN UINT32 c,
- IN UINT32 p
- )
- /*++
- Routine Description:
- Outputs an Original Character or a Pointer
- Arguments:
- c - The original character or the 'String Length' element of a Pointer
- p - The 'Position' field of a Pointer
- Returns: (VOID)
- --*/
- {
- 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) c;
- mCFreq[c]++;
- if (c >= (1U << UINT8_BIT)) {
- mBuf[CPos] |= mOutputMask;
- mBuf[mOutputPos++] = (UINT8)(p >> UINT8_BIT);
- mBuf[mOutputPos++] = (UINT8) p;
- c = 0;
- while (p) {
- p >>= 1;
- c++;
- }
- mPFreq[c]++;
- }
- }
- STATIC
- VOID
- HufEncodeStart ()
- {
- INT32 i;
- for (i = 0; i < NC; i++) {
- mCFreq[i] = 0;
- }
- for (i = 0; i < NP; i++) {
- mPFreq[i] = 0;
- }
- mOutputPos = mOutputMask = 0;
- InitPutBits();
- return;
- }
- STATIC
- VOID
- HufEncodeEnd ()
- {
- SendBlock();
- //
- // Flush remaining bits
- //
- PutBits(UINT8_BIT - 1, 0);
- return;
- }
- STATIC
- VOID
- MakeCrcTable ()
- {
- UINT32 i, j, r;
- for (i = 0; i <= UINT8_MAX; i++) {
- r = i;
- for (j = 0; j < UINT8_BIT; j++) {
- if (r & 1) {
- r = (r >> 1) ^ CRCPOLY;
- } else {
- r >>= 1;
- }
- }
- mCrcTable[i] = (UINT16)r;
- }
- }
- STATIC
- VOID
- PutBits (
- IN INT32 n,
- IN UINT32 x
- )
- /*++
- Routine Description:
- Outputs rightmost n bits of x
- Argments:
- n - the rightmost n bits of the data is used
- x - the data
- Returns: (VOID)
- --*/
- {
- UINT8 Temp;
- if (n < mBitCount) {
- mSubBitBuf |= x << (mBitCount -= n);
- } else {
- Temp = (UINT8)(mSubBitBuf | (x >> (n -= mBitCount)));
- if (mDst < mDstUpperLimit) {
- *mDst++ = Temp;
- }
- mCompSize++;
- if (n < UINT8_BIT) {
- mSubBitBuf = x << (mBitCount = UINT8_BIT - n);
- } else {
- Temp = (UINT8)(x >> (n - UINT8_BIT));
- if (mDst < mDstUpperLimit) {
- *mDst++ = Temp;
- }
- mCompSize++;
- mSubBitBuf = x << (mBitCount = 2 * UINT8_BIT - n);
- }
- }
- }
- STATIC
- INT32
- FreadCrc (
- OUT UINT8 *p,
- IN INT32 n
- )
- /*++
- Routine Description:
- Read in source data
- Arguments:
- p - the buffer to hold the data
- n - number of bytes to read
- Returns:
- number of bytes actually read
- --*/
- {
- INT32 i;
- for (i = 0; mSrc < mSrcUpperLimit && i < n; i++) {
- *p++ = *mSrc++;
- }
- n = i;
- p -= n;
- mOrigSize += n;
- while (--i >= 0) {
- UPDATE_CRC(*p++);
- }
- return n;
- }
- STATIC
- VOID
- InitPutBits ()
- {
- mBitCount = UINT8_BIT;
- mSubBitBuf = 0;
- }
- STATIC
- VOID
- CountLen (
- IN INT32 i
- )
- /*++
- Routine Description:
- Count the number of each code length for a Huffman tree.
- Arguments:
- i - the top node
- Returns: (VOID)
- --*/
- {
- STATIC INT32 Depth = 0;
- if (i < mN) {
- mLenCnt[(Depth < 16) ? Depth : 16]++;
- } else {
- Depth++;
- CountLen(mLeft [i]);
- CountLen(mRight[i]);
- Depth--;
- }
- }
- STATIC
- VOID
- MakeLen (
- IN INT32 Root
- )
- /*++
- Routine Description:
- Create code length array for a Huffman tree
- Arguments:
- Root - the root of the tree
- --*/
- {
- INT32 i, k;
- UINT32 Cum;
- for (i = 0; i <= 16; i++) {
- mLenCnt[i] = 0;
- }
- CountLen(Root);
- //
- // Adjust the length count array so that
- // no code will be generated longer than its designated length
- //
- Cum = 0;
- for (i = 16; i > 0; i--) {
- Cum += mLenCnt[i] << (16 - i);
- }
- while (Cum != (1U << 16)) {
- mLenCnt[16]--;
- for (i = 15; i > 0; i--) {
- if (mLenCnt[i] != 0) {
- mLenCnt[i]--;
- mLenCnt[i+1] += 2;
- break;
- }
- }
- Cum--;
- }
- for (i = 16; i > 0; i--) {
- k = mLenCnt[i];
- while (--k >= 0) {
- mLen[*mSortPtr++] = (UINT8)i;
- }
- }
- }
- STATIC
- VOID
- DownHeap (
- IN INT32 i
- )
- {
- INT32 j, k;
- //
- // priority queue: send i-th entry down heap
- //
- k = mHeap[i];
- while ((j = 2 * i) <= mHeapSize) {
- if (j < mHeapSize && mFreq[mHeap[j]] > mFreq[mHeap[j + 1]]) {
- j++;
- }
- if (mFreq[k] <= mFreq[mHeap[j]]) {
- break;
- }
- mHeap[i] = mHeap[j];
- i = j;
- }
- mHeap[i] = (INT16)k;
- }
- STATIC
- VOID
- MakeCode (
- IN INT32 n,
- IN UINT8 Len[],
- OUT UINT16 Code[]
- )
- /*++
- Routine Description:
- Assign code to each symbol based on the code length array
- Arguments:
- n - number of symbols
- Len - the code length array
- Code - stores codes for each symbol
- Returns: (VOID)
- --*/
- {
- INT32 i;
- UINT16 Start[18];
- Start[1] = 0;
- for (i = 1; i <= 16; i++) {
- Start[i + 1] = (UINT16)((Start[i] + mLenCnt[i]) << 1);
- }
- for (i = 0; i < n; i++) {
- Code[i] = Start[Len[i]]++;
- }
- }
- 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 i, j, k, Avail;
- //
- // make tree, calculate len[], return root
- //
- mN = NParm;
- mFreq = FreqParm;
- mLen = LenParm;
- Avail = mN;
- mHeapSize = 0;
- mHeap[1] = 0;
- for (i = 0; i < mN; i++) {
- mLen[i] = 0;
- if (mFreq[i]) {
- mHeap[++mHeapSize] = (INT16)i;
- }
- }
- if (mHeapSize < 2) {
- CodeParm[mHeap[1]] = 0;
- return mHeap[1];
- }
- for (i = mHeapSize / 2; i >= 1; i--) {
- //
- // make priority queue
- //
- DownHeap(i);
- }
- mSortPtr = CodeParm;
- do {
- i = mHeap[1];
- if (i < mN) {
- *mSortPtr++ = (UINT16)i;
- }
- mHeap[1] = mHeap[mHeapSize--];
- DownHeap(1);
- j = mHeap[1];
- if (j < mN) {
- *mSortPtr++ = (UINT16)j;
- }
- k = Avail++;
- mFreq[k] = (UINT16)(mFreq[i] + mFreq[j]);
- mHeap[1] = (INT16)k;
- DownHeap(1);
- mLeft[k] = (UINT16)i;
- mRight[k] = (UINT16)j;
- } while (mHeapSize > 1);
- mSortPtr = CodeParm;
- MakeLen(k);
- MakeCode(NParm, LenParm, CodeParm);
- //
- // return root
- //
- return k;
- }
- #ifndef FOR_LIBRARY
- int main(int argc, char *argv[])
- {
- char *progname;
- int retval = 1;
- progname = strrchr(argv[0], '/');
- if (progname)
- progname++;
- else
- progname = argv[0];
- if (argc != 3)
- {
- fprintf(stderr, "\nUsage: %s INFILE OUTFILE\n\n", progname);
- exit(1);
- }
- char *infile = argv[1];
- char *outfile = argv[2];
- struct stat istat;
- if (0 != stat(infile, &istat)) {
- fprintf(stderr, "%s: can't stat %s: %s\n",
- progname,
- infile,
- strerror(errno));
- exit(1);
- }
- uint32_t isize = (uint32_t)istat.st_size;
- printf("%s is %d bytes\n", infile, isize);
- FILE *ifp = fopen(infile, "rb");
- if (!ifp)
- {
- fprintf(stderr, "%s: can't read %s: %s\n",
- progname,
- infile,
- strerror(errno));
- exit(1);
- }
- // read input file into buffer
- uint8_t *ibuf = malloc(isize);
- if (!ibuf) {
- fprintf(stderr, "%s: can't malloc %d bytes: %s\n",
- progname,
- isize,
- strerror(errno));
- goto done1;
- }
- if (1 != fread(ibuf, isize, 1, ifp)) {
- fprintf(stderr, "%s: can't read %d bytes: %s\n",
- progname,
- isize,
- strerror(errno));
- goto done2;
- }
- // assume compression will actually work
- uint32_t osize = isize;
- uint8_t *obuf = malloc(osize);
- if (!obuf) {
- fprintf(stderr, "%s: can't allocate %d bytes: %s\n",
- progname,
- osize,
- strerror(errno));
- goto done2;
- }
- // try it and see
- EFI_STATUS r = EfiCompress(ibuf, isize, obuf, &osize);
- if (r != EFI_SUCCESS) {
- fprintf(stderr, "%s: compression failed with code %d\n",
- progname,
- r);
- goto done3;
- }
- printf("Compressed %d bytes to %d bytes\n", isize, osize);
- // Write it out
- FILE *ofp = fopen(outfile, "wb");
- if (!ofp)
- {
- fprintf(stderr, "%s: can't open %s for writing: %s\n",
- progname,
- outfile,
- strerror(errno));
- goto done3;
- }
- if (1 != fwrite(obuf, osize, 1, ofp)) {
- fprintf(stderr, "%s: can't write %d bytes: %s\n",
- progname,
- osize,
- strerror(errno));
- goto done4;
- }
- printf("wrote %d bytes to %s\n", osize, outfile);
- retval = 0;
- done4:
- fclose(ofp);
- done3:
- free(obuf);
- done2:
- free(ibuf);
- done1:
- fclose(ifp);
- return retval;
- }
- #endif // FOR_LIBRARY
|