]> git.proxmox.com Git - mirror_edk2.git/blame - BaseTools/Source/C/TianoCompress/TianoCompress.c
BaseTools/GenVtf: Avoid possible NULL pointer dereference
[mirror_edk2.git] / BaseTools / Source / C / TianoCompress / TianoCompress.c
CommitLineData
30fdf114 1/** @file\r
97fa0ee9
YL
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.\r
5This sequence is further divided into Blocks and Huffman codings are applied to \r
6each Block.\r
7 \r
8Copyright (c) 2007 - 2014, Intel Corporation. All rights reserved.<BR>\r
40d841f6 9This program and the accompanying materials \r
30fdf114
LG
10are licensed and made available under the terms and conditions of the BSD License \r
11which accompanies this distribution. The full text of the license may be found at \r
12http://opensource.org/licenses/bsd-license.php \r
13 \r
14THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, \r
15WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. \r
16\r
30fdf114
LG
17**/\r
18\r
19#include "Compress.h"\r
20#include "TianoCompress.h"\r
21#include "EfiUtilityMsgs.h"\r
22#include "ParseInf.h"\r
23#include <stdio.h>\r
24#include "assert.h"\r
25\r
26//\r
27// Macro Definitions\r
28//\r
29static BOOLEAN VerboseMode = FALSE;\r
30static BOOLEAN QuietMode = FALSE;\r
31#undef UINT8_MAX\r
32#define UINT8_MAX 0xff\r
33#define UINT8_BIT 8\r
34#define THRESHOLD 3\r
35#define INIT_CRC 0\r
36#define WNDBIT 19\r
37#define WNDSIZ (1U << WNDBIT)\r
38#define MAXMATCH 256\r
39#define BLKSIZ (1U << 14) // 16 * 1024U\r
40#define PERC_FLAG 0x80000000U\r
41#define CODE_BIT 16\r
42#define NIL 0\r
43#define MAX_HASH_VAL (3 * WNDSIZ + (WNDSIZ / 512 + 1) * UINT8_MAX)\r
44#define HASH(p, c) ((p) + ((c) << (WNDBIT - 9)) + WNDSIZ * 2)\r
45#define CRCPOLY 0xA001\r
46#define UPDATE_CRC(c) mCrc = mCrcTable[(mCrc ^ (c)) & 0xFF] ^ (mCrc >> UINT8_BIT)\r
47\r
48//\r
49// C: the Char&Len Set; P: the Position Set; T: the exTra Set\r
50//\r
51//#define NC (UINT8_MAX + MAXMATCH + 2 - THRESHOLD)\r
52#define CBIT 9\r
53#define NP (WNDBIT + 1)\r
54#define PBIT 5\r
55//#define NT (CODE_BIT + 3)\r
56//#define TBIT 5\r
57//#if NT > NP\r
58//#define NPT NT\r
59//#else\r
60//#define NPT NP\r
61//#endif\r
62\r
63//\r
64// Global Variables\r
65//\r
66STATIC BOOLEAN ENCODE = FALSE;\r
67STATIC BOOLEAN DECODE = FALSE;\r
68STATIC UINT8 *mSrc, *mDst, *mSrcUpperLimit, *mDstUpperLimit;\r
69STATIC UINT8 *mLevel, *mText, *mChildCount, *mBuf, mCLen[NC], mPTLen[NPT], *mLen;\r
70STATIC INT16 mHeap[NC + 1];\r
71STATIC INT32 mRemainder, mMatchLen, mBitCount, mHeapSize, mN;\r
72STATIC UINT32 mBufSiz = 0, mOutputPos, mOutputMask, mSubBitBuf, mCrc;\r
73STATIC UINT32 mCompSize, mOrigSize;\r
74\r
75STATIC UINT16 *mFreq, *mSortPtr, mLenCnt[17], mLeft[2 * NC - 1], mRight[2 * NC - 1], mCrcTable[UINT8_MAX + 1],\r
76 mCFreq[2 * NC - 1], mCCode[NC], mPFreq[2 * NP - 1], mPTCode[NPT], mTFreq[2 * NT - 1];\r
77\r
78STATIC NODE mPos, mMatchPos, mAvail, *mPosition, *mParent, *mPrev, *mNext = NULL;\r
79\r
fd171542 80static UINT64 DebugLevel;\r
30fdf114
LG
81static BOOLEAN DebugMode;\r
82//\r
83// functions\r
84//\r
85EFI_STATUS\r
86TianoCompress (\r
87 IN UINT8 *SrcBuffer,\r
88 IN UINT32 SrcSize,\r
89 IN UINT8 *DstBuffer,\r
90 IN OUT UINT32 *DstSize\r
91 )\r
92/*++\r
93\r
94Routine Description:\r
95\r
96 The internal implementation of [Efi/Tiano]Compress().\r
97\r
98Arguments:\r
99\r
100 SrcBuffer - The buffer storing the source data\r
101 SrcSize - The size of source data\r
102 DstBuffer - The buffer to store the compressed data\r
103 \r
104 Version - The version of de/compression algorithm.\r
105 Version 1 for EFI 1.1 de/compression algorithm.\r
106 Version 2 for Tiano de/compression algorithm.\r
107\r
108Returns:\r
109\r
110 EFI_BUFFER_TOO_SMALL - The DstBuffer is too small. In this case,\r
111 DstSize contains the size needed.\r
112 EFI_SUCCESS - Compression is successful.\r
113 EFI_OUT_OF_RESOURCES - No resource to complete function.\r
114 EFI_INVALID_PARAMETER - Parameter supplied is wrong.\r
115\r
116--*/\r
117{\r
118 EFI_STATUS Status;\r
119\r
120 //\r
121 // Initializations\r
122 //\r
123 mBufSiz = 0;\r
124 mBuf = NULL;\r
125 mText = NULL;\r
126 mLevel = NULL;\r
127 mChildCount = NULL;\r
128 mPosition = NULL;\r
129 mParent = NULL;\r
130 mPrev = NULL;\r
131 mNext = NULL;\r
132\r
133\r
134 mSrc = SrcBuffer;\r
135 mSrcUpperLimit = mSrc + SrcSize;\r
136 mDst = DstBuffer;\r
137 mDstUpperLimit = mDst +*DstSize;\r
138 \r
139 PutDword (0L);\r
140 PutDword (0L);\r
141 \r
142 MakeCrcTable ();\r
143 \r
144 mOrigSize = mCompSize = 0;\r
145 mCrc = INIT_CRC;\r
146\r
147 //\r
148 // Compress it\r
149 //\r
150 Status = Encode ();\r
151 if (EFI_ERROR (Status)) {\r
152 return EFI_OUT_OF_RESOURCES;\r
153 }\r
154 \r
155 //\r
156 // Null terminate the compressed data\r
157 //\r
158\r
159 if (mDst < mDstUpperLimit) {\r
160 *mDst++ = 0;\r
161 }\r
162\r
163 //\r
164 // Fill in compressed size and original size\r
165 //\r
166 mDst = DstBuffer; \r
167 \r
168 PutDword (mCompSize + 1);\r
169 PutDword (mOrigSize);\r
170 //\r
171 // Return\r
172 //\r
173\r
174 if (mCompSize + 1 + 8 > *DstSize) {\r
175 *DstSize = mCompSize + 1 + 8; \r
fd171542 176 return EFI_BUFFER_TOO_SMALL;\r
177 } else {\r
30fdf114 178 *DstSize = mCompSize + 1 + 8; \r
fd171542 179 return EFI_SUCCESS;\r
180 }\r
30fdf114
LG
181}\r
182\r
183STATIC\r
184VOID\r
185PutDword (\r
186 IN UINT32 Data\r
187 )\r
188/*++\r
189\r
190Routine Description:\r
191\r
192 Put a dword to output stream\r
193 \r
194Arguments:\r
195\r
196 Data - the dword to put\r
197 \r
198Returns: (VOID)\r
199 \r
200--*/\r
201{\r
202 if (mDst < mDstUpperLimit) {\r
203 *mDst++ = (UINT8) (((UINT8) (Data)) & 0xff);\r
204 }\r
205\r
206 if (mDst < mDstUpperLimit) {\r
207 *mDst++ = (UINT8) (((UINT8) (Data >> 0x08)) & 0xff);\r
208 }\r
209\r
210 if (mDst < mDstUpperLimit) {\r
211 *mDst++ = (UINT8) (((UINT8) (Data >> 0x10)) & 0xff);\r
212 }\r
213\r
214 if (mDst < mDstUpperLimit) {\r
215 *mDst++ = (UINT8) (((UINT8) (Data >> 0x18)) & 0xff);\r
216 }\r
217}\r
218\r
219STATIC\r
220EFI_STATUS\r
221AllocateMemory (\r
222 VOID\r
223 )\r
224/*++\r
225\r
226Routine Description:\r
227\r
228 Allocate memory spaces for data structures used in compression process\r
229 \r
230Argements: \r
231 VOID\r
232\r
233Returns:\r
234\r
235 EFI_SUCCESS - Memory is allocated successfully\r
236 EFI_OUT_OF_RESOURCES - Allocation fails\r
237\r
238--*/\r
239{\r
240 UINT32 Index;\r
241\r
242 mText = malloc (WNDSIZ * 2 + MAXMATCH);\r
243 for (Index = 0; Index < WNDSIZ * 2 + MAXMATCH; Index++) {\r
244 mText[Index] = 0;\r
245 }\r
246\r
247 mLevel = malloc ((WNDSIZ + UINT8_MAX + 1) * sizeof (*mLevel));\r
248 mChildCount = malloc ((WNDSIZ + UINT8_MAX + 1) * sizeof (*mChildCount));\r
249 mPosition = malloc ((WNDSIZ + UINT8_MAX + 1) * sizeof (*mPosition));\r
250 mParent = malloc (WNDSIZ * 2 * sizeof (*mParent));\r
251 mPrev = malloc (WNDSIZ * 2 * sizeof (*mPrev));\r
252 mNext = malloc ((MAX_HASH_VAL + 1) * sizeof (*mNext));\r
253\r
254 mBufSiz = BLKSIZ;\r
255 mBuf = malloc (mBufSiz);\r
256 while (mBuf == NULL) {\r
257 mBufSiz = (mBufSiz / 10U) * 9U;\r
258 if (mBufSiz < 4 * 1024U) {\r
259 return EFI_OUT_OF_RESOURCES;\r
260 }\r
261\r
262 mBuf = malloc (mBufSiz);\r
263 }\r
264\r
265 mBuf[0] = 0;\r
266\r
267 return EFI_SUCCESS;\r
268}\r
269\r
270VOID\r
271FreeMemory (\r
272 VOID\r
273 )\r
274/*++\r
275\r
276Routine Description:\r
277\r
278 Called when compression is completed to free memory previously allocated.\r
279 \r
280Arguments: (VOID)\r
281\r
282Returns: (VOID)\r
283\r
284--*/\r
285{\r
286 if (mText != NULL) {\r
287 free (mText);\r
288 }\r
289\r
290 if (mLevel != NULL) {\r
291 free (mLevel);\r
292 }\r
293\r
294 if (mChildCount != NULL) {\r
295 free (mChildCount);\r
296 }\r
297\r
298 if (mPosition != NULL) {\r
299 free (mPosition);\r
300 }\r
301\r
302 if (mParent != NULL) {\r
303 free (mParent);\r
304 }\r
305\r
306 if (mPrev != NULL) {\r
307 free (mPrev);\r
308 }\r
309\r
310 if (mNext != NULL) {\r
311 free (mNext);\r
312 }\r
313\r
314 if (mBuf != NULL) {\r
315 free (mBuf);\r
316 }\r
317\r
318 return ;\r
319}\r
320\r
321STATIC\r
322VOID\r
323InitSlide (\r
324 VOID\r
325 )\r
326/*++\r
327\r
328Routine Description:\r
329\r
330 Initialize String Info Log data structures\r
331 \r
332Arguments: (VOID)\r
333\r
334Returns: (VOID)\r
335\r
336--*/\r
337{\r
338 NODE Index;\r
339\r
340 for (Index = WNDSIZ; Index <= WNDSIZ + UINT8_MAX; Index++) {\r
341 mLevel[Index] = 1;\r
342 mPosition[Index] = NIL; // sentinel\r
343 }\r
344\r
345 for (Index = WNDSIZ; Index < WNDSIZ * 2; Index++) {\r
346 mParent[Index] = NIL;\r
347 }\r
348\r
349 mAvail = 1;\r
350 for (Index = 1; Index < WNDSIZ - 1; Index++) {\r
351 mNext[Index] = (NODE) (Index + 1);\r
352 }\r
353\r
354 mNext[WNDSIZ - 1] = NIL;\r
355 for (Index = WNDSIZ * 2; Index <= MAX_HASH_VAL; Index++) {\r
356 mNext[Index] = NIL;\r
357 }\r
358}\r
359\r
360STATIC\r
361NODE\r
362Child (\r
363 IN NODE NodeQ,\r
364 IN UINT8 CharC\r
365 )\r
366/*++\r
367\r
368Routine Description:\r
369\r
370 Find child node given the parent node and the edge character\r
371 \r
372Arguments:\r
373\r
374 NodeQ - the parent node\r
375 CharC - the edge character\r
376 \r
377Returns:\r
378\r
379 The child node (NIL if not found) \r
380 \r
381--*/\r
382{\r
383 NODE NodeR;\r
384\r
385 NodeR = mNext[HASH (NodeQ, CharC)];\r
386 //\r
387 // sentinel\r
388 //\r
389 mParent[NIL] = NodeQ;\r
390 while (mParent[NodeR] != NodeQ) {\r
391 NodeR = mNext[NodeR];\r
392 }\r
393\r
394 return NodeR;\r
395}\r
396\r
397STATIC\r
398VOID\r
399MakeChild (\r
400 IN NODE Parent,\r
401 IN UINT8 CharC,\r
402 IN NODE Child\r
403 )\r
404/*++\r
405\r
406Routine Description:\r
407\r
408 Create a new child for a given parent node.\r
409 \r
410Arguments:\r
411\r
412 Parent - the parent node\r
413 CharC - the edge character\r
414 Child - the child node\r
415 \r
416Returns: (VOID)\r
417\r
418--*/\r
419{\r
420 NODE Node1;\r
421 NODE Node2;\r
422\r
423 Node1 = (NODE) HASH (Parent, CharC);\r
424 Node2 = mNext[Node1];\r
425 mNext[Node1] = Child;\r
426 mNext[Child] = Node2;\r
427 mPrev[Node2] = Child;\r
428 mPrev[Child] = Node1;\r
429 mParent[Child] = Parent;\r
430 mChildCount[Parent]++;\r
431}\r
432\r
433STATIC\r
434VOID\r
435Split (\r
436 NODE Old\r
437 )\r
438/*++\r
439\r
440Routine Description:\r
441\r
442 Split a node.\r
443 \r
444Arguments:\r
445\r
446 Old - the node to split\r
447 \r
448Returns: (VOID)\r
449\r
450--*/\r
451{\r
452 NODE New;\r
453 NODE TempNode;\r
454\r
455 New = mAvail;\r
456 mAvail = mNext[New];\r
457 mChildCount[New] = 0;\r
458 TempNode = mPrev[Old];\r
459 mPrev[New] = TempNode;\r
460 mNext[TempNode] = New;\r
461 TempNode = mNext[Old];\r
462 mNext[New] = TempNode;\r
463 mPrev[TempNode] = New;\r
464 mParent[New] = mParent[Old];\r
465 mLevel[New] = (UINT8) mMatchLen;\r
466 mPosition[New] = mPos;\r
467 MakeChild (New, mText[mMatchPos + mMatchLen], Old);\r
468 MakeChild (New, mText[mPos + mMatchLen], mPos);\r
469}\r
470\r
471STATIC\r
472VOID\r
473InsertNode (\r
474 VOID\r
475 )\r
476/*++\r
477\r
478Routine Description:\r
479\r
480 Insert string info for current position into the String Info Log\r
481 \r
482Arguments: (VOID)\r
483\r
484Returns: (VOID)\r
485\r
486--*/\r
487{\r
488 NODE NodeQ;\r
489 NODE NodeR;\r
490 NODE Index2;\r
491 NODE NodeT;\r
492 UINT8 CharC;\r
493 UINT8 *t1;\r
494 UINT8 *t2;\r
495\r
496 if (mMatchLen >= 4) {\r
497 //\r
498 // We have just got a long match, the target tree\r
499 // can be located by MatchPos + 1. Travese the tree\r
500 // from bottom up to get to a proper starting point.\r
501 // The usage of PERC_FLAG ensures proper node deletion\r
502 // in DeleteNode() later.\r
503 //\r
504 mMatchLen--;\r
505 NodeR = (NODE) ((mMatchPos + 1) | WNDSIZ);\r
506 NodeQ = mParent[NodeR];\r
507 while (NodeQ == NIL) {\r
508 NodeR = mNext[NodeR];\r
509 NodeQ = mParent[NodeR];\r
510 }\r
511\r
512 while (mLevel[NodeQ] >= mMatchLen) {\r
513 NodeR = NodeQ;\r
514 NodeQ = mParent[NodeQ];\r
515 }\r
516\r
517 NodeT = NodeQ;\r
518 while (mPosition[NodeT] < 0) {\r
519 mPosition[NodeT] = mPos;\r
520 NodeT = mParent[NodeT];\r
521 }\r
522\r
523 if (NodeT < WNDSIZ) {\r
524 mPosition[NodeT] = (NODE) (mPos | (UINT32) PERC_FLAG);\r
525 }\r
526 } else {\r
527 //\r
528 // Locate the target tree\r
529 //\r
530 NodeQ = (NODE) (mText[mPos] + WNDSIZ);\r
531 CharC = mText[mPos + 1];\r
532 NodeR = Child (NodeQ, CharC);\r
533 if (NodeR == NIL) {\r
534 MakeChild (NodeQ, CharC, mPos);\r
535 mMatchLen = 1;\r
536 return ;\r
537 }\r
538\r
539 mMatchLen = 2;\r
540 }\r
541 //\r
542 // Traverse down the tree to find a match.\r
543 // Update Position value along the route.\r
544 // Node split or creation is involved.\r
545 //\r
546 for (;;) {\r
547 if (NodeR >= WNDSIZ) {\r
548 Index2 = MAXMATCH;\r
549 mMatchPos = NodeR;\r
550 } else {\r
551 Index2 = mLevel[NodeR];\r
552 mMatchPos = (NODE) (mPosition[NodeR] & (UINT32)~PERC_FLAG);\r
553 }\r
554\r
555 if (mMatchPos >= mPos) {\r
556 mMatchPos -= WNDSIZ;\r
557 }\r
558\r
559 t1 = &mText[mPos + mMatchLen];\r
560 t2 = &mText[mMatchPos + mMatchLen];\r
561 while (mMatchLen < Index2) {\r
562 if (*t1 != *t2) {\r
563 Split (NodeR);\r
564 return ;\r
565 }\r
566\r
567 mMatchLen++;\r
568 t1++;\r
569 t2++;\r
570 }\r
571\r
572 if (mMatchLen >= MAXMATCH) {\r
573 break;\r
574 }\r
575\r
576 mPosition[NodeR] = mPos;\r
577 NodeQ = NodeR;\r
578 NodeR = Child (NodeQ, *t1);\r
579 if (NodeR == NIL) {\r
580 MakeChild (NodeQ, *t1, mPos);\r
581 return ;\r
582 }\r
583\r
584 mMatchLen++;\r
585 }\r
586\r
587 NodeT = mPrev[NodeR];\r
588 mPrev[mPos] = NodeT;\r
589 mNext[NodeT] = mPos;\r
590 NodeT = mNext[NodeR];\r
591 mNext[mPos] = NodeT;\r
592 mPrev[NodeT] = mPos;\r
593 mParent[mPos] = NodeQ;\r
594 mParent[NodeR] = NIL;\r
595\r
596 //\r
597 // Special usage of 'next'\r
598 //\r
599 mNext[NodeR] = mPos;\r
600\r
601}\r
602\r
603STATIC\r
604VOID\r
605DeleteNode (\r
606 VOID\r
607 )\r
608/*++\r
609\r
610Routine Description:\r
611\r
612 Delete outdated string info. (The Usage of PERC_FLAG\r
613 ensures a clean deletion)\r
614 \r
615Arguments: (VOID)\r
616\r
617Returns: (VOID)\r
618\r
619--*/\r
620{\r
621 NODE NodeQ;\r
622 NODE NodeR;\r
623 NODE NodeS;\r
624 NODE NodeT;\r
625 NODE NodeU;\r
626\r
627 if (mParent[mPos] == NIL) {\r
628 return ;\r
629 }\r
630\r
631 NodeR = mPrev[mPos];\r
632 NodeS = mNext[mPos];\r
633 mNext[NodeR] = NodeS;\r
634 mPrev[NodeS] = NodeR;\r
635 NodeR = mParent[mPos];\r
636 mParent[mPos] = NIL;\r
637 if (NodeR >= WNDSIZ) {\r
638 return ;\r
639 }\r
640\r
641 mChildCount[NodeR]--;\r
642 if (mChildCount[NodeR] > 1) {\r
643 return ;\r
644 }\r
645\r
646 NodeT = (NODE) (mPosition[NodeR] & (UINT32)~PERC_FLAG);\r
647 if (NodeT >= mPos) {\r
648 NodeT -= WNDSIZ;\r
649 }\r
650\r
651 NodeS = NodeT;\r
652 NodeQ = mParent[NodeR];\r
653 NodeU = mPosition[NodeQ];\r
654 while (NodeU & (UINT32) PERC_FLAG) {\r
655 NodeU &= (UINT32)~PERC_FLAG;\r
656 if (NodeU >= mPos) {\r
657 NodeU -= WNDSIZ;\r
658 }\r
659\r
660 if (NodeU > NodeS) {\r
661 NodeS = NodeU;\r
662 }\r
663\r
664 mPosition[NodeQ] = (NODE) (NodeS | WNDSIZ);\r
665 NodeQ = mParent[NodeQ];\r
666 NodeU = mPosition[NodeQ];\r
667 }\r
668\r
669 if (NodeQ < WNDSIZ) {\r
670 if (NodeU >= mPos) {\r
671 NodeU -= WNDSIZ;\r
672 }\r
673\r
674 if (NodeU > NodeS) {\r
675 NodeS = NodeU;\r
676 }\r
677\r
678 mPosition[NodeQ] = (NODE) (NodeS | WNDSIZ | (UINT32) PERC_FLAG);\r
679 }\r
680\r
681 NodeS = Child (NodeR, mText[NodeT + mLevel[NodeR]]);\r
682 NodeT = mPrev[NodeS];\r
683 NodeU = mNext[NodeS];\r
684 mNext[NodeT] = NodeU;\r
685 mPrev[NodeU] = NodeT;\r
686 NodeT = mPrev[NodeR];\r
687 mNext[NodeT] = NodeS;\r
688 mPrev[NodeS] = NodeT;\r
689 NodeT = mNext[NodeR];\r
690 mPrev[NodeT] = NodeS;\r
691 mNext[NodeS] = NodeT;\r
692 mParent[NodeS] = mParent[NodeR];\r
693 mParent[NodeR] = NIL;\r
694 mNext[NodeR] = mAvail;\r
695 mAvail = NodeR;\r
696}\r
697\r
698STATIC\r
699VOID\r
700GetNextMatch (\r
701 VOID\r
702 )\r
703/*++\r
704\r
705Routine Description:\r
706\r
707 Advance the current position (read in new data if needed).\r
708 Delete outdated string info. Find a match string for current position.\r
709\r
710Arguments: (VOID)\r
711\r
712Returns: (VOID)\r
713\r
714--*/\r
715{\r
716 INT32 Number;\r
717\r
718 mRemainder--;\r
719 mPos++;\r
720 if (mPos == WNDSIZ * 2) {\r
721 memmove (&mText[0], &mText[WNDSIZ], WNDSIZ + MAXMATCH);\r
722 Number = FreadCrc (&mText[WNDSIZ + MAXMATCH], WNDSIZ);\r
723 mRemainder += Number;\r
724 mPos = WNDSIZ;\r
725 }\r
726\r
727 DeleteNode ();\r
728 InsertNode ();\r
729}\r
730\r
731STATIC\r
732EFI_STATUS\r
733Encode (\r
734 VOID\r
735 )\r
736/*++\r
737\r
738Routine Description:\r
739\r
740 The main controlling routine for compression process.\r
741\r
742Arguments: (VOID)\r
743\r
744Returns:\r
745 \r
746 EFI_SUCCESS - The compression is successful\r
747 EFI_OUT_0F_RESOURCES - Not enough memory for compression process\r
748\r
749--*/\r
750{\r
751 EFI_STATUS Status;\r
752 INT32 LastMatchLen;\r
753 NODE LastMatchPos;\r
754\r
755 Status = AllocateMemory ();\r
756 if (EFI_ERROR (Status)) {\r
757 FreeMemory ();\r
758 return Status;\r
759 }\r
760\r
761 InitSlide ();\r
762\r
763 HufEncodeStart ();\r
764\r
765 mRemainder = FreadCrc (&mText[WNDSIZ], WNDSIZ + MAXMATCH);\r
766\r
767 mMatchLen = 0;\r
768 mPos = WNDSIZ;\r
769 InsertNode ();\r
770 if (mMatchLen > mRemainder) {\r
771 mMatchLen = mRemainder;\r
772 }\r
773\r
774 while (mRemainder > 0) {\r
775 LastMatchLen = mMatchLen;\r
776 LastMatchPos = mMatchPos;\r
777 GetNextMatch ();\r
778 if (mMatchLen > mRemainder) {\r
779 mMatchLen = mRemainder;\r
780 }\r
781\r
782 if (mMatchLen > LastMatchLen || LastMatchLen < THRESHOLD) {\r
783 //\r
784 // Not enough benefits are gained by outputting a pointer,\r
785 // so just output the original character\r
786 //\r
787 Output (mText[mPos - 1], 0);\r
788\r
789 } else {\r
790\r
791 if (LastMatchLen == THRESHOLD) {\r
792 if (((mPos - LastMatchPos - 2) & (WNDSIZ - 1)) > (1U << 11)) {\r
793 Output (mText[mPos - 1], 0);\r
794 continue;\r
795 }\r
796 }\r
797 //\r
798 // Outputting a pointer is beneficial enough, do it.\r
799 //\r
800 Output (\r
801 LastMatchLen + (UINT8_MAX + 1 - THRESHOLD),\r
802 (mPos - LastMatchPos - 2) & (WNDSIZ - 1)\r
803 );\r
804 LastMatchLen--;\r
805 while (LastMatchLen > 0) {\r
806 GetNextMatch ();\r
807 LastMatchLen--;\r
808 }\r
809\r
810 if (mMatchLen > mRemainder) {\r
811 mMatchLen = mRemainder;\r
812 }\r
813 }\r
814 }\r
815\r
816 HufEncodeEnd ();\r
817 FreeMemory ();\r
818 return EFI_SUCCESS;\r
819}\r
820\r
821STATIC\r
822VOID\r
823CountTFreq (\r
824 VOID\r
825 )\r
826/*++\r
827\r
828Routine Description:\r
829\r
830 Count the frequencies for the Extra Set\r
831 \r
832Arguments: (VOID)\r
833\r
834Returns: (VOID)\r
835\r
836--*/\r
837{\r
838 INT32 Index;\r
839 INT32 Index3;\r
840 INT32 Number;\r
841 INT32 Count;\r
842\r
843 for (Index = 0; Index < NT; Index++) {\r
844 mTFreq[Index] = 0;\r
845 }\r
846\r
847 Number = NC;\r
848 while (Number > 0 && mCLen[Number - 1] == 0) {\r
849 Number--;\r
850 }\r
851\r
852 Index = 0;\r
853 while (Index < Number) {\r
854 Index3 = mCLen[Index++];\r
855 if (Index3 == 0) {\r
856 Count = 1;\r
857 while (Index < Number && mCLen[Index] == 0) {\r
858 Index++;\r
859 Count++;\r
860 }\r
861\r
862 if (Count <= 2) {\r
863 mTFreq[0] = (UINT16) (mTFreq[0] + Count);\r
864 } else if (Count <= 18) {\r
865 mTFreq[1]++;\r
866 } else if (Count == 19) {\r
867 mTFreq[0]++;\r
868 mTFreq[1]++;\r
869 } else {\r
870 mTFreq[2]++;\r
871 }\r
872 } else {\r
873 mTFreq[Index3 + 2]++;\r
874 }\r
875 }\r
876}\r
877\r
878STATIC\r
879VOID\r
880WritePTLen (\r
881 IN INT32 Number,\r
882 IN INT32 nbit,\r
883 IN INT32 Special\r
884 )\r
885/*++\r
886\r
887Routine Description:\r
888\r
889 Outputs the code length array for the Extra Set or the Position Set.\r
890 \r
891Arguments:\r
892\r
893 Number - the number of symbols\r
894 nbit - the number of bits needed to represent 'n'\r
895 Special - the special symbol that needs to be take care of\r
896 \r
897Returns: (VOID)\r
898\r
899--*/\r
900{\r
901 INT32 Index;\r
902 INT32 Index3;\r
903\r
904 while (Number > 0 && mPTLen[Number - 1] == 0) {\r
905 Number--;\r
906 }\r
907\r
908 PutBits (nbit, Number);\r
909 Index = 0;\r
910 while (Index < Number) {\r
911 Index3 = mPTLen[Index++];\r
912 if (Index3 <= 6) {\r
913 PutBits (3, Index3);\r
914 } else {\r
915 PutBits (Index3 - 3, (1U << (Index3 - 3)) - 2);\r
916 }\r
917\r
918 if (Index == Special) {\r
919 while (Index < 6 && mPTLen[Index] == 0) {\r
920 Index++;\r
921 }\r
922\r
923 PutBits (2, (Index - 3) & 3);\r
924 }\r
925 }\r
926}\r
927\r
928STATIC\r
929VOID\r
930WriteCLen (\r
931 VOID\r
932 )\r
933/*++\r
934\r
935Routine Description:\r
936\r
937 Outputs the code length array for Char&Length Set\r
938 \r
939Arguments: (VOID)\r
940\r
941Returns: (VOID)\r
942\r
943--*/\r
944{\r
945 INT32 Index;\r
946 INT32 Index3;\r
947 INT32 Number;\r
948 INT32 Count;\r
949\r
950 Number = NC;\r
951 while (Number > 0 && mCLen[Number - 1] == 0) {\r
952 Number--;\r
953 }\r
954\r
955 PutBits (CBIT, Number);\r
956 Index = 0;\r
957 while (Index < Number) {\r
958 Index3 = mCLen[Index++];\r
959 if (Index3 == 0) {\r
960 Count = 1;\r
961 while (Index < Number && mCLen[Index] == 0) {\r
962 Index++;\r
963 Count++;\r
964 }\r
965\r
966 if (Count <= 2) {\r
967 for (Index3 = 0; Index3 < Count; Index3++) {\r
968 PutBits (mPTLen[0], mPTCode[0]);\r
969 }\r
970 } else if (Count <= 18) {\r
971 PutBits (mPTLen[1], mPTCode[1]);\r
972 PutBits (4, Count - 3);\r
973 } else if (Count == 19) {\r
974 PutBits (mPTLen[0], mPTCode[0]);\r
975 PutBits (mPTLen[1], mPTCode[1]);\r
976 PutBits (4, 15);\r
977 } else {\r
978 PutBits (mPTLen[2], mPTCode[2]);\r
979 PutBits (CBIT, Count - 20);\r
980 }\r
981 } else {\r
982 PutBits (mPTLen[Index3 + 2], mPTCode[Index3 + 2]);\r
983 }\r
984 }\r
985}\r
986\r
987STATIC\r
988VOID\r
989EncodeC (\r
990 IN INT32 Value\r
991 )\r
992{\r
993 PutBits (mCLen[Value], mCCode[Value]);\r
994}\r
995\r
996STATIC\r
997VOID\r
998EncodeP (\r
999 IN UINT32 Value\r
1000 )\r
1001{\r
1002 UINT32 Index;\r
1003 UINT32 NodeQ;\r
1004\r
1005 Index = 0;\r
1006 NodeQ = Value;\r
1007 while (NodeQ) {\r
1008 NodeQ >>= 1;\r
1009 Index++;\r
1010 }\r
1011\r
1012 PutBits (mPTLen[Index], mPTCode[Index]);\r
1013 if (Index > 1) {\r
1014 PutBits (Index - 1, Value & (0xFFFFFFFFU >> (32 - Index + 1)));\r
1015 }\r
1016}\r
1017\r
1018STATIC\r
1019VOID\r
1020SendBlock (\r
1021 VOID\r
1022 )\r
1023/*++\r
1024\r
1025Routine Description:\r
1026\r
1027 Huffman code the block and output it.\r
1028 \r
1029Arguments: \r
1030 (VOID)\r
1031\r
1032Returns: \r
1033 (VOID)\r
1034\r
1035--*/\r
1036{\r
1037 UINT32 Index;\r
1038 UINT32 Index2;\r
1039 UINT32 Index3;\r
1040 UINT32 Flags;\r
1041 UINT32 Root;\r
1042 UINT32 Pos;\r
1043 UINT32 Size;\r
1044 Flags = 0;\r
1045\r
1046 Root = MakeTree (NC, mCFreq, mCLen, mCCode);\r
1047 Size = mCFreq[Root];\r
1048\r
1049 PutBits (16, Size);\r
1050 if (Root >= NC) {\r
1051 CountTFreq ();\r
1052 Root = MakeTree (NT, mTFreq, mPTLen, mPTCode);\r
1053 if (Root >= NT) {\r
1054 WritePTLen (NT, TBIT, 3);\r
1055 } else {\r
1056 PutBits (TBIT, 0);\r
1057 PutBits (TBIT, Root);\r
1058 }\r
1059\r
1060 WriteCLen ();\r
1061 } else {\r
1062 PutBits (TBIT, 0);\r
1063 PutBits (TBIT, 0);\r
1064 PutBits (CBIT, 0);\r
1065 PutBits (CBIT, Root);\r
1066 }\r
1067\r
1068 Root = MakeTree (NP, mPFreq, mPTLen, mPTCode);\r
1069 if (Root >= NP) {\r
1070 WritePTLen (NP, PBIT, -1);\r
1071 } else {\r
1072 PutBits (PBIT, 0);\r
1073 PutBits (PBIT, Root);\r
1074 }\r
1075\r
1076 Pos = 0;\r
1077 for (Index = 0; Index < Size; Index++) {\r
1078 if (Index % UINT8_BIT == 0) {\r
1079 Flags = mBuf[Pos++];\r
1080 } else {\r
1081 Flags <<= 1;\r
1082 }\r
1083\r
1084 if (Flags & (1U << (UINT8_BIT - 1))) {\r
1085 EncodeC (mBuf[Pos++] + (1U << UINT8_BIT));\r
1086 Index3 = mBuf[Pos++];\r
1087 for (Index2 = 0; Index2 < 3; Index2++) {\r
1088 Index3 <<= UINT8_BIT;\r
1089 Index3 += mBuf[Pos++];\r
1090 }\r
1091\r
1092 EncodeP (Index3);\r
1093 } else {\r
1094 EncodeC (mBuf[Pos++]);\r
1095 }\r
1096 }\r
1097\r
1098 for (Index = 0; Index < NC; Index++) {\r
1099 mCFreq[Index] = 0;\r
1100 }\r
1101\r
1102 for (Index = 0; Index < NP; Index++) {\r
1103 mPFreq[Index] = 0;\r
1104 }\r
1105}\r
1106\r
1107STATIC\r
1108VOID\r
1109Output (\r
1110 IN UINT32 CharC,\r
1111 IN UINT32 Pos\r
1112 )\r
1113/*++\r
1114\r
1115Routine Description:\r
1116\r
1117 Outputs an Original Character or a Pointer\r
1118\r
1119Arguments:\r
1120\r
1121 CharC - The original character or the 'String Length' element of a Pointer\r
1122 Pos - The 'Position' field of a Pointer\r
1123\r
1124Returns: (VOID)\r
1125\r
1126--*/\r
1127{\r
1128 STATIC UINT32 CPos;\r
1129\r
1130 if ((mOutputMask >>= 1) == 0) {\r
1131 mOutputMask = 1U << (UINT8_BIT - 1);\r
1132 //\r
1133 // Check the buffer overflow per outputing UINT8_BIT symbols\r
1134 // which is an Original Character or a Pointer. The biggest\r
1135 // symbol is a Pointer which occupies 5 bytes.\r
1136 //\r
1137 if (mOutputPos >= mBufSiz - 5 * UINT8_BIT) {\r
1138 SendBlock ();\r
1139 mOutputPos = 0;\r
1140 }\r
1141\r
1142 CPos = mOutputPos++;\r
1143 mBuf[CPos] = 0;\r
1144 }\r
1145\r
1146 mBuf[mOutputPos++] = (UINT8) CharC;\r
1147 mCFreq[CharC]++;\r
1148 if (CharC >= (1U << UINT8_BIT)) {\r
1149 mBuf[CPos] |= mOutputMask;\r
1150 mBuf[mOutputPos++] = (UINT8) (Pos >> 24);\r
1151 mBuf[mOutputPos++] = (UINT8) (Pos >> 16);\r
1152 mBuf[mOutputPos++] = (UINT8) (Pos >> (UINT8_BIT));\r
1153 mBuf[mOutputPos++] = (UINT8) Pos;\r
1154 CharC = 0;\r
1155 while (Pos) {\r
1156 Pos >>= 1;\r
1157 CharC++;\r
1158 }\r
1159\r
1160 mPFreq[CharC]++;\r
1161 }\r
1162}\r
1163\r
1164STATIC\r
1165VOID\r
1166HufEncodeStart (\r
1167 VOID\r
1168 )\r
1169{\r
1170 INT32 Index;\r
1171\r
1172 for (Index = 0; Index < NC; Index++) {\r
1173 mCFreq[Index] = 0;\r
1174 }\r
1175\r
1176 for (Index = 0; Index < NP; Index++) {\r
1177 mPFreq[Index] = 0;\r
1178 }\r
1179\r
1180 mOutputPos = mOutputMask = 0;\r
1181 InitPutBits ();\r
1182 return ;\r
1183}\r
1184\r
1185STATIC\r
1186VOID\r
1187HufEncodeEnd (\r
1188 VOID\r
1189 )\r
1190{\r
1191 SendBlock ();\r
1192\r
1193 //\r
1194 // Flush remaining bits\r
1195 //\r
1196 PutBits (UINT8_BIT - 1, 0);\r
1197\r
1198 return ;\r
1199}\r
1200\r
1201STATIC\r
1202VOID\r
1203MakeCrcTable (\r
1204 VOID\r
1205 )\r
1206{\r
1207 UINT32 Index;\r
1208 UINT32 Index2;\r
1209 UINT32 Temp;\r
1210\r
1211 for (Index = 0; Index <= UINT8_MAX; Index++) {\r
1212 Temp = Index;\r
1213 for (Index2 = 0; Index2 < UINT8_BIT; Index2++) {\r
1214 if (Temp & 1) {\r
1215 Temp = (Temp >> 1) ^ CRCPOLY;\r
1216 } else {\r
1217 Temp >>= 1;\r
1218 }\r
1219 }\r
1220\r
1221 mCrcTable[Index] = (UINT16) Temp;\r
1222 }\r
1223}\r
1224\r
1225STATIC\r
1226VOID\r
1227PutBits (\r
1228 IN INT32 Number,\r
1229 IN UINT32 Value\r
1230 )\r
1231/*++\r
1232\r
1233Routine Description:\r
1234\r
1235 Outputs rightmost n bits of x\r
1236\r
1237Arguments:\r
1238\r
1239 Number - the rightmost n bits of the data is used\r
1240 x - the data \r
1241\r
1242Returns: (VOID)\r
1243\r
1244--*/\r
1245{\r
1246 UINT8 Temp;\r
1247\r
1248 while (Number >= mBitCount) {\r
1249 //\r
1250 // Number -= mBitCount should never equal to 32\r
1251 //\r
1252 Temp = (UINT8) (mSubBitBuf | (Value >> (Number -= mBitCount)));\r
1253\r
1254 if (mDst < mDstUpperLimit) {\r
1255 *mDst++ = Temp;\r
1256 }\r
1257\r
1258 mCompSize++;\r
1259 mSubBitBuf = 0;\r
1260 mBitCount = UINT8_BIT;\r
1261 }\r
1262\r
1263 mSubBitBuf |= Value << (mBitCount -= Number);\r
1264}\r
1265\r
1266STATIC\r
1267INT32\r
1268FreadCrc (\r
1269 OUT UINT8 *Pointer,\r
1270 IN INT32 Number\r
1271 )\r
1272/*++\r
1273\r
1274Routine Description:\r
1275\r
1276 Read in source data\r
1277 \r
1278Arguments:\r
1279\r
1280 Pointer - the buffer to hold the data\r
1281 Number - number of bytes to read\r
1282\r
1283Returns:\r
1284\r
1285 number of bytes actually read\r
1286 \r
1287--*/\r
1288{\r
1289 INT32 Index;\r
1290\r
1291 for (Index = 0; mSrc < mSrcUpperLimit && Index < Number; Index++) {\r
1292 *Pointer++ = *mSrc++;\r
1293 }\r
1294\r
1295 Number = Index;\r
1296\r
1297 Pointer -= Number;\r
1298 mOrigSize += Number;\r
1299\r
1300 Index--;\r
1301 while (Index >= 0) {\r
1302 UPDATE_CRC (*Pointer++);\r
1303 Index--;\r
1304 }\r
1305\r
1306 return Number;\r
1307}\r
1308\r
1309STATIC\r
1310VOID\r
1311InitPutBits (\r
1312 VOID\r
1313 )\r
1314{\r
1315 mBitCount = UINT8_BIT;\r
1316 mSubBitBuf = 0;\r
1317}\r
1318\r
1319STATIC\r
1320VOID\r
1321CountLen (\r
1322 IN INT32 Index\r
1323 )\r
1324/*++\r
1325\r
1326Routine Description:\r
1327\r
1328 Count the number of each code length for a Huffman tree.\r
1329 \r
1330Arguments:\r
1331\r
1332 Index - the top node\r
1333 \r
1334Returns: (VOID)\r
1335\r
1336--*/\r
1337{\r
1338 STATIC INT32 Depth = 0;\r
1339\r
1340 if (Index < mN) {\r
1341 mLenCnt[(Depth < 16) ? Depth : 16]++;\r
1342 } else {\r
1343 Depth++;\r
1344 CountLen (mLeft[Index]);\r
1345 CountLen (mRight[Index]);\r
1346 Depth--;\r
1347 }\r
1348}\r
1349\r
1350STATIC\r
1351VOID\r
1352MakeLen (\r
1353 IN INT32 Root\r
1354 )\r
1355/*++\r
1356\r
1357Routine Description:\r
1358\r
1359 Create code length array for a Huffman tree\r
1360 \r
1361Arguments:\r
1362\r
1363 Root - the root of the tree\r
1364 \r
1365Returns:\r
1366\r
1367 VOID\r
1368\r
1369--*/\r
1370{\r
1371 INT32 Index;\r
1372 INT32 Index3;\r
1373 UINT32 Cum;\r
1374\r
1375 for (Index = 0; Index <= 16; Index++) {\r
1376 mLenCnt[Index] = 0;\r
1377 }\r
1378\r
1379 CountLen (Root);\r
1380\r
1381 //\r
1382 // Adjust the length count array so that\r
1383 // no code will be generated longer than its designated length\r
1384 //\r
1385 Cum = 0;\r
1386 for (Index = 16; Index > 0; Index--) {\r
1387 Cum += mLenCnt[Index] << (16 - Index);\r
1388 }\r
1389\r
1390 while (Cum != (1U << 16)) {\r
1391 mLenCnt[16]--;\r
1392 for (Index = 15; Index > 0; Index--) {\r
1393 if (mLenCnt[Index] != 0) {\r
1394 mLenCnt[Index]--;\r
1395 mLenCnt[Index + 1] += 2;\r
1396 break;\r
1397 }\r
1398 }\r
1399\r
1400 Cum--;\r
1401 }\r
1402\r
1403 for (Index = 16; Index > 0; Index--) {\r
1404 Index3 = mLenCnt[Index];\r
1405 Index3--;\r
1406 while (Index3 >= 0) {\r
1407 mLen[*mSortPtr++] = (UINT8) Index;\r
1408 Index3--;\r
1409 }\r
1410 }\r
1411}\r
1412\r
1413STATIC\r
1414VOID\r
1415DownHeap (\r
1416 IN INT32 Index\r
1417 )\r
1418{\r
1419 INT32 Index2;\r
1420 INT32 Index3;\r
1421\r
1422 //\r
1423 // priority queue: send Index-th entry down heap\r
1424 //\r
1425 Index3 = mHeap[Index];\r
1426 Index2 = 2 * Index;\r
1427 while (Index2 <= mHeapSize) {\r
1428 if (Index2 < mHeapSize && mFreq[mHeap[Index2]] > mFreq[mHeap[Index2 + 1]]) {\r
1429 Index2++;\r
1430 }\r
1431\r
1432 if (mFreq[Index3] <= mFreq[mHeap[Index2]]) {\r
1433 break;\r
1434 }\r
1435\r
1436 mHeap[Index] = mHeap[Index2];\r
1437 Index = Index2;\r
1438 Index2 = 2 * Index;\r
1439 }\r
1440\r
1441 mHeap[Index] = (INT16) Index3;\r
1442}\r
1443\r
1444STATIC\r
1445VOID\r
1446MakeCode (\r
1447 IN INT32 Number,\r
1448 IN UINT8 Len[ ],\r
1449 OUT UINT16 Code[]\r
1450 )\r
1451/*++\r
1452\r
1453Routine Description:\r
1454\r
1455 Assign code to each symbol based on the code length array\r
1456 \r
1457Arguments:\r
1458\r
1459 Number - number of symbols\r
1460 Len - the code length array\r
1461 Code - stores codes for each symbol\r
1462\r
1463Returns: (VOID)\r
1464\r
1465--*/\r
1466{\r
1467 INT32 Index;\r
1468 UINT16 Start[18];\r
1469\r
1470 Start[1] = 0;\r
1471 for (Index = 1; Index <= 16; Index++) {\r
1472 Start[Index + 1] = (UINT16) ((Start[Index] + mLenCnt[Index]) << 1);\r
1473 }\r
1474\r
1475 for (Index = 0; Index < Number; Index++) {\r
1476 Code[Index] = Start[Len[Index]]++;\r
1477 }\r
1478}\r
1479\r
1480STATIC\r
1481INT32\r
1482MakeTree (\r
1483 IN INT32 NParm,\r
1484 IN UINT16 FreqParm[],\r
1485 OUT UINT8 LenParm[ ],\r
1486 OUT UINT16 CodeParm[]\r
1487 )\r
1488/*++\r
1489\r
1490Routine Description:\r
1491\r
1492 Generates Huffman codes given a frequency distribution of symbols\r
1493 \r
1494Arguments:\r
1495\r
1496 NParm - number of symbols\r
1497 FreqParm - frequency of each symbol\r
1498 LenParm - code length for each symbol\r
1499 CodeParm - code for each symbol\r
1500 \r
1501Returns:\r
1502\r
1503 Root of the Huffman tree.\r
1504 \r
1505--*/\r
1506{\r
1507 INT32 Index;\r
1508 INT32 Index2;\r
1509 INT32 Index3;\r
1510 INT32 Avail;\r
1511\r
1512 //\r
1513 // make tree, calculate len[], return root\r
1514 //\r
1515 mN = NParm;\r
1516 mFreq = FreqParm;\r
1517 mLen = LenParm;\r
1518 Avail = mN;\r
1519 mHeapSize = 0;\r
1520 mHeap[1] = 0;\r
1521 for (Index = 0; Index < mN; Index++) {\r
1522 mLen[Index] = 0;\r
1523 if (mFreq[Index]) {\r
1524 mHeapSize++;\r
1525 mHeap[mHeapSize] = (INT16) Index;\r
1526 }\r
1527 }\r
1528\r
1529 if (mHeapSize < 2) {\r
1530 CodeParm[mHeap[1]] = 0;\r
1531 return mHeap[1];\r
1532 }\r
1533\r
1534 for (Index = mHeapSize / 2; Index >= 1; Index--) {\r
1535 //\r
1536 // make priority queue\r
1537 //\r
1538 DownHeap (Index);\r
1539 }\r
1540\r
1541 mSortPtr = CodeParm;\r
1542 do {\r
1543 Index = mHeap[1];\r
1544 if (Index < mN) {\r
1545 *mSortPtr++ = (UINT16) Index;\r
1546 }\r
1547\r
1548 mHeap[1] = mHeap[mHeapSize--];\r
1549 DownHeap (1);\r
1550 Index2 = mHeap[1];\r
1551 if (Index2 < mN) {\r
1552 *mSortPtr++ = (UINT16) Index2;\r
1553 }\r
1554\r
1555 Index3 = Avail++;\r
1556 mFreq[Index3] = (UINT16) (mFreq[Index] + mFreq[Index2]);\r
1557 mHeap[1] = (INT16) Index3;\r
1558 DownHeap (1);\r
1559 mLeft[Index3] = (UINT16) Index;\r
1560 mRight[Index3] = (UINT16) Index2;\r
1561 } while (mHeapSize > 1);\r
1562\r
1563 mSortPtr = CodeParm;\r
1564 MakeLen (Index3);\r
1565 MakeCode (NParm, LenParm, CodeParm);\r
1566\r
1567 //\r
1568 // return root\r
1569 //\r
1570 return Index3;\r
1571}\r
1572\r
1573EFI_STATUS\r
1574GetFileContents (\r
1575 IN char *InputFileName,\r
1576 OUT UINT8 *FileBuffer,\r
1577 OUT UINT32 *BufferLength\r
1578 )\r
1579/*++\r
1580 \r
1581Routine Description:\r
1582 \r
1583 Get the contents of file specified in InputFileName\r
1584 into FileBuffer.\r
1585 \r
1586Arguments:\r
1587 \r
1588 InputFileName - Name of the input file.\r
1589 \r
1590 FileBuffer - Output buffer to contain data\r
1591\r
1592 BufferLength - Actual length of the data \r
1593\r
1594Returns:\r
1595 \r
1596 EFI_SUCCESS on successful return\r
1597 EFI_ABORTED if unable to open input file.\r
1598\r
1599--*/\r
1600{\r
1601 UINTN Size;\r
1602 UINTN FileSize;\r
1603 FILE *InputFile;\r
1604\r
1605 Size = 0;\r
1606 //\r
1607 // Copy the file contents to the output buffer.\r
1608 //\r
97fa0ee9 1609 InputFile = fopen (LongFilePath (InputFileName), "rb");\r
30fdf114
LG
1610 if (InputFile == NULL) {\r
1611 Error (NULL, 0, 0001, "Error opening file: %s", InputFileName);\r
1612 return EFI_ABORTED;\r
1613 }\r
1614 \r
1615 fseek (InputFile, 0, SEEK_END);\r
1616 FileSize = ftell (InputFile);\r
1617 fseek (InputFile, 0, SEEK_SET);\r
1618 //\r
1619 // Now read the contents of the file into the buffer\r
1620 // \r
1621 if (FileSize > 0 && FileBuffer != NULL) {\r
1622 if (fread (FileBuffer, FileSize, 1, InputFile) != 1) {\r
1623 Error (NULL, 0, 0004, "Error reading contents of input file: %s", InputFileName);\r
1624 fclose (InputFile);\r
1625 return EFI_ABORTED;\r
1626 }\r
1627 }\r
1628\r
1629 fclose (InputFile);\r
1630 Size += (UINTN) FileSize;\r
1631 *BufferLength = Size;\r
1632 \r
1633 if (FileBuffer != NULL) {\r
1634 return EFI_SUCCESS;\r
1635 } else {\r
1636 return EFI_BUFFER_TOO_SMALL;\r
1637 }\r
1638}\r
1639\r
1640VOID\r
1641Version (\r
1642 VOID\r
1643 )\r
1644/*++\r
1645\r
1646Routine Description:\r
1647\r
1648 Displays the standard utility information to SDTOUT\r
1649\r
1650Arguments:\r
1651\r
1652 None\r
1653\r
1654Returns:\r
1655\r
1656 None\r
1657\r
1658--*/\r
1659{\r
b36d134f 1660 fprintf (stdout, "%s Version %d.%d %s \n", UTILITY_NAME, UTILITY_MAJOR_VERSION, UTILITY_MINOR_VERSION, __BUILD_VERSION);\r
30fdf114
LG
1661}\r
1662\r
1663VOID\r
1664Usage (\r
1665 VOID\r
1666 )\r
1667/*++\r
1668\r
1669Routine Description:\r
1670\r
1671 Displays the utility usage syntax to STDOUT\r
1672\r
1673Arguments:\r
1674\r
1675 None\r
1676\r
1677Returns:\r
1678\r
1679 None\r
1680\r
1681--*/\r
1682{\r
1683 //\r
1684 // Summary usage\r
1685 //\r
1686 fprintf (stdout, "Usage: %s -e|-d [options] <input_file>\n\n", UTILITY_NAME);\r
1687 \r
1688 //\r
1689 // Copyright declaration\r
1690 // \r
97fa0ee9 1691 fprintf (stdout, "Copyright (c) 2007 - 2014, Intel Corporation. All rights reserved.\n\n");\r
30fdf114
LG
1692\r
1693 //\r
1694 // Details Option\r
1695 //\r
1696 fprintf (stdout, "Options:\n");\r
1697 fprintf (stdout, " -o FileName, --output FileName\n\\r
1698 File will be created to store the ouput content.\n");\r
1699 fprintf (stdout, " -v, --verbose\n\\r
1700 Turn on verbose output with informational messages.\n");\r
1701 fprintf (stdout, " -q, --quiet\n\\r
1702 Disable all messages except key message and fatal error\n");\r
1703 fprintf (stdout, " --debug [0-9]\n\\r
1704 Enable debug messages, at input debug level.\n");\r
1705 fprintf (stdout, " --version\n\\r
1706 Show program's version number and exit.\n");\r
1707 fprintf (stdout, " -h, --help\n\\r
1708 Show this help message and exit.\n");\r
1709}\r
1710\r
1711\r
1712int\r
1713main (\r
1714 int argc,\r
1715 char *argv[]\r
1716 )\r
1717/*++\r
1718\r
1719Routine Description:\r
1720\r
1721 Main\r
1722\r
1723Arguments:\r
1724\r
1725 command line parameters\r
1726\r
1727Returns:\r
1728\r
1729 EFI_SUCCESS Section header successfully generated and section concatenated.\r
1730 EFI_ABORTED Could not generate the section\r
1731 EFI_OUT_OF_RESOURCES No resource to complete the operation.\r
1732\r
1733--*/ \r
1734{\r
1735 FILE *OutputFile;\r
1736 char *OutputFileName;\r
1737 char *InputFileName;\r
1738 FILE *InputFile;\r
1739 EFI_STATUS Status;\r
1740 UINT8 *FileBuffer;\r
1741 UINT8 *OutBuffer;\r
1742 UINT32 InputLength;\r
1743 UINT32 DstSize;\r
1744 SCRATCH_DATA *Scratch;\r
1745 UINT8 *Src;\r
1746 UINT32 OrigSize;\r
1747\r
1748 SetUtilityName(UTILITY_NAME);\r
1749 \r
1750 FileBuffer = NULL;\r
1751 Src = NULL;\r
1752 OutBuffer = NULL;\r
1753 Scratch = NULL;\r
1754 OrigSize = 0;\r
1755 InputLength = 0;\r
1756 InputFileName = NULL;\r
1757 OutputFileName = NULL;\r
1758 DstSize=0;\r
1759 DebugLevel = 0;\r
1760 DebugMode = FALSE;\r
1761\r
1762 //\r
1763 // Verify the correct number of arguments\r
1764 //\r
1765 if (argc == 1) {\r
1766 Error (NULL, 0, 1001, "Missing options", "No input options specified.");\r
1767 Usage();\r
1768 return 0;\r
1769 }\r
1770 \r
1771 if ((strcmp(argv[1], "-h") == 0) || (strcmp(argv[1], "--help") == 0)) {\r
1772 Usage();\r
1773 return 0;\r
1774 }\r
1775 \r
1776 if ((strcmp(argv[1], "--version") == 0)) {\r
1777 Version();\r
1778 return 0;\r
1779 }\r
1780\r
1781 argc--;\r
1782 argv++;\r
1783 if (strcmp(argv[0],"-e") == 0) {\r
1784 //\r
1785 // encode the input file\r
1786 //\r
1787 ENCODE = TRUE;\r
1788 argc--;\r
1789 argv++;\r
1790 } else if (strcmp(argv[0], "-d") == 0) {\r
1791 //\r
1792 // decode the input file\r
1793 //\r
1794 DECODE = TRUE;\r
1795 argc--;\r
1796 argv++;\r
1797 } else {\r
1798 //\r
1799 // Error command line\r
1800 //\r
1801 Error (NULL, 0, 1003, "Invalid option value", "the options specified are not recognized.");\r
1802 Usage();\r
1803 return 1;\r
1804 }\r
1805\r
1806 while (argc > 0) {\r
1807 if ((strcmp(argv[0], "-v") == 0) || (stricmp(argv[0], "--verbose") == 0)) {\r
1808 VerboseMode = TRUE;\r
1809 argc--;\r
1810 argv++;\r
1811 continue;\r
1812 }\r
1813\r
1814 if (stricmp (argv[0], "--debug") == 0) {\r
1815 argc-=2;\r
1816 argv++;\r
1817 Status = AsciiStringToUint64(argv[0], FALSE, &DebugLevel);\r
1818 if (DebugLevel > 9) {\r
1819 Error (NULL, 0 ,2000, "Invalid parameter", "Unrecognized argument %s", argv[0]);\r
1820 goto ERROR;\r
1821 }\r
1822 if (DebugLevel>=5 && DebugLevel <=9){\r
1823 DebugMode = TRUE;\r
1824 } else {\r
1825 DebugMode = FALSE;\r
1826 }\r
1827 argv++;\r
1828 continue;\r
1829 }\r
1830\r
1831 if ((strcmp(argv[0], "-q") == 0) || (stricmp (argv[0], "--quiet") == 0)) {\r
1832 QuietMode = TRUE;\r
1833 argc--;\r
1834 argv++;\r
1835 continue;\r
1836 }\r
1837\r
1838 if ((strcmp(argv[0], "-o") == 0) || (stricmp (argv[0], "--output") == 0)) {\r
1839 if (argv[1] == NULL || argv[1][0] == '-') {\r
1840 Error (NULL, 0, 1003, "Invalid option value", "Output File name is missing for -o option");\r
1841 goto ERROR;\r
1842 }\r
1843 OutputFileName = argv[1];\r
1844 argc -=2;\r
1845 argv +=2;\r
1846 continue; \r
1847 }\r
1848\r
1849 if (argv[0][0]!='-') {\r
1850 InputFileName = argv[0];\r
1851 argc--;\r
1852 argv++;\r
1853 continue;\r
1854 }\r
1855\r
1856 Error (NULL, 0, 1000, "Unknown option", argv[0]);\r
1857 goto ERROR; \r
1858 }\r
1859\r
1860 if (InputFileName == NULL) {\r
1861 Error (NULL, 0, 1001, "Missing options", "No input files specified.");\r
1862 goto ERROR;\r
1863 }\r
1864\r
1865//\r
1866// All Parameters has been parsed, now set the message print level\r
1867//\r
1868 if (QuietMode) {\r
1869 SetPrintLevel(40);\r
1870 } else if (VerboseMode) {\r
1871 SetPrintLevel(15);\r
1872 } else if (DebugMode) {\r
1873 SetPrintLevel(DebugLevel);\r
1874 }\r
1875 \r
1876 if (VerboseMode) {\r
1877 VerboseMsg("%s tool start.\n", UTILITY_NAME);\r
1878 }\r
1879 Scratch = (SCRATCH_DATA *)malloc(sizeof(SCRATCH_DATA));\r
1880 if (Scratch == NULL) {\r
1881 Error (NULL, 0, 4001, "Resource:", "Memory cannot be allocated!");\r
1882 goto ERROR;\r
1883 }\r
1884 \r
97fa0ee9 1885 InputFile = fopen (LongFilePath (InputFileName), "rb");\r
30fdf114
LG
1886 if (InputFile == NULL) {\r
1887 Error (NULL, 0, 0001, "Error opening input file", InputFileName);\r
1888 goto ERROR;\r
1889 }\r
1890 \r
1891 Status = GetFileContents(\r
1892 InputFileName,\r
1893 FileBuffer,\r
1894 &InputLength);\r
1895\r
1896 if (Status == EFI_BUFFER_TOO_SMALL) {\r
1897 FileBuffer = (UINT8 *) malloc (InputLength);\r
1898 if (FileBuffer == NULL) {\r
1899 Error (NULL, 0, 4001, "Resource:", "Memory cannot be allocated!");\r
1900 return 1;\r
1901 }\r
1902\r
1903 Status = GetFileContents (\r
1904 InputFileName,\r
1905 FileBuffer,\r
1906 &InputLength\r
1907 );\r
1908 }\r
1909\r
1910 if (EFI_ERROR(Status)) {\r
1911 free(FileBuffer);\r
1912 return 1;\r
1913 }\r
1914 \r
1915 if (OutputFileName != NULL) {\r
97fa0ee9 1916 OutputFile = fopen (LongFilePath (OutputFileName), "wb");\r
30fdf114
LG
1917 if (OutputFile == NULL) {\r
1918 Error (NULL, 0, 0001, "Error opening output file for writing", OutputFileName);\r
1919 if (InputFile != NULL) {\r
1920 fclose (InputFile);\r
1921 }\r
1922 goto ERROR;\r
1923 }\r
1924 } else {\r
1925 OutputFileName = DEFAULT_OUTPUT_FILE;\r
97fa0ee9 1926 OutputFile = fopen (LongFilePath (OutputFileName), "wb");\r
30fdf114
LG
1927 }\r
1928 \r
1929 if (ENCODE) {\r
1930 //\r
1931 // First call TianoCompress to get DstSize\r
1932 //\r
1933 if (DebugMode) {\r
1934 DebugMsg(UTILITY_NAME, 0, DebugLevel, "Encoding", NULL);\r
1935 }\r
1936 Status = TianoCompress ((UINT8 *)FileBuffer, InputLength, OutBuffer, &DstSize);\r
1937 \r
1938 if (Status == EFI_BUFFER_TOO_SMALL) {\r
1939 OutBuffer = (UINT8 *) malloc (DstSize);\r
1940 if (OutBuffer == NULL) {\r
1941 Error (NULL, 0, 4001, "Resource:", "Memory cannot be allocated!");\r
1942 goto ERROR;\r
1943 }\r
1944 }\r
1945 Status = TianoCompress ((UINT8 *)FileBuffer, InputLength, OutBuffer, &DstSize);\r
1946 if (Status != EFI_SUCCESS) {\r
1947 Error (NULL, 0, 0007, "Error compressing file", NULL);\r
1948 goto ERROR;\r
1949 }\r
1950\r
1951 fwrite(OutBuffer,(size_t)DstSize, 1, OutputFile);\r
1952 free(Scratch);\r
1953 free(FileBuffer);\r
1954 free(OutBuffer);\r
1955\r
1956 if (DebugMode) {\r
1957 DebugMsg(UTILITY_NAME, 0, DebugLevel, "Encoding Successful!\n", NULL);\r
1958 }\r
1959 if (VerboseMode) {\r
1960 VerboseMsg("Encoding successful\n");\r
1961 }\r
1962 return 0; \r
1963 }\r
1964 else if (DECODE) {\r
1965 if (DebugMode) {\r
1966 DebugMsg(UTILITY_NAME, 0, DebugLevel, "Decoding\n", NULL);\r
1967 }\r
1968 //\r
1969 // Get Compressed file original size\r
1970 // \r
1971 Src = (UINT8 *)FileBuffer; \r
1972 OrigSize = Src[4] + (Src[5] << 8) + (Src[6] << 16) + (Src[7] << 24); \r
1973 \r
1974 //\r
1975 // Allocate OutputBuffer\r
1976 //\r
1977 OutBuffer = (UINT8 *)malloc(OrigSize);\r
1978 if (OutBuffer == NULL) {\r
1979 Error (NULL, 0, 4001, "Resource:", "Memory cannot be allocated!");\r
1980 goto ERROR;\r
1981 } \r
1982\r
1983 Status = Decompress((VOID *)FileBuffer, (VOID *)OutBuffer, (VOID *)Scratch, 2);\r
1984 if (Status != EFI_SUCCESS) {\r
1985 goto ERROR; \r
1986 }\r
1987\r
1988 fwrite(OutBuffer, (size_t)(Scratch->mOrigSize), 1, OutputFile);\r
1989 free(Scratch);\r
1990 free(FileBuffer);\r
1991 free(OutBuffer);\r
1992\r
1993 if (DebugMode) {\r
1994 DebugMsg(UTILITY_NAME, 0, DebugLevel, "Encoding successful!\n", NULL);\r
1995 }\r
1996 \r
1997 if (VerboseMode) {\r
1998 VerboseMsg("Decoding successful\n");\r
1999 }\r
2000 return 0;\r
2001 }\r
2002 \r
2003ERROR:\r
2004 if (DebugMode) {\r
2005 if (ENCODE) {\r
2006 DebugMsg(UTILITY_NAME, 0, DebugLevel, "Encoding Error\n", NULL);\r
2007 } else if (DECODE) {\r
2008 DebugMsg(UTILITY_NAME, 0, DebugLevel, "Decoding Error\n", NULL);\r
2009 }\r
2010 }\r
2011 if (Scratch != NULL) {\r
2012 free(Scratch);\r
2013 }\r
2014 if (FileBuffer != NULL) {\r
2015 free(FileBuffer);\r
2016 }\r
2017 if (OutBuffer != NULL) {\r
2018 free(OutBuffer);\r
2019 }\r
2020 \r
2021 if (VerboseMode) {\r
2022 VerboseMsg("%s tool done with return code is 0x%x.\n", UTILITY_NAME, GetUtilityStatus ());\r
2023 }\r
2024 return GetUtilityStatus ();\r
2025}\r
2026\r
2027VOID\r
2028FillBuf (\r
2029 IN SCRATCH_DATA *Sd,\r
2030 IN UINT16 NumOfBits\r
2031 )\r
2032/*++\r
2033\r
2034Routine Description:\r
2035\r
2036 Shift mBitBuf NumOfBits left. Read in NumOfBits of bits from source.\r
2037\r
2038Arguments:\r
2039\r
2040 Sd - The global scratch data\r
2041 NumOfBits - The number of bits to shift and read.\r
2042\r
2043Returns: (VOID)\r
2044\r
2045--*/\r
2046{\r
2047 Sd->mBitBuf = (UINT32) (Sd->mBitBuf << NumOfBits);\r
2048\r
2049 while (NumOfBits > Sd->mBitCount) {\r
2050\r
2051 Sd->mBitBuf |= (UINT32) (Sd->mSubBitBuf << (NumOfBits = (UINT16) (NumOfBits - Sd->mBitCount)));\r
2052\r
2053 if (Sd->mCompSize > 0) {\r
2054 //\r
2055 // Get 1 byte into SubBitBuf\r
2056 //\r
2057 Sd->mCompSize--;\r
2058 Sd->mSubBitBuf = 0;\r
2059 Sd->mSubBitBuf = Sd->mSrcBase[Sd->mInBuf++];\r
2060 Sd->mBitCount = 8;\r
2061\r
2062 } else {\r
2063 //\r
2064 // No more bits from the source, just pad zero bit.\r
2065 //\r
2066 Sd->mSubBitBuf = 0;\r
2067 Sd->mBitCount = 8;\r
2068\r
2069 }\r
2070 }\r
2071\r
2072 Sd->mBitCount = (UINT16) (Sd->mBitCount - NumOfBits);\r
2073 Sd->mBitBuf |= Sd->mSubBitBuf >> Sd->mBitCount;\r
2074}\r
2075\r
2076UINT32\r
2077GetBits (\r
2078 IN SCRATCH_DATA *Sd,\r
2079 IN UINT16 NumOfBits\r
2080 )\r
2081/*++\r
2082\r
2083Routine Description:\r
2084\r
2085 Get NumOfBits of bits out from mBitBuf. Fill mBitBuf with subsequent \r
2086 NumOfBits of bits from source. Returns NumOfBits of bits that are \r
2087 popped out.\r
2088\r
2089Arguments:\r
2090\r
2091 Sd - The global scratch data.\r
2092 NumOfBits - The number of bits to pop and read.\r
2093\r
2094Returns:\r
2095\r
2096 The bits that are popped out.\r
2097\r
2098--*/\r
2099{\r
2100 UINT32 OutBits;\r
2101\r
2102 OutBits = (UINT32) (Sd->mBitBuf >> (BITBUFSIZ - NumOfBits));\r
2103\r
2104 FillBuf (Sd, NumOfBits);\r
2105\r
2106 return OutBits;\r
2107}\r
2108\r
2109UINT16\r
2110MakeTable (\r
2111 IN SCRATCH_DATA *Sd,\r
2112 IN UINT16 NumOfChar,\r
2113 IN UINT8 *BitLen,\r
2114 IN UINT16 TableBits,\r
2115 OUT UINT16 *Table\r
2116 )\r
2117/*++\r
2118\r
2119Routine Description:\r
2120\r
2121 Creates Huffman Code mapping table according to code length array.\r
2122\r
2123Arguments:\r
2124\r
2125 Sd - The global scratch data\r
2126 NumOfChar - Number of symbols in the symbol set\r
2127 BitLen - Code length array\r
2128 TableBits - The width of the mapping table\r
2129 Table - The table\r
2130 \r
2131Returns:\r
2132 \r
2133 0 - OK.\r
2134 BAD_TABLE - The table is corrupted.\r
2135\r
2136--*/\r
2137{\r
2138 UINT16 Count[17];\r
2139 UINT16 Weight[17];\r
2140 UINT16 Start[18];\r
2141 UINT16 *Pointer;\r
2142 UINT16 Index3;\r
2143 volatile UINT16 Index;\r
2144 UINT16 Len;\r
2145 UINT16 Char;\r
2146 UINT16 JuBits;\r
2147 UINT16 Avail;\r
2148 UINT16 NextCode;\r
2149 UINT16 Mask;\r
2150 UINT16 WordOfStart;\r
2151 UINT16 WordOfCount;\r
2152\r
2153 for (Index = 1; Index <= 16; Index++) {\r
2154 Count[Index] = 0;\r
2155 }\r
2156\r
2157 for (Index = 0; Index < NumOfChar; Index++) {\r
2158 Count[BitLen[Index]]++;\r
2159 }\r
2160\r
2161 Start[1] = 0;\r
2162\r
2163 for (Index = 1; Index <= 16; Index++) {\r
2164 WordOfStart = Start[Index];\r
2165 WordOfCount = Count[Index];\r
2166 Start[Index + 1] = (UINT16) (WordOfStart + (WordOfCount << (16 - Index)));\r
2167 }\r
2168\r
2169 if (Start[17] != 0) {\r
2170 //\r
2171 //(1U << 16)\r
2172 //\r
2173 return (UINT16) BAD_TABLE;\r
2174 }\r
2175\r
2176 JuBits = (UINT16) (16 - TableBits);\r
2177\r
2178 for (Index = 1; Index <= TableBits; Index++) {\r
2179 Start[Index] >>= JuBits;\r
2180 Weight[Index] = (UINT16) (1U << (TableBits - Index));\r
2181 }\r
2182\r
2183 while (Index <= 16) {\r
2184 Weight[Index] = (UINT16) (1U << (16 - Index));\r
2185 Index++;\r
2186 }\r
2187\r
2188 Index = (UINT16) (Start[TableBits + 1] >> JuBits);\r
2189\r
2190 if (Index != 0) {\r
2191 Index3 = (UINT16) (1U << TableBits);\r
2192 while (Index != Index3) {\r
2193 Table[Index++] = 0;\r
2194 }\r
2195 }\r
2196\r
2197 Avail = NumOfChar;\r
2198 Mask = (UINT16) (1U << (15 - TableBits));\r
2199\r
2200 for (Char = 0; Char < NumOfChar; Char++) {\r
2201\r
2202 Len = BitLen[Char];\r
2203 if (Len == 0) {\r
2204 continue;\r
2205 }\r
2206\r
2207 NextCode = (UINT16) (Start[Len] + Weight[Len]);\r
2208\r
2209 if (Len <= TableBits) {\r
2210\r
2211 for (Index = Start[Len]; Index < NextCode; Index++) {\r
2212 Table[Index] = Char;\r
2213 }\r
2214\r
2215 } else {\r
2216\r
2217 Index3 = Start[Len];\r
2218 Pointer = &Table[Index3 >> JuBits];\r
2219 Index = (UINT16) (Len - TableBits);\r
2220\r
2221 while (Index != 0) {\r
2222 if (*Pointer == 0) {\r
2223 Sd->mRight[Avail] = Sd->mLeft[Avail] = 0;\r
2224 *Pointer = Avail++;\r
2225 }\r
2226\r
2227 if (Index3 & Mask) {\r
2228 Pointer = &Sd->mRight[*Pointer];\r
2229 } else {\r
2230 Pointer = &Sd->mLeft[*Pointer];\r
2231 }\r
2232\r
2233 Index3 <<= 1;\r
2234 Index--;\r
2235 }\r
2236\r
2237 *Pointer = Char;\r
2238\r
2239 }\r
2240\r
2241 Start[Len] = NextCode;\r
2242 }\r
2243 //\r
2244 // Succeeds\r
2245 //\r
2246 return 0;\r
2247}\r
2248\r
2249UINT32\r
2250DecodeP (\r
2251 IN SCRATCH_DATA *Sd\r
2252 )\r
2253/*++\r
2254\r
2255Routine Description:\r
2256\r
2257 Decodes a position value.\r
2258\r
2259Arguments:\r
2260\r
2261 Sd - the global scratch data\r
2262\r
2263Returns:\r
2264\r
2265 The position value decoded.\r
2266\r
2267--*/\r
2268{\r
2269 UINT16 Val;\r
2270 UINT32 Mask;\r
2271 UINT32 Pos;\r
2272\r
2273 Val = Sd->mPTTable[Sd->mBitBuf >> (BITBUFSIZ - 8)];\r
2274\r
2275 if (Val >= MAXNP) {\r
2276 Mask = 1U << (BITBUFSIZ - 1 - 8);\r
2277\r
2278 do {\r
2279\r
2280 if (Sd->mBitBuf & Mask) {\r
2281 Val = Sd->mRight[Val];\r
2282 } else {\r
2283 Val = Sd->mLeft[Val];\r
2284 }\r
2285\r
2286 Mask >>= 1;\r
2287 } while (Val >= MAXNP);\r
2288 }\r
2289 //\r
2290 // Advance what we have read\r
2291 //\r
2292 FillBuf (Sd, Sd->mPTLen[Val]);\r
2293\r
2294 Pos = Val;\r
2295 if (Val > 1) {\r
2296 Pos = (UINT32) ((1U << (Val - 1)) + GetBits (Sd, (UINT16) (Val - 1)));\r
2297 }\r
2298\r
2299 return Pos;\r
2300}\r
2301\r
2302UINT16\r
2303ReadPTLen (\r
2304 IN SCRATCH_DATA *Sd,\r
2305 IN UINT16 nn,\r
2306 IN UINT16 nbit,\r
2307 IN UINT16 Special\r
2308 )\r
2309/*++\r
2310\r
2311Routine Description:\r
2312\r
2313 Reads code lengths for the Extra Set or the Position Set\r
2314\r
2315Arguments:\r
2316\r
2317 Sd - The global scratch data\r
2318 nn - Number of symbols\r
2319 nbit - Number of bits needed to represent nn\r
2320 Special - The special symbol that needs to be taken care of \r
2321\r
2322Returns:\r
2323\r
2324 0 - OK.\r
2325 BAD_TABLE - Table is corrupted.\r
2326\r
2327--*/\r
2328{\r
2329 UINT16 Number;\r
2330 UINT16 CharC;\r
2331 volatile UINT16 Index;\r
2332 UINT32 Mask;\r
2333\r
2334 Number = (UINT16) GetBits (Sd, nbit);\r
2335\r
2336 if (Number == 0) {\r
2337 CharC = (UINT16) GetBits (Sd, nbit);\r
2338\r
2339 for (Index = 0; Index < 256; Index++) {\r
2340 Sd->mPTTable[Index] = CharC;\r
2341 }\r
2342\r
2343 for (Index = 0; Index < nn; Index++) {\r
2344 Sd->mPTLen[Index] = 0;\r
2345 }\r
2346\r
2347 return 0;\r
2348 }\r
2349\r
2350 Index = 0;\r
2351\r
2352 while (Index < Number) {\r
2353\r
2354 CharC = (UINT16) (Sd->mBitBuf >> (BITBUFSIZ - 3));\r
2355\r
2356 if (CharC == 7) {\r
2357 Mask = 1U << (BITBUFSIZ - 1 - 3);\r
2358 while (Mask & Sd->mBitBuf) {\r
2359 Mask >>= 1;\r
2360 CharC += 1;\r
2361 }\r
2362 }\r
2363\r
2364 FillBuf (Sd, (UINT16) ((CharC < 7) ? 3 : CharC - 3));\r
2365\r
2366 Sd->mPTLen[Index++] = (UINT8) CharC;\r
2367\r
2368 if (Index == Special) {\r
2369 CharC = (UINT16) GetBits (Sd, 2);\r
2370 while ((INT16) (--CharC) >= 0) {\r
2371 Sd->mPTLen[Index++] = 0;\r
2372 }\r
2373 }\r
2374 }\r
2375\r
2376 while (Index < nn) {\r
2377 Sd->mPTLen[Index++] = 0;\r
2378 }\r
2379\r
2380 return MakeTable (Sd, nn, Sd->mPTLen, 8, Sd->mPTTable);\r
2381}\r
2382\r
2383VOID\r
2384ReadCLen (\r
2385 SCRATCH_DATA *Sd\r
2386 )\r
2387/*++\r
2388\r
2389Routine Description:\r
2390\r
2391 Reads code lengths for Char&Len Set.\r
2392\r
2393Arguments:\r
2394\r
2395 Sd - the global scratch data\r
2396\r
2397Returns: (VOID)\r
2398\r
2399--*/\r
2400{\r
2401 UINT16 Number;\r
2402 UINT16 CharC;\r
2403 volatile UINT16 Index;\r
2404 UINT32 Mask;\r
2405\r
2406 Number = (UINT16) GetBits (Sd, CBIT);\r
2407\r
2408 if (Number == 0) {\r
2409 CharC = (UINT16) GetBits (Sd, CBIT);\r
2410\r
2411 for (Index = 0; Index < NC; Index++) {\r
2412 Sd->mCLen[Index] = 0;\r
2413 }\r
2414\r
2415 for (Index = 0; Index < 4096; Index++) {\r
2416 Sd->mCTable[Index] = CharC;\r
2417 }\r
2418\r
2419 return ;\r
2420 }\r
2421\r
2422 Index = 0;\r
2423 while (Index < Number) {\r
2424\r
2425 CharC = Sd->mPTTable[Sd->mBitBuf >> (BITBUFSIZ - 8)];\r
2426 if (CharC >= NT) {\r
2427 Mask = 1U << (BITBUFSIZ - 1 - 8);\r
2428\r
2429 do {\r
2430\r
2431 if (Mask & Sd->mBitBuf) {\r
2432 CharC = Sd->mRight[CharC];\r
2433 } else {\r
2434 CharC = Sd->mLeft[CharC];\r
2435 }\r
2436\r
2437 Mask >>= 1;\r
2438\r
2439 } while (CharC >= NT);\r
2440 }\r
2441 //\r
2442 // Advance what we have read\r
2443 //\r
2444 FillBuf (Sd, Sd->mPTLen[CharC]);\r
2445\r
2446 if (CharC <= 2) {\r
2447\r
2448 if (CharC == 0) {\r
2449 CharC = 1;\r
2450 } else if (CharC == 1) {\r
2451 CharC = (UINT16) (GetBits (Sd, 4) + 3);\r
2452 } else if (CharC == 2) {\r
2453 CharC = (UINT16) (GetBits (Sd, CBIT) + 20);\r
2454 }\r
2455\r
2456 while ((INT16) (--CharC) >= 0) {\r
2457 Sd->mCLen[Index++] = 0;\r
2458 }\r
2459\r
2460 } else {\r
2461\r
2462 Sd->mCLen[Index++] = (UINT8) (CharC - 2);\r
2463\r
2464 }\r
2465 }\r
2466\r
2467 while (Index < NC) {\r
2468 Sd->mCLen[Index++] = 0;\r
2469 }\r
2470\r
2471 MakeTable (Sd, NC, Sd->mCLen, 12, Sd->mCTable);\r
2472\r
2473 return ;\r
2474}\r
2475\r
2476UINT16\r
2477DecodeC (\r
2478 SCRATCH_DATA *Sd\r
2479 )\r
2480/*++\r
2481\r
2482Routine Description:\r
2483\r
2484 Decode a character/length value.\r
2485\r
2486Arguments:\r
2487\r
2488 Sd - The global scratch data.\r
2489\r
2490Returns:\r
2491\r
2492 The value decoded.\r
2493\r
2494--*/\r
2495{\r
2496 UINT16 Index2;\r
2497 UINT32 Mask;\r
2498\r
2499 if (Sd->mBlockSize == 0) {\r
2500 //\r
2501 // Starting a new block\r
2502 //\r
2503 Sd->mBlockSize = (UINT16) GetBits (Sd, 16);\r
2504 Sd->mBadTableFlag = ReadPTLen (Sd, NT, TBIT, 3);\r
2505 if (Sd->mBadTableFlag != 0) {\r
2506 return 0;\r
2507 }\r
2508\r
2509 ReadCLen (Sd);\r
2510\r
2511 Sd->mBadTableFlag = ReadPTLen (Sd, MAXNP, Sd->mPBit, (UINT16) (-1));\r
2512 if (Sd->mBadTableFlag != 0) {\r
2513 return 0;\r
2514 }\r
2515 }\r
2516\r
2517 Sd->mBlockSize--;\r
2518 Index2 = Sd->mCTable[Sd->mBitBuf >> (BITBUFSIZ - 12)];\r
2519\r
2520 if (Index2 >= NC) {\r
2521 Mask = 1U << (BITBUFSIZ - 1 - 12);\r
2522\r
2523 do {\r
2524 if (Sd->mBitBuf & Mask) {\r
2525 Index2 = Sd->mRight[Index2];\r
2526 } else {\r
2527 Index2 = Sd->mLeft[Index2];\r
2528 }\r
2529\r
2530 Mask >>= 1;\r
2531 } while (Index2 >= NC);\r
2532 }\r
2533 //\r
2534 // Advance what we have read\r
2535 //\r
2536 FillBuf (Sd, Sd->mCLen[Index2]);\r
2537\r
2538 return Index2;\r
2539}\r
2540\r
2541VOID\r
2542Decode (\r
2543 SCRATCH_DATA *Sd\r
2544 )\r
2545/*++\r
2546\r
2547Routine Description:\r
2548\r
2549 Decode the source data and put the resulting data into the destination buffer.\r
2550\r
2551Arguments:\r
2552\r
2553 Sd - The global scratch data\r
2554\r
2555Returns: (VOID)\r
2556\r
2557 --*/\r
2558{\r
2559 UINT16 BytesRemain;\r
2560 UINT32 DataIdx;\r
2561 UINT16 CharC;\r
2562\r
2563 BytesRemain = (UINT16) (-1);\r
2564\r
2565 DataIdx = 0;\r
2566\r
2567 for (;;) {\r
2568 CharC = DecodeC (Sd);\r
2569 if (Sd->mBadTableFlag != 0) {\r
2570 goto Done ;\r
2571 }\r
2572\r
2573 if (CharC < 256) {\r
2574 //\r
2575 // Process an Original character\r
2576 //\r
2577 if (Sd->mOutBuf >= Sd->mOrigSize) {\r
2578 goto Done ;\r
2579 } else {\r
2580 Sd->mDstBase[Sd->mOutBuf++] = (UINT8) CharC;\r
2581 }\r
2582\r
2583 } else {\r
2584 //\r
2585 // Process a Pointer\r
2586 //\r
2587 CharC = (UINT16) (CharC - (UINT8_MAX + 1 - THRESHOLD));\r
2588\r
2589 BytesRemain = CharC;\r
2590\r
2591 DataIdx = Sd->mOutBuf - DecodeP (Sd) - 1;\r
2592\r
2593 BytesRemain--;\r
2594 while ((INT16) (BytesRemain) >= 0) {\r
2595 Sd->mDstBase[Sd->mOutBuf++] = Sd->mDstBase[DataIdx++];\r
2596 if (Sd->mOutBuf >= Sd->mOrigSize) {\r
2597 goto Done ;\r
2598 }\r
2599\r
2600 BytesRemain--;\r
2601 }\r
2602 }\r
2603 }\r
2604\r
2605Done:\r
2606 return ;\r
2607}\r
2608\r
2609RETURN_STATUS\r
2610EFIAPI\r
2611Decompress (\r
2612 IN VOID *Source,\r
2613 IN OUT VOID *Destination,\r
2614 IN OUT VOID *Scratch,\r
2615 IN UINT32 Version\r
2616 )\r
2617/*++\r
2618\r
2619Routine Description:\r
2620\r
2621 The internal implementation of Decompress().\r
2622\r
2623Arguments:\r
2624\r
2625 Source - The source buffer containing the compressed data.\r
2626 Destination - The destination buffer to store the decompressed data\r
2627 Scratch - The buffer used internally by the decompress routine. This buffer is needed to store intermediate data.\r
2628 Version - 1 for EFI1.1 Decompress algoruthm, 2 for Tiano Decompress algorithm\r
2629\r
2630Returns:\r
2631\r
2632 RETURN_SUCCESS - Decompression is successfull\r
2633 RETURN_INVALID_PARAMETER - The source data is corrupted\r
2634\r
2635--*/\r
2636{\r
2637 volatile UINT32 Index;\r
2638 UINT32 CompSize;\r
2639 UINT32 OrigSize;\r
2640 SCRATCH_DATA *Sd;\r
2641 CONST UINT8 *Src;\r
2642 UINT8 *Dst;\r
2643\r
2644 //\r
2645 // Verify input is not NULL\r
2646 //\r
2647 assert(Source);\r
2648// assert(Destination);\r
2649 assert(Scratch);\r
2650 \r
2651 Src = (UINT8 *)Source;\r
2652 Dst = (UINT8 *)Destination;\r
2653\r
2654 Sd = (SCRATCH_DATA *) Scratch;\r
2655 CompSize = Src[0] + (Src[1] << 8) + (Src[2] << 16) + (Src[3] << 24);\r
2656 OrigSize = Src[4] + (Src[5] << 8) + (Src[6] << 16) + (Src[7] << 24);\r
2657 \r
2658 //\r
2659 // If compressed file size is 0, return\r
2660 //\r
2661 if (OrigSize == 0) {\r
2662 return RETURN_SUCCESS;\r
2663 }\r
2664\r
2665 Src = Src + 8;\r
2666\r
2667 for (Index = 0; Index < sizeof (SCRATCH_DATA); Index++) {\r
2668 ((UINT8 *) Sd)[Index] = 0;\r
2669 }\r
2670 //\r
2671 // The length of the field 'Position Set Code Length Array Size' in Block Header.\r
2672 // For EFI 1.1 de/compression algorithm(Version 1), mPBit = 4\r
2673 // For Tiano de/compression algorithm(Version 2), mPBit = 5\r
2674 //\r
2675 switch (Version) {\r
2676 case 1 :\r
2677 Sd->mPBit = 4;\r
2678 break;\r
2679 case 2 :\r
2680 Sd->mPBit = 5;\r
2681 break;\r
2682 default:\r
2683 assert(FALSE);\r
2684 }\r
2685 Sd->mSrcBase = (UINT8 *)Src;\r
2686 Sd->mDstBase = Dst;\r
2687 Sd->mCompSize = CompSize;\r
2688 Sd->mOrigSize = OrigSize;\r
2689\r
2690 //\r
2691 // Fill the first BITBUFSIZ bits\r
2692 //\r
2693 FillBuf (Sd, BITBUFSIZ);\r
2694\r
2695 //\r
2696 // Decompress it\r
2697 //\r
2698 \r
2699 Decode (Sd);\r
2700 \r
2701 if (Sd->mBadTableFlag != 0) {\r
2702 //\r
2703 // Something wrong with the source\r
2704 //\r
2705 return RETURN_INVALID_PARAMETER;\r
2706 }\r
2707\r
2708 return RETURN_SUCCESS;\r
2709}\r
2710\r
2711\r