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