]>
git.proxmox.com Git - mirror_edk2.git/blob - BaseTools/Source/C/TianoCompress/TianoCompress.c
3 Copyright (c) 2007 - 2010, Intel Corporation. All rights reserved.<BR>
4 This program and the accompanying materials
5 are licensed and made available under the terms and conditions of the BSD License
6 which accompanies this distribution. The full text of the license may be found at
7 http://opensource.org/licenses/bsd-license.php
9 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
10 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
18 Compression routine. The compression algorithm is a mixture of
19 LZ77 and Huffman coding. LZ77 transforms the source data into a
20 sequence of Original Characters and Pointers to repeated strings.
21 This sequence is further divided into Blocks and Huffman codings
22 are applied to each Block.
27 #include "TianoCompress.h"
28 #include "EfiUtilityMsgs.h"
36 static BOOLEAN VerboseMode
= FALSE
;
37 static BOOLEAN QuietMode
= FALSE
;
39 #define UINT8_MAX 0xff
44 #define WNDSIZ (1U << WNDBIT)
46 #define BLKSIZ (1U << 14) // 16 * 1024U
47 #define PERC_FLAG 0x80000000U
50 #define MAX_HASH_VAL (3 * WNDSIZ + (WNDSIZ / 512 + 1) * UINT8_MAX)
51 #define HASH(p, c) ((p) + ((c) << (WNDBIT - 9)) + WNDSIZ * 2)
52 #define CRCPOLY 0xA001
53 #define UPDATE_CRC(c) mCrc = mCrcTable[(mCrc ^ (c)) & 0xFF] ^ (mCrc >> UINT8_BIT)
56 // C: the Char&Len Set; P: the Position Set; T: the exTra Set
58 //#define NC (UINT8_MAX + MAXMATCH + 2 - THRESHOLD)
60 #define NP (WNDBIT + 1)
62 //#define NT (CODE_BIT + 3)
73 STATIC BOOLEAN ENCODE
= FALSE
;
74 STATIC BOOLEAN DECODE
= FALSE
;
75 STATIC UINT8
*mSrc
, *mDst
, *mSrcUpperLimit
, *mDstUpperLimit
;
76 STATIC UINT8
*mLevel
, *mText
, *mChildCount
, *mBuf
, mCLen
[NC
], mPTLen
[NPT
], *mLen
;
77 STATIC INT16 mHeap
[NC
+ 1];
78 STATIC INT32 mRemainder
, mMatchLen
, mBitCount
, mHeapSize
, mN
;
79 STATIC UINT32 mBufSiz
= 0, mOutputPos
, mOutputMask
, mSubBitBuf
, mCrc
;
80 STATIC UINT32 mCompSize
, mOrigSize
;
82 STATIC UINT16
*mFreq
, *mSortPtr
, mLenCnt
[17], mLeft
[2 * NC
- 1], mRight
[2 * NC
- 1], mCrcTable
[UINT8_MAX
+ 1],
83 mCFreq
[2 * NC
- 1], mCCode
[NC
], mPFreq
[2 * NP
- 1], mPTCode
[NPT
], mTFreq
[2 * NT
- 1];
85 STATIC NODE mPos
, mMatchPos
, mAvail
, *mPosition
, *mParent
, *mPrev
, *mNext
= NULL
;
87 static UINT64 DebugLevel
;
88 static BOOLEAN DebugMode
;
97 IN OUT UINT32
*DstSize
103 The internal implementation of [Efi/Tiano]Compress().
107 SrcBuffer - The buffer storing the source data
108 SrcSize - The size of source data
109 DstBuffer - The buffer to store the compressed data
111 Version - The version of de/compression algorithm.
112 Version 1 for EFI 1.1 de/compression algorithm.
113 Version 2 for Tiano de/compression algorithm.
117 EFI_BUFFER_TOO_SMALL - The DstBuffer is too small. In this case,
118 DstSize contains the size needed.
119 EFI_SUCCESS - Compression is successful.
120 EFI_OUT_OF_RESOURCES - No resource to complete function.
121 EFI_INVALID_PARAMETER - Parameter supplied is wrong.
142 mSrcUpperLimit
= mSrc
+ SrcSize
;
144 mDstUpperLimit
= mDst
+*DstSize
;
151 mOrigSize
= mCompSize
= 0;
158 if (EFI_ERROR (Status
)) {
159 return EFI_OUT_OF_RESOURCES
;
163 // Null terminate the compressed data
166 if (mDst
< mDstUpperLimit
) {
171 // Fill in compressed size and original size
175 PutDword (mCompSize
+ 1);
176 PutDword (mOrigSize
);
181 if (mCompSize
+ 1 + 8 > *DstSize
) {
182 *DstSize
= mCompSize
+ 1 + 8;
183 return EFI_BUFFER_TOO_SMALL
;
185 *DstSize
= mCompSize
+ 1 + 8;
199 Put a dword to output stream
203 Data - the dword to put
209 if (mDst
< mDstUpperLimit
) {
210 *mDst
++ = (UINT8
) (((UINT8
) (Data
)) & 0xff);
213 if (mDst
< mDstUpperLimit
) {
214 *mDst
++ = (UINT8
) (((UINT8
) (Data
>> 0x08)) & 0xff);
217 if (mDst
< mDstUpperLimit
) {
218 *mDst
++ = (UINT8
) (((UINT8
) (Data
>> 0x10)) & 0xff);
221 if (mDst
< mDstUpperLimit
) {
222 *mDst
++ = (UINT8
) (((UINT8
) (Data
>> 0x18)) & 0xff);
235 Allocate memory spaces for data structures used in compression process
242 EFI_SUCCESS - Memory is allocated successfully
243 EFI_OUT_OF_RESOURCES - Allocation fails
249 mText
= malloc (WNDSIZ
* 2 + MAXMATCH
);
250 for (Index
= 0; Index
< WNDSIZ
* 2 + MAXMATCH
; Index
++) {
254 mLevel
= malloc ((WNDSIZ
+ UINT8_MAX
+ 1) * sizeof (*mLevel
));
255 mChildCount
= malloc ((WNDSIZ
+ UINT8_MAX
+ 1) * sizeof (*mChildCount
));
256 mPosition
= malloc ((WNDSIZ
+ UINT8_MAX
+ 1) * sizeof (*mPosition
));
257 mParent
= malloc (WNDSIZ
* 2 * sizeof (*mParent
));
258 mPrev
= malloc (WNDSIZ
* 2 * sizeof (*mPrev
));
259 mNext
= malloc ((MAX_HASH_VAL
+ 1) * sizeof (*mNext
));
262 mBuf
= malloc (mBufSiz
);
263 while (mBuf
== NULL
) {
264 mBufSiz
= (mBufSiz
/ 10U) * 9U;
265 if (mBufSiz
< 4 * 1024U) {
266 return EFI_OUT_OF_RESOURCES
;
269 mBuf
= malloc (mBufSiz
);
285 Called when compression is completed to free memory previously allocated.
297 if (mLevel
!= NULL
) {
301 if (mChildCount
!= NULL
) {
305 if (mPosition
!= NULL
) {
309 if (mParent
!= NULL
) {
337 Initialize String Info Log data structures
347 for (Index
= WNDSIZ
; Index
<= WNDSIZ
+ UINT8_MAX
; Index
++) {
349 mPosition
[Index
] = NIL
; // sentinel
352 for (Index
= WNDSIZ
; Index
< WNDSIZ
* 2; Index
++) {
353 mParent
[Index
] = NIL
;
357 for (Index
= 1; Index
< WNDSIZ
- 1; Index
++) {
358 mNext
[Index
] = (NODE
) (Index
+ 1);
361 mNext
[WNDSIZ
- 1] = NIL
;
362 for (Index
= WNDSIZ
* 2; Index
<= MAX_HASH_VAL
; Index
++) {
377 Find child node given the parent node and the edge character
381 NodeQ - the parent node
382 CharC - the edge character
386 The child node (NIL if not found)
392 NodeR
= mNext
[HASH (NodeQ
, CharC
)];
396 mParent
[NIL
] = NodeQ
;
397 while (mParent
[NodeR
] != NodeQ
) {
398 NodeR
= mNext
[NodeR
];
415 Create a new child for a given parent node.
419 Parent - the parent node
420 CharC - the edge character
421 Child - the child node
430 Node1
= (NODE
) HASH (Parent
, CharC
);
431 Node2
= mNext
[Node1
];
432 mNext
[Node1
] = Child
;
433 mNext
[Child
] = Node2
;
434 mPrev
[Node2
] = Child
;
435 mPrev
[Child
] = Node1
;
436 mParent
[Child
] = Parent
;
437 mChildCount
[Parent
]++;
453 Old - the node to split
464 mChildCount
[New
] = 0;
465 TempNode
= mPrev
[Old
];
466 mPrev
[New
] = TempNode
;
467 mNext
[TempNode
] = New
;
468 TempNode
= mNext
[Old
];
469 mNext
[New
] = TempNode
;
470 mPrev
[TempNode
] = New
;
471 mParent
[New
] = mParent
[Old
];
472 mLevel
[New
] = (UINT8
) mMatchLen
;
473 mPosition
[New
] = mPos
;
474 MakeChild (New
, mText
[mMatchPos
+ mMatchLen
], Old
);
475 MakeChild (New
, mText
[mPos
+ mMatchLen
], mPos
);
487 Insert string info for current position into the String Info Log
503 if (mMatchLen
>= 4) {
505 // We have just got a long match, the target tree
506 // can be located by MatchPos + 1. Travese the tree
507 // from bottom up to get to a proper starting point.
508 // The usage of PERC_FLAG ensures proper node deletion
509 // in DeleteNode() later.
512 NodeR
= (NODE
) ((mMatchPos
+ 1) | WNDSIZ
);
513 NodeQ
= mParent
[NodeR
];
514 while (NodeQ
== NIL
) {
515 NodeR
= mNext
[NodeR
];
516 NodeQ
= mParent
[NodeR
];
519 while (mLevel
[NodeQ
] >= mMatchLen
) {
521 NodeQ
= mParent
[NodeQ
];
525 while (mPosition
[NodeT
] < 0) {
526 mPosition
[NodeT
] = mPos
;
527 NodeT
= mParent
[NodeT
];
530 if (NodeT
< WNDSIZ
) {
531 mPosition
[NodeT
] = (NODE
) (mPos
| (UINT32
) PERC_FLAG
);
535 // Locate the target tree
537 NodeQ
= (NODE
) (mText
[mPos
] + WNDSIZ
);
538 CharC
= mText
[mPos
+ 1];
539 NodeR
= Child (NodeQ
, CharC
);
541 MakeChild (NodeQ
, CharC
, mPos
);
549 // Traverse down the tree to find a match.
550 // Update Position value along the route.
551 // Node split or creation is involved.
554 if (NodeR
>= WNDSIZ
) {
558 Index2
= mLevel
[NodeR
];
559 mMatchPos
= (NODE
) (mPosition
[NodeR
] & (UINT32
)~PERC_FLAG
);
562 if (mMatchPos
>= mPos
) {
566 t1
= &mText
[mPos
+ mMatchLen
];
567 t2
= &mText
[mMatchPos
+ mMatchLen
];
568 while (mMatchLen
< Index2
) {
579 if (mMatchLen
>= MAXMATCH
) {
583 mPosition
[NodeR
] = mPos
;
585 NodeR
= Child (NodeQ
, *t1
);
587 MakeChild (NodeQ
, *t1
, mPos
);
594 NodeT
= mPrev
[NodeR
];
597 NodeT
= mNext
[NodeR
];
600 mParent
[mPos
] = NodeQ
;
601 mParent
[NodeR
] = NIL
;
604 // Special usage of 'next'
619 Delete outdated string info. (The Usage of PERC_FLAG
620 ensures a clean deletion)
634 if (mParent
[mPos
] == NIL
) {
640 mNext
[NodeR
] = NodeS
;
641 mPrev
[NodeS
] = NodeR
;
642 NodeR
= mParent
[mPos
];
644 if (NodeR
>= WNDSIZ
) {
648 mChildCount
[NodeR
]--;
649 if (mChildCount
[NodeR
] > 1) {
653 NodeT
= (NODE
) (mPosition
[NodeR
] & (UINT32
)~PERC_FLAG
);
659 NodeQ
= mParent
[NodeR
];
660 NodeU
= mPosition
[NodeQ
];
661 while (NodeU
& (UINT32
) PERC_FLAG
) {
662 NodeU
&= (UINT32
)~PERC_FLAG
;
671 mPosition
[NodeQ
] = (NODE
) (NodeS
| WNDSIZ
);
672 NodeQ
= mParent
[NodeQ
];
673 NodeU
= mPosition
[NodeQ
];
676 if (NodeQ
< WNDSIZ
) {
685 mPosition
[NodeQ
] = (NODE
) (NodeS
| WNDSIZ
| (UINT32
) PERC_FLAG
);
688 NodeS
= Child (NodeR
, mText
[NodeT
+ mLevel
[NodeR
]]);
689 NodeT
= mPrev
[NodeS
];
690 NodeU
= mNext
[NodeS
];
691 mNext
[NodeT
] = NodeU
;
692 mPrev
[NodeU
] = NodeT
;
693 NodeT
= mPrev
[NodeR
];
694 mNext
[NodeT
] = NodeS
;
695 mPrev
[NodeS
] = NodeT
;
696 NodeT
= mNext
[NodeR
];
697 mPrev
[NodeT
] = NodeS
;
698 mNext
[NodeS
] = NodeT
;
699 mParent
[NodeS
] = mParent
[NodeR
];
700 mParent
[NodeR
] = NIL
;
701 mNext
[NodeR
] = mAvail
;
714 Advance the current position (read in new data if needed).
715 Delete outdated string info. Find a match string for current position.
727 if (mPos
== WNDSIZ
* 2) {
728 memmove (&mText
[0], &mText
[WNDSIZ
], WNDSIZ
+ MAXMATCH
);
729 Number
= FreadCrc (&mText
[WNDSIZ
+ MAXMATCH
], WNDSIZ
);
730 mRemainder
+= Number
;
747 The main controlling routine for compression process.
753 EFI_SUCCESS - The compression is successful
754 EFI_OUT_0F_RESOURCES - Not enough memory for compression process
762 Status
= AllocateMemory ();
763 if (EFI_ERROR (Status
)) {
772 mRemainder
= FreadCrc (&mText
[WNDSIZ
], WNDSIZ
+ MAXMATCH
);
777 if (mMatchLen
> mRemainder
) {
778 mMatchLen
= mRemainder
;
781 while (mRemainder
> 0) {
782 LastMatchLen
= mMatchLen
;
783 LastMatchPos
= mMatchPos
;
785 if (mMatchLen
> mRemainder
) {
786 mMatchLen
= mRemainder
;
789 if (mMatchLen
> LastMatchLen
|| LastMatchLen
< THRESHOLD
) {
791 // Not enough benefits are gained by outputting a pointer,
792 // so just output the original character
794 Output (mText
[mPos
- 1], 0);
798 if (LastMatchLen
== THRESHOLD
) {
799 if (((mPos
- LastMatchPos
- 2) & (WNDSIZ
- 1)) > (1U << 11)) {
800 Output (mText
[mPos
- 1], 0);
805 // Outputting a pointer is beneficial enough, do it.
808 LastMatchLen
+ (UINT8_MAX
+ 1 - THRESHOLD
),
809 (mPos
- LastMatchPos
- 2) & (WNDSIZ
- 1)
812 while (LastMatchLen
> 0) {
817 if (mMatchLen
> mRemainder
) {
818 mMatchLen
= mRemainder
;
837 Count the frequencies for the Extra Set
850 for (Index
= 0; Index
< NT
; Index
++) {
855 while (Number
> 0 && mCLen
[Number
- 1] == 0) {
860 while (Index
< Number
) {
861 Index3
= mCLen
[Index
++];
864 while (Index
< Number
&& mCLen
[Index
] == 0) {
870 mTFreq
[0] = (UINT16
) (mTFreq
[0] + Count
);
871 } else if (Count
<= 18) {
873 } else if (Count
== 19) {
880 mTFreq
[Index3
+ 2]++;
896 Outputs the code length array for the Extra Set or the Position Set.
900 Number - the number of symbols
901 nbit - the number of bits needed to represent 'n'
902 Special - the special symbol that needs to be take care of
911 while (Number
> 0 && mPTLen
[Number
- 1] == 0) {
915 PutBits (nbit
, Number
);
917 while (Index
< Number
) {
918 Index3
= mPTLen
[Index
++];
922 PutBits (Index3
- 3, (1U << (Index3
- 3)) - 2);
925 if (Index
== Special
) {
926 while (Index
< 6 && mPTLen
[Index
] == 0) {
930 PutBits (2, (Index
- 3) & 3);
944 Outputs the code length array for Char&Length Set
958 while (Number
> 0 && mCLen
[Number
- 1] == 0) {
962 PutBits (CBIT
, Number
);
964 while (Index
< Number
) {
965 Index3
= mCLen
[Index
++];
968 while (Index
< Number
&& mCLen
[Index
] == 0) {
974 for (Index3
= 0; Index3
< Count
; Index3
++) {
975 PutBits (mPTLen
[0], mPTCode
[0]);
977 } else if (Count
<= 18) {
978 PutBits (mPTLen
[1], mPTCode
[1]);
979 PutBits (4, Count
- 3);
980 } else if (Count
== 19) {
981 PutBits (mPTLen
[0], mPTCode
[0]);
982 PutBits (mPTLen
[1], mPTCode
[1]);
985 PutBits (mPTLen
[2], mPTCode
[2]);
986 PutBits (CBIT
, Count
- 20);
989 PutBits (mPTLen
[Index3
+ 2], mPTCode
[Index3
+ 2]);
1000 PutBits (mCLen
[Value
], mCCode
[Value
]);
1019 PutBits (mPTLen
[Index
], mPTCode
[Index
]);
1021 PutBits (Index
- 1, Value
& (0xFFFFFFFFU
>> (32 - Index
+ 1)));
1032 Routine Description:
1034 Huffman code the block and output it.
1053 Root
= MakeTree (NC
, mCFreq
, mCLen
, mCCode
);
1054 Size
= mCFreq
[Root
];
1059 Root
= MakeTree (NT
, mTFreq
, mPTLen
, mPTCode
);
1061 WritePTLen (NT
, TBIT
, 3);
1064 PutBits (TBIT
, Root
);
1072 PutBits (CBIT
, Root
);
1075 Root
= MakeTree (NP
, mPFreq
, mPTLen
, mPTCode
);
1077 WritePTLen (NP
, PBIT
, -1);
1080 PutBits (PBIT
, Root
);
1084 for (Index
= 0; Index
< Size
; Index
++) {
1085 if (Index
% UINT8_BIT
== 0) {
1086 Flags
= mBuf
[Pos
++];
1091 if (Flags
& (1U << (UINT8_BIT
- 1))) {
1092 EncodeC (mBuf
[Pos
++] + (1U << UINT8_BIT
));
1093 Index3
= mBuf
[Pos
++];
1094 for (Index2
= 0; Index2
< 3; Index2
++) {
1095 Index3
<<= UINT8_BIT
;
1096 Index3
+= mBuf
[Pos
++];
1101 EncodeC (mBuf
[Pos
++]);
1105 for (Index
= 0; Index
< NC
; Index
++) {
1109 for (Index
= 0; Index
< NP
; Index
++) {
1122 Routine Description:
1124 Outputs an Original Character or a Pointer
1128 CharC - The original character or the 'String Length' element of a Pointer
1129 Pos - The 'Position' field of a Pointer
1137 if ((mOutputMask
>>= 1) == 0) {
1138 mOutputMask
= 1U << (UINT8_BIT
- 1);
1140 // Check the buffer overflow per outputing UINT8_BIT symbols
1141 // which is an Original Character or a Pointer. The biggest
1142 // symbol is a Pointer which occupies 5 bytes.
1144 if (mOutputPos
>= mBufSiz
- 5 * UINT8_BIT
) {
1149 CPos
= mOutputPos
++;
1153 mBuf
[mOutputPos
++] = (UINT8
) CharC
;
1155 if (CharC
>= (1U << UINT8_BIT
)) {
1156 mBuf
[CPos
] |= mOutputMask
;
1157 mBuf
[mOutputPos
++] = (UINT8
) (Pos
>> 24);
1158 mBuf
[mOutputPos
++] = (UINT8
) (Pos
>> 16);
1159 mBuf
[mOutputPos
++] = (UINT8
) (Pos
>> (UINT8_BIT
));
1160 mBuf
[mOutputPos
++] = (UINT8
) Pos
;
1179 for (Index
= 0; Index
< NC
; Index
++) {
1183 for (Index
= 0; Index
< NP
; Index
++) {
1187 mOutputPos
= mOutputMask
= 0;
1201 // Flush remaining bits
1203 PutBits (UINT8_BIT
- 1, 0);
1218 for (Index
= 0; Index
<= UINT8_MAX
; Index
++) {
1220 for (Index2
= 0; Index2
< UINT8_BIT
; Index2
++) {
1222 Temp
= (Temp
>> 1) ^ CRCPOLY
;
1228 mCrcTable
[Index
] = (UINT16
) Temp
;
1240 Routine Description:
1242 Outputs rightmost n bits of x
1246 Number - the rightmost n bits of the data is used
1255 while (Number
>= mBitCount
) {
1257 // Number -= mBitCount should never equal to 32
1259 Temp
= (UINT8
) (mSubBitBuf
| (Value
>> (Number
-= mBitCount
)));
1261 if (mDst
< mDstUpperLimit
) {
1267 mBitCount
= UINT8_BIT
;
1270 mSubBitBuf
|= Value
<< (mBitCount
-= Number
);
1281 Routine Description:
1287 Pointer - the buffer to hold the data
1288 Number - number of bytes to read
1292 number of bytes actually read
1298 for (Index
= 0; mSrc
< mSrcUpperLimit
&& Index
< Number
; Index
++) {
1299 *Pointer
++ = *mSrc
++;
1305 mOrigSize
+= Number
;
1308 while (Index
>= 0) {
1309 UPDATE_CRC (*Pointer
++);
1322 mBitCount
= UINT8_BIT
;
1333 Routine Description:
1335 Count the number of each code length for a Huffman tree.
1339 Index - the top node
1345 STATIC INT32 Depth
= 0;
1348 mLenCnt
[(Depth
< 16) ? Depth
: 16]++;
1351 CountLen (mLeft
[Index
]);
1352 CountLen (mRight
[Index
]);
1364 Routine Description:
1366 Create code length array for a Huffman tree
1370 Root - the root of the tree
1382 for (Index
= 0; Index
<= 16; Index
++) {
1389 // Adjust the length count array so that
1390 // no code will be generated longer than its designated length
1393 for (Index
= 16; Index
> 0; Index
--) {
1394 Cum
+= mLenCnt
[Index
] << (16 - Index
);
1397 while (Cum
!= (1U << 16)) {
1399 for (Index
= 15; Index
> 0; Index
--) {
1400 if (mLenCnt
[Index
] != 0) {
1402 mLenCnt
[Index
+ 1] += 2;
1410 for (Index
= 16; Index
> 0; Index
--) {
1411 Index3
= mLenCnt
[Index
];
1413 while (Index3
>= 0) {
1414 mLen
[*mSortPtr
++] = (UINT8
) Index
;
1430 // priority queue: send Index-th entry down heap
1432 Index3
= mHeap
[Index
];
1434 while (Index2
<= mHeapSize
) {
1435 if (Index2
< mHeapSize
&& mFreq
[mHeap
[Index2
]] > mFreq
[mHeap
[Index2
+ 1]]) {
1439 if (mFreq
[Index3
] <= mFreq
[mHeap
[Index2
]]) {
1443 mHeap
[Index
] = mHeap
[Index2
];
1448 mHeap
[Index
] = (INT16
) Index3
;
1460 Routine Description:
1462 Assign code to each symbol based on the code length array
1466 Number - number of symbols
1467 Len - the code length array
1468 Code - stores codes for each symbol
1478 for (Index
= 1; Index
<= 16; Index
++) {
1479 Start
[Index
+ 1] = (UINT16
) ((Start
[Index
] + mLenCnt
[Index
]) << 1);
1482 for (Index
= 0; Index
< Number
; Index
++) {
1483 Code
[Index
] = Start
[Len
[Index
]]++;
1491 IN UINT16 FreqParm
[],
1492 OUT UINT8 LenParm
[ ],
1493 OUT UINT16 CodeParm
[]
1497 Routine Description:
1499 Generates Huffman codes given a frequency distribution of symbols
1503 NParm - number of symbols
1504 FreqParm - frequency of each symbol
1505 LenParm - code length for each symbol
1506 CodeParm - code for each symbol
1510 Root of the Huffman tree.
1520 // make tree, calculate len[], return root
1528 for (Index
= 0; Index
< mN
; Index
++) {
1532 mHeap
[mHeapSize
] = (INT16
) Index
;
1536 if (mHeapSize
< 2) {
1537 CodeParm
[mHeap
[1]] = 0;
1541 for (Index
= mHeapSize
/ 2; Index
>= 1; Index
--) {
1543 // make priority queue
1548 mSortPtr
= CodeParm
;
1552 *mSortPtr
++ = (UINT16
) Index
;
1555 mHeap
[1] = mHeap
[mHeapSize
--];
1559 *mSortPtr
++ = (UINT16
) Index2
;
1563 mFreq
[Index3
] = (UINT16
) (mFreq
[Index
] + mFreq
[Index2
]);
1564 mHeap
[1] = (INT16
) Index3
;
1566 mLeft
[Index3
] = (UINT16
) Index
;
1567 mRight
[Index3
] = (UINT16
) Index2
;
1568 } while (mHeapSize
> 1);
1570 mSortPtr
= CodeParm
;
1572 MakeCode (NParm
, LenParm
, CodeParm
);
1582 IN
char *InputFileName
,
1583 OUT UINT8
*FileBuffer
,
1584 OUT UINT32
*BufferLength
1588 Routine Description:
1590 Get the contents of file specified in InputFileName
1595 InputFileName - Name of the input file.
1597 FileBuffer - Output buffer to contain data
1599 BufferLength - Actual length of the data
1603 EFI_SUCCESS on successful return
1604 EFI_ABORTED if unable to open input file.
1614 // Copy the file contents to the output buffer.
1616 InputFile
= fopen (InputFileName
, "rb");
1617 if (InputFile
== NULL
) {
1618 Error (NULL
, 0, 0001, "Error opening file: %s", InputFileName
);
1622 fseek (InputFile
, 0, SEEK_END
);
1623 FileSize
= ftell (InputFile
);
1624 fseek (InputFile
, 0, SEEK_SET
);
1626 // Now read the contents of the file into the buffer
1628 if (FileSize
> 0 && FileBuffer
!= NULL
) {
1629 if (fread (FileBuffer
, FileSize
, 1, InputFile
) != 1) {
1630 Error (NULL
, 0, 0004, "Error reading contents of input file: %s", InputFileName
);
1637 Size
+= (UINTN
) FileSize
;
1638 *BufferLength
= Size
;
1640 if (FileBuffer
!= NULL
) {
1643 return EFI_BUFFER_TOO_SMALL
;
1653 Routine Description:
1655 Displays the standard utility information to SDTOUT
1667 fprintf (stdout
, "%s Version %d.%d %s \n", UTILITY_NAME
, UTILITY_MAJOR_VERSION
, UTILITY_MINOR_VERSION
, __BUILD_VERSION
);
1676 Routine Description:
1678 Displays the utility usage syntax to STDOUT
1693 fprintf (stdout
, "Usage: %s -e|-d [options] <input_file>\n\n", UTILITY_NAME
);
1696 // Copyright declaration
1698 fprintf (stdout
, "Copyright (c) 2007 - 2010, Intel Corporation. All rights reserved.\n\n");
1703 fprintf (stdout
, "Options:\n");
1704 fprintf (stdout
, " -o FileName, --output FileName\n\
1705 File will be created to store the ouput content.\n");
1706 fprintf (stdout
, " -v, --verbose\n\
1707 Turn on verbose output with informational messages.\n");
1708 fprintf (stdout
, " -q, --quiet\n\
1709 Disable all messages except key message and fatal error\n");
1710 fprintf (stdout
, " --debug [0-9]\n\
1711 Enable debug messages, at input debug level.\n");
1712 fprintf (stdout
, " --version\n\
1713 Show program's version number and exit.\n");
1714 fprintf (stdout
, " -h, --help\n\
1715 Show this help message and exit.\n");
1726 Routine Description:
1732 command line parameters
1736 EFI_SUCCESS Section header successfully generated and section concatenated.
1737 EFI_ABORTED Could not generate the section
1738 EFI_OUT_OF_RESOURCES No resource to complete the operation.
1743 char *OutputFileName
;
1744 char *InputFileName
;
1751 SCRATCH_DATA
*Scratch
;
1755 SetUtilityName(UTILITY_NAME
);
1763 InputFileName
= NULL
;
1764 OutputFileName
= NULL
;
1770 // Verify the correct number of arguments
1773 Error (NULL
, 0, 1001, "Missing options", "No input options specified.");
1778 if ((strcmp(argv
[1], "-h") == 0) || (strcmp(argv
[1], "--help") == 0)) {
1783 if ((strcmp(argv
[1], "--version") == 0)) {
1790 if (strcmp(argv
[0],"-e") == 0) {
1792 // encode the input file
1797 } else if (strcmp(argv
[0], "-d") == 0) {
1799 // decode the input file
1806 // Error command line
1808 Error (NULL
, 0, 1003, "Invalid option value", "the options specified are not recognized.");
1814 if ((strcmp(argv
[0], "-v") == 0) || (stricmp(argv
[0], "--verbose") == 0)) {
1821 if (stricmp (argv
[0], "--debug") == 0) {
1824 Status
= AsciiStringToUint64(argv
[0], FALSE
, &DebugLevel
);
1825 if (DebugLevel
> 9) {
1826 Error (NULL
, 0 ,2000, "Invalid parameter", "Unrecognized argument %s", argv
[0]);
1829 if (DebugLevel
>=5 && DebugLevel
<=9){
1838 if ((strcmp(argv
[0], "-q") == 0) || (stricmp (argv
[0], "--quiet") == 0)) {
1845 if ((strcmp(argv
[0], "-o") == 0) || (stricmp (argv
[0], "--output") == 0)) {
1846 if (argv
[1] == NULL
|| argv
[1][0] == '-') {
1847 Error (NULL
, 0, 1003, "Invalid option value", "Output File name is missing for -o option");
1850 OutputFileName
= argv
[1];
1856 if (argv
[0][0]!='-') {
1857 InputFileName
= argv
[0];
1863 Error (NULL
, 0, 1000, "Unknown option", argv
[0]);
1867 if (InputFileName
== NULL
) {
1868 Error (NULL
, 0, 1001, "Missing options", "No input files specified.");
1873 // All Parameters has been parsed, now set the message print level
1877 } else if (VerboseMode
) {
1879 } else if (DebugMode
) {
1880 SetPrintLevel(DebugLevel
);
1884 VerboseMsg("%s tool start.\n", UTILITY_NAME
);
1886 Scratch
= (SCRATCH_DATA
*)malloc(sizeof(SCRATCH_DATA
));
1887 if (Scratch
== NULL
) {
1888 Error (NULL
, 0, 4001, "Resource:", "Memory cannot be allocated!");
1892 InputFile
= fopen (InputFileName
, "rb");
1893 if (InputFile
== NULL
) {
1894 Error (NULL
, 0, 0001, "Error opening input file", InputFileName
);
1898 Status
= GetFileContents(
1903 if (Status
== EFI_BUFFER_TOO_SMALL
) {
1904 FileBuffer
= (UINT8
*) malloc (InputLength
);
1905 if (FileBuffer
== NULL
) {
1906 Error (NULL
, 0, 4001, "Resource:", "Memory cannot be allocated!");
1910 Status
= GetFileContents (
1917 if (EFI_ERROR(Status
)) {
1922 if (OutputFileName
!= NULL
) {
1923 OutputFile
= fopen (OutputFileName
, "wb");
1924 if (OutputFile
== NULL
) {
1925 Error (NULL
, 0, 0001, "Error opening output file for writing", OutputFileName
);
1926 if (InputFile
!= NULL
) {
1932 OutputFileName
= DEFAULT_OUTPUT_FILE
;
1933 OutputFile
= fopen (OutputFileName
, "wb");
1938 // First call TianoCompress to get DstSize
1941 DebugMsg(UTILITY_NAME
, 0, DebugLevel
, "Encoding", NULL
);
1943 Status
= TianoCompress ((UINT8
*)FileBuffer
, InputLength
, OutBuffer
, &DstSize
);
1945 if (Status
== EFI_BUFFER_TOO_SMALL
) {
1946 OutBuffer
= (UINT8
*) malloc (DstSize
);
1947 if (OutBuffer
== NULL
) {
1948 Error (NULL
, 0, 4001, "Resource:", "Memory cannot be allocated!");
1952 Status
= TianoCompress ((UINT8
*)FileBuffer
, InputLength
, OutBuffer
, &DstSize
);
1953 if (Status
!= EFI_SUCCESS
) {
1954 Error (NULL
, 0, 0007, "Error compressing file", NULL
);
1958 fwrite(OutBuffer
,(size_t)DstSize
, 1, OutputFile
);
1964 DebugMsg(UTILITY_NAME
, 0, DebugLevel
, "Encoding Successful!\n", NULL
);
1967 VerboseMsg("Encoding successful\n");
1973 DebugMsg(UTILITY_NAME
, 0, DebugLevel
, "Decoding\n", NULL
);
1976 // Get Compressed file original size
1978 Src
= (UINT8
*)FileBuffer
;
1979 OrigSize
= Src
[4] + (Src
[5] << 8) + (Src
[6] << 16) + (Src
[7] << 24);
1982 // Allocate OutputBuffer
1984 OutBuffer
= (UINT8
*)malloc(OrigSize
);
1985 if (OutBuffer
== NULL
) {
1986 Error (NULL
, 0, 4001, "Resource:", "Memory cannot be allocated!");
1990 Status
= Decompress((VOID
*)FileBuffer
, (VOID
*)OutBuffer
, (VOID
*)Scratch
, 2);
1991 if (Status
!= EFI_SUCCESS
) {
1995 fwrite(OutBuffer
, (size_t)(Scratch
->mOrigSize
), 1, OutputFile
);
2001 DebugMsg(UTILITY_NAME
, 0, DebugLevel
, "Encoding successful!\n", NULL
);
2005 VerboseMsg("Decoding successful\n");
2013 DebugMsg(UTILITY_NAME
, 0, DebugLevel
, "Encoding Error\n", NULL
);
2014 } else if (DECODE
) {
2015 DebugMsg(UTILITY_NAME
, 0, DebugLevel
, "Decoding Error\n", NULL
);
2018 if (Scratch
!= NULL
) {
2021 if (FileBuffer
!= NULL
) {
2024 if (OutBuffer
!= NULL
) {
2029 VerboseMsg("%s tool done with return code is 0x%x.\n", UTILITY_NAME
, GetUtilityStatus ());
2031 return GetUtilityStatus ();
2036 IN SCRATCH_DATA
*Sd
,
2041 Routine Description:
2043 Shift mBitBuf NumOfBits left. Read in NumOfBits of bits from source.
2047 Sd - The global scratch data
2048 NumOfBits - The number of bits to shift and read.
2054 Sd
->mBitBuf
= (UINT32
) (Sd
->mBitBuf
<< NumOfBits
);
2056 while (NumOfBits
> Sd
->mBitCount
) {
2058 Sd
->mBitBuf
|= (UINT32
) (Sd
->mSubBitBuf
<< (NumOfBits
= (UINT16
) (NumOfBits
- Sd
->mBitCount
)));
2060 if (Sd
->mCompSize
> 0) {
2062 // Get 1 byte into SubBitBuf
2066 Sd
->mSubBitBuf
= Sd
->mSrcBase
[Sd
->mInBuf
++];
2071 // No more bits from the source, just pad zero bit.
2079 Sd
->mBitCount
= (UINT16
) (Sd
->mBitCount
- NumOfBits
);
2080 Sd
->mBitBuf
|= Sd
->mSubBitBuf
>> Sd
->mBitCount
;
2085 IN SCRATCH_DATA
*Sd
,
2090 Routine Description:
2092 Get NumOfBits of bits out from mBitBuf. Fill mBitBuf with subsequent
2093 NumOfBits of bits from source. Returns NumOfBits of bits that are
2098 Sd - The global scratch data.
2099 NumOfBits - The number of bits to pop and read.
2103 The bits that are popped out.
2109 OutBits
= (UINT32
) (Sd
->mBitBuf
>> (BITBUFSIZ
- NumOfBits
));
2111 FillBuf (Sd
, NumOfBits
);
2118 IN SCRATCH_DATA
*Sd
,
2119 IN UINT16 NumOfChar
,
2121 IN UINT16 TableBits
,
2126 Routine Description:
2128 Creates Huffman Code mapping table according to code length array.
2132 Sd - The global scratch data
2133 NumOfChar - Number of symbols in the symbol set
2134 BitLen - Code length array
2135 TableBits - The width of the mapping table
2141 BAD_TABLE - The table is corrupted.
2150 volatile UINT16 Index
;
2160 for (Index
= 1; Index
<= 16; Index
++) {
2164 for (Index
= 0; Index
< NumOfChar
; Index
++) {
2165 Count
[BitLen
[Index
]]++;
2170 for (Index
= 1; Index
<= 16; Index
++) {
2171 WordOfStart
= Start
[Index
];
2172 WordOfCount
= Count
[Index
];
2173 Start
[Index
+ 1] = (UINT16
) (WordOfStart
+ (WordOfCount
<< (16 - Index
)));
2176 if (Start
[17] != 0) {
2180 return (UINT16
) BAD_TABLE
;
2183 JuBits
= (UINT16
) (16 - TableBits
);
2185 for (Index
= 1; Index
<= TableBits
; Index
++) {
2186 Start
[Index
] >>= JuBits
;
2187 Weight
[Index
] = (UINT16
) (1U << (TableBits
- Index
));
2190 while (Index
<= 16) {
2191 Weight
[Index
] = (UINT16
) (1U << (16 - Index
));
2195 Index
= (UINT16
) (Start
[TableBits
+ 1] >> JuBits
);
2198 Index3
= (UINT16
) (1U << TableBits
);
2199 while (Index
!= Index3
) {
2205 Mask
= (UINT16
) (1U << (15 - TableBits
));
2207 for (Char
= 0; Char
< NumOfChar
; Char
++) {
2214 NextCode
= (UINT16
) (Start
[Len
] + Weight
[Len
]);
2216 if (Len
<= TableBits
) {
2218 for (Index
= Start
[Len
]; Index
< NextCode
; Index
++) {
2219 Table
[Index
] = Char
;
2224 Index3
= Start
[Len
];
2225 Pointer
= &Table
[Index3
>> JuBits
];
2226 Index
= (UINT16
) (Len
- TableBits
);
2228 while (Index
!= 0) {
2229 if (*Pointer
== 0) {
2230 Sd
->mRight
[Avail
] = Sd
->mLeft
[Avail
] = 0;
2234 if (Index3
& Mask
) {
2235 Pointer
= &Sd
->mRight
[*Pointer
];
2237 Pointer
= &Sd
->mLeft
[*Pointer
];
2248 Start
[Len
] = NextCode
;
2262 Routine Description:
2264 Decodes a position value.
2268 Sd - the global scratch data
2272 The position value decoded.
2280 Val
= Sd
->mPTTable
[Sd
->mBitBuf
>> (BITBUFSIZ
- 8)];
2283 Mask
= 1U << (BITBUFSIZ
- 1 - 8);
2287 if (Sd
->mBitBuf
& Mask
) {
2288 Val
= Sd
->mRight
[Val
];
2290 Val
= Sd
->mLeft
[Val
];
2294 } while (Val
>= MAXNP
);
2297 // Advance what we have read
2299 FillBuf (Sd
, Sd
->mPTLen
[Val
]);
2303 Pos
= (UINT32
) ((1U << (Val
- 1)) + GetBits (Sd
, (UINT16
) (Val
- 1)));
2311 IN SCRATCH_DATA
*Sd
,
2318 Routine Description:
2320 Reads code lengths for the Extra Set or the Position Set
2324 Sd - The global scratch data
2325 nn - Number of symbols
2326 nbit - Number of bits needed to represent nn
2327 Special - The special symbol that needs to be taken care of
2332 BAD_TABLE - Table is corrupted.
2338 volatile UINT16 Index
;
2341 Number
= (UINT16
) GetBits (Sd
, nbit
);
2344 CharC
= (UINT16
) GetBits (Sd
, nbit
);
2346 for (Index
= 0; Index
< 256; Index
++) {
2347 Sd
->mPTTable
[Index
] = CharC
;
2350 for (Index
= 0; Index
< nn
; Index
++) {
2351 Sd
->mPTLen
[Index
] = 0;
2359 while (Index
< Number
) {
2361 CharC
= (UINT16
) (Sd
->mBitBuf
>> (BITBUFSIZ
- 3));
2364 Mask
= 1U << (BITBUFSIZ
- 1 - 3);
2365 while (Mask
& Sd
->mBitBuf
) {
2371 FillBuf (Sd
, (UINT16
) ((CharC
< 7) ? 3 : CharC
- 3));
2373 Sd
->mPTLen
[Index
++] = (UINT8
) CharC
;
2375 if (Index
== Special
) {
2376 CharC
= (UINT16
) GetBits (Sd
, 2);
2377 while ((INT16
) (--CharC
) >= 0) {
2378 Sd
->mPTLen
[Index
++] = 0;
2383 while (Index
< nn
) {
2384 Sd
->mPTLen
[Index
++] = 0;
2387 return MakeTable (Sd
, nn
, Sd
->mPTLen
, 8, Sd
->mPTTable
);
2396 Routine Description:
2398 Reads code lengths for Char&Len Set.
2402 Sd - the global scratch data
2410 volatile UINT16 Index
;
2413 Number
= (UINT16
) GetBits (Sd
, CBIT
);
2416 CharC
= (UINT16
) GetBits (Sd
, CBIT
);
2418 for (Index
= 0; Index
< NC
; Index
++) {
2419 Sd
->mCLen
[Index
] = 0;
2422 for (Index
= 0; Index
< 4096; Index
++) {
2423 Sd
->mCTable
[Index
] = CharC
;
2430 while (Index
< Number
) {
2432 CharC
= Sd
->mPTTable
[Sd
->mBitBuf
>> (BITBUFSIZ
- 8)];
2434 Mask
= 1U << (BITBUFSIZ
- 1 - 8);
2438 if (Mask
& Sd
->mBitBuf
) {
2439 CharC
= Sd
->mRight
[CharC
];
2441 CharC
= Sd
->mLeft
[CharC
];
2446 } while (CharC
>= NT
);
2449 // Advance what we have read
2451 FillBuf (Sd
, Sd
->mPTLen
[CharC
]);
2457 } else if (CharC
== 1) {
2458 CharC
= (UINT16
) (GetBits (Sd
, 4) + 3);
2459 } else if (CharC
== 2) {
2460 CharC
= (UINT16
) (GetBits (Sd
, CBIT
) + 20);
2463 while ((INT16
) (--CharC
) >= 0) {
2464 Sd
->mCLen
[Index
++] = 0;
2469 Sd
->mCLen
[Index
++] = (UINT8
) (CharC
- 2);
2474 while (Index
< NC
) {
2475 Sd
->mCLen
[Index
++] = 0;
2478 MakeTable (Sd
, NC
, Sd
->mCLen
, 12, Sd
->mCTable
);
2489 Routine Description:
2491 Decode a character/length value.
2495 Sd - The global scratch data.
2506 if (Sd
->mBlockSize
== 0) {
2508 // Starting a new block
2510 Sd
->mBlockSize
= (UINT16
) GetBits (Sd
, 16);
2511 Sd
->mBadTableFlag
= ReadPTLen (Sd
, NT
, TBIT
, 3);
2512 if (Sd
->mBadTableFlag
!= 0) {
2518 Sd
->mBadTableFlag
= ReadPTLen (Sd
, MAXNP
, Sd
->mPBit
, (UINT16
) (-1));
2519 if (Sd
->mBadTableFlag
!= 0) {
2525 Index2
= Sd
->mCTable
[Sd
->mBitBuf
>> (BITBUFSIZ
- 12)];
2528 Mask
= 1U << (BITBUFSIZ
- 1 - 12);
2531 if (Sd
->mBitBuf
& Mask
) {
2532 Index2
= Sd
->mRight
[Index2
];
2534 Index2
= Sd
->mLeft
[Index2
];
2538 } while (Index2
>= NC
);
2541 // Advance what we have read
2543 FillBuf (Sd
, Sd
->mCLen
[Index2
]);
2554 Routine Description:
2556 Decode the source data and put the resulting data into the destination buffer.
2560 Sd - The global scratch data
2570 BytesRemain
= (UINT16
) (-1);
2575 CharC
= DecodeC (Sd
);
2576 if (Sd
->mBadTableFlag
!= 0) {
2582 // Process an Original character
2584 if (Sd
->mOutBuf
>= Sd
->mOrigSize
) {
2587 Sd
->mDstBase
[Sd
->mOutBuf
++] = (UINT8
) CharC
;
2592 // Process a Pointer
2594 CharC
= (UINT16
) (CharC
- (UINT8_MAX
+ 1 - THRESHOLD
));
2596 BytesRemain
= CharC
;
2598 DataIdx
= Sd
->mOutBuf
- DecodeP (Sd
) - 1;
2601 while ((INT16
) (BytesRemain
) >= 0) {
2602 Sd
->mDstBase
[Sd
->mOutBuf
++] = Sd
->mDstBase
[DataIdx
++];
2603 if (Sd
->mOutBuf
>= Sd
->mOrigSize
) {
2620 IN OUT VOID
*Destination
,
2621 IN OUT VOID
*Scratch
,
2626 Routine Description:
2628 The internal implementation of Decompress().
2632 Source - The source buffer containing the compressed data.
2633 Destination - The destination buffer to store the decompressed data
2634 Scratch - The buffer used internally by the decompress routine. This buffer is needed to store intermediate data.
2635 Version - 1 for EFI1.1 Decompress algoruthm, 2 for Tiano Decompress algorithm
2639 RETURN_SUCCESS - Decompression is successfull
2640 RETURN_INVALID_PARAMETER - The source data is corrupted
2644 volatile UINT32 Index
;
2652 // Verify input is not NULL
2655 // assert(Destination);
2658 Src
= (UINT8
*)Source
;
2659 Dst
= (UINT8
*)Destination
;
2661 Sd
= (SCRATCH_DATA
*) Scratch
;
2662 CompSize
= Src
[0] + (Src
[1] << 8) + (Src
[2] << 16) + (Src
[3] << 24);
2663 OrigSize
= Src
[4] + (Src
[5] << 8) + (Src
[6] << 16) + (Src
[7] << 24);
2666 // If compressed file size is 0, return
2668 if (OrigSize
== 0) {
2669 return RETURN_SUCCESS
;
2674 for (Index
= 0; Index
< sizeof (SCRATCH_DATA
); Index
++) {
2675 ((UINT8
*) Sd
)[Index
] = 0;
2678 // The length of the field 'Position Set Code Length Array Size' in Block Header.
2679 // For EFI 1.1 de/compression algorithm(Version 1), mPBit = 4
2680 // For Tiano de/compression algorithm(Version 2), mPBit = 5
2692 Sd
->mSrcBase
= (UINT8
*)Src
;
2694 Sd
->mCompSize
= CompSize
;
2695 Sd
->mOrigSize
= OrigSize
;
2698 // Fill the first BITBUFSIZ bits
2700 FillBuf (Sd
, BITBUFSIZ
);
2708 if (Sd
->mBadTableFlag
!= 0) {
2710 // Something wrong with the source
2712 return RETURN_INVALID_PARAMETER
;
2715 return RETURN_SUCCESS
;