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