]> git.proxmox.com Git - mirror_edk2.git/blame_incremental - BaseTools/Source/C/Common/EfiCompress.c
UefiCpuPkg: Move AsmRelocateApLoopStart from Mpfuncs.nasm to AmdSev.nasm
[mirror_edk2.git] / BaseTools / Source / C / Common / EfiCompress.c
... / ...
CommitLineData
1/** @file\r
2Compression routine. The compression algorithm is a mixture of LZ77 and Huffman\r
3coding. LZ77 transforms the source data into a sequence of Original Characters\r
4and Pointers to repeated strings. This sequence is further divided into Blocks\r
5and Huffman codings are applied to each Block.\r
6\r
7Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.<BR>\r
8SPDX-License-Identifier: BSD-2-Clause-Patent\r
9\r
10**/\r
11\r
12#include "Compress.h"\r
13\r
14\r
15//\r
16// Macro Definitions\r
17//\r
18\r
19#undef UINT8_MAX\r
20typedef INT16 NODE;\r
21#define UINT8_MAX 0xff\r
22#define UINT8_BIT 8\r
23#define THRESHOLD 3\r
24#define INIT_CRC 0\r
25#define WNDBIT 13\r
26#define WNDSIZ (1U << WNDBIT)\r
27#define MAXMATCH 256\r
28#define PERC_FLAG 0x8000U\r
29#define CODE_BIT 16\r
30#define NIL 0\r
31#define MAX_HASH_VAL (3 * WNDSIZ + (WNDSIZ / 512 + 1) * UINT8_MAX)\r
32#define HASH(p, c) ((p) + ((c) << (WNDBIT - 9)) + WNDSIZ * 2)\r
33#define CRCPOLY 0xA001\r
34#define UPDATE_CRC(c) mCrc = mCrcTable[(mCrc ^ (c)) & 0xFF] ^ (mCrc >> UINT8_BIT)\r
35\r
36//\r
37// C: the Char&Len Set; P: the Position Set; T: the exTra Set\r
38//\r
39\r
40#define NC (UINT8_MAX + MAXMATCH + 2 - THRESHOLD)\r
41#define CBIT 9\r
42#define NP (WNDBIT + 1)\r
43#define PBIT 4\r
44#define NT (CODE_BIT + 3)\r
45#define TBIT 5\r
46#if NT > NP\r
47 #define NPT NT\r
48#else\r
49 #define NPT NP\r
50#endif\r
51\r
52//\r
53// Function Prototypes\r
54//\r
55\r
56STATIC\r
57VOID\r
58PutDword(\r
59 IN UINT32 Data\r
60 );\r
61\r
62STATIC\r
63EFI_STATUS\r
64AllocateMemory (\r
65 );\r
66\r
67STATIC\r
68VOID\r
69FreeMemory (\r
70 );\r
71\r
72STATIC\r
73VOID\r
74InitSlide (\r
75 );\r
76\r
77STATIC\r
78NODE\r
79Child (\r
80 IN NODE q,\r
81 IN UINT8 c\r
82 );\r
83\r
84STATIC\r
85VOID\r
86MakeChild (\r
87 IN NODE q,\r
88 IN UINT8 c,\r
89 IN NODE r\r
90 );\r
91\r
92STATIC\r
93VOID\r
94Split (\r
95 IN NODE Old\r
96 );\r
97\r
98STATIC\r
99VOID\r
100InsertNode (\r
101 );\r
102\r
103STATIC\r
104VOID\r
105DeleteNode (\r
106 );\r
107\r
108STATIC\r
109VOID\r
110GetNextMatch (\r
111 );\r
112\r
113STATIC\r
114EFI_STATUS\r
115Encode (\r
116 );\r
117\r
118STATIC\r
119VOID\r
120CountTFreq (\r
121 );\r
122\r
123STATIC\r
124VOID\r
125WritePTLen (\r
126 IN INT32 n,\r
127 IN INT32 nbit,\r
128 IN INT32 Special\r
129 );\r
130\r
131STATIC\r
132VOID\r
133WriteCLen (\r
134 );\r
135\r
136STATIC\r
137VOID\r
138EncodeC (\r
139 IN INT32 c\r
140 );\r
141\r
142STATIC\r
143VOID\r
144EncodeP (\r
145 IN UINT32 p\r
146 );\r
147\r
148STATIC\r
149VOID\r
150SendBlock (\r
151 );\r
152\r
153STATIC\r
154VOID\r
155Output (\r
156 IN UINT32 c,\r
157 IN UINT32 p\r
158 );\r
159\r
160STATIC\r
161VOID\r
162HufEncodeStart (\r
163 );\r
164\r
165STATIC\r
166VOID\r
167HufEncodeEnd (\r
168 );\r
169\r
170STATIC\r
171VOID\r
172MakeCrcTable (\r
173 );\r
174\r
175STATIC\r
176VOID\r
177PutBits (\r
178 IN INT32 n,\r
179 IN UINT32 x\r
180 );\r
181\r
182STATIC\r
183INT32\r
184FreadCrc (\r
185 OUT UINT8 *p,\r
186 IN INT32 n\r
187 );\r
188\r
189STATIC\r
190VOID\r
191InitPutBits (\r
192 );\r
193\r
194STATIC\r
195VOID\r
196CountLen (\r
197 IN INT32 i\r
198 );\r
199\r
200STATIC\r
201VOID\r
202MakeLen (\r
203 IN INT32 Root\r
204 );\r
205\r
206STATIC\r
207VOID\r
208DownHeap (\r
209 IN INT32 i\r
210 );\r
211\r
212STATIC\r
213VOID\r
214MakeCode (\r
215 IN INT32 n,\r
216 IN UINT8 Len[],\r
217 OUT UINT16 Code[]\r
218 );\r
219\r
220STATIC\r
221INT32\r
222MakeTree (\r
223 IN INT32 NParm,\r
224 IN UINT16 FreqParm[],\r
225 OUT UINT8 LenParm[],\r
226 OUT UINT16 CodeParm[]\r
227 );\r
228\r
229\r
230//\r
231// Global Variables\r
232//\r
233\r
234STATIC UINT8 *mSrc, *mDst, *mSrcUpperLimit, *mDstUpperLimit;\r
235\r
236STATIC UINT8 *mLevel, *mText, *mChildCount, *mBuf, mCLen[NC], mPTLen[NPT], *mLen;\r
237STATIC INT16 mHeap[NC + 1];\r
238STATIC INT32 mRemainder, mMatchLen, mBitCount, mHeapSize, mN;\r
239STATIC UINT32 mBufSiz = 0, mOutputPos, mOutputMask, mSubBitBuf, mCrc;\r
240STATIC UINT32 mCompSize, mOrigSize;\r
241\r
242STATIC UINT16 *mFreq, *mSortPtr, mLenCnt[17], mLeft[2 * NC - 1], mRight[2 * NC - 1],\r
243 mCrcTable[UINT8_MAX + 1], mCFreq[2 * NC - 1],mCCode[NC],\r
244 mPFreq[2 * NP - 1], mPTCode[NPT], mTFreq[2 * NT - 1];\r
245\r
246STATIC NODE mPos, mMatchPos, mAvail, *mPosition, *mParent, *mPrev, *mNext = NULL;\r
247\r
248\r
249//\r
250// functions\r
251//\r
252\r
253EFI_STATUS\r
254EfiCompress (\r
255 IN UINT8 *SrcBuffer,\r
256 IN UINT32 SrcSize,\r
257 IN UINT8 *DstBuffer,\r
258 IN OUT UINT32 *DstSize\r
259 )\r
260/*++\r
261\r
262Routine Description:\r
263\r
264 The main compression routine.\r
265\r
266Arguments:\r
267\r
268 SrcBuffer - The buffer storing the source data\r
269 SrcSize - The size of source data\r
270 DstBuffer - The buffer to store the compressed data\r
271 DstSize - On input, the size of DstBuffer; On output,\r
272 the size of the actual compressed data.\r
273\r
274Returns:\r
275\r
276 EFI_BUFFER_TOO_SMALL - The DstBuffer is too small. In this case,\r
277 DstSize contains the size needed.\r
278 EFI_SUCCESS - Compression is successful.\r
279\r
280--*/\r
281{\r
282 EFI_STATUS Status = EFI_SUCCESS;\r
283\r
284 //\r
285 // Initializations\r
286 //\r
287 mBufSiz = 0;\r
288 mBuf = NULL;\r
289 mText = NULL;\r
290 mLevel = NULL;\r
291 mChildCount = NULL;\r
292 mPosition = NULL;\r
293 mParent = NULL;\r
294 mPrev = NULL;\r
295 mNext = NULL;\r
296\r
297\r
298 mSrc = SrcBuffer;\r
299 mSrcUpperLimit = mSrc + SrcSize;\r
300 mDst = DstBuffer;\r
301 mDstUpperLimit = mDst + *DstSize;\r
302\r
303 PutDword(0L);\r
304 PutDword(0L);\r
305\r
306 MakeCrcTable ();\r
307\r
308 mOrigSize = mCompSize = 0;\r
309 mCrc = INIT_CRC;\r
310\r
311 //\r
312 // Compress it\r
313 //\r
314\r
315 Status = Encode();\r
316 if (EFI_ERROR (Status)) {\r
317 return EFI_OUT_OF_RESOURCES;\r
318 }\r
319\r
320 //\r
321 // Null terminate the compressed data\r
322 //\r
323 if (mDst < mDstUpperLimit) {\r
324 *mDst++ = 0;\r
325 }\r
326\r
327 //\r
328 // Fill in compressed size and original size\r
329 //\r
330 mDst = DstBuffer;\r
331 PutDword(mCompSize+1);\r
332 PutDword(mOrigSize);\r
333\r
334 //\r
335 // Return\r
336 //\r
337\r
338 if (mCompSize + 1 + 8 > *DstSize) {\r
339 *DstSize = mCompSize + 1 + 8;\r
340 return EFI_BUFFER_TOO_SMALL;\r
341 } else {\r
342 *DstSize = mCompSize + 1 + 8;\r
343 return EFI_SUCCESS;\r
344 }\r
345\r
346}\r
347\r
348STATIC\r
349VOID\r
350PutDword(\r
351 IN UINT32 Data\r
352 )\r
353/*++\r
354\r
355Routine Description:\r
356\r
357 Put a dword to output stream\r
358\r
359Arguments:\r
360\r
361 Data - the dword to put\r
362\r
363Returns: (VOID)\r
364\r
365--*/\r
366{\r
367 if (mDst < mDstUpperLimit) {\r
368 *mDst++ = (UINT8)(((UINT8)(Data )) & 0xff);\r
369 }\r
370\r
371 if (mDst < mDstUpperLimit) {\r
372 *mDst++ = (UINT8)(((UINT8)(Data >> 0x08)) & 0xff);\r
373 }\r
374\r
375 if (mDst < mDstUpperLimit) {\r
376 *mDst++ = (UINT8)(((UINT8)(Data >> 0x10)) & 0xff);\r
377 }\r
378\r
379 if (mDst < mDstUpperLimit) {\r
380 *mDst++ = (UINT8)(((UINT8)(Data >> 0x18)) & 0xff);\r
381 }\r
382}\r
383\r
384STATIC\r
385EFI_STATUS\r
386AllocateMemory ()\r
387/*++\r
388\r
389Routine Description:\r
390\r
391 Allocate memory spaces for data structures used in compression process\r
392\r
393Arguments: (VOID)\r
394\r
395Returns:\r
396\r
397 EFI_SUCCESS - Memory is allocated successfully\r
398 EFI_OUT_OF_RESOURCES - Allocation fails\r
399\r
400--*/\r
401{\r
402 UINT32 i;\r
403\r
404 mText = malloc (WNDSIZ * 2 + MAXMATCH);\r
405 if (mText == NULL) {\r
406 return EFI_OUT_OF_RESOURCES;\r
407 }\r
408 for (i = 0 ; i < WNDSIZ * 2 + MAXMATCH; i ++) {\r
409 mText[i] = 0;\r
410 }\r
411\r
412 mLevel = malloc ((WNDSIZ + UINT8_MAX + 1) * sizeof(*mLevel));\r
413 mChildCount = malloc ((WNDSIZ + UINT8_MAX + 1) * sizeof(*mChildCount));\r
414 mPosition = malloc ((WNDSIZ + UINT8_MAX + 1) * sizeof(*mPosition));\r
415 mParent = malloc (WNDSIZ * 2 * sizeof(*mParent));\r
416 mPrev = malloc (WNDSIZ * 2 * sizeof(*mPrev));\r
417 mNext = malloc ((MAX_HASH_VAL + 1) * sizeof(*mNext));\r
418 if (mLevel == NULL || mChildCount == NULL || mPosition == NULL ||\r
419 mParent == NULL || mPrev == NULL || mNext == NULL) {\r
420 return EFI_OUT_OF_RESOURCES;\r
421 }\r
422\r
423 mBufSiz = 16 * 1024U;\r
424 while ((mBuf = malloc(mBufSiz)) == NULL) {\r
425 mBufSiz = (mBufSiz / 10U) * 9U;\r
426 if (mBufSiz < 4 * 1024U) {\r
427 return EFI_OUT_OF_RESOURCES;\r
428 }\r
429 }\r
430 mBuf[0] = 0;\r
431\r
432 return EFI_SUCCESS;\r
433}\r
434\r
435VOID\r
436FreeMemory ()\r
437/*++\r
438\r
439Routine Description:\r
440\r
441 Called when compression is completed to free memory previously allocated.\r
442\r
443Arguments: (VOID)\r
444\r
445Returns: (VOID)\r
446\r
447--*/\r
448{\r
449 if (mText) {\r
450 free (mText);\r
451 }\r
452\r
453 if (mLevel) {\r
454 free (mLevel);\r
455 }\r
456\r
457 if (mChildCount) {\r
458 free (mChildCount);\r
459 }\r
460\r
461 if (mPosition) {\r
462 free (mPosition);\r
463 }\r
464\r
465 if (mParent) {\r
466 free (mParent);\r
467 }\r
468\r
469 if (mPrev) {\r
470 free (mPrev);\r
471 }\r
472\r
473 if (mNext) {\r
474 free (mNext);\r
475 }\r
476\r
477 if (mBuf) {\r
478 free (mBuf);\r
479 }\r
480\r
481 return;\r
482}\r
483\r
484\r
485STATIC\r
486VOID\r
487InitSlide ()\r
488/*++\r
489\r
490Routine Description:\r
491\r
492 Initialize String Info Log data structures\r
493\r
494Arguments: (VOID)\r
495\r
496Returns: (VOID)\r
497\r
498--*/\r
499{\r
500 NODE i;\r
501\r
502 for (i = WNDSIZ; i <= WNDSIZ + UINT8_MAX; i++) {\r
503 mLevel[i] = 1;\r
504 mPosition[i] = NIL; /* sentinel */\r
505 }\r
506 for (i = WNDSIZ; i < WNDSIZ * 2; i++) {\r
507 mParent[i] = NIL;\r
508 }\r
509 mAvail = 1;\r
510 for (i = 1; i < WNDSIZ - 1; i++) {\r
511 mNext[i] = (NODE)(i + 1);\r
512 }\r
513\r
514 mNext[WNDSIZ - 1] = NIL;\r
515 for (i = WNDSIZ * 2; i <= MAX_HASH_VAL; i++) {\r
516 mNext[i] = NIL;\r
517 }\r
518}\r
519\r
520\r
521STATIC\r
522NODE\r
523Child (\r
524 IN NODE q,\r
525 IN UINT8 c\r
526 )\r
527/*++\r
528\r
529Routine Description:\r
530\r
531 Find child node given the parent node and the edge character\r
532\r
533Arguments:\r
534\r
535 q - the parent node\r
536 c - the edge character\r
537\r
538Returns:\r
539\r
540 The child node (NIL if not found)\r
541\r
542--*/\r
543{\r
544 NODE r;\r
545\r
546 r = mNext[HASH(q, c)];\r
547 mParent[NIL] = q; /* sentinel */\r
548 while (mParent[r] != q) {\r
549 r = mNext[r];\r
550 }\r
551\r
552 return r;\r
553}\r
554\r
555STATIC\r
556VOID\r
557MakeChild (\r
558 IN NODE q,\r
559 IN UINT8 c,\r
560 IN NODE r\r
561 )\r
562/*++\r
563\r
564Routine Description:\r
565\r
566 Create a new child for a given parent node.\r
567\r
568Arguments:\r
569\r
570 q - the parent node\r
571 c - the edge character\r
572 r - the child node\r
573\r
574Returns: (VOID)\r
575\r
576--*/\r
577{\r
578 NODE h, t;\r
579\r
580 h = (NODE)HASH(q, c);\r
581 t = mNext[h];\r
582 mNext[h] = r;\r
583 mNext[r] = t;\r
584 mPrev[t] = r;\r
585 mPrev[r] = h;\r
586 mParent[r] = q;\r
587 mChildCount[q]++;\r
588}\r
589\r
590STATIC\r
591VOID\r
592Split (\r
593 NODE Old\r
594 )\r
595/*++\r
596\r
597Routine Description:\r
598\r
599 Split a node.\r
600\r
601Arguments:\r
602\r
603 Old - the node to split\r
604\r
605Returns: (VOID)\r
606\r
607--*/\r
608{\r
609 NODE New, t;\r
610\r
611 New = mAvail;\r
612 mAvail = mNext[New];\r
613 mChildCount[New] = 0;\r
614 t = mPrev[Old];\r
615 mPrev[New] = t;\r
616 mNext[t] = New;\r
617 t = mNext[Old];\r
618 mNext[New] = t;\r
619 mPrev[t] = New;\r
620 mParent[New] = mParent[Old];\r
621 mLevel[New] = (UINT8)mMatchLen;\r
622 mPosition[New] = mPos;\r
623 MakeChild(New, mText[mMatchPos + mMatchLen], Old);\r
624 MakeChild(New, mText[mPos + mMatchLen], mPos);\r
625}\r
626\r
627STATIC\r
628VOID\r
629InsertNode ()\r
630/*++\r
631\r
632Routine Description:\r
633\r
634 Insert string info for current position into the String Info Log\r
635\r
636Arguments: (VOID)\r
637\r
638Returns: (VOID)\r
639\r
640--*/\r
641{\r
642 NODE q, r, j, t;\r
643 UINT8 c, *t1, *t2;\r
644\r
645 if (mMatchLen >= 4) {\r
646\r
647 //\r
648 // We have just got a long match, the target tree\r
649 // can be located by MatchPos + 1. Traverse the tree\r
650 // from bottom up to get to a proper starting point.\r
651 // The usage of PERC_FLAG ensures proper node deletion\r
652 // in DeleteNode() later.\r
653 //\r
654\r
655 mMatchLen--;\r
656 r = (INT16)((mMatchPos + 1) | WNDSIZ);\r
657 while ((q = mParent[r]) == NIL) {\r
658 r = mNext[r];\r
659 }\r
660 while (mLevel[q] >= mMatchLen) {\r
661 r = q; q = mParent[q];\r
662 }\r
663 t = q;\r
664 while (mPosition[t] < 0) {\r
665 mPosition[t] = mPos;\r
666 t = mParent[t];\r
667 }\r
668 if (t < WNDSIZ) {\r
669 mPosition[t] = (NODE)(mPos | PERC_FLAG);\r
670 }\r
671 } else {\r
672\r
673 //\r
674 // Locate the target tree\r
675 //\r
676\r
677 q = (INT16)(mText[mPos] + WNDSIZ);\r
678 c = mText[mPos + 1];\r
679 if ((r = Child(q, c)) == NIL) {\r
680 MakeChild(q, c, mPos);\r
681 mMatchLen = 1;\r
682 return;\r
683 }\r
684 mMatchLen = 2;\r
685 }\r
686\r
687 //\r
688 // Traverse down the tree to find a match.\r
689 // Update Position value along the route.\r
690 // Node split or creation is involved.\r
691 //\r
692\r
693 for ( ; ; ) {\r
694 if (r >= WNDSIZ) {\r
695 j = MAXMATCH;\r
696 mMatchPos = r;\r
697 } else {\r
698 j = mLevel[r];\r
699 mMatchPos = (NODE)(mPosition[r] & ~PERC_FLAG);\r
700 }\r
701 if (mMatchPos >= mPos) {\r
702 mMatchPos -= WNDSIZ;\r
703 }\r
704 t1 = &mText[mPos + mMatchLen];\r
705 t2 = &mText[mMatchPos + mMatchLen];\r
706 while (mMatchLen < j) {\r
707 if (*t1 != *t2) {\r
708 Split(r);\r
709 return;\r
710 }\r
711 mMatchLen++;\r
712 t1++;\r
713 t2++;\r
714 }\r
715 if (mMatchLen >= MAXMATCH) {\r
716 break;\r
717 }\r
718 mPosition[r] = mPos;\r
719 q = r;\r
720 if ((r = Child(q, *t1)) == NIL) {\r
721 MakeChild(q, *t1, mPos);\r
722 return;\r
723 }\r
724 mMatchLen++;\r
725 }\r
726 t = mPrev[r];\r
727 mPrev[mPos] = t;\r
728 mNext[t] = mPos;\r
729 t = mNext[r];\r
730 mNext[mPos] = t;\r
731 mPrev[t] = mPos;\r
732 mParent[mPos] = q;\r
733 mParent[r] = NIL;\r
734\r
735 //\r
736 // Special usage of 'next'\r
737 //\r
738 mNext[r] = mPos;\r
739\r
740}\r
741\r
742STATIC\r
743VOID\r
744DeleteNode ()\r
745/*++\r
746\r
747Routine Description:\r
748\r
749 Delete outdated string info. (The Usage of PERC_FLAG\r
750 ensures a clean deletion)\r
751\r
752Arguments: (VOID)\r
753\r
754Returns: (VOID)\r
755\r
756--*/\r
757{\r
758 NODE q, r, s, t, u;\r
759\r
760 if (mParent[mPos] == NIL) {\r
761 return;\r
762 }\r
763\r
764 r = mPrev[mPos];\r
765 s = mNext[mPos];\r
766 mNext[r] = s;\r
767 mPrev[s] = r;\r
768 r = mParent[mPos];\r
769 mParent[mPos] = NIL;\r
770 if (r >= WNDSIZ || --mChildCount[r] > 1) {\r
771 return;\r
772 }\r
773 t = (NODE)(mPosition[r] & ~PERC_FLAG);\r
774 if (t >= mPos) {\r
775 t -= WNDSIZ;\r
776 }\r
777 s = t;\r
778 q = mParent[r];\r
779 while ((u = mPosition[q]) & PERC_FLAG) {\r
780 u &= ~PERC_FLAG;\r
781 if (u >= mPos) {\r
782 u -= WNDSIZ;\r
783 }\r
784 if (u > s) {\r
785 s = u;\r
786 }\r
787 mPosition[q] = (INT16)(s | WNDSIZ);\r
788 q = mParent[q];\r
789 }\r
790 if (q < WNDSIZ) {\r
791 if (u >= mPos) {\r
792 u -= WNDSIZ;\r
793 }\r
794 if (u > s) {\r
795 s = u;\r
796 }\r
797 mPosition[q] = (INT16)(s | WNDSIZ | PERC_FLAG);\r
798 }\r
799 s = Child(r, mText[t + mLevel[r]]);\r
800 t = mPrev[s];\r
801 u = mNext[s];\r
802 mNext[t] = u;\r
803 mPrev[u] = t;\r
804 t = mPrev[r];\r
805 mNext[t] = s;\r
806 mPrev[s] = t;\r
807 t = mNext[r];\r
808 mPrev[t] = s;\r
809 mNext[s] = t;\r
810 mParent[s] = mParent[r];\r
811 mParent[r] = NIL;\r
812 mNext[r] = mAvail;\r
813 mAvail = r;\r
814}\r
815\r
816STATIC\r
817VOID\r
818GetNextMatch ()\r
819/*++\r
820\r
821Routine Description:\r
822\r
823 Advance the current position (read in new data if needed).\r
824 Delete outdated string info. Find a match string for current position.\r
825\r
826Arguments: (VOID)\r
827\r
828Returns: (VOID)\r
829\r
830--*/\r
831{\r
832 INT32 n;\r
833\r
834 mRemainder--;\r
835 if (++mPos == WNDSIZ * 2) {\r
836 memmove(&mText[0], &mText[WNDSIZ], WNDSIZ + MAXMATCH);\r
837 n = FreadCrc(&mText[WNDSIZ + MAXMATCH], WNDSIZ);\r
838 mRemainder += n;\r
839 mPos = WNDSIZ;\r
840 }\r
841 DeleteNode();\r
842 InsertNode();\r
843}\r
844\r
845STATIC\r
846EFI_STATUS\r
847Encode ()\r
848/*++\r
849\r
850Routine Description:\r
851\r
852 The main controlling routine for compression process.\r
853\r
854Arguments: (VOID)\r
855\r
856Returns:\r
857\r
858 EFI_SUCCESS - The compression is successful\r
859 EFI_OUT_0F_RESOURCES - Not enough memory for compression process\r
860\r
861--*/\r
862{\r
863 EFI_STATUS Status;\r
864 INT32 LastMatchLen;\r
865 NODE LastMatchPos;\r
866\r
867 Status = AllocateMemory();\r
868 if (EFI_ERROR(Status)) {\r
869 FreeMemory();\r
870 return Status;\r
871 }\r
872\r
873 InitSlide();\r
874\r
875 HufEncodeStart();\r
876\r
877 mRemainder = FreadCrc(&mText[WNDSIZ], WNDSIZ + MAXMATCH);\r
878\r
879 mMatchLen = 0;\r
880 mPos = WNDSIZ;\r
881 InsertNode();\r
882 if (mMatchLen > mRemainder) {\r
883 mMatchLen = mRemainder;\r
884 }\r
885 while (mRemainder > 0) {\r
886 LastMatchLen = mMatchLen;\r
887 LastMatchPos = mMatchPos;\r
888 GetNextMatch();\r
889 if (mMatchLen > mRemainder) {\r
890 mMatchLen = mRemainder;\r
891 }\r
892\r
893 if (mMatchLen > LastMatchLen || LastMatchLen < THRESHOLD) {\r
894\r
895 //\r
896 // Not enough benefits are gained by outputting a pointer,\r
897 // so just output the original character\r
898 //\r
899\r
900 Output(mText[mPos - 1], 0);\r
901 } else {\r
902\r
903 //\r
904 // Outputting a pointer is beneficial enough, do it.\r
905 //\r
906\r
907 Output(LastMatchLen + (UINT8_MAX + 1 - THRESHOLD),\r
908 (mPos - LastMatchPos - 2) & (WNDSIZ - 1));\r
909 while (--LastMatchLen > 0) {\r
910 GetNextMatch();\r
911 }\r
912 if (mMatchLen > mRemainder) {\r
913 mMatchLen = mRemainder;\r
914 }\r
915 }\r
916 }\r
917\r
918 HufEncodeEnd();\r
919 FreeMemory();\r
920 return EFI_SUCCESS;\r
921}\r
922\r
923STATIC\r
924VOID\r
925CountTFreq ()\r
926/*++\r
927\r
928Routine Description:\r
929\r
930 Count the frequencies for the Extra Set\r
931\r
932Arguments: (VOID)\r
933\r
934Returns: (VOID)\r
935\r
936--*/\r
937{\r
938 INT32 i, k, n, Count;\r
939\r
940 for (i = 0; i < NT; i++) {\r
941 mTFreq[i] = 0;\r
942 }\r
943 n = NC;\r
944 while (n > 0 && mCLen[n - 1] == 0) {\r
945 n--;\r
946 }\r
947 i = 0;\r
948 while (i < n) {\r
949 k = mCLen[i++];\r
950 if (k == 0) {\r
951 Count = 1;\r
952 while (i < n && mCLen[i] == 0) {\r
953 i++;\r
954 Count++;\r
955 }\r
956 if (Count <= 2) {\r
957 mTFreq[0] = (UINT16)(mTFreq[0] + Count);\r
958 } else if (Count <= 18) {\r
959 mTFreq[1]++;\r
960 } else if (Count == 19) {\r
961 mTFreq[0]++;\r
962 mTFreq[1]++;\r
963 } else {\r
964 mTFreq[2]++;\r
965 }\r
966 } else {\r
967 mTFreq[k + 2]++;\r
968 }\r
969 }\r
970}\r
971\r
972STATIC\r
973VOID\r
974WritePTLen (\r
975 IN INT32 n,\r
976 IN INT32 nbit,\r
977 IN INT32 Special\r
978 )\r
979/*++\r
980\r
981Routine Description:\r
982\r
983 Outputs the code length array for the Extra Set or the Position Set.\r
984\r
985Arguments:\r
986\r
987 n - the number of symbols\r
988 nbit - the number of bits needed to represent 'n'\r
989 Special - the special symbol that needs to be take care of\r
990\r
991Returns: (VOID)\r
992\r
993--*/\r
994{\r
995 INT32 i, k;\r
996\r
997 while (n > 0 && mPTLen[n - 1] == 0) {\r
998 n--;\r
999 }\r
1000 PutBits(nbit, n);\r
1001 i = 0;\r
1002 while (i < n) {\r
1003 k = mPTLen[i++];\r
1004 if (k <= 6) {\r
1005 PutBits(3, k);\r
1006 } else {\r
1007 PutBits(k - 3, (1U << (k - 3)) - 2);\r
1008 }\r
1009 if (i == Special) {\r
1010 while (i < 6 && mPTLen[i] == 0) {\r
1011 i++;\r
1012 }\r
1013 PutBits(2, (i - 3) & 3);\r
1014 }\r
1015 }\r
1016}\r
1017\r
1018STATIC\r
1019VOID\r
1020WriteCLen ()\r
1021/*++\r
1022\r
1023Routine Description:\r
1024\r
1025 Outputs the code length array for Char&Length Set\r
1026\r
1027Arguments: (VOID)\r
1028\r
1029Returns: (VOID)\r
1030\r
1031--*/\r
1032{\r
1033 INT32 i, k, n, Count;\r
1034\r
1035 n = NC;\r
1036 while (n > 0 && mCLen[n - 1] == 0) {\r
1037 n--;\r
1038 }\r
1039 PutBits(CBIT, n);\r
1040 i = 0;\r
1041 while (i < n) {\r
1042 k = mCLen[i++];\r
1043 if (k == 0) {\r
1044 Count = 1;\r
1045 while (i < n && mCLen[i] == 0) {\r
1046 i++;\r
1047 Count++;\r
1048 }\r
1049 if (Count <= 2) {\r
1050 for (k = 0; k < Count; k++) {\r
1051 PutBits(mPTLen[0], mPTCode[0]);\r
1052 }\r
1053 } else if (Count <= 18) {\r
1054 PutBits(mPTLen[1], mPTCode[1]);\r
1055 PutBits(4, Count - 3);\r
1056 } else if (Count == 19) {\r
1057 PutBits(mPTLen[0], mPTCode[0]);\r
1058 PutBits(mPTLen[1], mPTCode[1]);\r
1059 PutBits(4, 15);\r
1060 } else {\r
1061 PutBits(mPTLen[2], mPTCode[2]);\r
1062 PutBits(CBIT, Count - 20);\r
1063 }\r
1064 } else {\r
1065 PutBits(mPTLen[k + 2], mPTCode[k + 2]);\r
1066 }\r
1067 }\r
1068}\r
1069\r
1070STATIC\r
1071VOID\r
1072EncodeC (\r
1073 IN INT32 c\r
1074 )\r
1075{\r
1076 PutBits(mCLen[c], mCCode[c]);\r
1077}\r
1078\r
1079STATIC\r
1080VOID\r
1081EncodeP (\r
1082 IN UINT32 p\r
1083 )\r
1084{\r
1085 UINT32 c, q;\r
1086\r
1087 c = 0;\r
1088 q = p;\r
1089 while (q) {\r
1090 q >>= 1;\r
1091 c++;\r
1092 }\r
1093 PutBits(mPTLen[c], mPTCode[c]);\r
1094 if (c > 1) {\r
1095 PutBits(c - 1, p & (0xFFFFU >> (17 - c)));\r
1096 }\r
1097}\r
1098\r
1099STATIC\r
1100VOID\r
1101SendBlock ()\r
1102/*++\r
1103\r
1104Routine Description:\r
1105\r
1106 Huffman code the block and output it.\r
1107\r
1108Argument: (VOID)\r
1109\r
1110Returns: (VOID)\r
1111\r
1112--*/\r
1113{\r
1114 UINT32 i, k, Flags, Root, Pos, Size;\r
1115 Flags = 0;\r
1116\r
1117 Root = MakeTree(NC, mCFreq, mCLen, mCCode);\r
1118 Size = mCFreq[Root];\r
1119 PutBits(16, Size);\r
1120 if (Root >= NC) {\r
1121 CountTFreq();\r
1122 Root = MakeTree(NT, mTFreq, mPTLen, mPTCode);\r
1123 if (Root >= NT) {\r
1124 WritePTLen(NT, TBIT, 3);\r
1125 } else {\r
1126 PutBits(TBIT, 0);\r
1127 PutBits(TBIT, Root);\r
1128 }\r
1129 WriteCLen();\r
1130 } else {\r
1131 PutBits(TBIT, 0);\r
1132 PutBits(TBIT, 0);\r
1133 PutBits(CBIT, 0);\r
1134 PutBits(CBIT, Root);\r
1135 }\r
1136 Root = MakeTree(NP, mPFreq, mPTLen, mPTCode);\r
1137 if (Root >= NP) {\r
1138 WritePTLen(NP, PBIT, -1);\r
1139 } else {\r
1140 PutBits(PBIT, 0);\r
1141 PutBits(PBIT, Root);\r
1142 }\r
1143 Pos = 0;\r
1144 for (i = 0; i < Size; i++) {\r
1145 if (i % UINT8_BIT == 0) {\r
1146 Flags = mBuf[Pos++];\r
1147 } else {\r
1148 Flags <<= 1;\r
1149 }\r
1150 if (Flags & (1U << (UINT8_BIT - 1))) {\r
1151 EncodeC(mBuf[Pos++] + (1U << UINT8_BIT));\r
1152 k = mBuf[Pos++] << UINT8_BIT;\r
1153 k += mBuf[Pos++];\r
1154 EncodeP(k);\r
1155 } else {\r
1156 EncodeC(mBuf[Pos++]);\r
1157 }\r
1158 }\r
1159 for (i = 0; i < NC; i++) {\r
1160 mCFreq[i] = 0;\r
1161 }\r
1162 for (i = 0; i < NP; i++) {\r
1163 mPFreq[i] = 0;\r
1164 }\r
1165}\r
1166\r
1167\r
1168STATIC\r
1169VOID\r
1170Output (\r
1171 IN UINT32 c,\r
1172 IN UINT32 p\r
1173 )\r
1174/*++\r
1175\r
1176Routine Description:\r
1177\r
1178 Outputs an Original Character or a Pointer\r
1179\r
1180Arguments:\r
1181\r
1182 c - The original character or the 'String Length' element of a Pointer\r
1183 p - The 'Position' field of a Pointer\r
1184\r
1185Returns: (VOID)\r
1186\r
1187--*/\r
1188{\r
1189 STATIC UINT32 CPos;\r
1190\r
1191 if ((mOutputMask >>= 1) == 0) {\r
1192 mOutputMask = 1U << (UINT8_BIT - 1);\r
1193 if (mOutputPos >= mBufSiz - 3 * UINT8_BIT) {\r
1194 SendBlock();\r
1195 mOutputPos = 0;\r
1196 }\r
1197 CPos = mOutputPos++;\r
1198 mBuf[CPos] = 0;\r
1199 }\r
1200 mBuf[mOutputPos++] = (UINT8) c;\r
1201 mCFreq[c]++;\r
1202 if (c >= (1U << UINT8_BIT)) {\r
1203 mBuf[CPos] |= mOutputMask;\r
1204 mBuf[mOutputPos++] = (UINT8)(p >> UINT8_BIT);\r
1205 mBuf[mOutputPos++] = (UINT8) p;\r
1206 c = 0;\r
1207 while (p) {\r
1208 p >>= 1;\r
1209 c++;\r
1210 }\r
1211 mPFreq[c]++;\r
1212 }\r
1213}\r
1214\r
1215STATIC\r
1216VOID\r
1217HufEncodeStart ()\r
1218{\r
1219 INT32 i;\r
1220\r
1221 for (i = 0; i < NC; i++) {\r
1222 mCFreq[i] = 0;\r
1223 }\r
1224 for (i = 0; i < NP; i++) {\r
1225 mPFreq[i] = 0;\r
1226 }\r
1227 mOutputPos = mOutputMask = 0;\r
1228 InitPutBits();\r
1229 return;\r
1230}\r
1231\r
1232STATIC\r
1233VOID\r
1234HufEncodeEnd ()\r
1235{\r
1236 SendBlock();\r
1237\r
1238 //\r
1239 // Flush remaining bits\r
1240 //\r
1241 PutBits(UINT8_BIT - 1, 0);\r
1242\r
1243 return;\r
1244}\r
1245\r
1246\r
1247STATIC\r
1248VOID\r
1249MakeCrcTable ()\r
1250{\r
1251 UINT32 i, j, r;\r
1252\r
1253 for (i = 0; i <= UINT8_MAX; i++) {\r
1254 r = i;\r
1255 for (j = 0; j < UINT8_BIT; j++) {\r
1256 if (r & 1) {\r
1257 r = (r >> 1) ^ CRCPOLY;\r
1258 } else {\r
1259 r >>= 1;\r
1260 }\r
1261 }\r
1262 mCrcTable[i] = (UINT16)r;\r
1263 }\r
1264}\r
1265\r
1266STATIC\r
1267VOID\r
1268PutBits (\r
1269 IN INT32 n,\r
1270 IN UINT32 x\r
1271 )\r
1272/*++\r
1273\r
1274Routine Description:\r
1275\r
1276 Outputs rightmost n bits of x\r
1277\r
1278Arguments:\r
1279\r
1280 n - the rightmost n bits of the data is used\r
1281 x - the data\r
1282\r
1283Returns: (VOID)\r
1284\r
1285--*/\r
1286{\r
1287 UINT8 Temp;\r
1288\r
1289 if (n < mBitCount) {\r
1290 mSubBitBuf |= x << (mBitCount -= n);\r
1291 } else {\r
1292\r
1293 Temp = (UINT8)(mSubBitBuf | (x >> (n -= mBitCount)));\r
1294 if (mDst < mDstUpperLimit) {\r
1295 *mDst++ = Temp;\r
1296 }\r
1297 mCompSize++;\r
1298\r
1299 if (n < UINT8_BIT) {\r
1300 mSubBitBuf = x << (mBitCount = UINT8_BIT - n);\r
1301 } else {\r
1302\r
1303 Temp = (UINT8)(x >> (n - UINT8_BIT));\r
1304 if (mDst < mDstUpperLimit) {\r
1305 *mDst++ = Temp;\r
1306 }\r
1307 mCompSize++;\r
1308\r
1309 mSubBitBuf = x << (mBitCount = 2 * UINT8_BIT - n);\r
1310 }\r
1311 }\r
1312}\r
1313\r
1314STATIC\r
1315INT32\r
1316FreadCrc (\r
1317 OUT UINT8 *p,\r
1318 IN INT32 n\r
1319 )\r
1320/*++\r
1321\r
1322Routine Description:\r
1323\r
1324 Read in source data\r
1325\r
1326Arguments:\r
1327\r
1328 p - the buffer to hold the data\r
1329 n - number of bytes to read\r
1330\r
1331Returns:\r
1332\r
1333 number of bytes actually read\r
1334\r
1335--*/\r
1336{\r
1337 INT32 i;\r
1338\r
1339 for (i = 0; mSrc < mSrcUpperLimit && i < n; i++) {\r
1340 *p++ = *mSrc++;\r
1341 }\r
1342 n = i;\r
1343\r
1344 p -= n;\r
1345 mOrigSize += n;\r
1346 while (--i >= 0) {\r
1347 UPDATE_CRC(*p++);\r
1348 }\r
1349 return n;\r
1350}\r
1351\r
1352\r
1353STATIC\r
1354VOID\r
1355InitPutBits ()\r
1356{\r
1357 mBitCount = UINT8_BIT;\r
1358 mSubBitBuf = 0;\r
1359}\r
1360\r
1361STATIC\r
1362VOID\r
1363CountLen (\r
1364 IN INT32 i\r
1365 )\r
1366/*++\r
1367\r
1368Routine Description:\r
1369\r
1370 Count the number of each code length for a Huffman tree.\r
1371\r
1372Arguments:\r
1373\r
1374 i - the top node\r
1375\r
1376Returns: (VOID)\r
1377\r
1378--*/\r
1379{\r
1380 STATIC INT32 Depth = 0;\r
1381\r
1382 if (i < mN) {\r
1383 mLenCnt[(Depth < 16) ? Depth : 16]++;\r
1384 } else {\r
1385 Depth++;\r
1386 CountLen(mLeft [i]);\r
1387 CountLen(mRight[i]);\r
1388 Depth--;\r
1389 }\r
1390}\r
1391\r
1392STATIC\r
1393VOID\r
1394MakeLen (\r
1395 IN INT32 Root\r
1396 )\r
1397/*++\r
1398\r
1399Routine Description:\r
1400\r
1401 Create code length array for a Huffman tree\r
1402\r
1403Arguments:\r
1404\r
1405 Root - the root of the tree\r
1406\r
1407--*/\r
1408{\r
1409 INT32 i, k;\r
1410 UINT32 Cum;\r
1411\r
1412 for (i = 0; i <= 16; i++) {\r
1413 mLenCnt[i] = 0;\r
1414 }\r
1415 CountLen(Root);\r
1416\r
1417 //\r
1418 // Adjust the length count array so that\r
1419 // no code will be generated longer than its designated length\r
1420 //\r
1421\r
1422 Cum = 0;\r
1423 for (i = 16; i > 0; i--) {\r
1424 Cum += mLenCnt[i] << (16 - i);\r
1425 }\r
1426 while (Cum != (1U << 16)) {\r
1427 mLenCnt[16]--;\r
1428 for (i = 15; i > 0; i--) {\r
1429 if (mLenCnt[i] != 0) {\r
1430 mLenCnt[i]--;\r
1431 mLenCnt[i+1] += 2;\r
1432 break;\r
1433 }\r
1434 }\r
1435 Cum--;\r
1436 }\r
1437 for (i = 16; i > 0; i--) {\r
1438 k = mLenCnt[i];\r
1439 while (--k >= 0) {\r
1440 mLen[*mSortPtr++] = (UINT8)i;\r
1441 }\r
1442 }\r
1443}\r
1444\r
1445STATIC\r
1446VOID\r
1447DownHeap (\r
1448 IN INT32 i\r
1449 )\r
1450{\r
1451 INT32 j, k;\r
1452\r
1453 //\r
1454 // priority queue: send i-th entry down heap\r
1455 //\r
1456\r
1457 k = mHeap[i];\r
1458 while ((j = 2 * i) <= mHeapSize) {\r
1459 if (j < mHeapSize && mFreq[mHeap[j]] > mFreq[mHeap[j + 1]]) {\r
1460 j++;\r
1461 }\r
1462 if (mFreq[k] <= mFreq[mHeap[j]]) {\r
1463 break;\r
1464 }\r
1465 mHeap[i] = mHeap[j];\r
1466 i = j;\r
1467 }\r
1468 mHeap[i] = (INT16)k;\r
1469}\r
1470\r
1471STATIC\r
1472VOID\r
1473MakeCode (\r
1474 IN INT32 n,\r
1475 IN UINT8 Len[],\r
1476 OUT UINT16 Code[]\r
1477 )\r
1478/*++\r
1479\r
1480Routine Description:\r
1481\r
1482 Assign code to each symbol based on the code length array\r
1483\r
1484Arguments:\r
1485\r
1486 n - number of symbols\r
1487 Len - the code length array\r
1488 Code - stores codes for each symbol\r
1489\r
1490Returns: (VOID)\r
1491\r
1492--*/\r
1493{\r
1494 INT32 i;\r
1495 UINT16 Start[18];\r
1496\r
1497 Start[1] = 0;\r
1498 for (i = 1; i <= 16; i++) {\r
1499 Start[i + 1] = (UINT16)((Start[i] + mLenCnt[i]) << 1);\r
1500 }\r
1501 for (i = 0; i < n; i++) {\r
1502 Code[i] = Start[Len[i]]++;\r
1503 }\r
1504}\r
1505\r
1506STATIC\r
1507INT32\r
1508MakeTree (\r
1509 IN INT32 NParm,\r
1510 IN UINT16 FreqParm[],\r
1511 OUT UINT8 LenParm[],\r
1512 OUT UINT16 CodeParm[]\r
1513 )\r
1514/*++\r
1515\r
1516Routine Description:\r
1517\r
1518 Generates Huffman codes given a frequency distribution of symbols\r
1519\r
1520Arguments:\r
1521\r
1522 NParm - number of symbols\r
1523 FreqParm - frequency of each symbol\r
1524 LenParm - code length for each symbol\r
1525 CodeParm - code for each symbol\r
1526\r
1527Returns:\r
1528\r
1529 Root of the Huffman tree.\r
1530\r
1531--*/\r
1532{\r
1533 INT32 i, j, k, Avail;\r
1534\r
1535 //\r
1536 // make tree, calculate len[], return root\r
1537 //\r
1538\r
1539 mN = NParm;\r
1540 mFreq = FreqParm;\r
1541 mLen = LenParm;\r
1542 Avail = mN;\r
1543 mHeapSize = 0;\r
1544 mHeap[1] = 0;\r
1545 for (i = 0; i < mN; i++) {\r
1546 mLen[i] = 0;\r
1547 if (mFreq[i]) {\r
1548 mHeap[++mHeapSize] = (INT16)i;\r
1549 }\r
1550 }\r
1551 if (mHeapSize < 2) {\r
1552 CodeParm[mHeap[1]] = 0;\r
1553 return mHeap[1];\r
1554 }\r
1555 for (i = mHeapSize / 2; i >= 1; i--) {\r
1556\r
1557 //\r
1558 // make priority queue\r
1559 //\r
1560 DownHeap(i);\r
1561 }\r
1562 mSortPtr = CodeParm;\r
1563 do {\r
1564 i = mHeap[1];\r
1565 if (i < mN) {\r
1566 *mSortPtr++ = (UINT16)i;\r
1567 }\r
1568 mHeap[1] = mHeap[mHeapSize--];\r
1569 DownHeap(1);\r
1570 j = mHeap[1];\r
1571 if (j < mN) {\r
1572 *mSortPtr++ = (UINT16)j;\r
1573 }\r
1574 k = Avail++;\r
1575 mFreq[k] = (UINT16)(mFreq[i] + mFreq[j]);\r
1576 mHeap[1] = (INT16)k;\r
1577 DownHeap(1);\r
1578 mLeft[k] = (UINT16)i;\r
1579 mRight[k] = (UINT16)j;\r
1580 } while (mHeapSize > 1);\r
1581\r
1582 mSortPtr = CodeParm;\r
1583 MakeLen(k);\r
1584 MakeCode(NParm, LenParm, CodeParm);\r
1585\r
1586 //\r
1587 // return root\r
1588 //\r
1589 return k;\r
1590}\r
1591\r