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