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