]> git.proxmox.com Git - mirror_edk2.git/blame - MdeModulePkg/Library/BrotliCustomDecompressLib/BrotliDecompress.c
MdeModulePkg: Replace BSD License with BSD+Patent License
[mirror_edk2.git] / MdeModulePkg / Library / BrotliCustomDecompressLib / BrotliDecompress.c
CommitLineData
841b2590
SB
1/** @file\r
2 Brotli Decompress interfaces\r
3\r
792ace0a 4 Copyright (c) 2017 - 2018, Intel Corporation. All rights reserved.<BR>\r
9d510e61 5 SPDX-License-Identifier: BSD-2-Clause-Patent\r
841b2590
SB
6\r
7**/\r
8#include <BrotliDecompressLibInternal.h>\r
9\r
10/**\r
11 Dummy malloc function for compiler.\r
12**/\r
13VOID *\r
792ace0a 14BrDummyMalloc (\r
841b2590
SB
15 IN size_t Size\r
16 )\r
17{\r
18 ASSERT (FALSE);\r
19 return NULL;\r
20}\r
21\r
22/**\r
23 Dummy free function for compiler.\r
24**/\r
25VOID\r
792ace0a 26BrDummyFree (\r
841b2590
SB
27 IN VOID * Ptr\r
28 )\r
29{\r
30 ASSERT (FALSE);\r
31}\r
32\r
33/**\r
34 Allocation routine used by BROTLI decompression.\r
35\r
36 @param Ptr Pointer to the BROTLI_BUFF instance.\r
37 @param Size The size in bytes to be allocated.\r
38\r
39 @return The allocated pointer address, or NULL on failure\r
40**/\r
41VOID *\r
42BrAlloc (\r
43 IN VOID * Ptr,\r
44 IN size_t Size\r
45 )\r
46{\r
47 VOID *Addr;\r
48 BROTLI_BUFF *Private;\r
49\r
50 Private = (BROTLI_BUFF *)Ptr;\r
51\r
52 if (Private->BuffSize >= Size) {\r
53 Addr = Private->Buff;\r
54 Private->Buff = (VOID *) ((UINT8 *)Addr + Size);\r
55 Private->BuffSize -= Size;\r
56 return Addr;\r
57 } else {\r
58 ASSERT (FALSE);\r
59 return NULL;\r
60 }\r
61}\r
62\r
63/**\r
64 Free routine used by BROTLI decompression.\r
65\r
66 @param Ptr Pointer to the BROTLI_BUFF instance\r
67 @param Address The address to be freed\r
68**/\r
69VOID\r
70BrFree (\r
71 IN VOID * Ptr,\r
72 IN VOID * Address\r
73 )\r
74{\r
75 //\r
76 // We use the 'scratch buffer' for allocations, so there is no free\r
77 // operation required. The scratch buffer will be freed by the caller\r
78 // of the decompression code.\r
79 //\r
80}\r
81\r
82/**\r
83 Decompresses a Brotli compressed source buffer.\r
84\r
85 Extracts decompressed data to its original form.\r
86 If the compressed source data specified by Source is successfully decompressed\r
87 into Destination, then EFI_SUCCESS is returned. If the compressed source data\r
88 specified by Source is not in a valid compressed data format,\r
89 then EFI_INVALID_PARAMETER is returned.\r
90\r
91 @param Source The source buffer containing the compressed data.\r
92 @param SourceSize The size of source buffer.\r
93 @param Destination The destination buffer to store the decompressed data.\r
94 @param DestSize The destination buffer size.\r
95 @param BuffInfo The pointer to the BROTLI_BUFF instance.\r
96\r
97 @retval EFI_SUCCESS Decompression completed successfully, and\r
98 the uncompressed buffer is returned in Destination.\r
99 @retval EFI_INVALID_PARAMETER\r
100 The source buffer specified by Source is corrupted\r
101 (not in a valid compressed format).\r
102**/\r
103EFI_STATUS\r
104BrotliDecompress (\r
105 IN CONST VOID* Source,\r
106 IN UINTN SourceSize,\r
107 IN OUT VOID* Destination,\r
108 IN OUT UINTN DestSize,\r
109 IN VOID * BuffInfo\r
110 )\r
111{\r
112 UINT8 * Input;\r
113 UINT8 * Output;\r
114 const UINT8 * NextIn;\r
115 UINT8 * NextOut;\r
116 size_t TotalOut;\r
117 size_t AvailableIn;\r
118 size_t AvailableOut;\r
841b2590 119 VOID * Temp;\r
2730470f
LG
120 BrotliDecoderResult Result;\r
121 BrotliDecoderState * BroState;\r
841b2590 122\r
36a0d5ca 123 TotalOut = 0;\r
841b2590 124 AvailableOut = FILE_BUFFER_SIZE;\r
2730470f
LG
125 Result = BROTLI_DECODER_RESULT_ERROR;\r
126 BroState = BrotliDecoderCreateInstance(BrAlloc, BrFree, BuffInfo);\r
841b2590
SB
127 Temp = Destination;\r
128\r
129 if (BroState == NULL) {\r
130 return EFI_INVALID_PARAMETER;\r
131 }\r
132 Input = (UINT8 *)BrAlloc(BuffInfo, FILE_BUFFER_SIZE);\r
133 Output = (UINT8 *)BrAlloc(BuffInfo, FILE_BUFFER_SIZE);\r
134 if ((Input==NULL) || (Output==NULL)) {\r
135 BrFree(BuffInfo, Input);\r
136 BrFree(BuffInfo, Output);\r
2730470f 137 BrotliDecoderDestroyInstance(BroState);\r
841b2590
SB
138 return EFI_INVALID_PARAMETER;\r
139 }\r
140 NextOut = Output;\r
2730470f 141 Result = BROTLI_DECODER_RESULT_NEEDS_MORE_INPUT;\r
841b2590 142 while (1) {\r
2730470f 143 if (Result == BROTLI_DECODER_RESULT_NEEDS_MORE_INPUT) {\r
841b2590
SB
144 if (SourceSize == 0) {\r
145 break;\r
146 }\r
147 if (SourceSize >= FILE_BUFFER_SIZE) {\r
148 AvailableIn = FILE_BUFFER_SIZE;\r
149 }else{\r
150 AvailableIn = SourceSize;\r
151 }\r
152 CopyMem(Input, Source, AvailableIn);\r
153 Source = (VOID *)((UINT8 *)Source + AvailableIn);\r
154 SourceSize -= AvailableIn;\r
155 NextIn = Input;\r
2730470f 156 } else if (Result == BROTLI_DECODER_RESULT_NEEDS_MORE_OUTPUT) {\r
841b2590
SB
157 CopyMem(Temp, Output, FILE_BUFFER_SIZE);\r
158 AvailableOut = FILE_BUFFER_SIZE;\r
159 Temp = (VOID *)((UINT8 *)Temp +FILE_BUFFER_SIZE);\r
160 NextOut = Output;\r
161 } else {\r
162 break; /* Error or success. */\r
163 }\r
2730470f
LG
164 Result = BrotliDecoderDecompressStream(\r
165 BroState,\r
841b2590
SB
166 &AvailableIn,\r
167 &NextIn,\r
168 &AvailableOut,\r
169 &NextOut,\r
2730470f 170 &TotalOut\r
841b2590
SB
171 );\r
172 }\r
173 if (NextOut != Output) {\r
174 CopyMem(Temp, Output, (size_t)(NextOut - Output));\r
175 }\r
176\r
177 DestSize = TotalOut;\r
178\r
179 BrFree(BuffInfo, Input);\r
180 BrFree(BuffInfo, Output);\r
2730470f
LG
181 BrotliDecoderDestroyInstance(BroState);\r
182 return (Result == BROTLI_DECODER_RESULT_SUCCESS) ? EFI_SUCCESS : EFI_INVALID_PARAMETER;\r
841b2590
SB
183}\r
184\r
185/**\r
186 Get the size of the uncompressed buffer by parsing EncodeData header.\r
187\r
188 @param EncodedData Pointer to the compressed data.\r
189 @param StartOffset Start offset of the compressed data.\r
190 @param EndOffset End offset of the compressed data.\r
191\r
192 @return The size of the uncompressed buffer.\r
193**/\r
194UINT64\r
792ace0a 195BrGetDecodedSizeOfBuf(\r
841b2590
SB
196 IN UINT8 * EncodedData,\r
197 IN UINT8 StartOffset,\r
198 IN UINT8 EndOffset\r
199 )\r
200{\r
201 UINT64 DecodedSize;\r
202 INTN Index;\r
203\r
204 /* Parse header */\r
205 DecodedSize = 0;\r
206 for (Index = EndOffset - 1; Index >= StartOffset; Index--)\r
207 DecodedSize = LShiftU64(DecodedSize, 8) + EncodedData[Index];\r
208\r
209 return DecodedSize;\r
210}\r
211\r
212/**\r
213 Given a Brotli compressed source buffer, this function retrieves the size of\r
214 the uncompressed buffer and the size of the scratch buffer required\r
215 to decompress the compressed source buffer.\r
216\r
217 Retrieves the size of the uncompressed buffer and the temporary scratch buffer\r
218 required to decompress the buffer specified by Source and SourceSize.\r
219 The size of the uncompressed buffer is returned in DestinationSize,\r
220 the size of the scratch buffer is returned in ScratchSize, and EFI_SUCCESS is returned.\r
221 This function does not have scratch buffer available to perform a thorough\r
222 checking of the validity of the source data. It just retrieves the "Original Size"\r
223 field from the BROTLI_SCRATCH_MAX beginning bytes of the source data and output it as DestinationSize.\r
224 And ScratchSize is specific to the decompression implementation.\r
225\r
226 If SourceSize is less than BROTLI_SCRATCH_MAX, then ASSERT().\r
227\r
228 @param Source The source buffer containing the compressed data.\r
229 @param SourceSize The size, in bytes, of the source buffer.\r
230 @param DestinationSize A pointer to the size, in bytes, of the uncompressed buffer\r
231 that will be generated when the compressed buffer specified\r
232 by Source and SourceSize is decompressed.\r
233 @param ScratchSize A pointer to the size, in bytes, of the scratch buffer that\r
234 is required to decompress the compressed buffer specified\r
235 by Source and SourceSize.\r
236\r
237 @retval EFI_SUCCESS The size of the uncompressed data was returned\r
238 in DestinationSize and the size of the scratch\r
239 buffer was returned in ScratchSize.\r
240**/\r
241EFI_STATUS\r
242EFIAPI\r
243BrotliUefiDecompressGetInfo (\r
244 IN CONST VOID * Source,\r
245 IN UINT32 SourceSize,\r
246 OUT UINT32 * DestinationSize,\r
247 OUT UINT32 * ScratchSize\r
248 )\r
249{\r
250 UINT64 GetSize;\r
251 UINT8 MaxOffset;\r
252\r
253 ASSERT(SourceSize >= BROTLI_SCRATCH_MAX);\r
254\r
255 MaxOffset = BROTLI_DECODE_MAX;\r
792ace0a 256 GetSize = BrGetDecodedSizeOfBuf((UINT8 *)Source, MaxOffset - BROTLI_INFO_SIZE, MaxOffset);\r
841b2590
SB
257 *DestinationSize = (UINT32)GetSize;\r
258 MaxOffset = BROTLI_SCRATCH_MAX;\r
792ace0a 259 GetSize = BrGetDecodedSizeOfBuf((UINT8 *)Source, MaxOffset - BROTLI_INFO_SIZE, MaxOffset);\r
841b2590
SB
260 *ScratchSize = (UINT32)GetSize;\r
261 return EFI_SUCCESS;\r
262}\r
263\r
264/**\r
265 Decompresses a Brotli compressed source buffer.\r
266\r
267 Extracts decompressed data to its original form.\r
268 If the compressed source data specified by Source is successfully decompressed\r
269 into Destination, then RETURN_SUCCESS is returned. If the compressed source data\r
270 specified by Source is not in a valid compressed data format,\r
271 then RETURN_INVALID_PARAMETER is returned.\r
272\r
273 @param Source The source buffer containing the compressed data.\r
274 @param SourceSize The size of source buffer.\r
275 @param Destination The destination buffer to store the decompressed data\r
276 @param Scratch A temporary scratch buffer that is used to perform the decompression.\r
277 This is an optional parameter that may be NULL if the\r
278 required scratch buffer size is 0.\r
279\r
280 @retval EFI_SUCCESS Decompression completed successfully, and\r
281 the uncompressed buffer is returned in Destination.\r
282 @retval EFI_INVALID_PARAMETER\r
283 The source buffer specified by Source is corrupted\r
284 (not in a valid compressed format).\r
285**/\r
286EFI_STATUS\r
287EFIAPI\r
288BrotliUefiDecompress (\r
289 IN CONST VOID * Source,\r
290 IN UINTN SourceSize,\r
291 IN OUT VOID * Destination,\r
292 IN OUT VOID * Scratch\r
293 )\r
294{\r
295 UINTN DestSize = 0;\r
296 EFI_STATUS Status;\r
297 BROTLI_BUFF BroBuff;\r
298 UINT64 GetSize;\r
299 UINT8 MaxOffset;\r
300\r
301 MaxOffset = BROTLI_SCRATCH_MAX;\r
792ace0a 302 GetSize = BrGetDecodedSizeOfBuf((UINT8 *)Source, MaxOffset - BROTLI_INFO_SIZE, MaxOffset);\r
841b2590
SB
303\r
304 BroBuff.Buff = Scratch;\r
305 BroBuff.BuffSize = (UINTN)GetSize;\r
306\r
307 Status = BrotliDecompress(\r
308 (VOID *)((UINT8 *)Source + BROTLI_SCRATCH_MAX),\r
309 SourceSize - BROTLI_SCRATCH_MAX,\r
310 Destination,\r
311 DestSize,\r
312 (VOID *)(&BroBuff)\r
313 );\r
314\r
315 return Status;\r
316}\r