1 /* Copyright (c) 2010 The Chromium OS Authors. All rights reserved.
2  * Use of this source code is governed by a BSD-style license that can be
3  * found in the LICENSE file.
4  */
5 
6 /*++
7 
8 Copyright (c) 2004 - 2006, Intel Corporation
9 All rights reserved. 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 Module Name:
18 
19   Decompress.c
20 
21 Abstract:
22 
23   Decompressor. Algorithm Ported from OPSD code (Decomp.asm)
24 
25 --*/
26 
27 #include <errno.h>
28 #include <stdint.h>
29 #include <stdio.h>
30 #include <stdlib.h>
31 #include <string.h>
32 #include <sys/types.h>
33 #include <sys/stat.h>
34 #include <unistd.h>
35 
36 #include "eficompress.h"
37 
38 
39 //
40 // Decompression algorithm begins here
41 //
42 #define BITBUFSIZ 32
43 #define MAXMATCH  256
44 #define THRESHOLD 3
45 #define CODE_BIT  16
46 #define BAD_TABLE - 1
47 
48 //
49 // C: Char&Len Set; P: Position Set; T: exTra Set
50 //
51 #define NC      (0xff + MAXMATCH + 2 - THRESHOLD)
52 #define CBIT    9
53 #define MAXPBIT 5
54 #define TBIT    5
55 #define MAXNP   ((1U << MAXPBIT) - 1)
56 #define NT      (CODE_BIT + 3)
57 #if NT > MAXNP
58 #define NPT NT
59 #else
60 #define NPT MAXNP
61 #endif
62 
63 typedef struct {
64   UINT8   *mSrcBase;  // Starting address of compressed data
65   UINT8   *mDstBase;  // Starting address of decompressed data
66   UINT32  mOutBuf;
67   UINT32  mInBuf;
68 
69   UINT16  mBitCount;
70   UINT32  mBitBuf;
71   UINT32  mSubBitBuf;
72   UINT16  mBlockSize;
73   UINT32  mCompSize;
74   UINT32  mOrigSize;
75 
76   UINT16  mBadTableFlag;
77 
78   UINT16  mLeft[2 * NC - 1];
79   UINT16  mRight[2 * NC - 1];
80   UINT8   mCLen[NC];
81   UINT8   mPTLen[NPT];
82   UINT16  mCTable[4096];
83   UINT16  mPTTable[256];
84 
85   //
86   // The length of the field 'Position Set Code Length Array Size' in Block Header.
87   // For EFI 1.1 de/compression algorithm, mPBit = 4
88   // For Tiano de/compression algorithm, mPBit = 5
89   //
90   UINT8   mPBit;
91 } SCRATCH_DATA;
92 
93 STATIC
94 VOID
FillBuf(IN SCRATCH_DATA * Sd,IN UINT16 NumOfBits)95 FillBuf (
96   IN  SCRATCH_DATA  *Sd,
97   IN  UINT16        NumOfBits
98   )
99 /*++
100 
101 Routine Description:
102 
103   Shift mBitBuf NumOfBits left. Read in NumOfBits of bits from source.
104 
105 Arguments:
106 
107   Sd        - The global scratch data
108   NumOfBits  - The number of bits to shift and read.
109 
110 Returns: (VOID)
111 
112 --*/
113 {
114   Sd->mBitBuf = (UINT32) (Sd->mBitBuf << NumOfBits);
115 
116   while (NumOfBits > Sd->mBitCount) {
117 
118     Sd->mBitBuf |= (UINT32) (Sd->mSubBitBuf << (NumOfBits = (UINT16) (NumOfBits - Sd->mBitCount)));
119 
120     if (Sd->mCompSize > 0) {
121       //
122       // Get 1 byte into SubBitBuf
123       //
124       Sd->mCompSize--;
125       Sd->mSubBitBuf  = 0;
126       Sd->mSubBitBuf  = Sd->mSrcBase[Sd->mInBuf++];
127       Sd->mBitCount   = 8;
128 
129     } else {
130       //
131       // No more bits from the source, just pad zero bit.
132       //
133       Sd->mSubBitBuf  = 0;
134       Sd->mBitCount   = 8;
135 
136     }
137   }
138 
139   Sd->mBitCount = (UINT16) (Sd->mBitCount - NumOfBits);
140   Sd->mBitBuf |= Sd->mSubBitBuf >> Sd->mBitCount;
141 }
142 
143 STATIC
144 UINT32
GetBits(IN SCRATCH_DATA * Sd,IN UINT16 NumOfBits)145 GetBits (
146   IN  SCRATCH_DATA  *Sd,
147   IN  UINT16        NumOfBits
148   )
149 /*++
150 
151 Routine Description:
152 
153   Get NumOfBits of bits out from mBitBuf. Fill mBitBuf with subsequent
154   NumOfBits of bits from source. Returns NumOfBits of bits that are
155   popped out.
156 
157 Arguments:
158 
159   Sd            - The global scratch data.
160   NumOfBits     - The number of bits to pop and read.
161 
162 Returns:
163 
164   The bits that are popped out.
165 
166 --*/
167 {
168   UINT32  OutBits;
169 
170   OutBits = (UINT32) (Sd->mBitBuf >> (BITBUFSIZ - NumOfBits));
171 
172   FillBuf (Sd, NumOfBits);
173 
174   return OutBits;
175 }
176 
177 STATIC
178 UINT16
MakeTable(IN SCRATCH_DATA * Sd,IN UINT16 NumOfChar,IN UINT8 * BitLen,IN UINT16 TableBits,OUT UINT16 * Table)179 MakeTable (
180   IN  SCRATCH_DATA  *Sd,
181   IN  UINT16        NumOfChar,
182   IN  UINT8         *BitLen,
183   IN  UINT16        TableBits,
184   OUT UINT16        *Table
185   )
186 /*++
187 
188 Routine Description:
189 
190   Creates Huffman Code mapping table according to code length array.
191 
192 Arguments:
193 
194   Sd        - The global scratch data
195   NumOfChar - Number of symbols in the symbol set
196   BitLen    - Code length array
197   TableBits - The width of the mapping table
198   Table     - The table
199 
200 Returns:
201 
202   0         - OK.
203   BAD_TABLE - The table is corrupted.
204 
205 --*/
206 {
207   UINT16  Count[17];
208   UINT16  Weight[17];
209   UINT16  Start[18];
210   UINT16  *Pointer;
211   UINT16  Index3;
212   UINT16  Index;
213   UINT16  Len;
214   UINT16  Char;
215   UINT16  JuBits;
216   UINT16  Avail;
217   UINT16  NextCode;
218   UINT16  Mask;
219 
220   for (Index = 1; Index <= 16; Index++) {
221     Count[Index] = 0;
222   }
223 
224   for (Index = 0; Index < NumOfChar; Index++) {
225     Count[BitLen[Index]]++;
226   }
227 
228   Start[1] = 0;
229 
230   for (Index = 1; Index <= 16; Index++) {
231     Start[Index + 1] = (UINT16) (Start[Index] + (Count[Index] << (16 - Index)));
232   }
233 
234   if (Start[17] != 0) {
235     /*(1U << 16)*/
236     return (UINT16) BAD_TABLE;
237   }
238 
239   JuBits = (UINT16) (16 - TableBits);
240 
241   for (Index = 1; Index <= TableBits; Index++) {
242     Start[Index] >>= JuBits;
243     Weight[Index] = (UINT16) (1U << (TableBits - Index));
244   }
245 
246   while (Index <= 16) {
247     Weight[Index] = (UINT16) (1U << (16 - Index));
248     Index++;
249   }
250 
251   Index = (UINT16) (Start[TableBits + 1] >> JuBits);
252 
253   if (Index != 0) {
254     Index3 = (UINT16) (1U << TableBits);
255     while (Index != Index3) {
256       Table[Index++] = 0;
257     }
258   }
259 
260   Avail = NumOfChar;
261   Mask  = (UINT16) (1U << (15 - TableBits));
262 
263   for (Char = 0; Char < NumOfChar; Char++) {
264 
265     Len = BitLen[Char];
266     if (Len == 0) {
267       continue;
268     }
269 
270     NextCode = (UINT16) (Start[Len] + Weight[Len]);
271 
272     if (Len <= TableBits) {
273 
274       for (Index = Start[Len]; Index < NextCode; Index++) {
275         Table[Index] = Char;
276       }
277 
278     } else {
279 
280       Index3  = Start[Len];
281       Pointer = &Table[Index3 >> JuBits];
282       Index   = (UINT16) (Len - TableBits);
283 
284       while (Index != 0) {
285         if (*Pointer == 0) {
286           Sd->mRight[Avail]                     = Sd->mLeft[Avail] = 0;
287           *Pointer = Avail++;
288         }
289 
290         if (Index3 & Mask) {
291           Pointer = &Sd->mRight[*Pointer];
292         } else {
293           Pointer = &Sd->mLeft[*Pointer];
294         }
295 
296         Index3 <<= 1;
297         Index--;
298       }
299 
300       *Pointer = Char;
301 
302     }
303 
304     Start[Len] = NextCode;
305   }
306   //
307   // Succeeds
308   //
309   return 0;
310 }
311 
312 STATIC
313 UINT32
DecodeP(IN SCRATCH_DATA * Sd)314 DecodeP (
315   IN  SCRATCH_DATA  *Sd
316   )
317 /*++
318 
319 Routine Description:
320 
321   Decodes a position value.
322 
323 Arguments:
324 
325   Sd      - the global scratch data
326 
327 Returns:
328 
329   The position value decoded.
330 
331 --*/
332 {
333   UINT16  Val;
334   UINT32  Mask;
335   UINT32  Pos;
336 
337   Val = Sd->mPTTable[Sd->mBitBuf >> (BITBUFSIZ - 8)];
338 
339   if (Val >= MAXNP) {
340     Mask = 1U << (BITBUFSIZ - 1 - 8);
341 
342     do {
343 
344       if (Sd->mBitBuf & Mask) {
345         Val = Sd->mRight[Val];
346       } else {
347         Val = Sd->mLeft[Val];
348       }
349 
350       Mask >>= 1;
351     } while (Val >= MAXNP);
352   }
353   //
354   // Advance what we have read
355   //
356   FillBuf (Sd, Sd->mPTLen[Val]);
357 
358   Pos = Val;
359   if (Val > 1) {
360     Pos = (UINT32) ((1U << (Val - 1)) + GetBits (Sd, (UINT16) (Val - 1)));
361   }
362 
363   return Pos;
364 }
365 
366 STATIC
367 UINT16
ReadPTLen(IN SCRATCH_DATA * Sd,IN UINT16 nn,IN UINT16 nbit,IN UINT16 Special)368 ReadPTLen (
369   IN  SCRATCH_DATA  *Sd,
370   IN  UINT16        nn,
371   IN  UINT16        nbit,
372   IN  UINT16        Special
373   )
374 /*++
375 
376 Routine Description:
377 
378   Reads code lengths for the Extra Set or the Position Set
379 
380 Arguments:
381 
382   Sd        - The global scratch data
383   nn        - Number of symbols
384   nbit      - Number of bits needed to represent nn
385   Special   - The special symbol that needs to be taken care of
386 
387 Returns:
388 
389   0         - OK.
390   BAD_TABLE - Table is corrupted.
391 
392 --*/
393 {
394   UINT16  Number;
395   UINT16  CharC;
396   UINT16  Index;
397   UINT32  Mask;
398 
399   Number = (UINT16) GetBits (Sd, nbit);
400 
401   if (Number == 0) {
402     CharC = (UINT16) GetBits (Sd, nbit);
403 
404     for (Index = 0; Index < 256; Index++) {
405       Sd->mPTTable[Index] = CharC;
406     }
407 
408     for (Index = 0; Index < nn; Index++) {
409       Sd->mPTLen[Index] = 0;
410     }
411 
412     return 0;
413   }
414 
415   Index = 0;
416 
417   while (Index < Number) {
418 
419     CharC = (UINT16) (Sd->mBitBuf >> (BITBUFSIZ - 3));
420 
421     if (CharC == 7) {
422       Mask = 1U << (BITBUFSIZ - 1 - 3);
423       while (Mask & Sd->mBitBuf) {
424         Mask >>= 1;
425         CharC += 1;
426       }
427     }
428 
429     FillBuf (Sd, (UINT16) ((CharC < 7) ? 3 : CharC - 3));
430 
431     Sd->mPTLen[Index++] = (UINT8) CharC;
432 
433     if (Index == Special) {
434       CharC = (UINT16) GetBits (Sd, 2);
435       while ((INT16) (--CharC) >= 0) {
436         Sd->mPTLen[Index++] = 0;
437       }
438     }
439   }
440 
441   while (Index < nn) {
442     Sd->mPTLen[Index++] = 0;
443   }
444 
445   return MakeTable (Sd, nn, Sd->mPTLen, 8, Sd->mPTTable);
446 }
447 
448 STATIC
449 VOID
ReadCLen(SCRATCH_DATA * Sd)450 ReadCLen (
451   SCRATCH_DATA  *Sd
452   )
453 /*++
454 
455 Routine Description:
456 
457   Reads code lengths for Char&Len Set.
458 
459 Arguments:
460 
461   Sd    - the global scratch data
462 
463 Returns: (VOID)
464 
465 --*/
466 {
467   UINT16  Number;
468   UINT16  CharC;
469   UINT16  Index;
470   UINT32  Mask;
471 
472   Number = (UINT16) GetBits (Sd, CBIT);
473 
474   if (Number == 0) {
475     CharC = (UINT16) GetBits (Sd, CBIT);
476 
477     for (Index = 0; Index < NC; Index++) {
478       Sd->mCLen[Index] = 0;
479     }
480 
481     for (Index = 0; Index < 4096; Index++) {
482       Sd->mCTable[Index] = CharC;
483     }
484 
485     return ;
486   }
487 
488   Index = 0;
489   while (Index < Number) {
490 
491     CharC = Sd->mPTTable[Sd->mBitBuf >> (BITBUFSIZ - 8)];
492     if (CharC >= NT) {
493       Mask = 1U << (BITBUFSIZ - 1 - 8);
494 
495       do {
496 
497         if (Mask & Sd->mBitBuf) {
498           CharC = Sd->mRight[CharC];
499         } else {
500           CharC = Sd->mLeft[CharC];
501         }
502 
503         Mask >>= 1;
504 
505       } while (CharC >= NT);
506     }
507     //
508     // Advance what we have read
509     //
510     FillBuf (Sd, Sd->mPTLen[CharC]);
511 
512     if (CharC <= 2) {
513 
514       if (CharC == 0) {
515         CharC = 1;
516       } else if (CharC == 1) {
517         CharC = (UINT16) (GetBits (Sd, 4) + 3);
518       } else if (CharC == 2) {
519         CharC = (UINT16) (GetBits (Sd, CBIT) + 20);
520       }
521 
522       while ((INT16) (--CharC) >= 0) {
523         Sd->mCLen[Index++] = 0;
524       }
525 
526     } else {
527 
528       Sd->mCLen[Index++] = (UINT8) (CharC - 2);
529 
530     }
531   }
532 
533   while (Index < NC) {
534     Sd->mCLen[Index++] = 0;
535   }
536 
537   MakeTable (Sd, NC, Sd->mCLen, 12, Sd->mCTable);
538 
539   return ;
540 }
541 
542 STATIC
543 UINT16
DecodeC(SCRATCH_DATA * Sd)544 DecodeC (
545   SCRATCH_DATA  *Sd
546   )
547 /*++
548 
549 Routine Description:
550 
551   Decode a character/length value.
552 
553 Arguments:
554 
555   Sd    - The global scratch data.
556 
557 Returns:
558 
559   The value decoded.
560 
561 --*/
562 {
563   UINT16  Index2;
564   UINT32  Mask;
565 
566   if (Sd->mBlockSize == 0) {
567     //
568     // Starting a new block
569     //
570     Sd->mBlockSize    = (UINT16) GetBits (Sd, 16);
571     Sd->mBadTableFlag = ReadPTLen (Sd, NT, TBIT, 3);
572     if (Sd->mBadTableFlag != 0) {
573       return 0;
574     }
575 
576     ReadCLen (Sd);
577 
578     Sd->mBadTableFlag = ReadPTLen (Sd, MAXNP, Sd->mPBit, (UINT16) (-1));
579     if (Sd->mBadTableFlag != 0) {
580       return 0;
581     }
582   }
583 
584   Sd->mBlockSize--;
585   Index2 = Sd->mCTable[Sd->mBitBuf >> (BITBUFSIZ - 12)];
586 
587   if (Index2 >= NC) {
588     Mask = 1U << (BITBUFSIZ - 1 - 12);
589 
590     do {
591       if (Sd->mBitBuf & Mask) {
592         Index2 = Sd->mRight[Index2];
593       } else {
594         Index2 = Sd->mLeft[Index2];
595       }
596 
597       Mask >>= 1;
598     } while (Index2 >= NC);
599   }
600   //
601   // Advance what we have read
602   //
603   FillBuf (Sd, Sd->mCLen[Index2]);
604 
605   return Index2;
606 }
607 
608 STATIC
609 VOID
Decode(SCRATCH_DATA * Sd)610 Decode (
611   SCRATCH_DATA  *Sd
612   )
613 /*++
614 
615 Routine Description:
616 
617   Decode the source data and put the resulting data into the destination buffer.
618 
619 Arguments:
620 
621   Sd            - The global scratch data
622 
623 Returns: (VOID)
624 
625  --*/
626 {
627   UINT16  BytesRemain;
628   UINT32  DataIdx;
629   UINT16  CharC;
630 
631   BytesRemain = (UINT16) (-1);
632 
633   DataIdx     = 0;
634 
635   for (;;) {
636     CharC = DecodeC (Sd);
637     if (Sd->mBadTableFlag != 0) {
638       return ;
639     }
640 
641     if (CharC < 256) {
642       //
643       // Process an Original character
644       //
645       if (Sd->mOutBuf >= Sd->mOrigSize) {
646         return ;
647       } else {
648         Sd->mDstBase[Sd->mOutBuf++] = (UINT8) CharC;
649       }
650 
651     } else {
652       //
653       // Process a Pointer
654       //
655       CharC       = (UINT16) (CharC - (UINT8_MAX + 1 - THRESHOLD));
656 
657       BytesRemain = CharC;
658 
659       DataIdx     = Sd->mOutBuf - DecodeP (Sd) - 1;
660 
661       BytesRemain--;
662       while ((INT16) (BytesRemain) >= 0) {
663         Sd->mDstBase[Sd->mOutBuf++] = Sd->mDstBase[DataIdx++];
664         if (Sd->mOutBuf >= Sd->mOrigSize) {
665           return ;
666         }
667 
668         BytesRemain--;
669       }
670     }
671   }
672 
673   return ;
674 }
675 
676 EFI_STATUS
GetInfo(IN VOID * Source,IN UINT32 SrcSize,OUT UINT32 * DstSize,OUT UINT32 * ScratchSize)677 GetInfo (
678   IN      VOID    *Source,
679   IN      UINT32  SrcSize,
680   OUT     UINT32  *DstSize,
681   OUT     UINT32  *ScratchSize
682   )
683 /*++
684 
685 Routine Description:
686 
687   The internal implementation of *_DECOMPRESS_PROTOCOL.GetInfo().
688 
689 Arguments:
690 
691   Source      - The source buffer containing the compressed data.
692   SrcSize     - The size of source buffer
693   DstSize     - The size of destination buffer.
694   ScratchSize - The size of scratch buffer.
695 
696 Returns:
697 
698   EFI_SUCCESS           - The size of destination buffer and the size of scratch buffer are successull retrieved.
699   EFI_INVALID_PARAMETER - The source data is corrupted
700 
701 --*/
702 {
703   UINT8 *Src;
704 
705   *ScratchSize  = sizeof (SCRATCH_DATA);
706 
707   Src           = Source;
708   if (SrcSize < 8) {
709     return EFI_INVALID_PARAMETER;
710   }
711 
712   *DstSize = Src[4] + (Src[5] << 8) + (Src[6] << 16) + (Src[7] << 24);
713   return EFI_SUCCESS;
714 }
715 
716 EFI_STATUS
Decompress(IN VOID * Source,IN UINT32 SrcSize,IN OUT VOID * Destination,IN UINT32 DstSize,IN OUT VOID * Scratch,IN UINT32 ScratchSize,IN UINT8 Version)717 Decompress (
718   IN      VOID    *Source,
719   IN      UINT32  SrcSize,
720   IN OUT  VOID    *Destination,
721   IN      UINT32  DstSize,
722   IN OUT  VOID    *Scratch,
723   IN      UINT32  ScratchSize,
724   IN      UINT8   Version
725   )
726 /*++
727 
728 Routine Description:
729 
730   The internal implementation of *_DECOMPRESS_PROTOCOL.Decompress().
731 
732 Arguments:
733 
734   Source      - The source buffer containing the compressed data.
735   SrcSize     - The size of source buffer
736   Destination - The destination buffer to store the decompressed data
737   DstSize     - The size of destination buffer.
738   Scratch     - The buffer used internally by the decompress routine. This  buffer is needed to store intermediate data.
739   ScratchSize - The size of scratch buffer.
740   Version     - The version of de/compression algorithm.
741                 Version 1 for EFI 1.1 de/compression algorithm.
742                 Version 2 for Tiano de/compression algorithm.
743 
744 Returns:
745 
746   EFI_SUCCESS           - Decompression is successfull
747   EFI_INVALID_PARAMETER - The source data is corrupted
748 
749 --*/
750 {
751   UINT32        Index;
752   UINT32        CompSize;
753   UINT32        OrigSize;
754   EFI_STATUS    Status;
755   SCRATCH_DATA  *Sd;
756   UINT8         *Src;
757   UINT8         *Dst;
758 
759   Status  = EFI_SUCCESS;
760   Src     = Source;
761   Dst     = Destination;
762 
763   if (ScratchSize < sizeof (SCRATCH_DATA)) {
764     return EFI_INVALID_PARAMETER;
765   }
766 
767   Sd = (SCRATCH_DATA *) Scratch;
768 
769   if (SrcSize < 8) {
770     return EFI_INVALID_PARAMETER;
771   }
772 
773   CompSize  = Src[0] + (Src[1] << 8) + (Src[2] << 16) + (Src[3] << 24);
774   OrigSize  = Src[4] + (Src[5] << 8) + (Src[6] << 16) + (Src[7] << 24);
775 
776   //
777   // If compressed file size is 0, return
778   //
779   if (OrigSize == 0) {
780     return Status;
781   }
782 
783   if (SrcSize < CompSize + 8) {
784     return EFI_INVALID_PARAMETER;
785   }
786 
787   if (DstSize != OrigSize) {
788     return EFI_INVALID_PARAMETER;
789   }
790 
791   Src = Src + 8;
792 
793   for (Index = 0; Index < sizeof (SCRATCH_DATA); Index++) {
794     ((UINT8 *) Sd)[Index] = 0;
795   }
796   //
797   // The length of the field 'Position Set Code Length Array Size' in Block Header.
798   // For EFI 1.1 de/compression algorithm(Version 1), mPBit = 4
799   // For Tiano de/compression algorithm(Version 2), mPBit = 5
800   //
801   switch (Version) {
802   case 1:
803     Sd->mPBit = 4;
804     break;
805 
806   case 2:
807     Sd->mPBit = 5;
808     break;
809 
810   default:
811     //
812     // Currently, only have 2 versions
813     //
814     return EFI_INVALID_PARAMETER;
815   }
816 
817   Sd->mSrcBase  = Src;
818   Sd->mDstBase  = Dst;
819   Sd->mCompSize = CompSize;
820   Sd->mOrigSize = OrigSize;
821 
822   //
823   // Fill the first BITBUFSIZ bits
824   //
825   FillBuf (Sd, BITBUFSIZ);
826 
827   //
828   // Decompress it
829   //
830   Decode (Sd);
831 
832   if (Sd->mBadTableFlag != 0) {
833     //
834     // Something wrong with the source
835     //
836     Status = EFI_INVALID_PARAMETER;
837   }
838 
839   return Status;
840 }
841 
842 EFI_STATUS
843 EFIAPI
EfiGetInfo(IN VOID * Source,IN UINT32 SrcSize,OUT UINT32 * DstSize,OUT UINT32 * ScratchSize)844 EfiGetInfo (
845   IN      VOID                    *Source,
846   IN      UINT32                  SrcSize,
847   OUT     UINT32                  *DstSize,
848   OUT     UINT32                  *ScratchSize
849   )
850 /*++
851 
852 Routine Description:
853 
854   The implementation is same as that  of EFI_DECOMPRESS_PROTOCOL.GetInfo().
855 
856 Arguments:
857 
858   This        - The protocol instance pointer
859   Source      - The source buffer containing the compressed data.
860   SrcSize     - The size of source buffer
861   DstSize     - The size of destination buffer.
862   ScratchSize - The size of scratch buffer.
863 
864 Returns:
865 
866   EFI_SUCCESS           - The size of destination buffer and the size of scratch buffer are successull retrieved.
867   EFI_INVALID_PARAMETER - The source data is corrupted
868 
869 --*/
870 {
871   return GetInfo (
872           Source,
873           SrcSize,
874           DstSize,
875           ScratchSize
876           );
877 }
878 
879 EFI_STATUS
880 EFIAPI
EfiDecompress(IN VOID * Source,IN UINT32 SrcSize,IN OUT VOID * Destination,IN UINT32 DstSize,IN OUT VOID * Scratch,IN UINT32 ScratchSize)881 EfiDecompress (
882   IN      VOID                    *Source,
883   IN      UINT32                  SrcSize,
884   IN OUT  VOID                    *Destination,
885   IN      UINT32                  DstSize,
886   IN OUT  VOID                    *Scratch,
887   IN      UINT32                  ScratchSize
888   )
889 /*++
890 
891 Routine Description:
892 
893   The implementation is same as that of EFI_DECOMPRESS_PROTOCOL.Decompress().
894 
895 Arguments:
896 
897   This        - The protocol instance pointer
898   Source      - The source buffer containing the compressed data.
899   SrcSize     - The size of source buffer
900   Destination - The destination buffer to store the decompressed data
901   DstSize     - The size of destination buffer.
902   Scratch     - The buffer used internally by the decompress routine. This  buffer is needed to store intermediate data.
903   ScratchSize - The size of scratch buffer.
904 
905 Returns:
906 
907   EFI_SUCCESS           - Decompression is successfull
908   EFI_INVALID_PARAMETER - The source data is corrupted
909 
910 --*/
911 {
912   //
913   // For EFI 1.1 de/compression algorithm, the version is 1.
914   //
915   return Decompress (
916           Source,
917           SrcSize,
918           Destination,
919           DstSize,
920           Scratch,
921           ScratchSize,
922           1
923           );
924 }
925 
926 EFI_STATUS
927 EFIAPI
TianoGetInfo(IN VOID * Source,IN UINT32 SrcSize,OUT UINT32 * DstSize,OUT UINT32 * ScratchSize)928 TianoGetInfo (
929   IN      VOID                          *Source,
930   IN      UINT32                        SrcSize,
931   OUT     UINT32                        *DstSize,
932   OUT     UINT32                        *ScratchSize
933   )
934 /*++
935 
936 Routine Description:
937 
938   The implementation is same as that of EFI_TIANO_DECOMPRESS_PROTOCOL.GetInfo().
939 
940 Arguments:
941 
942   This        - The protocol instance pointer
943   Source      - The source buffer containing the compressed data.
944   SrcSize     - The size of source buffer
945   DstSize     - The size of destination buffer.
946   ScratchSize - The size of scratch buffer.
947 
948 Returns:
949 
950   EFI_SUCCESS           - The size of destination buffer and the size of scratch buffer are successull retrieved.
951   EFI_INVALID_PARAMETER - The source data is corrupted
952 
953 --*/
954 {
955   return GetInfo (
956           Source,
957           SrcSize,
958           DstSize,
959           ScratchSize
960           );
961 }
962 
963 EFI_STATUS
964 EFIAPI
TianoDecompress(IN VOID * Source,IN UINT32 SrcSize,IN OUT VOID * Destination,IN UINT32 DstSize,IN OUT VOID * Scratch,IN UINT32 ScratchSize)965 TianoDecompress (
966   IN      VOID                          *Source,
967   IN      UINT32                        SrcSize,
968   IN OUT  VOID                          *Destination,
969   IN      UINT32                        DstSize,
970   IN OUT  VOID                          *Scratch,
971   IN      UINT32                        ScratchSize
972   )
973 /*++
974 
975 Routine Description:
976 
977   The implementation is same as that  of EFI_TIANO_DECOMPRESS_PROTOCOL.Decompress().
978 
979 Arguments:
980 
981   This        - The protocol instance pointer
982   Source      - The source buffer containing the compressed data.
983   SrcSize     - The size of source buffer
984   Destination - The destination buffer to store the decompressed data
985   DstSize     - The size of destination buffer.
986   Scratch     - The buffer used internally by the decompress routine. This  buffer is needed to store intermediate data.
987   ScratchSize - The size of scratch buffer.
988 
989 Returns:
990 
991   EFI_SUCCESS           - Decompression is successfull
992   EFI_INVALID_PARAMETER - The source data is corrupted
993 
994 --*/
995 {
996   //
997   // For Tiano de/compression algorithm, the version is 2.
998   //
999   return Decompress (
1000           Source,
1001           SrcSize,
1002           Destination,
1003           DstSize,
1004           Scratch,
1005           ScratchSize,
1006           2
1007           );
1008 }
1009 
1010 
1011 #ifndef FOR_LIBRARY
main(int argc,char * argv[])1012 int main(int argc, char *argv[])
1013 {
1014   char *progname;
1015   int retval = 1;
1016 
1017   progname = strrchr(argv[0], '/');
1018   if (progname)
1019     progname++;
1020   else
1021     progname = argv[0];
1022 
1023   if (argc != 3)
1024   {
1025     fprintf(stderr, "\nUsage:  %s INFILE OUTFILE\n\n", progname);
1026     exit(1);
1027   }
1028 
1029   char *infile = argv[1];
1030   char *outfile = argv[2];
1031 
1032   struct stat istat;
1033   if (0 != stat(infile, &istat)) {
1034     fprintf(stderr, "%s: can't stat %s: %s\n",
1035             progname,
1036             infile,
1037             strerror(errno));
1038     exit(1);
1039   }
1040   uint32_t isize = (uint32_t)istat.st_size;
1041 
1042   printf("%s is %d bytes\n", infile, isize);
1043 
1044   FILE *ifp = fopen(infile, "rb");
1045   if (!ifp)
1046   {
1047     fprintf(stderr, "%s: can't read %s: %s\n",
1048             progname,
1049             infile,
1050             strerror(errno));
1051     exit(1);
1052   }
1053 
1054   // read input file into buffer
1055   uint8_t *ibuf = malloc(isize);
1056   if (!ibuf) {
1057     fprintf(stderr, "%s: can't allocate %d bytes: %s\n",
1058             progname,
1059             isize,
1060             strerror(errno));
1061     goto done1;
1062   }
1063   if (1 != fread(ibuf, isize, 1, ifp)) {
1064     fprintf(stderr, "%s: can't read %d bytes: %s\n",
1065             progname,
1066             isize,
1067             strerror(errno));
1068     goto done2;
1069   }
1070 
1071 
1072   // Determine required parameters
1073   uint32_t ssize=0, osize=0;
1074   EFI_STATUS r = GetInfo(ibuf, isize, &osize, &ssize);
1075   if (r != EFI_SUCCESS) {
1076     fprintf(stderr, "%s: GetInfo failed with code %d\n",
1077             progname,
1078             r);
1079     goto done2;
1080   }
1081   printf("need %d bytes of scratch to produce %d bytes of data\n",
1082          ssize, osize);
1083 
1084   uint8_t *sbuf = malloc(ssize);
1085   if (!sbuf) {
1086     fprintf(stderr, "%s: can't allocate %d bytes: %s\n",
1087             progname,
1088             ssize,
1089             strerror(errno));
1090     goto done2;
1091   }
1092 
1093   uint8_t *obuf = malloc(osize);
1094   if (!obuf) {
1095     fprintf(stderr, "%s: can't allocate %d bytes: %s\n",
1096             progname,
1097             osize,
1098             strerror(errno));
1099     goto done3;
1100   }
1101 
1102   // Try new version first
1103   r = TianoDecompress(ibuf, isize, obuf, osize, sbuf, ssize);
1104   if (r != EFI_SUCCESS) {
1105     fprintf(stderr, "%s: TianoDecompress failed with code %d\n",
1106             progname,
1107             r);
1108 
1109     // Try old version
1110     r = EfiDecompress(ibuf, isize, obuf, osize, sbuf, ssize);
1111     if (r != EFI_SUCCESS) {
1112       fprintf(stderr, "%s: TianoDecompress failed with code %d\n",
1113               progname,
1114               r);
1115       goto done4;
1116     }
1117   }
1118 
1119   printf("Uncompressed %d bytes to %d bytes\n", isize, osize);
1120 
1121   // Write it out
1122   FILE *ofp = fopen(outfile, "wb");
1123   if (!ofp)
1124   {
1125     fprintf(stderr, "%s: can't open %s for writing: %s\n",
1126             progname,
1127             outfile,
1128             strerror(errno));
1129     goto done4;
1130   }
1131 
1132   if (1 != fwrite(obuf, osize, 1, ofp)) {
1133     fprintf(stderr, "%s: can't write %d bytes: %s\n",
1134             progname,
1135             osize,
1136             strerror(errno));
1137     goto done5;
1138   }
1139 
1140   printf("wrote %d bytes to %s\n", osize, outfile);
1141   retval = 0;
1142 
1143 done5:
1144   fclose(ofp);
1145 
1146 done4:
1147   free(obuf);
1148 
1149 done3:
1150   free(sbuf);
1151 
1152 done2:
1153   free(ibuf);
1154 
1155 done1:
1156   fclose(ifp);
1157 
1158   return retval;
1159 }
1160 #endif // FOR_LIBRARY
1161