• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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