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