]> git.proxmox.com Git - mirror_edk2.git/blame - BaseTools/Source/C/TianoCompress/TianoCompress.c
BaseTools: Clean up source files
[mirror_edk2.git] / BaseTools / Source / C / TianoCompress / TianoCompress.c
CommitLineData
30fdf114 1/** @file\r
f7496d71
LG
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
97fa0ee9 4and Pointers to repeated strings.\r
f7496d71 5This sequence is further divided into Blocks and Huffman codings are applied to\r
97fa0ee9 6each Block.\r
f7496d71
LG
7\r
8Copyright (c) 2007 - 2018, Intel Corporation. All rights reserved.<BR>\r
9This program and the accompanying materials\r
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
30fdf114 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
f7496d71 103\r
30fdf114
LG
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
f7496d71 138\r
30fdf114
LG
139 PutDword (0L);\r
140 PutDword (0L);\r
f7496d71 141\r
30fdf114 142 MakeCrcTable ();\r
f7496d71 143\r
30fdf114
LG
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
f7496d71 154\r
30fdf114
LG
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
f7496d71
LG
166 mDst = DstBuffer;\r
167\r
30fdf114
LG
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
f7496d71 175 *DstSize = mCompSize + 1 + 8;\r
fd171542 176 return EFI_BUFFER_TOO_SMALL;\r
177 } else {\r
f7496d71 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
f7496d71 193\r
30fdf114
LG
194Arguments:\r
195\r
196 Data - the dword to put\r
f7496d71 197\r
30fdf114 198Returns: (VOID)\r
f7496d71 199\r
30fdf114
LG
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
f7496d71
LG
229\r
230Argements:\r
30fdf114
LG
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
f7496d71 288\r
30fdf114
LG
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
f7496d71 340\r
30fdf114
LG
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
f7496d71 380\r
30fdf114
LG
381Arguments:\r
382\r
383 NodeQ - the parent node\r
384 CharC - the edge character\r
f7496d71 385\r
30fdf114
LG
386Returns:\r
387\r
f7496d71
LG
388 The child node (NIL if not found)\r
389\r
30fdf114
LG
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
f7496d71 418\r
30fdf114
LG
419Arguments:\r
420\r
421 Parent - the parent node\r
422 CharC - the edge character\r
423 Child - the child node\r
f7496d71 424\r
30fdf114
LG
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
f7496d71 452\r
30fdf114
LG
453Arguments:\r
454\r
455 Old - the node to split\r
f7496d71 456\r
30fdf114
LG
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
f7496d71 490\r
30fdf114
LG
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
f7496d71 623\r
30fdf114
LG
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
f7496d71 754\r
30fdf114
LG
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
f7496d71 840\r
30fdf114
LG
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
f7496d71 899\r
30fdf114
LG
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
f7496d71 905\r
30fdf114
LG
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
f7496d71 947\r
30fdf114
LG
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
f7496d71
LG
1037\r
1038Arguments:\r
30fdf114
LG
1039 (VOID)\r
1040\r
f7496d71 1041Returns:\r
30fdf114
LG
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
f7496d71 1249 x - the data\r
30fdf114
LG
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
f7496d71 1286\r
30fdf114
LG
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
f7496d71 1295\r
30fdf114
LG
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
f7496d71 1338\r
30fdf114
LG
1339Arguments:\r
1340\r
1341 Index - the top node\r
f7496d71 1342\r
30fdf114
LG
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
f7496d71 1369\r
30fdf114
LG
1370Arguments:\r
1371\r
1372 Root - the root of the tree\r
f7496d71 1373\r
30fdf114
LG
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
f7496d71 1465\r
30fdf114
LG
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
f7496d71 1502\r
30fdf114
LG
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
f7496d71 1509\r
30fdf114
LG
1510Returns:\r
1511\r
1512 Root of the Huffman tree.\r
f7496d71 1513\r
30fdf114
LG
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
f7496d71 1589\r
30fdf114 1590Routine Description:\r
f7496d71 1591\r
30fdf114
LG
1592 Get the contents of file specified in InputFileName\r
1593 into FileBuffer.\r
f7496d71 1594\r
30fdf114 1595Arguments:\r
f7496d71 1596\r
30fdf114 1597 InputFileName - Name of the input file.\r
f7496d71 1598\r
30fdf114
LG
1599 FileBuffer - Output buffer to contain data\r
1600\r
f7496d71 1601 BufferLength - Actual length of the data\r
30fdf114
LG
1602\r
1603Returns:\r
f7496d71 1604\r
30fdf114
LG
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
f7496d71 1623\r
30fdf114
LG
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
f7496d71 1629 //\r
30fdf114
LG
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
f7496d71 1641\r
30fdf114
LG
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
f7496d71 1696\r
30fdf114
LG
1697 //\r
1698 // Copyright declaration\r
f7496d71
LG
1699 //\r
1700 fprintf (stdout, "Copyright (c) 2007 - 2018, 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
f7496d71 1742--*/\r
30fdf114
LG
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
f7496d71 1758\r
30fdf114
LG
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
4d32be88
HW
1767 InputFile = NULL;\r
1768 OutputFile = NULL;\r
30fdf114
LG
1769 DstSize=0;\r
1770 DebugLevel = 0;\r
1771 DebugMode = FALSE;\r
1772\r
1773 //\r
1774 // Verify the correct number of arguments\r
1775 //\r
1776 if (argc == 1) {\r
1777 Error (NULL, 0, 1001, "Missing options", "No input options specified.");\r
1778 Usage();\r
1779 return 0;\r
1780 }\r
f7496d71 1781\r
30fdf114
LG
1782 if ((strcmp(argv[1], "-h") == 0) || (strcmp(argv[1], "--help") == 0)) {\r
1783 Usage();\r
1784 return 0;\r
1785 }\r
f7496d71 1786\r
30fdf114
LG
1787 if ((strcmp(argv[1], "--version") == 0)) {\r
1788 Version();\r
1789 return 0;\r
1790 }\r
1791\r
1792 argc--;\r
1793 argv++;\r
1794 if (strcmp(argv[0],"-e") == 0) {\r
1795 //\r
1796 // encode the input file\r
1797 //\r
1798 ENCODE = TRUE;\r
1799 argc--;\r
1800 argv++;\r
1801 } else if (strcmp(argv[0], "-d") == 0) {\r
1802 //\r
1803 // decode the input file\r
1804 //\r
1805 DECODE = TRUE;\r
1806 argc--;\r
1807 argv++;\r
1808 } else {\r
1809 //\r
1810 // Error command line\r
1811 //\r
1812 Error (NULL, 0, 1003, "Invalid option value", "the options specified are not recognized.");\r
1813 Usage();\r
1814 return 1;\r
1815 }\r
1816\r
1817 while (argc > 0) {\r
1818 if ((strcmp(argv[0], "-v") == 0) || (stricmp(argv[0], "--verbose") == 0)) {\r
1819 VerboseMode = TRUE;\r
1820 argc--;\r
1821 argv++;\r
1822 continue;\r
1823 }\r
1824\r
1825 if (stricmp (argv[0], "--debug") == 0) {\r
1826 argc-=2;\r
1827 argv++;\r
1828 Status = AsciiStringToUint64(argv[0], FALSE, &DebugLevel);\r
1829 if (DebugLevel > 9) {\r
1830 Error (NULL, 0 ,2000, "Invalid parameter", "Unrecognized argument %s", argv[0]);\r
1831 goto ERROR;\r
1832 }\r
1833 if (DebugLevel>=5 && DebugLevel <=9){\r
1834 DebugMode = TRUE;\r
1835 } else {\r
1836 DebugMode = FALSE;\r
1837 }\r
1838 argv++;\r
1839 continue;\r
1840 }\r
1841\r
1842 if ((strcmp(argv[0], "-q") == 0) || (stricmp (argv[0], "--quiet") == 0)) {\r
1843 QuietMode = TRUE;\r
1844 argc--;\r
1845 argv++;\r
1846 continue;\r
1847 }\r
1848\r
1849 if ((strcmp(argv[0], "-o") == 0) || (stricmp (argv[0], "--output") == 0)) {\r
1850 if (argv[1] == NULL || argv[1][0] == '-') {\r
1851 Error (NULL, 0, 1003, "Invalid option value", "Output File name is missing for -o option");\r
1852 goto ERROR;\r
1853 }\r
1854 OutputFileName = argv[1];\r
1855 argc -=2;\r
1856 argv +=2;\r
f7496d71 1857 continue;\r
30fdf114
LG
1858 }\r
1859\r
1860 if (argv[0][0]!='-') {\r
1861 InputFileName = argv[0];\r
1862 argc--;\r
1863 argv++;\r
1864 continue;\r
1865 }\r
1866\r
1867 Error (NULL, 0, 1000, "Unknown option", argv[0]);\r
f7496d71 1868 goto ERROR;\r
30fdf114
LG
1869 }\r
1870\r
1871 if (InputFileName == NULL) {\r
1872 Error (NULL, 0, 1001, "Missing options", "No input files specified.");\r
1873 goto ERROR;\r
1874 }\r
1875\r
1876//\r
1877// All Parameters has been parsed, now set the message print level\r
1878//\r
1879 if (QuietMode) {\r
1880 SetPrintLevel(40);\r
1881 } else if (VerboseMode) {\r
1882 SetPrintLevel(15);\r
1883 } else if (DebugMode) {\r
1884 SetPrintLevel(DebugLevel);\r
1885 }\r
f7496d71 1886\r
30fdf114
LG
1887 if (VerboseMode) {\r
1888 VerboseMsg("%s tool start.\n", UTILITY_NAME);\r
1889 }\r
1890 Scratch = (SCRATCH_DATA *)malloc(sizeof(SCRATCH_DATA));\r
1891 if (Scratch == NULL) {\r
1892 Error (NULL, 0, 4001, "Resource:", "Memory cannot be allocated!");\r
1893 goto ERROR;\r
1894 }\r
f7496d71 1895\r
97fa0ee9 1896 InputFile = fopen (LongFilePath (InputFileName), "rb");\r
30fdf114
LG
1897 if (InputFile == NULL) {\r
1898 Error (NULL, 0, 0001, "Error opening input file", InputFileName);\r
1899 goto ERROR;\r
1900 }\r
f7496d71 1901\r
30fdf114
LG
1902 Status = GetFileContents(\r
1903 InputFileName,\r
1904 FileBuffer,\r
1905 &InputLength);\r
1906\r
1907 if (Status == EFI_BUFFER_TOO_SMALL) {\r
1908 FileBuffer = (UINT8 *) malloc (InputLength);\r
1909 if (FileBuffer == NULL) {\r
1910 Error (NULL, 0, 4001, "Resource:", "Memory cannot be allocated!");\r
076947cf 1911 goto ERROR;\r
30fdf114
LG
1912 }\r
1913\r
1914 Status = GetFileContents (\r
1915 InputFileName,\r
1916 FileBuffer,\r
1917 &InputLength\r
1918 );\r
1919 }\r
1920\r
1921 if (EFI_ERROR(Status)) {\r
076947cf
HW
1922 Error (NULL, 0, 0004, "Error getting contents of file: %s", InputFileName);\r
1923 goto ERROR;\r
30fdf114 1924 }\r
d1f6eb27
HW
1925\r
1926 if (OutputFileName == NULL) {\r
1927 OutputFileName = DEFAULT_OUTPUT_FILE;\r
1928 }\r
1929 OutputFile = fopen (LongFilePath (OutputFileName), "wb");\r
1930 if (OutputFile == NULL) {\r
1931 Error (NULL, 0, 0001, "Error opening output file for writing", OutputFileName);\r
d1f6eb27
HW
1932 goto ERROR;\r
1933 }\r
f7496d71 1934\r
30fdf114
LG
1935 if (ENCODE) {\r
1936 //\r
1937 // First call TianoCompress to get DstSize\r
1938 //\r
1939 if (DebugMode) {\r
1940 DebugMsg(UTILITY_NAME, 0, DebugLevel, "Encoding", NULL);\r
1941 }\r
1942 Status = TianoCompress ((UINT8 *)FileBuffer, InputLength, OutBuffer, &DstSize);\r
f7496d71 1943\r
30fdf114
LG
1944 if (Status == EFI_BUFFER_TOO_SMALL) {\r
1945 OutBuffer = (UINT8 *) malloc (DstSize);\r
1946 if (OutBuffer == NULL) {\r
1947 Error (NULL, 0, 4001, "Resource:", "Memory cannot be allocated!");\r
1948 goto ERROR;\r
1949 }\r
1950 }\r
d1f6eb27 1951\r
30fdf114
LG
1952 Status = TianoCompress ((UINT8 *)FileBuffer, InputLength, OutBuffer, &DstSize);\r
1953 if (Status != EFI_SUCCESS) {\r
1954 Error (NULL, 0, 0007, "Error compressing file", NULL);\r
1955 goto ERROR;\r
1956 }\r
1957\r
d1f6eb27
HW
1958 if (OutBuffer == NULL) {\r
1959 Error (NULL, 0, 4001, "Resource:", "Memory cannot be allocated!");\r
1960 goto ERROR;\r
1961 }\r
1962\r
30fdf114 1963 fwrite(OutBuffer,(size_t)DstSize, 1, OutputFile);\r
4d32be88
HW
1964 fclose(OutputFile);\r
1965 fclose(InputFile);\r
30fdf114
LG
1966 free(Scratch);\r
1967 free(FileBuffer);\r
1968 free(OutBuffer);\r
1969\r
1970 if (DebugMode) {\r
1971 DebugMsg(UTILITY_NAME, 0, DebugLevel, "Encoding Successful!\n", NULL);\r
1972 }\r
1973 if (VerboseMode) {\r
1974 VerboseMsg("Encoding successful\n");\r
1975 }\r
f7496d71 1976 return 0;\r
30fdf114
LG
1977 }\r
1978 else if (DECODE) {\r
1979 if (DebugMode) {\r
1980 DebugMsg(UTILITY_NAME, 0, DebugLevel, "Decoding\n", NULL);\r
1981 }\r
1982 //\r
1983 // Get Compressed file original size\r
f7496d71
LG
1984 //\r
1985 Src = (UINT8 *)FileBuffer;\r
1986 OrigSize = Src[4] + (Src[5] << 8) + (Src[6] << 16) + (Src[7] << 24);\r
1987\r
30fdf114
LG
1988 //\r
1989 // Allocate OutputBuffer\r
1990 //\r
1991 OutBuffer = (UINT8 *)malloc(OrigSize);\r
1992 if (OutBuffer == NULL) {\r
1993 Error (NULL, 0, 4001, "Resource:", "Memory cannot be allocated!");\r
1994 goto ERROR;\r
f7496d71 1995 }\r
30fdf114
LG
1996\r
1997 Status = Decompress((VOID *)FileBuffer, (VOID *)OutBuffer, (VOID *)Scratch, 2);\r
1998 if (Status != EFI_SUCCESS) {\r
f7496d71 1999 goto ERROR;\r
30fdf114
LG
2000 }\r
2001\r
2002 fwrite(OutBuffer, (size_t)(Scratch->mOrigSize), 1, OutputFile);\r
4d32be88
HW
2003 fclose(OutputFile);\r
2004 fclose(InputFile);\r
30fdf114
LG
2005 free(Scratch);\r
2006 free(FileBuffer);\r
2007 free(OutBuffer);\r
2008\r
2009 if (DebugMode) {\r
2010 DebugMsg(UTILITY_NAME, 0, DebugLevel, "Encoding successful!\n", NULL);\r
2011 }\r
f7496d71 2012\r
30fdf114
LG
2013 if (VerboseMode) {\r
2014 VerboseMsg("Decoding successful\n");\r
2015 }\r
2016 return 0;\r
2017 }\r
f7496d71 2018\r
30fdf114
LG
2019ERROR:\r
2020 if (DebugMode) {\r
2021 if (ENCODE) {\r
2022 DebugMsg(UTILITY_NAME, 0, DebugLevel, "Encoding Error\n", NULL);\r
2023 } else if (DECODE) {\r
2024 DebugMsg(UTILITY_NAME, 0, DebugLevel, "Decoding Error\n", NULL);\r
2025 }\r
2026 }\r
4d32be88
HW
2027 if (OutputFile != NULL) {\r
2028 fclose(OutputFile);\r
2029 }\r
2030 if (InputFile != NULL) {\r
2031 fclose (InputFile);\r
2032 }\r
30fdf114
LG
2033 if (Scratch != NULL) {\r
2034 free(Scratch);\r
2035 }\r
2036 if (FileBuffer != NULL) {\r
2037 free(FileBuffer);\r
2038 }\r
2039 if (OutBuffer != NULL) {\r
2040 free(OutBuffer);\r
2041 }\r
f7496d71 2042\r
30fdf114
LG
2043 if (VerboseMode) {\r
2044 VerboseMsg("%s tool done with return code is 0x%x.\n", UTILITY_NAME, GetUtilityStatus ());\r
2045 }\r
2046 return GetUtilityStatus ();\r
2047}\r
2048\r
2049VOID\r
2050FillBuf (\r
2051 IN SCRATCH_DATA *Sd,\r
2052 IN UINT16 NumOfBits\r
2053 )\r
2054/*++\r
2055\r
2056Routine Description:\r
2057\r
2058 Shift mBitBuf NumOfBits left. Read in NumOfBits of bits from source.\r
2059\r
2060Arguments:\r
2061\r
2062 Sd - The global scratch data\r
2063 NumOfBits - The number of bits to shift and read.\r
2064\r
2065Returns: (VOID)\r
2066\r
2067--*/\r
2068{\r
59bc913c 2069 Sd->mBitBuf = (UINT32) (((UINT64)Sd->mBitBuf) << NumOfBits);\r
30fdf114
LG
2070\r
2071 while (NumOfBits > Sd->mBitCount) {\r
2072\r
59bc913c 2073 Sd->mBitBuf |= (UINT32) (((UINT64)Sd->mSubBitBuf) << (NumOfBits = (UINT16) (NumOfBits - Sd->mBitCount)));\r
30fdf114
LG
2074\r
2075 if (Sd->mCompSize > 0) {\r
2076 //\r
2077 // Get 1 byte into SubBitBuf\r
2078 //\r
2079 Sd->mCompSize--;\r
2080 Sd->mSubBitBuf = 0;\r
2081 Sd->mSubBitBuf = Sd->mSrcBase[Sd->mInBuf++];\r
2082 Sd->mBitCount = 8;\r
2083\r
2084 } else {\r
2085 //\r
2086 // No more bits from the source, just pad zero bit.\r
2087 //\r
2088 Sd->mSubBitBuf = 0;\r
2089 Sd->mBitCount = 8;\r
2090\r
2091 }\r
2092 }\r
2093\r
2094 Sd->mBitCount = (UINT16) (Sd->mBitCount - NumOfBits);\r
2095 Sd->mBitBuf |= Sd->mSubBitBuf >> Sd->mBitCount;\r
2096}\r
2097\r
2098UINT32\r
2099GetBits (\r
2100 IN SCRATCH_DATA *Sd,\r
2101 IN UINT16 NumOfBits\r
2102 )\r
2103/*++\r
2104\r
2105Routine Description:\r
2106\r
f7496d71
LG
2107 Get NumOfBits of bits out from mBitBuf. Fill mBitBuf with subsequent\r
2108 NumOfBits of bits from source. Returns NumOfBits of bits that are\r
30fdf114
LG
2109 popped out.\r
2110\r
2111Arguments:\r
2112\r
2113 Sd - The global scratch data.\r
2114 NumOfBits - The number of bits to pop and read.\r
2115\r
2116Returns:\r
2117\r
2118 The bits that are popped out.\r
2119\r
2120--*/\r
2121{\r
2122 UINT32 OutBits;\r
2123\r
2124 OutBits = (UINT32) (Sd->mBitBuf >> (BITBUFSIZ - NumOfBits));\r
2125\r
2126 FillBuf (Sd, NumOfBits);\r
2127\r
2128 return OutBits;\r
2129}\r
2130\r
2131UINT16\r
2132MakeTable (\r
2133 IN SCRATCH_DATA *Sd,\r
2134 IN UINT16 NumOfChar,\r
2135 IN UINT8 *BitLen,\r
2136 IN UINT16 TableBits,\r
2137 OUT UINT16 *Table\r
2138 )\r
2139/*++\r
2140\r
2141Routine Description:\r
2142\r
2143 Creates Huffman Code mapping table according to code length array.\r
2144\r
2145Arguments:\r
2146\r
2147 Sd - The global scratch data\r
2148 NumOfChar - Number of symbols in the symbol set\r
2149 BitLen - Code length array\r
2150 TableBits - The width of the mapping table\r
2151 Table - The table\r
f7496d71 2152\r
30fdf114 2153Returns:\r
f7496d71 2154\r
30fdf114
LG
2155 0 - OK.\r
2156 BAD_TABLE - The table is corrupted.\r
2157\r
2158--*/\r
2159{\r
2160 UINT16 Count[17];\r
2161 UINT16 Weight[17];\r
2162 UINT16 Start[18];\r
2163 UINT16 *Pointer;\r
2164 UINT16 Index3;\r
10bcabc6 2165 UINT16 Index;\r
30fdf114
LG
2166 UINT16 Len;\r
2167 UINT16 Char;\r
2168 UINT16 JuBits;\r
2169 UINT16 Avail;\r
2170 UINT16 NextCode;\r
2171 UINT16 Mask;\r
2172 UINT16 WordOfStart;\r
2173 UINT16 WordOfCount;\r
2174\r
10bcabc6 2175 for (Index = 0; Index <= 16; Index++) {\r
30fdf114
LG
2176 Count[Index] = 0;\r
2177 }\r
2178\r
2179 for (Index = 0; Index < NumOfChar; Index++) {\r
2180 Count[BitLen[Index]]++;\r
2181 }\r
2182\r
10bcabc6 2183 Start[0] = 0;\r
30fdf114
LG
2184 Start[1] = 0;\r
2185\r
2186 for (Index = 1; Index <= 16; Index++) {\r
2187 WordOfStart = Start[Index];\r
2188 WordOfCount = Count[Index];\r
2189 Start[Index + 1] = (UINT16) (WordOfStart + (WordOfCount << (16 - Index)));\r
2190 }\r
2191\r
2192 if (Start[17] != 0) {\r
2193 //\r
2194 //(1U << 16)\r
2195 //\r
2196 return (UINT16) BAD_TABLE;\r
2197 }\r
2198\r
2199 JuBits = (UINT16) (16 - TableBits);\r
2200\r
10bcabc6 2201 Weight[0] = 0;\r
30fdf114
LG
2202 for (Index = 1; Index <= TableBits; Index++) {\r
2203 Start[Index] >>= JuBits;\r
2204 Weight[Index] = (UINT16) (1U << (TableBits - Index));\r
2205 }\r
2206\r
2207 while (Index <= 16) {\r
2208 Weight[Index] = (UINT16) (1U << (16 - Index));\r
2209 Index++;\r
2210 }\r
2211\r
2212 Index = (UINT16) (Start[TableBits + 1] >> JuBits);\r
2213\r
2214 if (Index != 0) {\r
2215 Index3 = (UINT16) (1U << TableBits);\r
2216 while (Index != Index3) {\r
2217 Table[Index++] = 0;\r
2218 }\r
2219 }\r
2220\r
2221 Avail = NumOfChar;\r
2222 Mask = (UINT16) (1U << (15 - TableBits));\r
2223\r
2224 for (Char = 0; Char < NumOfChar; Char++) {\r
2225\r
2226 Len = BitLen[Char];\r
5acc8d3c 2227 if (Len == 0 || Len >= 17) {\r
30fdf114
LG
2228 continue;\r
2229 }\r
2230\r
2231 NextCode = (UINT16) (Start[Len] + Weight[Len]);\r
2232\r
2233 if (Len <= TableBits) {\r
2234\r
2235 for (Index = Start[Len]; Index < NextCode; Index++) {\r
2236 Table[Index] = Char;\r
2237 }\r
2238\r
2239 } else {\r
2240\r
2241 Index3 = Start[Len];\r
2242 Pointer = &Table[Index3 >> JuBits];\r
2243 Index = (UINT16) (Len - TableBits);\r
2244\r
2245 while (Index != 0) {\r
2246 if (*Pointer == 0) {\r
2247 Sd->mRight[Avail] = Sd->mLeft[Avail] = 0;\r
2248 *Pointer = Avail++;\r
2249 }\r
2250\r
2251 if (Index3 & Mask) {\r
2252 Pointer = &Sd->mRight[*Pointer];\r
2253 } else {\r
2254 Pointer = &Sd->mLeft[*Pointer];\r
2255 }\r
2256\r
2257 Index3 <<= 1;\r
2258 Index--;\r
2259 }\r
2260\r
2261 *Pointer = Char;\r
2262\r
2263 }\r
2264\r
2265 Start[Len] = NextCode;\r
2266 }\r
2267 //\r
2268 // Succeeds\r
2269 //\r
2270 return 0;\r
2271}\r
2272\r
2273UINT32\r
2274DecodeP (\r
2275 IN SCRATCH_DATA *Sd\r
2276 )\r
2277/*++\r
2278\r
2279Routine Description:\r
2280\r
2281 Decodes a position value.\r
2282\r
2283Arguments:\r
2284\r
2285 Sd - the global scratch data\r
2286\r
2287Returns:\r
2288\r
2289 The position value decoded.\r
2290\r
2291--*/\r
2292{\r
2293 UINT16 Val;\r
2294 UINT32 Mask;\r
2295 UINT32 Pos;\r
2296\r
2297 Val = Sd->mPTTable[Sd->mBitBuf >> (BITBUFSIZ - 8)];\r
2298\r
2299 if (Val >= MAXNP) {\r
2300 Mask = 1U << (BITBUFSIZ - 1 - 8);\r
2301\r
2302 do {\r
2303\r
2304 if (Sd->mBitBuf & Mask) {\r
2305 Val = Sd->mRight[Val];\r
2306 } else {\r
2307 Val = Sd->mLeft[Val];\r
2308 }\r
2309\r
2310 Mask >>= 1;\r
2311 } while (Val >= MAXNP);\r
2312 }\r
2313 //\r
2314 // Advance what we have read\r
2315 //\r
2316 FillBuf (Sd, Sd->mPTLen[Val]);\r
2317\r
2318 Pos = Val;\r
2319 if (Val > 1) {\r
2320 Pos = (UINT32) ((1U << (Val - 1)) + GetBits (Sd, (UINT16) (Val - 1)));\r
2321 }\r
2322\r
2323 return Pos;\r
2324}\r
2325\r
2326UINT16\r
2327ReadPTLen (\r
2328 IN SCRATCH_DATA *Sd,\r
2329 IN UINT16 nn,\r
2330 IN UINT16 nbit,\r
2331 IN UINT16 Special\r
2332 )\r
2333/*++\r
2334\r
2335Routine Description:\r
2336\r
2337 Reads code lengths for the Extra Set or the Position Set\r
2338\r
2339Arguments:\r
2340\r
2341 Sd - The global scratch data\r
2342 nn - Number of symbols\r
2343 nbit - Number of bits needed to represent nn\r
f7496d71 2344 Special - The special symbol that needs to be taken care of\r
30fdf114
LG
2345\r
2346Returns:\r
2347\r
2348 0 - OK.\r
2349 BAD_TABLE - Table is corrupted.\r
2350\r
2351--*/\r
2352{\r
2353 UINT16 Number;\r
2354 UINT16 CharC;\r
2355 volatile UINT16 Index;\r
2356 UINT32 Mask;\r
2357\r
5acc8d3c
HW
2358 assert (nn <= NPT);\r
2359\r
30fdf114
LG
2360 Number = (UINT16) GetBits (Sd, nbit);\r
2361\r
2362 if (Number == 0) {\r
2363 CharC = (UINT16) GetBits (Sd, nbit);\r
2364\r
2365 for (Index = 0; Index < 256; Index++) {\r
2366 Sd->mPTTable[Index] = CharC;\r
2367 }\r
2368\r
2369 for (Index = 0; Index < nn; Index++) {\r
2370 Sd->mPTLen[Index] = 0;\r
2371 }\r
2372\r
2373 return 0;\r
2374 }\r
2375\r
2376 Index = 0;\r
2377\r
2378 while (Index < Number) {\r
2379\r
2380 CharC = (UINT16) (Sd->mBitBuf >> (BITBUFSIZ - 3));\r
2381\r
2382 if (CharC == 7) {\r
2383 Mask = 1U << (BITBUFSIZ - 1 - 3);\r
2384 while (Mask & Sd->mBitBuf) {\r
2385 Mask >>= 1;\r
2386 CharC += 1;\r
2387 }\r
2388 }\r
2389\r
2390 FillBuf (Sd, (UINT16) ((CharC < 7) ? 3 : CharC - 3));\r
2391\r
2392 Sd->mPTLen[Index++] = (UINT8) CharC;\r
2393\r
2394 if (Index == Special) {\r
2395 CharC = (UINT16) GetBits (Sd, 2);\r
2396 while ((INT16) (--CharC) >= 0) {\r
2397 Sd->mPTLen[Index++] = 0;\r
2398 }\r
2399 }\r
2400 }\r
2401\r
2402 while (Index < nn) {\r
2403 Sd->mPTLen[Index++] = 0;\r
2404 }\r
2405\r
2406 return MakeTable (Sd, nn, Sd->mPTLen, 8, Sd->mPTTable);\r
2407}\r
2408\r
2409VOID\r
2410ReadCLen (\r
2411 SCRATCH_DATA *Sd\r
2412 )\r
2413/*++\r
2414\r
2415Routine Description:\r
2416\r
2417 Reads code lengths for Char&Len Set.\r
2418\r
2419Arguments:\r
2420\r
2421 Sd - the global scratch data\r
2422\r
2423Returns: (VOID)\r
2424\r
2425--*/\r
2426{\r
2427 UINT16 Number;\r
2428 UINT16 CharC;\r
2429 volatile UINT16 Index;\r
2430 UINT32 Mask;\r
2431\r
2432 Number = (UINT16) GetBits (Sd, CBIT);\r
2433\r
2434 if (Number == 0) {\r
2435 CharC = (UINT16) GetBits (Sd, CBIT);\r
2436\r
2437 for (Index = 0; Index < NC; Index++) {\r
2438 Sd->mCLen[Index] = 0;\r
2439 }\r
2440\r
2441 for (Index = 0; Index < 4096; Index++) {\r
2442 Sd->mCTable[Index] = CharC;\r
2443 }\r
2444\r
2445 return ;\r
2446 }\r
2447\r
2448 Index = 0;\r
2449 while (Index < Number) {\r
2450\r
2451 CharC = Sd->mPTTable[Sd->mBitBuf >> (BITBUFSIZ - 8)];\r
2452 if (CharC >= NT) {\r
2453 Mask = 1U << (BITBUFSIZ - 1 - 8);\r
2454\r
2455 do {\r
2456\r
2457 if (Mask & Sd->mBitBuf) {\r
2458 CharC = Sd->mRight[CharC];\r
2459 } else {\r
2460 CharC = Sd->mLeft[CharC];\r
2461 }\r
2462\r
2463 Mask >>= 1;\r
2464\r
2465 } while (CharC >= NT);\r
2466 }\r
2467 //\r
2468 // Advance what we have read\r
2469 //\r
2470 FillBuf (Sd, Sd->mPTLen[CharC]);\r
2471\r
2472 if (CharC <= 2) {\r
2473\r
2474 if (CharC == 0) {\r
2475 CharC = 1;\r
2476 } else if (CharC == 1) {\r
2477 CharC = (UINT16) (GetBits (Sd, 4) + 3);\r
2478 } else if (CharC == 2) {\r
2479 CharC = (UINT16) (GetBits (Sd, CBIT) + 20);\r
2480 }\r
2481\r
2482 while ((INT16) (--CharC) >= 0) {\r
2483 Sd->mCLen[Index++] = 0;\r
2484 }\r
2485\r
2486 } else {\r
2487\r
2488 Sd->mCLen[Index++] = (UINT8) (CharC - 2);\r
2489\r
2490 }\r
2491 }\r
2492\r
2493 while (Index < NC) {\r
2494 Sd->mCLen[Index++] = 0;\r
2495 }\r
2496\r
2497 MakeTable (Sd, NC, Sd->mCLen, 12, Sd->mCTable);\r
2498\r
2499 return ;\r
2500}\r
2501\r
2502UINT16\r
2503DecodeC (\r
2504 SCRATCH_DATA *Sd\r
2505 )\r
2506/*++\r
2507\r
2508Routine Description:\r
2509\r
2510 Decode a character/length value.\r
2511\r
2512Arguments:\r
2513\r
2514 Sd - The global scratch data.\r
2515\r
2516Returns:\r
2517\r
2518 The value decoded.\r
2519\r
2520--*/\r
2521{\r
2522 UINT16 Index2;\r
2523 UINT32 Mask;\r
2524\r
2525 if (Sd->mBlockSize == 0) {\r
2526 //\r
2527 // Starting a new block\r
2528 //\r
2529 Sd->mBlockSize = (UINT16) GetBits (Sd, 16);\r
2530 Sd->mBadTableFlag = ReadPTLen (Sd, NT, TBIT, 3);\r
2531 if (Sd->mBadTableFlag != 0) {\r
2532 return 0;\r
2533 }\r
2534\r
2535 ReadCLen (Sd);\r
2536\r
2537 Sd->mBadTableFlag = ReadPTLen (Sd, MAXNP, Sd->mPBit, (UINT16) (-1));\r
2538 if (Sd->mBadTableFlag != 0) {\r
2539 return 0;\r
2540 }\r
2541 }\r
2542\r
2543 Sd->mBlockSize--;\r
2544 Index2 = Sd->mCTable[Sd->mBitBuf >> (BITBUFSIZ - 12)];\r
2545\r
2546 if (Index2 >= NC) {\r
2547 Mask = 1U << (BITBUFSIZ - 1 - 12);\r
2548\r
2549 do {\r
2550 if (Sd->mBitBuf & Mask) {\r
2551 Index2 = Sd->mRight[Index2];\r
2552 } else {\r
2553 Index2 = Sd->mLeft[Index2];\r
2554 }\r
2555\r
2556 Mask >>= 1;\r
2557 } while (Index2 >= NC);\r
2558 }\r
2559 //\r
2560 // Advance what we have read\r
2561 //\r
2562 FillBuf (Sd, Sd->mCLen[Index2]);\r
2563\r
2564 return Index2;\r
2565}\r
2566\r
2567VOID\r
2568Decode (\r
2569 SCRATCH_DATA *Sd\r
2570 )\r
2571/*++\r
2572\r
2573Routine Description:\r
2574\r
2575 Decode the source data and put the resulting data into the destination buffer.\r
2576\r
2577Arguments:\r
2578\r
2579 Sd - The global scratch data\r
2580\r
2581Returns: (VOID)\r
2582\r
2583 --*/\r
2584{\r
2585 UINT16 BytesRemain;\r
2586 UINT32 DataIdx;\r
2587 UINT16 CharC;\r
2588\r
2589 BytesRemain = (UINT16) (-1);\r
2590\r
2591 DataIdx = 0;\r
2592\r
2593 for (;;) {\r
2594 CharC = DecodeC (Sd);\r
2595 if (Sd->mBadTableFlag != 0) {\r
2596 goto Done ;\r
2597 }\r
2598\r
2599 if (CharC < 256) {\r
2600 //\r
2601 // Process an Original character\r
2602 //\r
2603 if (Sd->mOutBuf >= Sd->mOrigSize) {\r
2604 goto Done ;\r
2605 } else {\r
2606 Sd->mDstBase[Sd->mOutBuf++] = (UINT8) CharC;\r
2607 }\r
2608\r
2609 } else {\r
2610 //\r
2611 // Process a Pointer\r
2612 //\r
2613 CharC = (UINT16) (CharC - (UINT8_MAX + 1 - THRESHOLD));\r
2614\r
2615 BytesRemain = CharC;\r
2616\r
2617 DataIdx = Sd->mOutBuf - DecodeP (Sd) - 1;\r
2618\r
2619 BytesRemain--;\r
2620 while ((INT16) (BytesRemain) >= 0) {\r
2621 Sd->mDstBase[Sd->mOutBuf++] = Sd->mDstBase[DataIdx++];\r
2622 if (Sd->mOutBuf >= Sd->mOrigSize) {\r
2623 goto Done ;\r
2624 }\r
2625\r
2626 BytesRemain--;\r
2627 }\r
2628 }\r
2629 }\r
2630\r
2631Done:\r
2632 return ;\r
2633}\r
2634\r
2635RETURN_STATUS\r
2636EFIAPI\r
2637Decompress (\r
2638 IN VOID *Source,\r
2639 IN OUT VOID *Destination,\r
2640 IN OUT VOID *Scratch,\r
2641 IN UINT32 Version\r
2642 )\r
2643/*++\r
2644\r
2645Routine Description:\r
2646\r
2647 The internal implementation of Decompress().\r
2648\r
2649Arguments:\r
2650\r
2651 Source - The source buffer containing the compressed data.\r
2652 Destination - The destination buffer to store the decompressed data\r
2653 Scratch - The buffer used internally by the decompress routine. This buffer is needed to store intermediate data.\r
2654 Version - 1 for EFI1.1 Decompress algoruthm, 2 for Tiano Decompress algorithm\r
2655\r
2656Returns:\r
2657\r
2658 RETURN_SUCCESS - Decompression is successfull\r
2659 RETURN_INVALID_PARAMETER - The source data is corrupted\r
2660\r
2661--*/\r
2662{\r
2663 volatile UINT32 Index;\r
2664 UINT32 CompSize;\r
2665 UINT32 OrigSize;\r
2666 SCRATCH_DATA *Sd;\r
2667 CONST UINT8 *Src;\r
2668 UINT8 *Dst;\r
2669\r
2670 //\r
2671 // Verify input is not NULL\r
2672 //\r
2673 assert(Source);\r
2674// assert(Destination);\r
2675 assert(Scratch);\r
f7496d71 2676\r
30fdf114
LG
2677 Src = (UINT8 *)Source;\r
2678 Dst = (UINT8 *)Destination;\r
2679\r
2680 Sd = (SCRATCH_DATA *) Scratch;\r
2681 CompSize = Src[0] + (Src[1] << 8) + (Src[2] << 16) + (Src[3] << 24);\r
2682 OrigSize = Src[4] + (Src[5] << 8) + (Src[6] << 16) + (Src[7] << 24);\r
f7496d71 2683\r
30fdf114
LG
2684 //\r
2685 // If compressed file size is 0, return\r
2686 //\r
2687 if (OrigSize == 0) {\r
2688 return RETURN_SUCCESS;\r
2689 }\r
2690\r
2691 Src = Src + 8;\r
2692\r
2693 for (Index = 0; Index < sizeof (SCRATCH_DATA); Index++) {\r
2694 ((UINT8 *) Sd)[Index] = 0;\r
2695 }\r
2696 //\r
2697 // The length of the field 'Position Set Code Length Array Size' in Block Header.\r
2698 // For EFI 1.1 de/compression algorithm(Version 1), mPBit = 4\r
2699 // For Tiano de/compression algorithm(Version 2), mPBit = 5\r
2700 //\r
2701 switch (Version) {\r
2702 case 1 :\r
2703 Sd->mPBit = 4;\r
2704 break;\r
2705 case 2 :\r
2706 Sd->mPBit = 5;\r
2707 break;\r
2708 default:\r
2709 assert(FALSE);\r
2710 }\r
2711 Sd->mSrcBase = (UINT8 *)Src;\r
2712 Sd->mDstBase = Dst;\r
2713 Sd->mCompSize = CompSize;\r
2714 Sd->mOrigSize = OrigSize;\r
2715\r
2716 //\r
2717 // Fill the first BITBUFSIZ bits\r
2718 //\r
2719 FillBuf (Sd, BITBUFSIZ);\r
2720\r
2721 //\r
2722 // Decompress it\r
2723 //\r
f7496d71 2724\r
30fdf114 2725 Decode (Sd);\r
f7496d71 2726\r
30fdf114
LG
2727 if (Sd->mBadTableFlag != 0) {\r
2728 //\r
2729 // Something wrong with the source\r
2730 //\r
2731 return RETURN_INVALID_PARAMETER;\r
2732 }\r
2733\r
2734 return RETURN_SUCCESS;\r
2735}\r
2736\r
2737\r