2 Main file for compression routine.
4 Compression routine. The compression algorithm is a mixture of
5 LZ77 and Huffman coding. LZ77 transforms the source data into a
6 sequence of Original Characters and Pointers to repeated strings.
7 This sequence is further divided into Blocks and Huffman codings
8 are applied to each Block.
10 Copyright (c) 2007 - 2018, Intel Corporation. All rights reserved.<BR>
11 SPDX-License-Identifier: BSD-2-Clause-Patent
15 #include <Library/MemoryAllocationLib.h>
16 #include <Library/BaseMemoryLib.h>
17 #include <Library/DebugLib.h>
18 #include <Library/ShellLib.h>
26 #define UINT8_MAX 0xff
31 #define WNDSIZ (1U << WNDBIT)
33 #define BLKSIZ (1U << 14) // 16 * 1024U
34 #define PERC_FLAG 0x8000U
37 #define MAX_HASH_VAL (3 * WNDSIZ + (WNDSIZ / 512 + 1) * UINT8_MAX)
38 #define HASH(LoopVar7, LoopVar5) ((LoopVar7) + ((LoopVar5) << (WNDBIT - 9)) + WNDSIZ * 2)
39 #define CRCPOLY 0xA001
40 #define UPDATE_CRC(LoopVar5) mCrc = mCrcTable[(mCrc ^ (LoopVar5)) & 0xFF] ^ (mCrc >> UINT8_BIT)
43 // C: the Char&Len Set; P: the Position Set; T: the exTra Set
45 #define NC (UINT8_MAX + MAXMATCH + 2 - THRESHOLD)
47 #define NP (WNDBIT + 1)
49 #define NT (CODE_BIT + 3)
57 // Function Prototypes
61 Put a dword to output stream
63 @param[in] Data The dword to put.
75 STATIC UINT8
*mSrcUpperLimit
;
76 STATIC UINT8
*mDstUpperLimit
;
80 STATIC UINT8
*mChildCount
;
82 STATIC UINT8 mCLen
[NC
];
83 STATIC UINT8 mPTLen
[NPT
];
85 STATIC INT16 mHeap
[NC
+ 1];
86 STATIC INT32 mRemainder
;
87 STATIC INT32 mMatchLen
;
88 STATIC INT32 mBitCount
;
89 STATIC INT32 mHeapSize
;
90 STATIC INT32 mTempInt32
;
91 STATIC UINT32 mBufSiz
= 0;
92 STATIC UINT32 mOutputPos
;
93 STATIC UINT32 mOutputMask
;
94 STATIC UINT32 mSubBitBuf
;
96 STATIC UINT32 mCompSize
;
97 STATIC UINT32 mOrigSize
;
100 STATIC UINT16
*mSortPtr
;
101 STATIC UINT16 mLenCnt
[17];
102 STATIC UINT16 mLeft
[2 * NC
- 1];
103 STATIC UINT16 mRight
[2 * NC
- 1];
104 STATIC UINT16 mCrcTable
[UINT8_MAX
+ 1];
105 STATIC UINT16 mCFreq
[2 * NC
- 1];
106 STATIC UINT16 mCCode
[NC
];
107 STATIC UINT16 mPFreq
[2 * NP
- 1];
108 STATIC UINT16 mPTCode
[NPT
];
109 STATIC UINT16 mTFreq
[2 * NT
- 1];
112 STATIC NODE mMatchPos
;
114 STATIC NODE
*mPosition
;
115 STATIC NODE
*mParent
;
117 STATIC NODE
*mNext
= NULL
;
118 INT32 mHuffmanDepth
= 0;
135 for (LoopVar1
= 0; LoopVar1
<= UINT8_MAX
; LoopVar1
++) {
137 for (LoopVar2
= 0; LoopVar2
< UINT8_BIT
; LoopVar2
++) {
138 if ((LoopVar4
& 1) != 0) {
139 LoopVar4
= (LoopVar4
>> 1) ^ CRCPOLY
;
145 mCrcTable
[LoopVar1
] = (UINT16
)LoopVar4
;
150 Put a dword to output stream
152 @param[in] Data The dword to put.
159 if (mDst
< mDstUpperLimit
) {
160 *mDst
++ = (UINT8
)(((UINT8
)(Data
)) & 0xff);
163 if (mDst
< mDstUpperLimit
) {
164 *mDst
++ = (UINT8
)(((UINT8
)(Data
>> 0x08)) & 0xff);
167 if (mDst
< mDstUpperLimit
) {
168 *mDst
++ = (UINT8
)(((UINT8
)(Data
>> 0x10)) & 0xff);
171 if (mDst
< mDstUpperLimit
) {
172 *mDst
++ = (UINT8
)(((UINT8
)(Data
>> 0x18)) & 0xff);
177 Allocate memory spaces for data structures used in compression process.
179 @retval EFI_SUCCESS Memory was allocated successfully.
180 @retval EFI_OUT_OF_RESOURCES A memory allocation failed.
187 mText
= AllocateZeroPool (WNDSIZ
* 2 + MAXMATCH
);
188 mLevel
= AllocateZeroPool ((WNDSIZ
+ UINT8_MAX
+ 1) * sizeof (*mLevel
));
189 mChildCount
= AllocateZeroPool ((WNDSIZ
+ UINT8_MAX
+ 1) * sizeof (*mChildCount
));
190 mPosition
= AllocateZeroPool ((WNDSIZ
+ UINT8_MAX
+ 1) * sizeof (*mPosition
));
191 mParent
= AllocateZeroPool (WNDSIZ
* 2 * sizeof (*mParent
));
192 mPrev
= AllocateZeroPool (WNDSIZ
* 2 * sizeof (*mPrev
));
193 mNext
= AllocateZeroPool ((MAX_HASH_VAL
+ 1) * sizeof (*mNext
));
196 mBuf
= AllocateZeroPool (mBufSiz
);
197 while (mBuf
== NULL
) {
198 mBufSiz
= (mBufSiz
/ 10U) * 9U;
199 if (mBufSiz
< 4 * 1024U) {
200 return EFI_OUT_OF_RESOURCES
;
203 mBuf
= AllocateZeroPool (mBufSiz
);
212 Called when compression is completed to free memory previously allocated.
220 SHELL_FREE_NON_NULL (mText
);
221 SHELL_FREE_NON_NULL (mLevel
);
222 SHELL_FREE_NON_NULL (mChildCount
);
223 SHELL_FREE_NON_NULL (mPosition
);
224 SHELL_FREE_NON_NULL (mParent
);
225 SHELL_FREE_NON_NULL (mPrev
);
226 SHELL_FREE_NON_NULL (mNext
);
227 SHELL_FREE_NON_NULL (mBuf
);
231 Initialize String Info Log data structures.
240 SetMem (mLevel
+ WNDSIZ
, (UINT8_MAX
+ 1) * sizeof (UINT8
), 1);
241 SetMem (mPosition
+ WNDSIZ
, (UINT8_MAX
+ 1) * sizeof (NODE
), 0);
243 SetMem (mParent
+ WNDSIZ
, WNDSIZ
* sizeof (NODE
), 0);
246 for (LoopVar1
= 1; LoopVar1
< WNDSIZ
- 1; LoopVar1
++) {
247 mNext
[LoopVar1
] = (NODE
)(LoopVar1
+ 1);
250 mNext
[WNDSIZ
- 1] = NIL
;
251 SetMem (mNext
+ WNDSIZ
* 2, (MAX_HASH_VAL
- WNDSIZ
* 2 + 1) * sizeof (NODE
), 0);
255 Find child node given the parent node and the edge character
257 @param[in] LoopVar6 The parent node.
258 @param[in] LoopVar5 The edge character.
260 @return The child node.
261 @retval NIL(Zero) No child could be found.
272 LoopVar4
= mNext
[HASH (LoopVar6
, LoopVar5
)];
273 mParent
[NIL
] = LoopVar6
; /* sentinel */
274 while (mParent
[LoopVar4
] != LoopVar6
) {
275 LoopVar4
= mNext
[LoopVar4
];
282 Create a new child for a given parent node.
284 @param[in] LoopVar6 The parent node.
285 @param[in] LoopVar5 The edge character.
286 @param[in] LoopVar4 The child node.
299 LoopVar12
= (NODE
)HASH (LoopVar6
, LoopVar5
);
300 LoopVar10
= mNext
[LoopVar12
];
301 mNext
[LoopVar12
] = LoopVar4
;
302 mNext
[LoopVar4
] = LoopVar10
;
303 mPrev
[LoopVar10
] = LoopVar4
;
304 mPrev
[LoopVar4
] = LoopVar12
;
305 mParent
[LoopVar4
] = LoopVar6
;
306 mChildCount
[LoopVar6
]++;
312 @param[in] Old The node to split.
325 mChildCount
[New
] = 0;
326 LoopVar10
= mPrev
[Old
];
327 mPrev
[New
] = LoopVar10
;
328 mNext
[LoopVar10
] = New
;
329 LoopVar10
= mNext
[Old
];
330 mNext
[New
] = LoopVar10
;
331 mPrev
[LoopVar10
] = New
;
332 mParent
[New
] = mParent
[Old
];
333 mLevel
[New
] = (UINT8
)mMatchLen
;
334 mPosition
[New
] = mPos
;
335 MakeChild (New
, mText
[mMatchPos
+ mMatchLen
], Old
);
336 MakeChild (New
, mText
[mPos
+ mMatchLen
], mPos
);
340 Insert string info for current position into the String Info Log.
359 if (mMatchLen
>= 4) {
361 // We have just got a long match, the target tree
362 // can be located by MatchPos + 1. Travese the tree
363 // from bottom up to get to a proper starting point.
364 // The usage of PERC_FLAG ensures proper node deletion
365 // in DeleteNode() later.
368 LoopVar4
= (NODE
)((mMatchPos
+ 1) | WNDSIZ
);
369 LoopVar6
= mParent
[LoopVar4
];
370 while (LoopVar6
== NIL
) {
371 LoopVar4
= mNext
[LoopVar4
];
372 LoopVar6
= mParent
[LoopVar4
];
375 while (mLevel
[LoopVar6
] >= mMatchLen
) {
377 LoopVar6
= mParent
[LoopVar6
];
380 LoopVar10
= LoopVar6
;
381 while (mPosition
[LoopVar10
] < 0) {
382 mPosition
[LoopVar10
] = mPos
;
383 LoopVar10
= mParent
[LoopVar10
];
386 if (LoopVar10
< WNDSIZ
) {
387 mPosition
[LoopVar10
] = (NODE
)(mPos
| PERC_FLAG
);
391 // Locate the target tree
393 LoopVar6
= (NODE
)(mText
[mPos
] + WNDSIZ
);
394 LoopVar5
= mText
[mPos
+ 1];
395 LoopVar4
= Child (LoopVar6
, LoopVar5
);
396 if (LoopVar4
== NIL
) {
397 MakeChild (LoopVar6
, LoopVar5
, mPos
);
406 // Traverse down the tree to find a match.
407 // Update Position value along the route.
408 // Node split or creation is involved.
411 if (LoopVar4
>= WNDSIZ
) {
413 mMatchPos
= LoopVar4
;
415 LoopVar2
= mLevel
[LoopVar4
];
416 mMatchPos
= (NODE
)(mPosition
[LoopVar4
] & ~PERC_FLAG
);
419 if (mMatchPos
>= mPos
) {
423 TempString3
= &mText
[mPos
+ mMatchLen
];
424 TempString2
= &mText
[mMatchPos
+ mMatchLen
];
425 while (mMatchLen
< LoopVar2
) {
426 if (*TempString3
!= *TempString2
) {
436 if (mMatchLen
>= MAXMATCH
) {
440 mPosition
[LoopVar4
] = mPos
;
442 LoopVar4
= Child (LoopVar6
, *TempString3
);
443 if (LoopVar4
== NIL
) {
444 MakeChild (LoopVar6
, *TempString3
, mPos
);
451 LoopVar10
= mPrev
[LoopVar4
];
452 mPrev
[mPos
] = LoopVar10
;
453 mNext
[LoopVar10
] = mPos
;
454 LoopVar10
= mNext
[LoopVar4
];
455 mNext
[mPos
] = LoopVar10
;
456 mPrev
[LoopVar10
] = mPos
;
457 mParent
[mPos
] = LoopVar6
;
458 mParent
[LoopVar4
] = NIL
;
461 // Special usage of 'next'
463 mNext
[LoopVar4
] = mPos
;
467 Delete outdated string info. (The Usage of PERC_FLAG
468 ensures a clean deletion).
486 if (mParent
[mPos
] == NIL
) {
490 LoopVar4
= mPrev
[mPos
];
491 LoopVar11
= mNext
[mPos
];
492 mNext
[LoopVar4
] = LoopVar11
;
493 mPrev
[LoopVar11
] = LoopVar4
;
494 LoopVar4
= mParent
[mPos
];
496 if (LoopVar4
>= WNDSIZ
) {
500 mChildCount
[LoopVar4
]--;
501 if (mChildCount
[LoopVar4
] > 1) {
505 LoopVar10
= (NODE
)(mPosition
[LoopVar4
] & ~PERC_FLAG
);
506 if (LoopVar10
>= mPos
) {
510 LoopVar11
= LoopVar10
;
511 LoopVar6
= mParent
[LoopVar4
];
512 LoopVar9
= mPosition
[LoopVar6
];
513 while ((LoopVar9
& PERC_FLAG
) != 0) {
514 LoopVar9
&= ~PERC_FLAG
;
515 if (LoopVar9
>= mPos
) {
519 if (LoopVar9
> LoopVar11
) {
520 LoopVar11
= LoopVar9
;
523 mPosition
[LoopVar6
] = (NODE
)(LoopVar11
| WNDSIZ
);
524 LoopVar6
= mParent
[LoopVar6
];
525 LoopVar9
= mPosition
[LoopVar6
];
528 if (LoopVar6
< WNDSIZ
) {
529 if (LoopVar9
>= mPos
) {
533 if (LoopVar9
> LoopVar11
) {
534 LoopVar11
= LoopVar9
;
537 mPosition
[LoopVar6
] = (NODE
)(LoopVar11
| WNDSIZ
| PERC_FLAG
);
540 LoopVar11
= Child (LoopVar4
, mText
[LoopVar10
+ mLevel
[LoopVar4
]]);
541 LoopVar10
= mPrev
[LoopVar11
];
542 LoopVar9
= mNext
[LoopVar11
];
543 mNext
[LoopVar10
] = LoopVar9
;
544 mPrev
[LoopVar9
] = LoopVar10
;
545 LoopVar10
= mPrev
[LoopVar4
];
546 mNext
[LoopVar10
] = LoopVar11
;
547 mPrev
[LoopVar11
] = LoopVar10
;
548 LoopVar10
= mNext
[LoopVar4
];
549 mPrev
[LoopVar10
] = LoopVar11
;
550 mNext
[LoopVar11
] = LoopVar10
;
551 mParent
[LoopVar11
] = mParent
[LoopVar4
];
552 mParent
[LoopVar4
] = NIL
;
553 mNext
[LoopVar4
] = mAvail
;
560 @param[out] LoopVar7 The buffer to hold the data.
561 @param[in] LoopVar8 The number of bytes to read.
563 @return The number of bytes actually read.
573 for (LoopVar1
= 0; mSrc
< mSrcUpperLimit
&& LoopVar1
< LoopVar8
; LoopVar1
++) {
574 *LoopVar7
++ = *mSrc
++;
579 LoopVar7
-= LoopVar8
;
580 mOrigSize
+= LoopVar8
;
582 while (LoopVar1
>= 0) {
583 UPDATE_CRC (*LoopVar7
++);
591 Advance the current position (read in new data if needed).
592 Delete outdated string info. Find a match string for current position.
594 @retval TRUE The operation was successful.
595 @retval FALSE The operation failed due to insufficient memory.
607 if (mPos
== WNDSIZ
* 2) {
608 Temp
= AllocateZeroPool (WNDSIZ
+ MAXMATCH
);
613 CopyMem (Temp
, &mText
[WNDSIZ
], WNDSIZ
+ MAXMATCH
);
614 CopyMem (&mText
[0], Temp
, WNDSIZ
+ MAXMATCH
);
616 LoopVar8
= FreadCrc (&mText
[WNDSIZ
+ MAXMATCH
], WNDSIZ
);
617 mRemainder
+= LoopVar8
;
628 Send entry LoopVar1 down the queue.
630 @param[in] LoopVar1 The index of the item to move.
642 // priority queue: send i-th entry down heap
646 while (LoopVar1
<= mHeapSize
) {
647 if ((LoopVar1
< mHeapSize
) && (mFreq
[mHeap
[LoopVar1
]] > mFreq
[mHeap
[LoopVar1
+ 1]])) {
651 if (mFreq
[LoopVar2
] <= mFreq
[mHeap
[LoopVar1
]]) {
655 mHeap
[i
] = mHeap
[LoopVar1
];
660 mHeap
[i
] = (INT16
)LoopVar2
;
664 Count the number of each code length for a Huffman tree.
666 @param[in] LoopVar1 The top node.
673 if (LoopVar1
< mTempInt32
) {
674 mLenCnt
[(mHuffmanDepth
< 16) ? mHuffmanDepth
: 16]++;
677 CountLen (mLeft
[LoopVar1
]);
678 CountLen (mRight
[LoopVar1
]);
684 Create code length array for a Huffman tree.
686 @param[in] Root The root of the tree.
698 for (LoopVar1
= 0; LoopVar1
<= 16; LoopVar1
++) {
699 mLenCnt
[LoopVar1
] = 0;
705 // Adjust the length count array so that
706 // no code will be generated longer than its designated length
709 for (LoopVar1
= 16; LoopVar1
> 0; LoopVar1
--) {
710 Cum
+= mLenCnt
[LoopVar1
] << (16 - LoopVar1
);
713 while (Cum
!= (1U << 16)) {
715 for (LoopVar1
= 15; LoopVar1
> 0; LoopVar1
--) {
716 if (mLenCnt
[LoopVar1
] != 0) {
718 mLenCnt
[LoopVar1
+ 1] += 2;
726 for (LoopVar1
= 16; LoopVar1
> 0; LoopVar1
--) {
727 LoopVar2
= mLenCnt
[LoopVar1
];
729 while (LoopVar2
>= 0) {
730 mLen
[*mSortPtr
++] = (UINT8
)LoopVar1
;
737 Assign code to each symbol based on the code length array.
739 @param[in] LoopVar8 The number of symbols.
740 @param[in] Len The code length array.
741 @param[out] Code The stores codes for each symbol.
754 for (LoopVar1
= 1; LoopVar1
<= 16; LoopVar1
++) {
755 Start
[LoopVar1
+ 1] = (UINT16
)((Start
[LoopVar1
] + mLenCnt
[LoopVar1
]) << 1);
758 for (LoopVar1
= 0; LoopVar1
< LoopVar8
; LoopVar1
++) {
759 Code
[LoopVar1
] = Start
[Len
[LoopVar1
]]++;
764 Generates Huffman codes given a frequency distribution of symbols.
766 @param[in] NParm The number of symbols.
767 @param[in] FreqParm The frequency of each symbol.
768 @param[out] LenParm The code length for each symbol.
769 @param[out] CodeParm The code for each symbol.
771 @return The root of the Huffman tree.
776 IN UINT16 FreqParm
[],
778 OUT UINT16 CodeParm
[]
790 // make tree, calculate len[], return root
798 for (LoopVar1
= 0; LoopVar1
< mTempInt32
; LoopVar1
++) {
800 if ((mFreq
[LoopVar1
]) != 0) {
802 mHeap
[mHeapSize
] = (INT16
)LoopVar1
;
807 CodeParm
[mHeap
[1]] = 0;
811 for (LoopVar1
= mHeapSize
/ 2; LoopVar1
>= 1; LoopVar1
--) {
813 // make priority queue
821 if (LoopVar1
< mTempInt32
) {
822 *mSortPtr
++ = (UINT16
)LoopVar1
;
825 mHeap
[1] = mHeap
[mHeapSize
--];
828 if (LoopVar2
< mTempInt32
) {
829 *mSortPtr
++ = (UINT16
)LoopVar2
;
833 mFreq
[LoopVar3
] = (UINT16
)(mFreq
[LoopVar1
] + mFreq
[LoopVar2
]);
834 mHeap
[1] = (INT16
)LoopVar3
;
836 mLeft
[LoopVar3
] = (UINT16
)LoopVar1
;
837 mRight
[LoopVar3
] = (UINT16
)LoopVar2
;
838 } while (mHeapSize
> 1);
842 MakeCode (NParm
, LenParm
, CodeParm
);
851 Outputs rightmost LoopVar8 bits of x
853 @param[in] LoopVar8 The rightmost LoopVar8 bits of the data is used.
854 @param[in] x The data.
864 if (LoopVar8
< mBitCount
) {
865 mSubBitBuf
|= x
<< (mBitCount
-= LoopVar8
);
867 Temp
= (UINT8
)(mSubBitBuf
| (x
>> (LoopVar8
-= mBitCount
)));
868 if (mDst
< mDstUpperLimit
) {
874 if (LoopVar8
< UINT8_BIT
) {
875 mSubBitBuf
= x
<< (mBitCount
= UINT8_BIT
- LoopVar8
);
877 Temp
= (UINT8
)(x
>> (LoopVar8
- UINT8_BIT
));
878 if (mDst
< mDstUpperLimit
) {
884 mSubBitBuf
= x
<< (mBitCount
= 2 * UINT8_BIT
- LoopVar8
);
890 Encode a signed 32 bit number.
892 @param[in] LoopVar5 The number to encode.
899 PutBits (mCLen
[LoopVar5
], mCCode
[LoopVar5
]);
903 Encode a unsigned 32 bit number.
905 @param[in] LoopVar7 The number to encode.
918 while (LoopVar6
!= 0) {
923 PutBits (mPTLen
[LoopVar5
], mPTCode
[LoopVar5
]);
925 PutBits (LoopVar5
- 1, LoopVar7
& (0xFFFFU
>> (17 - LoopVar5
)));
930 Count the frequencies for the Extra Set.
946 for (LoopVar1
= 0; LoopVar1
< NT
; LoopVar1
++) {
947 mTFreq
[LoopVar1
] = 0;
951 while (LoopVar8
> 0 && mCLen
[LoopVar8
- 1] == 0) {
956 while (LoopVar1
< LoopVar8
) {
957 LoopVar3
= mCLen
[LoopVar1
++];
960 while (LoopVar1
< LoopVar8
&& mCLen
[LoopVar1
] == 0) {
966 mTFreq
[0] = (UINT16
)(mTFreq
[0] + Count
);
967 } else if (Count
<= 18) {
969 } else if (Count
== 19) {
976 ASSERT ((LoopVar3
+2) < (2 * NT
- 1));
977 mTFreq
[LoopVar3
+ 2]++;
983 Outputs the code length array for the Extra Set or the Position Set.
985 @param[in] LoopVar8 The number of symbols.
986 @param[in] nbit The number of bits needed to represent 'LoopVar8'.
987 @param[in] Special The special symbol that needs to be take care of.
1001 while (LoopVar8
> 0 && mPTLen
[LoopVar8
- 1] == 0) {
1005 PutBits (nbit
, LoopVar8
);
1007 while (LoopVar1
< LoopVar8
) {
1008 LoopVar3
= mPTLen
[LoopVar1
++];
1009 if (LoopVar3
<= 6) {
1010 PutBits (3, LoopVar3
);
1012 PutBits (LoopVar3
- 3, (1U << (LoopVar3
- 3)) - 2);
1015 if (LoopVar1
== Special
) {
1016 while (LoopVar1
< 6 && mPTLen
[LoopVar1
] == 0) {
1020 PutBits (2, (LoopVar1
- 3) & 3);
1026 Outputs the code length array for Char&Length Set.
1042 while (LoopVar8
> 0 && mCLen
[LoopVar8
- 1] == 0) {
1046 PutBits (CBIT
, LoopVar8
);
1048 while (LoopVar1
< LoopVar8
) {
1049 LoopVar3
= mCLen
[LoopVar1
++];
1050 if (LoopVar3
== 0) {
1052 while (LoopVar1
< LoopVar8
&& mCLen
[LoopVar1
] == 0) {
1058 for (LoopVar3
= 0; LoopVar3
< Count
; LoopVar3
++) {
1059 PutBits (mPTLen
[0], mPTCode
[0]);
1061 } else if (Count
<= 18) {
1062 PutBits (mPTLen
[1], mPTCode
[1]);
1063 PutBits (4, Count
- 3);
1064 } else if (Count
== 19) {
1065 PutBits (mPTLen
[0], mPTCode
[0]);
1066 PutBits (mPTLen
[1], mPTCode
[1]);
1069 PutBits (mPTLen
[2], mPTCode
[2]);
1070 PutBits (CBIT
, Count
- 20);
1073 ASSERT ((LoopVar3
+2) < NPT
);
1074 PutBits (mPTLen
[LoopVar3
+ 2], mPTCode
[LoopVar3
+ 2]);
1080 Huffman code the block and output it.
1102 Root
= MakeTree (NC
, mCFreq
, mCLen
, mCCode
);
1103 Size
= mCFreq
[Root
];
1107 Root
= MakeTree (NT
, mTFreq
, mPTLen
, mPTCode
);
1109 WritePTLen (NT
, TBIT
, 3);
1112 PutBits (TBIT
, Root
);
1120 PutBits (CBIT
, Root
);
1123 Root
= MakeTree (NP
, mPFreq
, mPTLen
, mPTCode
);
1125 WritePTLen (NP
, PBIT
, -1);
1128 PutBits (PBIT
, Root
);
1132 for (LoopVar1
= 0; LoopVar1
< Size
; LoopVar1
++) {
1133 if (LoopVar1
% UINT8_BIT
== 0) {
1134 Flags
= mBuf
[Pos
++];
1139 if ((Flags
& (1U << (UINT8_BIT
- 1))) != 0) {
1140 EncodeC (mBuf
[Pos
++] + (1U << UINT8_BIT
));
1141 LoopVar3
= mBuf
[Pos
++] << UINT8_BIT
;
1142 LoopVar3
+= mBuf
[Pos
++];
1146 EncodeC (mBuf
[Pos
++]);
1150 SetMem (mCFreq
, NC
* sizeof (UINT16
), 0);
1151 SetMem (mPFreq
, NP
* sizeof (UINT16
), 0);
1155 Start the huffman encoding.
1163 SetMem (mCFreq
, NC
* sizeof (UINT16
), 0);
1164 SetMem (mPFreq
, NP
* sizeof (UINT16
), 0);
1166 mOutputPos
= mOutputMask
= 0;
1168 mBitCount
= UINT8_BIT
;
1173 Outputs an Original Character or a Pointer.
1175 @param[in] LoopVar5 The original character or the 'String Length' element of
1177 @param[in] LoopVar7 The 'Position' field of a Pointer.
1187 if ((mOutputMask
>>= 1) == 0) {
1188 mOutputMask
= 1U << (UINT8_BIT
- 1);
1189 if (mOutputPos
>= mBufSiz
- 3 * UINT8_BIT
) {
1194 CPos
= mOutputPos
++;
1198 mBuf
[mOutputPos
++] = (UINT8
)LoopVar5
;
1200 if (LoopVar5
>= (1U << UINT8_BIT
)) {
1201 mBuf
[CPos
] = (UINT8
)(mBuf
[CPos
]|mOutputMask
);
1202 mBuf
[mOutputPos
++] = (UINT8
)(LoopVar7
>> UINT8_BIT
);
1203 mBuf
[mOutputPos
++] = (UINT8
)LoopVar7
;
1205 while (LoopVar7
!= 0) {
1215 End the huffman encoding.
1226 // Flush remaining bits
1228 PutBits (UINT8_BIT
- 1, 0);
1232 The main controlling routine for compression process.
1234 @retval EFI_SUCCESS The compression is successful.
1235 @retval EFI_OUT_0F_RESOURCES Not enough memory for compression process.
1246 Status
= AllocateMemory ();
1247 if (EFI_ERROR (Status
)) {
1256 mRemainder
= FreadCrc (&mText
[WNDSIZ
], WNDSIZ
+ MAXMATCH
);
1261 if (mMatchLen
> mRemainder
) {
1262 mMatchLen
= mRemainder
;
1265 while (mRemainder
> 0) {
1266 LastMatchLen
= mMatchLen
;
1267 LastMatchPos
= mMatchPos
;
1268 if (!GetNextMatch ()) {
1269 Status
= EFI_OUT_OF_RESOURCES
;
1272 if (mMatchLen
> mRemainder
) {
1273 mMatchLen
= mRemainder
;
1276 if ((mMatchLen
> LastMatchLen
) || (LastMatchLen
< THRESHOLD
)) {
1278 // Not enough benefits are gained by outputting a pointer,
1279 // so just output the original character
1281 CompressOutput (mText
[mPos
- 1], 0);
1284 // Outputting a pointer is beneficial enough, do it.
1288 LastMatchLen
+ (UINT8_MAX
+ 1 - THRESHOLD
),
1289 (mPos
- LastMatchPos
- 2) & (WNDSIZ
- 1)
1292 while (LastMatchLen
> 0) {
1293 if (!GetNextMatch ()) {
1294 Status
= EFI_OUT_OF_RESOURCES
;
1300 if (mMatchLen
> mRemainder
) {
1301 mMatchLen
= mRemainder
;
1312 The compression routine.
1314 @param[in] SrcBuffer The buffer containing the source data.
1315 @param[in] SrcSize Number of bytes in SrcBuffer.
1316 @param[in] DstBuffer The buffer to put the compressed image in.
1317 @param[in, out] DstSize On input the size (in bytes) of DstBuffer, on
1318 return the number of bytes placed in DstBuffer.
1320 @retval EFI_SUCCESS The compression was sucessful.
1321 @retval EFI_BUFFER_TOO_SMALL The buffer was too small. DstSize is required.
1328 IN OUT UINT64
*DstSize
1347 mSrcUpperLimit
= mSrc
+ SrcSize
;
1349 mDstUpperLimit
= mDst
+*DstSize
;
1356 mOrigSize
= mCompSize
= 0;
1363 if (EFI_ERROR (Status
)) {
1364 return EFI_OUT_OF_RESOURCES
;
1368 // Null terminate the compressed data
1370 if (mDst
< mDstUpperLimit
) {
1375 // Fill in compressed size and original size
1378 PutDword (mCompSize
+ 1);
1379 PutDword (mOrigSize
);
1384 if (mCompSize
+ 1 + 8 > *DstSize
) {
1385 *DstSize
= mCompSize
+ 1 + 8;
1386 return EFI_BUFFER_TOO_SMALL
;
1388 *DstSize
= mCompSize
+ 1 + 8;