]> git.proxmox.com Git - mirror_edk2.git/blame - BaseTools/Source/C/TianoCompress/TianoCompress.c
BaseTools/VolInfo: 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
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
1909 return 1;\r
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
1920 free(FileBuffer);\r
1921 return 1;\r
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
2156 volatile UINT16 Index;\r
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
2166 for (Index = 1; Index <= 16; Index++) {\r
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
2174 Start[1] = 0;\r
2175\r
2176 for (Index = 1; Index <= 16; Index++) {\r
2177 WordOfStart = Start[Index];\r
2178 WordOfCount = Count[Index];\r
2179 Start[Index + 1] = (UINT16) (WordOfStart + (WordOfCount << (16 - Index)));\r
2180 }\r
2181\r
2182 if (Start[17] != 0) {\r
2183 //\r
2184 //(1U << 16)\r
2185 //\r
2186 return (UINT16) BAD_TABLE;\r
2187 }\r
2188\r
2189 JuBits = (UINT16) (16 - TableBits);\r
2190\r
2191 for (Index = 1; Index <= TableBits; Index++) {\r
2192 Start[Index] >>= JuBits;\r
2193 Weight[Index] = (UINT16) (1U << (TableBits - Index));\r
2194 }\r
2195\r
2196 while (Index <= 16) {\r
2197 Weight[Index] = (UINT16) (1U << (16 - Index));\r
2198 Index++;\r
2199 }\r
2200\r
2201 Index = (UINT16) (Start[TableBits + 1] >> JuBits);\r
2202\r
2203 if (Index != 0) {\r
2204 Index3 = (UINT16) (1U << TableBits);\r
2205 while (Index != Index3) {\r
2206 Table[Index++] = 0;\r
2207 }\r
2208 }\r
2209\r
2210 Avail = NumOfChar;\r
2211 Mask = (UINT16) (1U << (15 - TableBits));\r
2212\r
2213 for (Char = 0; Char < NumOfChar; Char++) {\r
2214\r
2215 Len = BitLen[Char];\r
2216 if (Len == 0) {\r
2217 continue;\r
2218 }\r
2219\r
2220 NextCode = (UINT16) (Start[Len] + Weight[Len]);\r
2221\r
2222 if (Len <= TableBits) {\r
2223\r
2224 for (Index = Start[Len]; Index < NextCode; Index++) {\r
2225 Table[Index] = Char;\r
2226 }\r
2227\r
2228 } else {\r
2229\r
2230 Index3 = Start[Len];\r
2231 Pointer = &Table[Index3 >> JuBits];\r
2232 Index = (UINT16) (Len - TableBits);\r
2233\r
2234 while (Index != 0) {\r
2235 if (*Pointer == 0) {\r
2236 Sd->mRight[Avail] = Sd->mLeft[Avail] = 0;\r
2237 *Pointer = Avail++;\r
2238 }\r
2239\r
2240 if (Index3 & Mask) {\r
2241 Pointer = &Sd->mRight[*Pointer];\r
2242 } else {\r
2243 Pointer = &Sd->mLeft[*Pointer];\r
2244 }\r
2245\r
2246 Index3 <<= 1;\r
2247 Index--;\r
2248 }\r
2249\r
2250 *Pointer = Char;\r
2251\r
2252 }\r
2253\r
2254 Start[Len] = NextCode;\r
2255 }\r
2256 //\r
2257 // Succeeds\r
2258 //\r
2259 return 0;\r
2260}\r
2261\r
2262UINT32\r
2263DecodeP (\r
2264 IN SCRATCH_DATA *Sd\r
2265 )\r
2266/*++\r
2267\r
2268Routine Description:\r
2269\r
2270 Decodes a position value.\r
2271\r
2272Arguments:\r
2273\r
2274 Sd - the global scratch data\r
2275\r
2276Returns:\r
2277\r
2278 The position value decoded.\r
2279\r
2280--*/\r
2281{\r
2282 UINT16 Val;\r
2283 UINT32 Mask;\r
2284 UINT32 Pos;\r
2285\r
2286 Val = Sd->mPTTable[Sd->mBitBuf >> (BITBUFSIZ - 8)];\r
2287\r
2288 if (Val >= MAXNP) {\r
2289 Mask = 1U << (BITBUFSIZ - 1 - 8);\r
2290\r
2291 do {\r
2292\r
2293 if (Sd->mBitBuf & Mask) {\r
2294 Val = Sd->mRight[Val];\r
2295 } else {\r
2296 Val = Sd->mLeft[Val];\r
2297 }\r
2298\r
2299 Mask >>= 1;\r
2300 } while (Val >= MAXNP);\r
2301 }\r
2302 //\r
2303 // Advance what we have read\r
2304 //\r
2305 FillBuf (Sd, Sd->mPTLen[Val]);\r
2306\r
2307 Pos = Val;\r
2308 if (Val > 1) {\r
2309 Pos = (UINT32) ((1U << (Val - 1)) + GetBits (Sd, (UINT16) (Val - 1)));\r
2310 }\r
2311\r
2312 return Pos;\r
2313}\r
2314\r
2315UINT16\r
2316ReadPTLen (\r
2317 IN SCRATCH_DATA *Sd,\r
2318 IN UINT16 nn,\r
2319 IN UINT16 nbit,\r
2320 IN UINT16 Special\r
2321 )\r
2322/*++\r
2323\r
2324Routine Description:\r
2325\r
2326 Reads code lengths for the Extra Set or the Position Set\r
2327\r
2328Arguments:\r
2329\r
2330 Sd - The global scratch data\r
2331 nn - Number of symbols\r
2332 nbit - Number of bits needed to represent nn\r
2333 Special - The special symbol that needs to be taken care of \r
2334\r
2335Returns:\r
2336\r
2337 0 - OK.\r
2338 BAD_TABLE - Table is corrupted.\r
2339\r
2340--*/\r
2341{\r
2342 UINT16 Number;\r
2343 UINT16 CharC;\r
2344 volatile UINT16 Index;\r
2345 UINT32 Mask;\r
2346\r
2347 Number = (UINT16) GetBits (Sd, nbit);\r
2348\r
2349 if (Number == 0) {\r
2350 CharC = (UINT16) GetBits (Sd, nbit);\r
2351\r
2352 for (Index = 0; Index < 256; Index++) {\r
2353 Sd->mPTTable[Index] = CharC;\r
2354 }\r
2355\r
2356 for (Index = 0; Index < nn; Index++) {\r
2357 Sd->mPTLen[Index] = 0;\r
2358 }\r
2359\r
2360 return 0;\r
2361 }\r
2362\r
2363 Index = 0;\r
2364\r
2365 while (Index < Number) {\r
2366\r
2367 CharC = (UINT16) (Sd->mBitBuf >> (BITBUFSIZ - 3));\r
2368\r
2369 if (CharC == 7) {\r
2370 Mask = 1U << (BITBUFSIZ - 1 - 3);\r
2371 while (Mask & Sd->mBitBuf) {\r
2372 Mask >>= 1;\r
2373 CharC += 1;\r
2374 }\r
2375 }\r
2376\r
2377 FillBuf (Sd, (UINT16) ((CharC < 7) ? 3 : CharC - 3));\r
2378\r
2379 Sd->mPTLen[Index++] = (UINT8) CharC;\r
2380\r
2381 if (Index == Special) {\r
2382 CharC = (UINT16) GetBits (Sd, 2);\r
2383 while ((INT16) (--CharC) >= 0) {\r
2384 Sd->mPTLen[Index++] = 0;\r
2385 }\r
2386 }\r
2387 }\r
2388\r
2389 while (Index < nn) {\r
2390 Sd->mPTLen[Index++] = 0;\r
2391 }\r
2392\r
2393 return MakeTable (Sd, nn, Sd->mPTLen, 8, Sd->mPTTable);\r
2394}\r
2395\r
2396VOID\r
2397ReadCLen (\r
2398 SCRATCH_DATA *Sd\r
2399 )\r
2400/*++\r
2401\r
2402Routine Description:\r
2403\r
2404 Reads code lengths for Char&Len Set.\r
2405\r
2406Arguments:\r
2407\r
2408 Sd - the global scratch data\r
2409\r
2410Returns: (VOID)\r
2411\r
2412--*/\r
2413{\r
2414 UINT16 Number;\r
2415 UINT16 CharC;\r
2416 volatile UINT16 Index;\r
2417 UINT32 Mask;\r
2418\r
2419 Number = (UINT16) GetBits (Sd, CBIT);\r
2420\r
2421 if (Number == 0) {\r
2422 CharC = (UINT16) GetBits (Sd, CBIT);\r
2423\r
2424 for (Index = 0; Index < NC; Index++) {\r
2425 Sd->mCLen[Index] = 0;\r
2426 }\r
2427\r
2428 for (Index = 0; Index < 4096; Index++) {\r
2429 Sd->mCTable[Index] = CharC;\r
2430 }\r
2431\r
2432 return ;\r
2433 }\r
2434\r
2435 Index = 0;\r
2436 while (Index < Number) {\r
2437\r
2438 CharC = Sd->mPTTable[Sd->mBitBuf >> (BITBUFSIZ - 8)];\r
2439 if (CharC >= NT) {\r
2440 Mask = 1U << (BITBUFSIZ - 1 - 8);\r
2441\r
2442 do {\r
2443\r
2444 if (Mask & Sd->mBitBuf) {\r
2445 CharC = Sd->mRight[CharC];\r
2446 } else {\r
2447 CharC = Sd->mLeft[CharC];\r
2448 }\r
2449\r
2450 Mask >>= 1;\r
2451\r
2452 } while (CharC >= NT);\r
2453 }\r
2454 //\r
2455 // Advance what we have read\r
2456 //\r
2457 FillBuf (Sd, Sd->mPTLen[CharC]);\r
2458\r
2459 if (CharC <= 2) {\r
2460\r
2461 if (CharC == 0) {\r
2462 CharC = 1;\r
2463 } else if (CharC == 1) {\r
2464 CharC = (UINT16) (GetBits (Sd, 4) + 3);\r
2465 } else if (CharC == 2) {\r
2466 CharC = (UINT16) (GetBits (Sd, CBIT) + 20);\r
2467 }\r
2468\r
2469 while ((INT16) (--CharC) >= 0) {\r
2470 Sd->mCLen[Index++] = 0;\r
2471 }\r
2472\r
2473 } else {\r
2474\r
2475 Sd->mCLen[Index++] = (UINT8) (CharC - 2);\r
2476\r
2477 }\r
2478 }\r
2479\r
2480 while (Index < NC) {\r
2481 Sd->mCLen[Index++] = 0;\r
2482 }\r
2483\r
2484 MakeTable (Sd, NC, Sd->mCLen, 12, Sd->mCTable);\r
2485\r
2486 return ;\r
2487}\r
2488\r
2489UINT16\r
2490DecodeC (\r
2491 SCRATCH_DATA *Sd\r
2492 )\r
2493/*++\r
2494\r
2495Routine Description:\r
2496\r
2497 Decode a character/length value.\r
2498\r
2499Arguments:\r
2500\r
2501 Sd - The global scratch data.\r
2502\r
2503Returns:\r
2504\r
2505 The value decoded.\r
2506\r
2507--*/\r
2508{\r
2509 UINT16 Index2;\r
2510 UINT32 Mask;\r
2511\r
2512 if (Sd->mBlockSize == 0) {\r
2513 //\r
2514 // Starting a new block\r
2515 //\r
2516 Sd->mBlockSize = (UINT16) GetBits (Sd, 16);\r
2517 Sd->mBadTableFlag = ReadPTLen (Sd, NT, TBIT, 3);\r
2518 if (Sd->mBadTableFlag != 0) {\r
2519 return 0;\r
2520 }\r
2521\r
2522 ReadCLen (Sd);\r
2523\r
2524 Sd->mBadTableFlag = ReadPTLen (Sd, MAXNP, Sd->mPBit, (UINT16) (-1));\r
2525 if (Sd->mBadTableFlag != 0) {\r
2526 return 0;\r
2527 }\r
2528 }\r
2529\r
2530 Sd->mBlockSize--;\r
2531 Index2 = Sd->mCTable[Sd->mBitBuf >> (BITBUFSIZ - 12)];\r
2532\r
2533 if (Index2 >= NC) {\r
2534 Mask = 1U << (BITBUFSIZ - 1 - 12);\r
2535\r
2536 do {\r
2537 if (Sd->mBitBuf & Mask) {\r
2538 Index2 = Sd->mRight[Index2];\r
2539 } else {\r
2540 Index2 = Sd->mLeft[Index2];\r
2541 }\r
2542\r
2543 Mask >>= 1;\r
2544 } while (Index2 >= NC);\r
2545 }\r
2546 //\r
2547 // Advance what we have read\r
2548 //\r
2549 FillBuf (Sd, Sd->mCLen[Index2]);\r
2550\r
2551 return Index2;\r
2552}\r
2553\r
2554VOID\r
2555Decode (\r
2556 SCRATCH_DATA *Sd\r
2557 )\r
2558/*++\r
2559\r
2560Routine Description:\r
2561\r
2562 Decode the source data and put the resulting data into the destination buffer.\r
2563\r
2564Arguments:\r
2565\r
2566 Sd - The global scratch data\r
2567\r
2568Returns: (VOID)\r
2569\r
2570 --*/\r
2571{\r
2572 UINT16 BytesRemain;\r
2573 UINT32 DataIdx;\r
2574 UINT16 CharC;\r
2575\r
2576 BytesRemain = (UINT16) (-1);\r
2577\r
2578 DataIdx = 0;\r
2579\r
2580 for (;;) {\r
2581 CharC = DecodeC (Sd);\r
2582 if (Sd->mBadTableFlag != 0) {\r
2583 goto Done ;\r
2584 }\r
2585\r
2586 if (CharC < 256) {\r
2587 //\r
2588 // Process an Original character\r
2589 //\r
2590 if (Sd->mOutBuf >= Sd->mOrigSize) {\r
2591 goto Done ;\r
2592 } else {\r
2593 Sd->mDstBase[Sd->mOutBuf++] = (UINT8) CharC;\r
2594 }\r
2595\r
2596 } else {\r
2597 //\r
2598 // Process a Pointer\r
2599 //\r
2600 CharC = (UINT16) (CharC - (UINT8_MAX + 1 - THRESHOLD));\r
2601\r
2602 BytesRemain = CharC;\r
2603\r
2604 DataIdx = Sd->mOutBuf - DecodeP (Sd) - 1;\r
2605\r
2606 BytesRemain--;\r
2607 while ((INT16) (BytesRemain) >= 0) {\r
2608 Sd->mDstBase[Sd->mOutBuf++] = Sd->mDstBase[DataIdx++];\r
2609 if (Sd->mOutBuf >= Sd->mOrigSize) {\r
2610 goto Done ;\r
2611 }\r
2612\r
2613 BytesRemain--;\r
2614 }\r
2615 }\r
2616 }\r
2617\r
2618Done:\r
2619 return ;\r
2620}\r
2621\r
2622RETURN_STATUS\r
2623EFIAPI\r
2624Decompress (\r
2625 IN VOID *Source,\r
2626 IN OUT VOID *Destination,\r
2627 IN OUT VOID *Scratch,\r
2628 IN UINT32 Version\r
2629 )\r
2630/*++\r
2631\r
2632Routine Description:\r
2633\r
2634 The internal implementation of Decompress().\r
2635\r
2636Arguments:\r
2637\r
2638 Source - The source buffer containing the compressed data.\r
2639 Destination - The destination buffer to store the decompressed data\r
2640 Scratch - The buffer used internally by the decompress routine. This buffer is needed to store intermediate data.\r
2641 Version - 1 for EFI1.1 Decompress algoruthm, 2 for Tiano Decompress algorithm\r
2642\r
2643Returns:\r
2644\r
2645 RETURN_SUCCESS - Decompression is successfull\r
2646 RETURN_INVALID_PARAMETER - The source data is corrupted\r
2647\r
2648--*/\r
2649{\r
2650 volatile UINT32 Index;\r
2651 UINT32 CompSize;\r
2652 UINT32 OrigSize;\r
2653 SCRATCH_DATA *Sd;\r
2654 CONST UINT8 *Src;\r
2655 UINT8 *Dst;\r
2656\r
2657 //\r
2658 // Verify input is not NULL\r
2659 //\r
2660 assert(Source);\r
2661// assert(Destination);\r
2662 assert(Scratch);\r
2663 \r
2664 Src = (UINT8 *)Source;\r
2665 Dst = (UINT8 *)Destination;\r
2666\r
2667 Sd = (SCRATCH_DATA *) Scratch;\r
2668 CompSize = Src[0] + (Src[1] << 8) + (Src[2] << 16) + (Src[3] << 24);\r
2669 OrigSize = Src[4] + (Src[5] << 8) + (Src[6] << 16) + (Src[7] << 24);\r
2670 \r
2671 //\r
2672 // If compressed file size is 0, return\r
2673 //\r
2674 if (OrigSize == 0) {\r
2675 return RETURN_SUCCESS;\r
2676 }\r
2677\r
2678 Src = Src + 8;\r
2679\r
2680 for (Index = 0; Index < sizeof (SCRATCH_DATA); Index++) {\r
2681 ((UINT8 *) Sd)[Index] = 0;\r
2682 }\r
2683 //\r
2684 // The length of the field 'Position Set Code Length Array Size' in Block Header.\r
2685 // For EFI 1.1 de/compression algorithm(Version 1), mPBit = 4\r
2686 // For Tiano de/compression algorithm(Version 2), mPBit = 5\r
2687 //\r
2688 switch (Version) {\r
2689 case 1 :\r
2690 Sd->mPBit = 4;\r
2691 break;\r
2692 case 2 :\r
2693 Sd->mPBit = 5;\r
2694 break;\r
2695 default:\r
2696 assert(FALSE);\r
2697 }\r
2698 Sd->mSrcBase = (UINT8 *)Src;\r
2699 Sd->mDstBase = Dst;\r
2700 Sd->mCompSize = CompSize;\r
2701 Sd->mOrigSize = OrigSize;\r
2702\r
2703 //\r
2704 // Fill the first BITBUFSIZ bits\r
2705 //\r
2706 FillBuf (Sd, BITBUFSIZ);\r
2707\r
2708 //\r
2709 // Decompress it\r
2710 //\r
2711 \r
2712 Decode (Sd);\r
2713 \r
2714 if (Sd->mBadTableFlag != 0) {\r
2715 //\r
2716 // Something wrong with the source\r
2717 //\r
2718 return RETURN_INVALID_PARAMETER;\r
2719 }\r
2720\r
2721 return RETURN_SUCCESS;\r
2722}\r
2723\r
2724\r