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