1 /** @file
2   LZMA Decompress interfaces
3 
4   Copyright (c) 2009 - 2010, 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/Types.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 *
SzAlloc(VOID * P,size_t Size)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
SzFree(VOID * P,VOID * Address)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
GetDecodedSizeOfBuf(UINT8 * EncodedData)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
LzmaUefiDecompressGetInfo(IN CONST VOID * Source,IN UINT32 SourceSize,OUT UINT32 * DestinationSize,OUT UINT32 * ScratchSize)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
LzmaUefiDecompress(IN CONST VOID * Source,IN UINTN SourceSize,IN OUT VOID * Destination,IN OUT VOID * Scratch)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