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