Home | History | Annotate | Download | only in utility
      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
     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
    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
    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
    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
    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
    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
    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
    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
    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
    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
    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
    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
    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
    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
   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