Home | History | Annotate | Download | only in LzmaCustomDecompressLib
      1 /** @file
      2   LZMA Decompress interfaces
      3 
      4   Copyright (c) 2009 - 2016, Intel Corporation. All rights reserved.<BR>
      5   This program and the accompanying materials
      6   are licensed and made available under the terms and conditions of the BSD License
      7   which accompanies this distribution.  The full text of the license may be found at
      8   http://opensource.org/licenses/bsd-license.php
      9 
     10   THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
     11   WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
     12 
     13 **/
     14 
     15 #include "LzmaDecompressLibInternal.h"
     16 #include "Sdk/C/7zTypes.h"
     17 #include "Sdk/C/7zVersion.h"
     18 #include "Sdk/C/LzmaDec.h"
     19 
     20 #define SCRATCH_BUFFER_REQUEST_SIZE SIZE_64KB
     21 
     22 typedef struct
     23 {
     24   ISzAlloc Functions;
     25   VOID     *Buffer;
     26   UINTN    BufferSize;
     27 } ISzAllocWithData;
     28 
     29 /**
     30   Allocation routine used by LZMA decompression.
     31 
     32   @param P                Pointer to the ISzAlloc instance
     33   @param Size             The size in bytes to be allocated
     34 
     35   @return The allocated pointer address, or NULL on failure
     36 **/
     37 VOID *
     38 SzAlloc (
     39   VOID *P,
     40   size_t Size
     41   )
     42 {
     43   VOID *Addr;
     44   ISzAllocWithData *Private;
     45 
     46   Private = (ISzAllocWithData*) P;
     47 
     48   if (Private->BufferSize >= Size) {
     49     Addr = Private->Buffer;
     50     Private->Buffer = (VOID*) ((UINT8*)Addr + Size);
     51     Private->BufferSize -= Size;
     52     return Addr;
     53   } else {
     54     ASSERT (FALSE);
     55     return NULL;
     56   }
     57 }
     58 
     59 /**
     60   Free routine used by LZMA decompression.
     61 
     62   @param P                Pointer to the ISzAlloc instance
     63   @param Address          The address to be freed
     64 **/
     65 VOID
     66 SzFree (
     67   VOID *P,
     68   VOID *Address
     69   )
     70 {
     71   //
     72   // We use the 'scratch buffer' for allocations, so there is no free
     73   // operation required.  The scratch buffer will be freed by the caller
     74   // of the decompression code.
     75   //
     76 }
     77 
     78 #define LZMA_HEADER_SIZE (LZMA_PROPS_SIZE + 8)
     79 
     80 /**
     81   Get the size of the uncompressed buffer by parsing EncodeData header.
     82 
     83   @param EncodedData  Pointer to the compressed data.
     84 
     85   @return The size of the uncompressed buffer.
     86 **/
     87 UINT64
     88 GetDecodedSizeOfBuf(
     89   UINT8 *EncodedData
     90   )
     91 {
     92   UINT64 DecodedSize;
     93   INTN   Index;
     94 
     95   /* Parse header */
     96   DecodedSize = 0;
     97   for (Index = LZMA_PROPS_SIZE + 7; Index >= LZMA_PROPS_SIZE; Index--)
     98     DecodedSize = LShiftU64(DecodedSize, 8) + EncodedData[Index];
     99 
    100   return DecodedSize;
    101 }
    102 
    103 //
    104 // LZMA functions and data as defined in local LzmaDecompressLibInternal.h
    105 //
    106 
    107 /**
    108   Given a Lzma compressed source buffer, this function retrieves the size of
    109   the uncompressed buffer and the size of the scratch buffer required
    110   to decompress the compressed source buffer.
    111 
    112   Retrieves the size of the uncompressed buffer and the temporary scratch buffer
    113   required to decompress the buffer specified by Source and SourceSize.
    114   The size of the uncompressed buffer is returned in DestinationSize,
    115   the size of the scratch buffer is returned in ScratchSize, and RETURN_SUCCESS is returned.
    116   This function does not have scratch buffer available to perform a thorough
    117   checking of the validity of the source data. It just retrieves the "Original Size"
    118   field from the LZMA_HEADER_SIZE beginning bytes of the source data and output it as DestinationSize.
    119   And ScratchSize is specific to the decompression implementation.
    120 
    121   If SourceSize is less than LZMA_HEADER_SIZE, then ASSERT().
    122 
    123   @param  Source          The source buffer containing the compressed data.
    124   @param  SourceSize      The size, in bytes, of the source buffer.
    125   @param  DestinationSize A pointer to the size, in bytes, of the uncompressed buffer
    126                           that will be generated when the compressed buffer specified
    127                           by Source and SourceSize is decompressed.
    128   @param  ScratchSize     A pointer to the size, in bytes, of the scratch buffer that
    129                           is required to decompress the compressed buffer specified
    130                           by Source and SourceSize.
    131 
    132   @retval  RETURN_SUCCESS The size of the uncompressed data was returned
    133                           in DestinationSize and the size of the scratch
    134                           buffer was returned in ScratchSize.
    135 
    136 **/
    137 RETURN_STATUS
    138 EFIAPI
    139 LzmaUefiDecompressGetInfo (
    140   IN  CONST VOID  *Source,
    141   IN  UINT32      SourceSize,
    142   OUT UINT32      *DestinationSize,
    143   OUT UINT32      *ScratchSize
    144   )
    145 {
    146   UInt64  DecodedSize;
    147 
    148   ASSERT(SourceSize >= LZMA_HEADER_SIZE);
    149 
    150   DecodedSize = GetDecodedSizeOfBuf((UINT8*)Source);
    151 
    152   *DestinationSize = (UINT32)DecodedSize;
    153   *ScratchSize = SCRATCH_BUFFER_REQUEST_SIZE;
    154   return RETURN_SUCCESS;
    155 }
    156 
    157 /**
    158   Decompresses a Lzma compressed source buffer.
    159 
    160   Extracts decompressed data to its original form.
    161   If the compressed source data specified by Source is successfully decompressed
    162   into Destination, then RETURN_SUCCESS is returned.  If the compressed source data
    163   specified by Source is not in a valid compressed data format,
    164   then RETURN_INVALID_PARAMETER is returned.
    165 
    166   @param  Source      The source buffer containing the compressed data.
    167   @param  SourceSize  The size of source buffer.
    168   @param  Destination The destination buffer to store the decompressed data
    169   @param  Scratch     A temporary scratch buffer that is used to perform the decompression.
    170                       This is an optional parameter that may be NULL if the
    171                       required scratch buffer size is 0.
    172 
    173   @retval  RETURN_SUCCESS Decompression completed successfully, and
    174                           the uncompressed buffer is returned in Destination.
    175   @retval  RETURN_INVALID_PARAMETER
    176                           The source buffer specified by Source is corrupted
    177                           (not in a valid compressed format).
    178 **/
    179 RETURN_STATUS
    180 EFIAPI
    181 LzmaUefiDecompress (
    182   IN CONST VOID  *Source,
    183   IN UINTN       SourceSize,
    184   IN OUT VOID    *Destination,
    185   IN OUT VOID    *Scratch
    186   )
    187 {
    188   SRes              LzmaResult;
    189   ELzmaStatus       Status;
    190   SizeT             DecodedBufSize;
    191   SizeT             EncodedDataSize;
    192   ISzAllocWithData  AllocFuncs;
    193 
    194   AllocFuncs.Functions.Alloc  = SzAlloc;
    195   AllocFuncs.Functions.Free   = SzFree;
    196   AllocFuncs.Buffer           = Scratch;
    197   AllocFuncs.BufferSize       = SCRATCH_BUFFER_REQUEST_SIZE;
    198 
    199   DecodedBufSize = (SizeT)GetDecodedSizeOfBuf((UINT8*)Source);
    200   EncodedDataSize = (SizeT) (SourceSize - LZMA_HEADER_SIZE);
    201 
    202   LzmaResult = LzmaDecode(
    203     Destination,
    204     &DecodedBufSize,
    205     (Byte*)((UINT8*)Source + LZMA_HEADER_SIZE),
    206     &EncodedDataSize,
    207     Source,
    208     LZMA_PROPS_SIZE,
    209     LZMA_FINISH_END,
    210     &Status,
    211     &(AllocFuncs.Functions)
    212     );
    213 
    214   if (LzmaResult == SZ_OK) {
    215     return RETURN_SUCCESS;
    216   } else {
    217     return RETURN_INVALID_PARAMETER;
    218   }
    219 }
    220 
    221