3 Copyright (c) 2007, Intel Corporation
\r
4 All rights reserved. This program and the accompanying materials
\r
5 are licensed and made available under the terms and conditions of the BSD License
\r
6 which accompanies this distribution. The full text of the license may be found at
\r
7 http://opensource.org/licenses/bsd-license.php
\r
9 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
\r
10 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
\r
18 Compression routine. The compression algorithm is a mixture of
\r
19 LZ77 and Huffman coding. LZ77 transforms the source data into a
\r
20 sequence of Original Characters and Pointers to repeated strings.
\r
21 This sequence is further divided into Blocks and Huffman codings
\r
22 are applied to each Block.
\r
26 #include "Compress.h"
\r
27 #include "TianoCompress.h"
\r
32 // Macro Definitions
\r
34 static BOOLEAN VerboseMode = FALSE;
\r
35 static BOOLEAN QuietMode = FALSE;
\r
36 #define UINT8_MAX 0xff
\r
41 #define WNDSIZ (1U << WNDBIT)
\r
42 #define MAXMATCH 256
\r
43 #define BLKSIZ (1U << 14) // 16 * 1024U
\r
44 #define PERC_FLAG 0x80000000U
\r
47 #define MAX_HASH_VAL (3 * WNDSIZ + (WNDSIZ / 512 + 1) * UINT8_MAX)
\r
48 #define HASH(p, c) ((p) + ((c) << (WNDBIT - 9)) + WNDSIZ * 2)
\r
49 #define CRCPOLY 0xA001
\r
50 #define UPDATE_CRC(c) mCrc = mCrcTable[(mCrc ^ (c)) & 0xFF] ^ (mCrc >> UINT8_BIT)
\r
53 // C: the Char&Len Set; P: the Position Set; T: the exTra Set
\r
55 //#define NC (UINT8_MAX + MAXMATCH + 2 - THRESHOLD)
\r
57 #define NP (WNDBIT + 1)
\r
59 //#define NT (CODE_BIT + 3)
\r
70 STATIC BOOLEAN ENCODE = FALSE;
\r
71 STATIC BOOLEAN DECODE = FALSE;
\r
72 STATIC UINT8 *mSrc, *mDst, *mSrcUpperLimit, *mDstUpperLimit;
\r
73 STATIC UINT8 *mLevel, *mText, *mChildCount, *mBuf, mCLen[NC], mPTLen[NPT], *mLen;
\r
74 STATIC INT16 mHeap[NC + 1];
\r
75 STATIC INT32 mRemainder, mMatchLen, mBitCount, mHeapSize, mN;
\r
76 STATIC UINT32 mBufSiz = 0, mOutputPos, mOutputMask, mSubBitBuf, mCrc;
\r
77 STATIC UINT32 mCompSize, mOrigSize;
\r
79 STATIC UINT16 *mFreq, *mSortPtr, mLenCnt[17], mLeft[2 * NC - 1], mRight[2 * NC - 1], mCrcTable[UINT8_MAX + 1],
\r
80 mCFreq[2 * NC - 1], mCTable[4096], mCCode[NC], mPFreq[2 * NP - 1], mPTCode[NPT], mTFreq[2 * NT - 1];
\r
82 STATIC NODE mPos, mMatchPos, mAvail, *mPosition, *mParent, *mPrev, *mNext = NULL;
\r
84 static UINTN DebugLevel;
\r
85 static BOOLEAN DebugMode;
\r
91 IN UINT8 *SrcBuffer,
\r
93 IN UINT8 *DstBuffer,
\r
94 IN OUT UINT32 *DstSize
\r
98 Routine Description:
\r
100 The internal implementation of [Efi/Tiano]Compress().
\r
104 SrcBuffer - The buffer storing the source data
\r
105 SrcSize - The size of source data
\r
106 DstBuffer - The buffer to store the compressed data
\r
108 Version - The version of de/compression algorithm.
\r
109 Version 1 for EFI 1.1 de/compression algorithm.
\r
110 Version 2 for Tiano de/compression algorithm.
\r
114 EFI_BUFFER_TOO_SMALL - The DstBuffer is too small. In this case,
\r
115 DstSize contains the size needed.
\r
116 EFI_SUCCESS - Compression is successful.
\r
117 EFI_OUT_OF_RESOURCES - No resource to complete function.
\r
118 EFI_INVALID_PARAMETER - Parameter supplied is wrong.
\r
131 mChildCount = NULL;
\r
139 mSrcUpperLimit = mSrc + SrcSize;
\r
141 mDstUpperLimit = mDst +*DstSize;
\r
148 mOrigSize = mCompSize = 0;
\r
154 Status = Encode ();
\r
155 if (EFI_ERROR (Status)) {
\r
156 return EFI_OUT_OF_RESOURCES;
\r
160 // Null terminate the compressed data
\r
163 if (mDst < mDstUpperLimit) {
\r
168 // Fill in compressed size and original size
\r
172 PutDword (mCompSize + 1);
\r
173 PutDword (mOrigSize);
\r
178 if (mCompSize + 1 + 8 > *DstSize) {
\r
179 *DstSize = mCompSize + 1 + 8;
\r
180 return EFI_BUFFER_TOO_SMALL;
\r
182 *DstSize = mCompSize + 1 + 8;
\r
183 return EFI_SUCCESS;
\r
185 return EFI_SUCCESS;
\r
195 Routine Description:
\r
197 Put a dword to output stream
\r
201 Data - the dword to put
\r
207 if (mDst < mDstUpperLimit) {
\r
208 *mDst++ = (UINT8) (((UINT8) (Data)) & 0xff);
\r
211 if (mDst < mDstUpperLimit) {
\r
212 *mDst++ = (UINT8) (((UINT8) (Data >> 0x08)) & 0xff);
\r
215 if (mDst < mDstUpperLimit) {
\r
216 *mDst++ = (UINT8) (((UINT8) (Data >> 0x10)) & 0xff);
\r
219 if (mDst < mDstUpperLimit) {
\r
220 *mDst++ = (UINT8) (((UINT8) (Data >> 0x18)) & 0xff);
\r
231 Routine Description:
\r
233 Allocate memory spaces for data structures used in compression process
\r
240 EFI_SUCCESS - Memory is allocated successfully
\r
241 EFI_OUT_OF_RESOURCES - Allocation fails
\r
247 mText = malloc (WNDSIZ * 2 + MAXMATCH);
\r
248 for (Index = 0; Index < WNDSIZ * 2 + MAXMATCH; Index++) {
\r
252 mLevel = malloc ((WNDSIZ + UINT8_MAX + 1) * sizeof (*mLevel));
\r
253 mChildCount = malloc ((WNDSIZ + UINT8_MAX + 1) * sizeof (*mChildCount));
\r
254 mPosition = malloc ((WNDSIZ + UINT8_MAX + 1) * sizeof (*mPosition));
\r
255 mParent = malloc (WNDSIZ * 2 * sizeof (*mParent));
\r
256 mPrev = malloc (WNDSIZ * 2 * sizeof (*mPrev));
\r
257 mNext = malloc ((MAX_HASH_VAL + 1) * sizeof (*mNext));
\r
260 mBuf = malloc (mBufSiz);
\r
261 while (mBuf == NULL) {
\r
262 mBufSiz = (mBufSiz / 10U) * 9U;
\r
263 if (mBufSiz < 4 * 1024U) {
\r
264 return EFI_OUT_OF_RESOURCES;
\r
267 mBuf = malloc (mBufSiz);
\r
272 return EFI_SUCCESS;
\r
281 Routine Description:
\r
283 Called when compression is completed to free memory previously allocated.
\r
291 if (mText != NULL) {
\r
295 if (mLevel != NULL) {
\r
299 if (mChildCount != NULL) {
\r
300 free (mChildCount);
\r
303 if (mPosition != NULL) {
\r
307 if (mParent != NULL) {
\r
311 if (mPrev != NULL) {
\r
315 if (mNext != NULL) {
\r
319 if (mBuf != NULL) {
\r
333 Routine Description:
\r
335 Initialize String Info Log data structures
\r
345 for (Index = WNDSIZ; Index <= WNDSIZ + UINT8_MAX; Index++) {
\r
347 mPosition[Index] = NIL; // sentinel
\r
350 for (Index = WNDSIZ; Index < WNDSIZ * 2; Index++) {
\r
351 mParent[Index] = NIL;
\r
355 for (Index = 1; Index < WNDSIZ - 1; Index++) {
\r
356 mNext[Index] = (NODE) (Index + 1);
\r
359 mNext[WNDSIZ - 1] = NIL;
\r
360 for (Index = WNDSIZ * 2; Index <= MAX_HASH_VAL; Index++) {
\r
361 mNext[Index] = NIL;
\r
373 Routine Description:
\r
375 Find child node given the parent node and the edge character
\r
379 NodeQ - the parent node
\r
380 CharC - the edge character
\r
384 The child node (NIL if not found)
\r
390 NodeR = mNext[HASH (NodeQ, CharC)];
\r
394 mParent[NIL] = NodeQ;
\r
395 while (mParent[NodeR] != NodeQ) {
\r
396 NodeR = mNext[NodeR];
\r
411 Routine Description:
\r
413 Create a new child for a given parent node.
\r
417 Parent - the parent node
\r
418 CharC - the edge character
\r
419 Child - the child node
\r
428 Node1 = (NODE) HASH (Parent, CharC);
\r
429 Node2 = mNext[Node1];
\r
430 mNext[Node1] = Child;
\r
431 mNext[Child] = Node2;
\r
432 mPrev[Node2] = Child;
\r
433 mPrev[Child] = Node1;
\r
434 mParent[Child] = Parent;
\r
435 mChildCount[Parent]++;
\r
445 Routine Description:
\r
451 Old - the node to split
\r
461 mAvail = mNext[New];
\r
462 mChildCount[New] = 0;
\r
463 TempNode = mPrev[Old];
\r
464 mPrev[New] = TempNode;
\r
465 mNext[TempNode] = New;
\r
466 TempNode = mNext[Old];
\r
467 mNext[New] = TempNode;
\r
468 mPrev[TempNode] = New;
\r
469 mParent[New] = mParent[Old];
\r
470 mLevel[New] = (UINT8) mMatchLen;
\r
471 mPosition[New] = mPos;
\r
472 MakeChild (New, mText[mMatchPos + mMatchLen], Old);
\r
473 MakeChild (New, mText[mPos + mMatchLen], mPos);
\r
483 Routine Description:
\r
485 Insert string info for current position into the String Info Log
\r
501 if (mMatchLen >= 4) {
\r
503 // We have just got a long match, the target tree
\r
504 // can be located by MatchPos + 1. Travese the tree
\r
505 // from bottom up to get to a proper starting point.
\r
506 // The usage of PERC_FLAG ensures proper node deletion
\r
507 // in DeleteNode() later.
\r
510 NodeR = (NODE) ((mMatchPos + 1) | WNDSIZ);
\r
511 NodeQ = mParent[NodeR];
\r
512 while (NodeQ == NIL) {
\r
513 NodeR = mNext[NodeR];
\r
514 NodeQ = mParent[NodeR];
\r
517 while (mLevel[NodeQ] >= mMatchLen) {
\r
519 NodeQ = mParent[NodeQ];
\r
523 while (mPosition[NodeT] < 0) {
\r
524 mPosition[NodeT] = mPos;
\r
525 NodeT = mParent[NodeT];
\r
528 if (NodeT < WNDSIZ) {
\r
529 mPosition[NodeT] = (NODE) (mPos | (UINT32) PERC_FLAG);
\r
533 // Locate the target tree
\r
535 NodeQ = (NODE) (mText[mPos] + WNDSIZ);
\r
536 CharC = mText[mPos + 1];
\r
537 NodeR = Child (NodeQ, CharC);
\r
538 if (NodeR == NIL) {
\r
539 MakeChild (NodeQ, CharC, mPos);
\r
547 // Traverse down the tree to find a match.
\r
548 // Update Position value along the route.
\r
549 // Node split or creation is involved.
\r
552 if (NodeR >= WNDSIZ) {
\r
556 Index2 = mLevel[NodeR];
\r
557 mMatchPos = (NODE) (mPosition[NodeR] & (UINT32)~PERC_FLAG);
\r
560 if (mMatchPos >= mPos) {
\r
561 mMatchPos -= WNDSIZ;
\r
564 t1 = &mText[mPos + mMatchLen];
\r
565 t2 = &mText[mMatchPos + mMatchLen];
\r
566 while (mMatchLen < Index2) {
\r
577 if (mMatchLen >= MAXMATCH) {
\r
581 mPosition[NodeR] = mPos;
\r
583 NodeR = Child (NodeQ, *t1);
\r
584 if (NodeR == NIL) {
\r
585 MakeChild (NodeQ, *t1, mPos);
\r
592 NodeT = mPrev[NodeR];
\r
593 mPrev[mPos] = NodeT;
\r
594 mNext[NodeT] = mPos;
\r
595 NodeT = mNext[NodeR];
\r
596 mNext[mPos] = NodeT;
\r
597 mPrev[NodeT] = mPos;
\r
598 mParent[mPos] = NodeQ;
\r
599 mParent[NodeR] = NIL;
\r
602 // Special usage of 'next'
\r
604 mNext[NodeR] = mPos;
\r
615 Routine Description:
\r
617 Delete outdated string info. (The Usage of PERC_FLAG
\r
618 ensures a clean deletion)
\r
632 if (mParent[mPos] == NIL) {
\r
636 NodeR = mPrev[mPos];
\r
637 NodeS = mNext[mPos];
\r
638 mNext[NodeR] = NodeS;
\r
639 mPrev[NodeS] = NodeR;
\r
640 NodeR = mParent[mPos];
\r
641 mParent[mPos] = NIL;
\r
642 if (NodeR >= WNDSIZ) {
\r
646 mChildCount[NodeR]--;
\r
647 if (mChildCount[NodeR] > 1) {
\r
651 NodeT = (NODE) (mPosition[NodeR] & (UINT32)~PERC_FLAG);
\r
652 if (NodeT >= mPos) {
\r
657 NodeQ = mParent[NodeR];
\r
658 NodeU = mPosition[NodeQ];
\r
659 while (NodeU & (UINT32) PERC_FLAG) {
\r
660 NodeU &= (UINT32)~PERC_FLAG;
\r
661 if (NodeU >= mPos) {
\r
665 if (NodeU > NodeS) {
\r
669 mPosition[NodeQ] = (NODE) (NodeS | WNDSIZ);
\r
670 NodeQ = mParent[NodeQ];
\r
671 NodeU = mPosition[NodeQ];
\r
674 if (NodeQ < WNDSIZ) {
\r
675 if (NodeU >= mPos) {
\r
679 if (NodeU > NodeS) {
\r
683 mPosition[NodeQ] = (NODE) (NodeS | WNDSIZ | (UINT32) PERC_FLAG);
\r
686 NodeS = Child (NodeR, mText[NodeT + mLevel[NodeR]]);
\r
687 NodeT = mPrev[NodeS];
\r
688 NodeU = mNext[NodeS];
\r
689 mNext[NodeT] = NodeU;
\r
690 mPrev[NodeU] = NodeT;
\r
691 NodeT = mPrev[NodeR];
\r
692 mNext[NodeT] = NodeS;
\r
693 mPrev[NodeS] = NodeT;
\r
694 NodeT = mNext[NodeR];
\r
695 mPrev[NodeT] = NodeS;
\r
696 mNext[NodeS] = NodeT;
\r
697 mParent[NodeS] = mParent[NodeR];
\r
698 mParent[NodeR] = NIL;
\r
699 mNext[NodeR] = mAvail;
\r
710 Routine Description:
\r
712 Advance the current position (read in new data if needed).
\r
713 Delete outdated string info. Find a match string for current position.
\r
725 if (mPos == WNDSIZ * 2) {
\r
726 memmove (&mText[0], &mText[WNDSIZ], WNDSIZ + MAXMATCH);
\r
727 Number = FreadCrc (&mText[WNDSIZ + MAXMATCH], WNDSIZ);
\r
728 mRemainder += Number;
\r
743 Routine Description:
\r
745 The main controlling routine for compression process.
\r
751 EFI_SUCCESS - The compression is successful
\r
752 EFI_OUT_0F_RESOURCES - Not enough memory for compression process
\r
757 INT32 LastMatchLen;
\r
760 Status = AllocateMemory ();
\r
761 if (EFI_ERROR (Status)) {
\r
770 mRemainder = FreadCrc (&mText[WNDSIZ], WNDSIZ + MAXMATCH);
\r
775 if (mMatchLen > mRemainder) {
\r
776 mMatchLen = mRemainder;
\r
779 while (mRemainder > 0) {
\r
780 LastMatchLen = mMatchLen;
\r
781 LastMatchPos = mMatchPos;
\r
783 if (mMatchLen > mRemainder) {
\r
784 mMatchLen = mRemainder;
\r
787 if (mMatchLen > LastMatchLen || LastMatchLen < THRESHOLD) {
\r
789 // Not enough benefits are gained by outputting a pointer,
\r
790 // so just output the original character
\r
792 Output (mText[mPos - 1], 0);
\r
796 if (LastMatchLen == THRESHOLD) {
\r
797 if (((mPos - LastMatchPos - 2) & (WNDSIZ - 1)) > (1U << 11)) {
\r
798 Output (mText[mPos - 1], 0);
\r
803 // Outputting a pointer is beneficial enough, do it.
\r
806 LastMatchLen + (UINT8_MAX + 1 - THRESHOLD),
\r
807 (mPos - LastMatchPos - 2) & (WNDSIZ - 1)
\r
810 while (LastMatchLen > 0) {
\r
815 if (mMatchLen > mRemainder) {
\r
816 mMatchLen = mRemainder;
\r
823 return EFI_SUCCESS;
\r
833 Routine Description:
\r
835 Count the frequencies for the Extra Set
\r
848 for (Index = 0; Index < NT; Index++) {
\r
853 while (Number > 0 && mCLen[Number - 1] == 0) {
\r
858 while (Index < Number) {
\r
859 Index3 = mCLen[Index++];
\r
862 while (Index < Number && mCLen[Index] == 0) {
\r
868 mTFreq[0] = (UINT16) (mTFreq[0] + Count);
\r
869 } else if (Count <= 18) {
\r
871 } else if (Count == 19) {
\r
878 mTFreq[Index3 + 2]++;
\r
892 Routine Description:
\r
894 Outputs the code length array for the Extra Set or the Position Set.
\r
898 Number - the number of symbols
\r
899 nbit - the number of bits needed to represent 'n'
\r
900 Special - the special symbol that needs to be take care of
\r
909 while (Number > 0 && mPTLen[Number - 1] == 0) {
\r
913 PutBits (nbit, Number);
\r
915 while (Index < Number) {
\r
916 Index3 = mPTLen[Index++];
\r
918 PutBits (3, Index3);
\r
920 PutBits (Index3 - 3, (1U << (Index3 - 3)) - 2);
\r
923 if (Index == Special) {
\r
924 while (Index < 6 && mPTLen[Index] == 0) {
\r
928 PutBits (2, (Index - 3) & 3);
\r
940 Routine Description:
\r
942 Outputs the code length array for Char&Length Set
\r
956 while (Number > 0 && mCLen[Number - 1] == 0) {
\r
960 PutBits (CBIT, Number);
\r
962 while (Index < Number) {
\r
963 Index3 = mCLen[Index++];
\r
966 while (Index < Number && mCLen[Index] == 0) {
\r
972 for (Index3 = 0; Index3 < Count; Index3++) {
\r
973 PutBits (mPTLen[0], mPTCode[0]);
\r
975 } else if (Count <= 18) {
\r
976 PutBits (mPTLen[1], mPTCode[1]);
\r
977 PutBits (4, Count - 3);
\r
978 } else if (Count == 19) {
\r
979 PutBits (mPTLen[0], mPTCode[0]);
\r
980 PutBits (mPTLen[1], mPTCode[1]);
\r
983 PutBits (mPTLen[2], mPTCode[2]);
\r
984 PutBits (CBIT, Count - 20);
\r
987 PutBits (mPTLen[Index3 + 2], mPTCode[Index3 + 2]);
\r
998 PutBits (mCLen[Value], mCCode[Value]);
\r
1017 PutBits (mPTLen[Index], mPTCode[Index]);
\r
1019 PutBits (Index - 1, Value & (0xFFFFFFFFU >> (32 - Index + 1)));
\r
1030 Routine Description:
\r
1032 Huffman code the block and output it.
\r
1051 Root = MakeTree (NC, mCFreq, mCLen, mCCode);
\r
1052 Size = mCFreq[Root];
\r
1054 PutBits (16, Size);
\r
1057 Root = MakeTree (NT, mTFreq, mPTLen, mPTCode);
\r
1059 WritePTLen (NT, TBIT, 3);
\r
1061 PutBits (TBIT, 0);
\r
1062 PutBits (TBIT, Root);
\r
1067 PutBits (TBIT, 0);
\r
1068 PutBits (TBIT, 0);
\r
1069 PutBits (CBIT, 0);
\r
1070 PutBits (CBIT, Root);
\r
1073 Root = MakeTree (NP, mPFreq, mPTLen, mPTCode);
\r
1075 WritePTLen (NP, PBIT, -1);
\r
1077 PutBits (PBIT, 0);
\r
1078 PutBits (PBIT, Root);
\r
1082 for (Index = 0; Index < Size; Index++) {
\r
1083 if (Index % UINT8_BIT == 0) {
\r
1084 Flags = mBuf[Pos++];
\r
1089 if (Flags & (1U << (UINT8_BIT - 1))) {
\r
1090 EncodeC (mBuf[Pos++] + (1U << UINT8_BIT));
\r
1091 Index3 = mBuf[Pos++];
\r
1092 for (Index2 = 0; Index2 < 3; Index2++) {
\r
1093 Index3 <<= UINT8_BIT;
\r
1094 Index3 += mBuf[Pos++];
\r
1099 EncodeC (mBuf[Pos++]);
\r
1103 for (Index = 0; Index < NC; Index++) {
\r
1104 mCFreq[Index] = 0;
\r
1107 for (Index = 0; Index < NP; Index++) {
\r
1108 mPFreq[Index] = 0;
\r
1120 Routine Description:
\r
1122 Outputs an Original Character or a Pointer
\r
1126 CharC - The original character or the 'String Length' element of a Pointer
\r
1127 Pos - The 'Position' field of a Pointer
\r
1133 STATIC UINT32 CPos;
\r
1135 if ((mOutputMask >>= 1) == 0) {
\r
1136 mOutputMask = 1U << (UINT8_BIT - 1);
\r
1138 // Check the buffer overflow per outputing UINT8_BIT symbols
\r
1139 // which is an Original Character or a Pointer. The biggest
\r
1140 // symbol is a Pointer which occupies 5 bytes.
\r
1142 if (mOutputPos >= mBufSiz - 5 * UINT8_BIT) {
\r
1147 CPos = mOutputPos++;
\r
1151 mBuf[mOutputPos++] = (UINT8) CharC;
\r
1153 if (CharC >= (1U << UINT8_BIT)) {
\r
1154 mBuf[CPos] |= mOutputMask;
\r
1155 mBuf[mOutputPos++] = (UINT8) (Pos >> 24);
\r
1156 mBuf[mOutputPos++] = (UINT8) (Pos >> 16);
\r
1157 mBuf[mOutputPos++] = (UINT8) (Pos >> (UINT8_BIT));
\r
1158 mBuf[mOutputPos++] = (UINT8) Pos;
\r
1177 for (Index = 0; Index < NC; Index++) {
\r
1178 mCFreq[Index] = 0;
\r
1181 for (Index = 0; Index < NP; Index++) {
\r
1182 mPFreq[Index] = 0;
\r
1185 mOutputPos = mOutputMask = 0;
\r
1199 // Flush remaining bits
\r
1201 PutBits (UINT8_BIT - 1, 0);
\r
1216 for (Index = 0; Index <= UINT8_MAX; Index++) {
\r
1218 for (Index2 = 0; Index2 < UINT8_BIT; Index2++) {
\r
1220 Temp = (Temp >> 1) ^ CRCPOLY;
\r
1226 mCrcTable[Index] = (UINT16) Temp;
\r
1238 Routine Description:
\r
1240 Outputs rightmost n bits of x
\r
1244 Number - the rightmost n bits of the data is used
\r
1253 while (Number >= mBitCount) {
\r
1255 // Number -= mBitCount should never equal to 32
\r
1257 Temp = (UINT8) (mSubBitBuf | (Value >> (Number -= mBitCount)));
\r
1259 if (mDst < mDstUpperLimit) {
\r
1265 mBitCount = UINT8_BIT;
\r
1268 mSubBitBuf |= Value << (mBitCount -= Number);
\r
1274 OUT UINT8 *Pointer,
\r
1279 Routine Description:
\r
1281 Read in source data
\r
1285 Pointer - the buffer to hold the data
\r
1286 Number - number of bytes to read
\r
1290 number of bytes actually read
\r
1296 for (Index = 0; mSrc < mSrcUpperLimit && Index < Number; Index++) {
\r
1297 *Pointer++ = *mSrc++;
\r
1302 Pointer -= Number;
\r
1303 mOrigSize += Number;
\r
1306 while (Index >= 0) {
\r
1307 UPDATE_CRC (*Pointer++);
\r
1320 mBitCount = UINT8_BIT;
\r
1331 Routine Description:
\r
1333 Count the number of each code length for a Huffman tree.
\r
1337 Index - the top node
\r
1343 STATIC INT32 Depth = 0;
\r
1346 mLenCnt[(Depth < 16) ? Depth : 16]++;
\r
1349 CountLen (mLeft[Index]);
\r
1350 CountLen (mRight[Index]);
\r
1362 Routine Description:
\r
1364 Create code length array for a Huffman tree
\r
1368 Root - the root of the tree
\r
1380 for (Index = 0; Index <= 16; Index++) {
\r
1381 mLenCnt[Index] = 0;
\r
1387 // Adjust the length count array so that
\r
1388 // no code will be generated longer than its designated length
\r
1391 for (Index = 16; Index > 0; Index--) {
\r
1392 Cum += mLenCnt[Index] << (16 - Index);
\r
1395 while (Cum != (1U << 16)) {
\r
1397 for (Index = 15; Index > 0; Index--) {
\r
1398 if (mLenCnt[Index] != 0) {
\r
1400 mLenCnt[Index + 1] += 2;
\r
1408 for (Index = 16; Index > 0; Index--) {
\r
1409 Index3 = mLenCnt[Index];
\r
1411 while (Index3 >= 0) {
\r
1412 mLen[*mSortPtr++] = (UINT8) Index;
\r
1428 // priority queue: send Index-th entry down heap
\r
1430 Index3 = mHeap[Index];
\r
1431 Index2 = 2 * Index;
\r
1432 while (Index2 <= mHeapSize) {
\r
1433 if (Index2 < mHeapSize && mFreq[mHeap[Index2]] > mFreq[mHeap[Index2 + 1]]) {
\r
1437 if (mFreq[Index3] <= mFreq[mHeap[Index2]]) {
\r
1441 mHeap[Index] = mHeap[Index2];
\r
1443 Index2 = 2 * Index;
\r
1446 mHeap[Index] = (INT16) Index3;
\r
1458 Routine Description:
\r
1460 Assign code to each symbol based on the code length array
\r
1464 Number - number of symbols
\r
1465 Len - the code length array
\r
1466 Code - stores codes for each symbol
\r
1476 for (Index = 1; Index <= 16; Index++) {
\r
1477 Start[Index + 1] = (UINT16) ((Start[Index] + mLenCnt[Index]) << 1);
\r
1480 for (Index = 0; Index < Number; Index++) {
\r
1481 Code[Index] = Start[Len[Index]]++;
\r
1489 IN UINT16 FreqParm[],
\r
1490 OUT UINT8 LenParm[ ],
\r
1491 OUT UINT16 CodeParm[]
\r
1495 Routine Description:
\r
1497 Generates Huffman codes given a frequency distribution of symbols
\r
1501 NParm - number of symbols
\r
1502 FreqParm - frequency of each symbol
\r
1503 LenParm - code length for each symbol
\r
1504 CodeParm - code for each symbol
\r
1508 Root of the Huffman tree.
\r
1518 // make tree, calculate len[], return root
\r
1526 for (Index = 0; Index < mN; Index++) {
\r
1528 if (mFreq[Index]) {
\r
1530 mHeap[mHeapSize] = (INT16) Index;
\r
1534 if (mHeapSize < 2) {
\r
1535 CodeParm[mHeap[1]] = 0;
\r
1539 for (Index = mHeapSize / 2; Index >= 1; Index--) {
\r
1541 // make priority queue
\r
1546 mSortPtr = CodeParm;
\r
1550 *mSortPtr++ = (UINT16) Index;
\r
1553 mHeap[1] = mHeap[mHeapSize--];
\r
1555 Index2 = mHeap[1];
\r
1556 if (Index2 < mN) {
\r
1557 *mSortPtr++ = (UINT16) Index2;
\r
1561 mFreq[Index3] = (UINT16) (mFreq[Index] + mFreq[Index2]);
\r
1562 mHeap[1] = (INT16) Index3;
\r
1564 mLeft[Index3] = (UINT16) Index;
\r
1565 mRight[Index3] = (UINT16) Index2;
\r
1566 } while (mHeapSize > 1);
\r
1568 mSortPtr = CodeParm;
\r
1570 MakeCode (NParm, LenParm, CodeParm);
\r
1580 IN char *InputFileName,
\r
1581 OUT UINT8 *FileBuffer,
\r
1582 OUT UINT32 *BufferLength
\r
1586 Routine Description:
\r
1588 Get the contents of file specified in InputFileName
\r
1593 InputFileName - Name of the input file.
\r
1595 FileBuffer - Output buffer to contain data
\r
1597 BufferLength - Actual length of the data
\r
1601 EFI_SUCCESS on successful return
\r
1602 EFI_ABORTED if unable to open input file.
\r
1613 // Copy the file contents to the output buffer.
\r
1615 InputFile = fopen (InputFileName, "rb");
\r
1616 if (InputFile == NULL) {
\r
1617 Error(NULL, 0, 0001, "Error opening file: %s", InputFileName);
\r
1618 return EFI_ABORTED;
\r
1621 fseek (InputFile, 0, SEEK_END);
\r
1622 FileSize = ftell (InputFile);
\r
1623 fseek (InputFile, 0, SEEK_SET);
\r
1625 // Now read the contents of the file into the buffer
\r
1627 if (FileSize > 0 && FileBuffer != NULL) {
\r
1628 if (fread (FileBuffer, FileSize, 1, InputFile) != 1) {
\r
1629 Error(NULL, 0, 0004, "Error reading contents of input file: %s", InputFileName);
\r
1630 fclose (InputFile);
\r
1631 return EFI_ABORTED;
\r
1635 fclose (InputFile);
\r
1636 Size += (UINTN) FileSize;
\r
1637 *BufferLength = Size;
\r
1639 if (FileBuffer != NULL) {
\r
1640 return EFI_SUCCESS;
\r
1642 return EFI_BUFFER_TOO_SMALL;
\r
1652 Routine Description:
\r
1654 Displays the standard utility information to SDTOUT
\r
1666 fprintf (stdout, "%s Version %d.%d\n", UTILITY_NAME, UTILITY_MAJOR_VERSION, UTILITY_MINOR_VERSION);
\r
1675 Routine Description:
\r
1677 Displays the utility usage syntax to STDOUT
\r
1692 fprintf (stdout, "Usage: %s -e|-d [options] <input_file>\n\n", UTILITY_NAME);
\r
1695 // Copyright declaration
\r
1697 fprintf (stdout, "Copyright (c) 2007, Intel Corporation. All rights reserved.\n\n");
\r
1702 fprintf (stdout, "Options:\n");
\r
1703 fprintf (stdout, " -o FileName, --output FileName\n\
\r
1704 File will be created to store the ouput content.\n");
\r
1705 fprintf (stdout, " -v, --verbose\n\
\r
1706 Turn on verbose output with informational messages.\n");
\r
1707 fprintf (stdout, " --version\n\
\r
1708 Show program's version number and exit.\n");
\r
1709 fprintf (stdout, " -h, --help\n\
\r
1710 Show this help message and exit.\n");
\r
1711 fprintf (stdout, " -q, --quiet\n\
\r
1712 Disable all messages except FATAL ERRORS.\n");
\r
1713 fprintf (stdout, " -d, --debug [#]\n\
\r
1714 Enable debug messages at level #.\n");
\r
1725 Routine Description:
\r
1731 command line parameters
\r
1735 EFI_SUCCESS Section header successfully generated and section concatenated.
\r
1736 EFI_ABORTED Could not generate the section
\r
1737 EFI_OUT_OF_RESOURCES No resource to complete the operation.
\r
1742 char *OutputFileName;
\r
1743 char *InputFileName;
\r
1745 EFI_STATUS Status;
\r
1746 UINT8 *FileBuffer;
\r
1748 UINT32 InputLength;
\r
1750 SCRATCH_DATA *Scratch;
\r
1754 SetUtilityName(UTILITY_NAME);
\r
1756 FileBuffer = NULL;
\r
1761 InputFileName = NULL;
\r
1762 OutputFileName = NULL;
\r
1765 DebugMode = FALSE;
\r
1768 // Verify the correct number of arguments
\r
1775 if ((strcmp(argv[1], "-h") == 0) || (strcmp(argv[1], "--help") == 0) ||
\r
1776 (strcmp(argv[1], "-?") == 0) || (strcmp(argv[1], "/?") == 0)) {
\r
1781 if ( (strcmp(argv[1], "--version") == 0)) {
\r
1788 if (strcmp(argv[0],"-e") == 0) {
\r
1790 // encode the input file
\r
1796 else if (strcmp(argv[0], "-d") == 0) {
\r
1798 // decode the input file
\r
1806 // Error command line
\r
1812 while (argc > 0) {
\r
1813 if ((strcmp(argv[0], "-v") == 0) || (stricmp(argv[0], "--verbose") == 0)) {
\r
1814 VerboseMode = TRUE;
\r
1819 if ((stricmp (argv[0], "-d") == 0) || (stricmp (argv[0], "--debug") == 0)) {
\r
1822 Status = AsciiStringToUint64(argv[0], FALSE, &DebugLevel);
\r
1823 if (DebugLevel > 9 || DebugLevel < 0) {
\r
1824 Error(NULL, 0 ,2000, "Invalid parameter", "Unrecognized argument %s", argv[0]);
\r
1827 if (DebugLevel>=5 && DebugLevel <=9){
\r
1830 DebugMode = FALSE;
\r
1835 if ((strcmp(argv[0], "-q") == 0) || (stricmp (argv[0], "--debug") == 0)) {
\r
1841 if ((strcmp(argv[0], "-o") == 0) || (stricmp (argv[0], "--output") == 0)) {
\r
1844 OutputFileName = argv[0];
\r
1848 if (argv[0][0]!='-') {
\r
1849 InputFileName = argv[0];
\r
1854 Error (NULL, 0, 1000, "Unknown option", argv[0]);
\r
1858 if (InputFileName == NULL) {
\r
1859 Error(NULL, 0, 2000, " Invalid parameter");
\r
1865 // All Parameters has been parsed
\r
1867 if (VerboseMode) {
\r
1868 fprintf (stdout, "%s tool start.\n", UTILITY_NAME);
\r
1870 Scratch = (SCRATCH_DATA *)malloc(sizeof(SCRATCH_DATA));
\r
1871 if (Scratch == NULL) {
\r
1872 Error(NULL, 0, 4001, "Resource:", "Memory cannot be allocated!");
\r
1877 InputFile = fopen (InputFileName, "rb");
\r
1878 if (InputFile == NULL) {
\r
1879 Error(NULL, 0, 0001, "Error opening input file", InputFileName);
\r
1884 Status = GetFileContents(
\r
1889 if (Status == EFI_BUFFER_TOO_SMALL) {
\r
1890 FileBuffer = (UINT8 *) malloc (InputLength);
\r
1891 if (FileBuffer == NULL) {
\r
1892 Error(NULL, 0, 4001, "Resource:", "Memory cannot be allocated!");
\r
1893 return EFI_OUT_OF_RESOURCES;
\r
1896 Status = GetFileContents (
\r
1903 if (EFI_ERROR(Status)) {
\r
1908 if (OutputFileName != NULL) {
\r
1909 OutputFile = fopen (OutputFileName, "wb");
\r
1910 if (OutputFile == NULL) {
\r
1911 Error(NULL, 0, 0001, "Error opening output file for writing", OutputFileName);
\r
1912 if (InputFile != NULL) {
\r
1913 fclose (InputFile);
\r
1915 //return EFI_ABORTED;
\r
1922 // First call TianoCompress to get DstSize
\r
1925 fprintf(stdout, "Encoding\n");
\r
1927 Status = TianoCompress ((UINT8 *)FileBuffer, InputLength, OutBuffer, &DstSize);
\r
1929 if (Status == EFI_BUFFER_TOO_SMALL) {
\r
1930 OutBuffer = (UINT8 *) malloc (DstSize);
\r
1931 if (OutBuffer == NULL) {
\r
1932 Error(NULL, 0, 4001, "Resource:", "Memory cannot be allocated!");
\r
1936 Status = TianoCompress ((UINT8 *)FileBuffer, InputLength, OutBuffer, &DstSize);
\r
1937 if (Status != EFI_SUCCESS) {
\r
1938 Error(NULL, 0, 0007, "Error compressing file");
\r
1942 fwrite(OutBuffer,(size_t)DstSize, 1, OutputFile);
\r
1947 fprintf(stdout, "Encoding successful\n");
\r
1951 else if (DECODE) {
\r
1953 fprintf(stdout, "Decoding\n");
\r
1956 // Get Compressed file original size
\r
1958 Src = (UINT8 *)FileBuffer;
\r
1959 OrigSize = Src[4] + (Src[5] << 8) + (Src[6] << 16) + (Src[7] << 24);
\r
1962 // Allocate OutputBuffer
\r
1964 OutBuffer = (UINT8 *)malloc(OrigSize);
\r
1965 if (OutBuffer == NULL) {
\r
1966 Error(NULL, 0, 4001, "Resource:", "Memory cannot be allocated!");
\r
1970 Status = Decompress((VOID *)FileBuffer, (VOID *)OutBuffer, (VOID *)Scratch, 2);
\r
1971 if (Status != EFI_SUCCESS) {
\r
1972 //Error(NULL, 0, 0008, "Error decompressing file: %s", InputFileName);
\r
1976 fwrite(OutBuffer, (size_t)(Scratch->mOrigSize), 1, OutputFile);
\r
1982 fprintf(stdout, "Decoding successful\n");
\r
1990 fprintf(stdout, "Encoding Error\n");
\r
1991 } else if (DECODE) {
\r
1992 fprintf(stdout, "Decoding Error\n");
\r
1998 if (VerboseMode) {
\r
1999 fprintf (stdout, "%s tool done with return code is 0x%x.\n", UTILITY_NAME, GetUtilityStatus ());
\r
2001 return GetUtilityStatus ();
\r
2006 IN SCRATCH_DATA *Sd,
\r
2007 IN UINT16 NumOfBits
\r
2011 Routine Description:
\r
2013 Shift mBitBuf NumOfBits left. Read in NumOfBits of bits from source.
\r
2017 Sd - The global scratch data
\r
2018 NumOfBits - The number of bits to shift and read.
\r
2024 Sd->mBitBuf = (UINT32) (Sd->mBitBuf << NumOfBits);
\r
2026 while (NumOfBits > Sd->mBitCount) {
\r
2028 Sd->mBitBuf |= (UINT32) (Sd->mSubBitBuf << (NumOfBits = (UINT16) (NumOfBits - Sd->mBitCount)));
\r
2030 if (Sd->mCompSize > 0) {
\r
2032 // Get 1 byte into SubBitBuf
\r
2035 Sd->mSubBitBuf = 0;
\r
2036 Sd->mSubBitBuf = Sd->mSrcBase[Sd->mInBuf++];
\r
2037 Sd->mBitCount = 8;
\r
2041 // No more bits from the source, just pad zero bit.
\r
2043 Sd->mSubBitBuf = 0;
\r
2044 Sd->mBitCount = 8;
\r
2049 Sd->mBitCount = (UINT16) (Sd->mBitCount - NumOfBits);
\r
2050 Sd->mBitBuf |= Sd->mSubBitBuf >> Sd->mBitCount;
\r
2055 IN SCRATCH_DATA *Sd,
\r
2056 IN UINT16 NumOfBits
\r
2060 Routine Description:
\r
2062 Get NumOfBits of bits out from mBitBuf. Fill mBitBuf with subsequent
\r
2063 NumOfBits of bits from source. Returns NumOfBits of bits that are
\r
2068 Sd - The global scratch data.
\r
2069 NumOfBits - The number of bits to pop and read.
\r
2073 The bits that are popped out.
\r
2079 OutBits = (UINT32) (Sd->mBitBuf >> (BITBUFSIZ - NumOfBits));
\r
2081 FillBuf (Sd, NumOfBits);
\r
2088 IN SCRATCH_DATA *Sd,
\r
2089 IN UINT16 NumOfChar,
\r
2091 IN UINT16 TableBits,
\r
2096 Routine Description:
\r
2098 Creates Huffman Code mapping table according to code length array.
\r
2102 Sd - The global scratch data
\r
2103 NumOfChar - Number of symbols in the symbol set
\r
2104 BitLen - Code length array
\r
2105 TableBits - The width of the mapping table
\r
2111 BAD_TABLE - The table is corrupted.
\r
2116 UINT16 Weight[17];
\r
2120 volatile UINT16 Index;
\r
2127 UINT16 WordOfStart;
\r
2128 UINT16 WordOfCount;
\r
2130 for (Index = 1; Index <= 16; Index++) {
\r
2134 for (Index = 0; Index < NumOfChar; Index++) {
\r
2135 Count[BitLen[Index]]++;
\r
2140 for (Index = 1; Index <= 16; Index++) {
\r
2141 WordOfStart = Start[Index];
\r
2142 WordOfCount = Count[Index];
\r
2143 Start[Index + 1] = (UINT16) (WordOfStart + (WordOfCount << (16 - Index)));
\r
2146 if (Start[17] != 0) {
\r
2150 return (UINT16) BAD_TABLE;
\r
2153 JuBits = (UINT16) (16 - TableBits);
\r
2155 for (Index = 1; Index <= TableBits; Index++) {
\r
2156 Start[Index] >>= JuBits;
\r
2157 Weight[Index] = (UINT16) (1U << (TableBits - Index));
\r
2160 while (Index <= 16) {
\r
2161 Weight[Index] = (UINT16) (1U << (16 - Index));
\r
2165 Index = (UINT16) (Start[TableBits + 1] >> JuBits);
\r
2168 Index3 = (UINT16) (1U << TableBits);
\r
2169 while (Index != Index3) {
\r
2170 Table[Index++] = 0;
\r
2174 Avail = NumOfChar;
\r
2175 Mask = (UINT16) (1U << (15 - TableBits));
\r
2177 for (Char = 0; Char < NumOfChar; Char++) {
\r
2179 Len = BitLen[Char];
\r
2184 NextCode = (UINT16) (Start[Len] + Weight[Len]);
\r
2186 if (Len <= TableBits) {
\r
2188 for (Index = Start[Len]; Index < NextCode; Index++) {
\r
2189 Table[Index] = Char;
\r
2194 Index3 = Start[Len];
\r
2195 Pointer = &Table[Index3 >> JuBits];
\r
2196 Index = (UINT16) (Len - TableBits);
\r
2198 while (Index != 0) {
\r
2199 if (*Pointer == 0) {
\r
2200 Sd->mRight[Avail] = Sd->mLeft[Avail] = 0;
\r
2201 *Pointer = Avail++;
\r
2204 if (Index3 & Mask) {
\r
2205 Pointer = &Sd->mRight[*Pointer];
\r
2207 Pointer = &Sd->mLeft[*Pointer];
\r
2218 Start[Len] = NextCode;
\r
2228 IN SCRATCH_DATA *Sd
\r
2232 Routine Description:
\r
2234 Decodes a position value.
\r
2238 Sd - the global scratch data
\r
2242 The position value decoded.
\r
2250 Val = Sd->mPTTable[Sd->mBitBuf >> (BITBUFSIZ - 8)];
\r
2252 if (Val >= MAXNP) {
\r
2253 Mask = 1U << (BITBUFSIZ - 1 - 8);
\r
2257 if (Sd->mBitBuf & Mask) {
\r
2258 Val = Sd->mRight[Val];
\r
2260 Val = Sd->mLeft[Val];
\r
2264 } while (Val >= MAXNP);
\r
2267 // Advance what we have read
\r
2269 FillBuf (Sd, Sd->mPTLen[Val]);
\r
2273 Pos = (UINT32) ((1U << (Val - 1)) + GetBits (Sd, (UINT16) (Val - 1)));
\r
2281 IN SCRATCH_DATA *Sd,
\r
2288 Routine Description:
\r
2290 Reads code lengths for the Extra Set or the Position Set
\r
2294 Sd - The global scratch data
\r
2295 nn - Number of symbols
\r
2296 nbit - Number of bits needed to represent nn
\r
2297 Special - The special symbol that needs to be taken care of
\r
2302 BAD_TABLE - Table is corrupted.
\r
2308 volatile UINT16 Index;
\r
2311 Number = (UINT16) GetBits (Sd, nbit);
\r
2313 if (Number == 0) {
\r
2314 CharC = (UINT16) GetBits (Sd, nbit);
\r
2316 for (Index = 0; Index < 256; Index++) {
\r
2317 Sd->mPTTable[Index] = CharC;
\r
2320 for (Index = 0; Index < nn; Index++) {
\r
2321 Sd->mPTLen[Index] = 0;
\r
2329 while (Index < Number) {
\r
2331 CharC = (UINT16) (Sd->mBitBuf >> (BITBUFSIZ - 3));
\r
2334 Mask = 1U << (BITBUFSIZ - 1 - 3);
\r
2335 while (Mask & Sd->mBitBuf) {
\r
2341 FillBuf (Sd, (UINT16) ((CharC < 7) ? 3 : CharC - 3));
\r
2343 Sd->mPTLen[Index++] = (UINT8) CharC;
\r
2345 if (Index == Special) {
\r
2346 CharC = (UINT16) GetBits (Sd, 2);
\r
2347 while ((INT16) (--CharC) >= 0) {
\r
2348 Sd->mPTLen[Index++] = 0;
\r
2353 while (Index < nn) {
\r
2354 Sd->mPTLen[Index++] = 0;
\r
2357 return MakeTable (Sd, nn, Sd->mPTLen, 8, Sd->mPTTable);
\r
2366 Routine Description:
\r
2368 Reads code lengths for Char&Len Set.
\r
2372 Sd - the global scratch data
\r
2380 volatile UINT16 Index;
\r
2383 Number = (UINT16) GetBits (Sd, CBIT);
\r
2385 if (Number == 0) {
\r
2386 CharC = (UINT16) GetBits (Sd, CBIT);
\r
2388 for (Index = 0; Index < NC; Index++) {
\r
2389 Sd->mCLen[Index] = 0;
\r
2392 for (Index = 0; Index < 4096; Index++) {
\r
2393 Sd->mCTable[Index] = CharC;
\r
2400 while (Index < Number) {
\r
2402 CharC = Sd->mPTTable[Sd->mBitBuf >> (BITBUFSIZ - 8)];
\r
2403 if (CharC >= NT) {
\r
2404 Mask = 1U << (BITBUFSIZ - 1 - 8);
\r
2408 if (Mask & Sd->mBitBuf) {
\r
2409 CharC = Sd->mRight[CharC];
\r
2411 CharC = Sd->mLeft[CharC];
\r
2416 } while (CharC >= NT);
\r
2419 // Advance what we have read
\r
2421 FillBuf (Sd, Sd->mPTLen[CharC]);
\r
2427 } else if (CharC == 1) {
\r
2428 CharC = (UINT16) (GetBits (Sd, 4) + 3);
\r
2429 } else if (CharC == 2) {
\r
2430 CharC = (UINT16) (GetBits (Sd, CBIT) + 20);
\r
2433 while ((INT16) (--CharC) >= 0) {
\r
2434 Sd->mCLen[Index++] = 0;
\r
2439 Sd->mCLen[Index++] = (UINT8) (CharC - 2);
\r
2444 while (Index < NC) {
\r
2445 Sd->mCLen[Index++] = 0;
\r
2448 MakeTable (Sd, NC, Sd->mCLen, 12, Sd->mCTable);
\r
2459 Routine Description:
\r
2461 Decode a character/length value.
\r
2465 Sd - The global scratch data.
\r
2469 The value decoded.
\r
2476 if (Sd->mBlockSize == 0) {
\r
2478 // Starting a new block
\r
2480 Sd->mBlockSize = (UINT16) GetBits (Sd, 16);
\r
2481 Sd->mBadTableFlag = ReadPTLen (Sd, NT, TBIT, 3);
\r
2482 if (Sd->mBadTableFlag != 0) {
\r
2488 Sd->mBadTableFlag = ReadPTLen (Sd, MAXNP, Sd->mPBit, (UINT16) (-1));
\r
2489 if (Sd->mBadTableFlag != 0) {
\r
2495 Index2 = Sd->mCTable[Sd->mBitBuf >> (BITBUFSIZ - 12)];
\r
2497 if (Index2 >= NC) {
\r
2498 Mask = 1U << (BITBUFSIZ - 1 - 12);
\r
2501 if (Sd->mBitBuf & Mask) {
\r
2502 Index2 = Sd->mRight[Index2];
\r
2504 Index2 = Sd->mLeft[Index2];
\r
2508 } while (Index2 >= NC);
\r
2511 // Advance what we have read
\r
2513 FillBuf (Sd, Sd->mCLen[Index2]);
\r
2524 Routine Description:
\r
2526 Decode the source data and put the resulting data into the destination buffer.
\r
2530 Sd - The global scratch data
\r
2536 UINT16 BytesRemain;
\r
2540 BytesRemain = (UINT16) (-1);
\r
2545 CharC = DecodeC (Sd);
\r
2546 if (Sd->mBadTableFlag != 0) {
\r
2550 if (CharC < 256) {
\r
2552 // Process an Original character
\r
2554 if (Sd->mOutBuf >= Sd->mOrigSize) {
\r
2557 Sd->mDstBase[Sd->mOutBuf++] = (UINT8) CharC;
\r
2562 // Process a Pointer
\r
2564 CharC = (UINT16) (CharC - (UINT8_MAX + 1 - THRESHOLD));
\r
2566 BytesRemain = CharC;
\r
2568 DataIdx = Sd->mOutBuf - DecodeP (Sd) - 1;
\r
2571 while ((INT16) (BytesRemain) >= 0) {
\r
2572 Sd->mDstBase[Sd->mOutBuf++] = Sd->mDstBase[DataIdx++];
\r
2573 if (Sd->mOutBuf >= Sd->mOrigSize) {
\r
2590 IN OUT VOID *Destination,
\r
2591 IN OUT VOID *Scratch,
\r
2596 Routine Description:
\r
2598 The internal implementation of Decompress().
\r
2602 Source - The source buffer containing the compressed data.
\r
2603 Destination - The destination buffer to store the decompressed data
\r
2604 Scratch - The buffer used internally by the decompress routine. This buffer is needed to store intermediate data.
\r
2605 Version - 1 for EFI1.1 Decompress algoruthm, 2 for Tiano Decompress algorithm
\r
2609 RETURN_SUCCESS - Decompression is successfull
\r
2610 RETURN_INVALID_PARAMETER - The source data is corrupted
\r
2614 volatile UINT32 Index;
\r
2622 // Verify input is not NULL
\r
2625 // assert(Destination);
\r
2628 Src = (UINT8 *)Source;
\r
2629 Dst = (UINT8 *)Destination;
\r
2631 Sd = (SCRATCH_DATA *) Scratch;
\r
2632 CompSize = Src[0] + (Src[1] << 8) + (Src[2] << 16) + (Src[3] << 24);
\r
2633 OrigSize = Src[4] + (Src[5] << 8) + (Src[6] << 16) + (Src[7] << 24);
\r
2636 // If compressed file size is 0, return
\r
2638 if (OrigSize == 0) {
\r
2639 return RETURN_SUCCESS;
\r
2644 for (Index = 0; Index < sizeof (SCRATCH_DATA); Index++) {
\r
2645 ((UINT8 *) Sd)[Index] = 0;
\r
2648 // The length of the field 'Position Set Code Length Array Size' in Block Header.
\r
2649 // For EFI 1.1 de/compression algorithm(Version 1), mPBit = 4
\r
2650 // For Tiano de/compression algorithm(Version 2), mPBit = 5
\r
2652 switch (Version) {
\r
2662 Sd->mSrcBase = (UINT8 *)Src;
\r
2663 Sd->mDstBase = Dst;
\r
2664 Sd->mCompSize = CompSize;
\r
2665 Sd->mOrigSize = OrigSize;
\r
2668 // Fill the first BITBUFSIZ bits
\r
2670 FillBuf (Sd, BITBUFSIZ);
\r
2678 if (Sd->mBadTableFlag != 0) {
\r
2680 // Something wrong with the source
\r
2682 return RETURN_INVALID_PARAMETER;
\r
2685 return RETURN_SUCCESS;
\r