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