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