| /** @file | |
| Brotli Decompress interfaces | |
| Copyright (c) 2017, Intel Corporation. All rights reserved.<BR> | |
| This program and the accompanying materials | |
| are licensed and made available under the terms and conditions of the BSD License | |
| which accompanies this distribution. The full text of the license may be found at | |
| http://opensource.org/licenses/bsd-license.php | |
| THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, | |
| WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. | |
| **/ | |
| #include <BrotliDecompressLibInternal.h> | |
| /** | |
| Dummy malloc function for compiler. | |
| **/ | |
| VOID * | |
| malloc ( | |
| IN size_t Size | |
| ) | |
| { | |
| ASSERT (FALSE); | |
| return NULL; | |
| } | |
| /** | |
| Dummy free function for compiler. | |
| **/ | |
| VOID | |
| free ( | |
| IN VOID * Ptr | |
| ) | |
| { | |
| ASSERT (FALSE); | |
| } | |
| /** | |
| Allocation routine used by BROTLI decompression. | |
| @param Ptr Pointer to the BROTLI_BUFF instance. | |
| @param Size The size in bytes to be allocated. | |
| @return The allocated pointer address, or NULL on failure | |
| **/ | |
| VOID * | |
| BrAlloc ( | |
| IN VOID * Ptr, | |
| IN size_t Size | |
| ) | |
| { | |
| VOID *Addr; | |
| BROTLI_BUFF *Private; | |
| Private = (BROTLI_BUFF *)Ptr; | |
| if (Private->BuffSize >= Size) { | |
| Addr = Private->Buff; | |
| Private->Buff = (VOID *) ((UINT8 *)Addr + Size); | |
| Private->BuffSize -= Size; | |
| return Addr; | |
| } else { | |
| ASSERT (FALSE); | |
| return NULL; | |
| } | |
| } | |
| /** | |
| Free routine used by BROTLI decompression. | |
| @param Ptr Pointer to the BROTLI_BUFF instance | |
| @param Address The address to be freed | |
| **/ | |
| VOID | |
| BrFree ( | |
| IN VOID * Ptr, | |
| IN VOID * Address | |
| ) | |
| { | |
| // | |
| // We use the 'scratch buffer' for allocations, so there is no free | |
| // operation required. The scratch buffer will be freed by the caller | |
| // of the decompression code. | |
| // | |
| } | |
| /** | |
| Decompresses a Brotli compressed source buffer. | |
| Extracts decompressed data to its original form. | |
| If the compressed source data specified by Source is successfully decompressed | |
| into Destination, then EFI_SUCCESS is returned. If the compressed source data | |
| specified by Source is not in a valid compressed data format, | |
| then EFI_INVALID_PARAMETER is returned. | |
| @param Source The source buffer containing the compressed data. | |
| @param SourceSize The size of source buffer. | |
| @param Destination The destination buffer to store the decompressed data. | |
| @param DestSize The destination buffer size. | |
| @param BuffInfo The pointer to the BROTLI_BUFF instance. | |
| @retval EFI_SUCCESS Decompression completed successfully, and | |
| the uncompressed buffer is returned in Destination. | |
| @retval EFI_INVALID_PARAMETER | |
| The source buffer specified by Source is corrupted | |
| (not in a valid compressed format). | |
| **/ | |
| EFI_STATUS | |
| BrotliDecompress ( | |
| IN CONST VOID* Source, | |
| IN UINTN SourceSize, | |
| IN OUT VOID* Destination, | |
| IN OUT UINTN DestSize, | |
| IN VOID * BuffInfo | |
| ) | |
| { | |
| UINT8 * Input; | |
| UINT8 * Output; | |
| const UINT8 * NextIn; | |
| UINT8 * NextOut; | |
| size_t TotalOut; | |
| size_t AvailableIn; | |
| size_t AvailableOut; | |
| BrotliResult Result; | |
| BrotliState * BroState; | |
| VOID * Temp; | |
| TotalOut = 0; | |
| AvailableOut = FILE_BUFFER_SIZE; | |
| Result = BROTLI_RESULT_ERROR; | |
| BroState = BrotliCreateState(BrAlloc, BrFree, BuffInfo); | |
| Temp = Destination; | |
| if (BroState == NULL) { | |
| return EFI_INVALID_PARAMETER; | |
| } | |
| Input = (UINT8 *)BrAlloc(BuffInfo, FILE_BUFFER_SIZE); | |
| Output = (UINT8 *)BrAlloc(BuffInfo, FILE_BUFFER_SIZE); | |
| if ((Input==NULL) || (Output==NULL)) { | |
| BrFree(BuffInfo, Input); | |
| BrFree(BuffInfo, Output); | |
| BrotliDestroyState(BroState); | |
| return EFI_INVALID_PARAMETER; | |
| } | |
| NextOut = Output; | |
| Result = BROTLI_RESULT_NEEDS_MORE_INPUT; | |
| while (1) { | |
| if (Result == BROTLI_RESULT_NEEDS_MORE_INPUT) { | |
| if (SourceSize == 0) { | |
| break; | |
| } | |
| if (SourceSize >= FILE_BUFFER_SIZE) { | |
| AvailableIn = FILE_BUFFER_SIZE; | |
| }else{ | |
| AvailableIn = SourceSize; | |
| } | |
| CopyMem(Input, Source, AvailableIn); | |
| Source = (VOID *)((UINT8 *)Source + AvailableIn); | |
| SourceSize -= AvailableIn; | |
| NextIn = Input; | |
| } else if (Result == BROTLI_RESULT_NEEDS_MORE_OUTPUT) { | |
| CopyMem(Temp, Output, FILE_BUFFER_SIZE); | |
| AvailableOut = FILE_BUFFER_SIZE; | |
| Temp = (VOID *)((UINT8 *)Temp +FILE_BUFFER_SIZE); | |
| NextOut = Output; | |
| } else { | |
| break; /* Error or success. */ | |
| } | |
| Result = BrotliDecompressStream( | |
| &AvailableIn, | |
| &NextIn, | |
| &AvailableOut, | |
| &NextOut, | |
| &TotalOut, | |
| BroState | |
| ); | |
| } | |
| if (NextOut != Output) { | |
| CopyMem(Temp, Output, (size_t)(NextOut - Output)); | |
| } | |
| DestSize = TotalOut; | |
| BrFree(BuffInfo, Input); | |
| BrFree(BuffInfo, Output); | |
| BrotliDestroyState(BroState); | |
| return (Result == BROTLI_RESULT_SUCCESS) ? EFI_SUCCESS : EFI_INVALID_PARAMETER; | |
| } | |
| /** | |
| Get the size of the uncompressed buffer by parsing EncodeData header. | |
| @param EncodedData Pointer to the compressed data. | |
| @param StartOffset Start offset of the compressed data. | |
| @param EndOffset End offset of the compressed data. | |
| @return The size of the uncompressed buffer. | |
| **/ | |
| UINT64 | |
| GetDecodedSizeOfBuf( | |
| IN UINT8 * EncodedData, | |
| IN UINT8 StartOffset, | |
| IN UINT8 EndOffset | |
| ) | |
| { | |
| UINT64 DecodedSize; | |
| INTN Index; | |
| /* Parse header */ | |
| DecodedSize = 0; | |
| for (Index = EndOffset - 1; Index >= StartOffset; Index--) | |
| DecodedSize = LShiftU64(DecodedSize, 8) + EncodedData[Index]; | |
| return DecodedSize; | |
| } | |
| /** | |
| Given a Brotli compressed source buffer, this function retrieves the size of | |
| the uncompressed buffer and the size of the scratch buffer required | |
| to decompress the compressed source buffer. | |
| Retrieves the size of the uncompressed buffer and the temporary scratch buffer | |
| required to decompress the buffer specified by Source and SourceSize. | |
| The size of the uncompressed buffer is returned in DestinationSize, | |
| the size of the scratch buffer is returned in ScratchSize, and EFI_SUCCESS is returned. | |
| This function does not have scratch buffer available to perform a thorough | |
| checking of the validity of the source data. It just retrieves the "Original Size" | |
| field from the BROTLI_SCRATCH_MAX beginning bytes of the source data and output it as DestinationSize. | |
| And ScratchSize is specific to the decompression implementation. | |
| If SourceSize is less than BROTLI_SCRATCH_MAX, then ASSERT(). | |
| @param Source The source buffer containing the compressed data. | |
| @param SourceSize The size, in bytes, of the source buffer. | |
| @param DestinationSize A pointer to the size, in bytes, of the uncompressed buffer | |
| that will be generated when the compressed buffer specified | |
| by Source and SourceSize is decompressed. | |
| @param ScratchSize A pointer to the size, in bytes, of the scratch buffer that | |
| is required to decompress the compressed buffer specified | |
| by Source and SourceSize. | |
| @retval EFI_SUCCESS The size of the uncompressed data was returned | |
| in DestinationSize and the size of the scratch | |
| buffer was returned in ScratchSize. | |
| **/ | |
| EFI_STATUS | |
| EFIAPI | |
| BrotliUefiDecompressGetInfo ( | |
| IN CONST VOID * Source, | |
| IN UINT32 SourceSize, | |
| OUT UINT32 * DestinationSize, | |
| OUT UINT32 * ScratchSize | |
| ) | |
| { | |
| UINT64 GetSize; | |
| UINT8 MaxOffset; | |
| ASSERT(SourceSize >= BROTLI_SCRATCH_MAX); | |
| MaxOffset = BROTLI_DECODE_MAX; | |
| GetSize = GetDecodedSizeOfBuf((UINT8 *)Source, MaxOffset - BROTLI_INFO_SIZE, MaxOffset); | |
| *DestinationSize = (UINT32)GetSize; | |
| MaxOffset = BROTLI_SCRATCH_MAX; | |
| GetSize = GetDecodedSizeOfBuf((UINT8 *)Source, MaxOffset - BROTLI_INFO_SIZE, MaxOffset); | |
| *ScratchSize = (UINT32)GetSize; | |
| return EFI_SUCCESS; | |
| } | |
| /** | |
| Decompresses a Brotli compressed source buffer. | |
| Extracts decompressed data to its original form. | |
| If the compressed source data specified by Source is successfully decompressed | |
| into Destination, then RETURN_SUCCESS is returned. If the compressed source data | |
| specified by Source is not in a valid compressed data format, | |
| then RETURN_INVALID_PARAMETER is returned. | |
| @param Source The source buffer containing the compressed data. | |
| @param SourceSize The size of source buffer. | |
| @param Destination The destination buffer to store the decompressed data | |
| @param Scratch A temporary scratch buffer that is used to perform the decompression. | |
| This is an optional parameter that may be NULL if the | |
| required scratch buffer size is 0. | |
| @retval EFI_SUCCESS Decompression completed successfully, and | |
| the uncompressed buffer is returned in Destination. | |
| @retval EFI_INVALID_PARAMETER | |
| The source buffer specified by Source is corrupted | |
| (not in a valid compressed format). | |
| **/ | |
| EFI_STATUS | |
| EFIAPI | |
| BrotliUefiDecompress ( | |
| IN CONST VOID * Source, | |
| IN UINTN SourceSize, | |
| IN OUT VOID * Destination, | |
| IN OUT VOID * Scratch | |
| ) | |
| { | |
| UINTN DestSize = 0; | |
| EFI_STATUS Status; | |
| BROTLI_BUFF BroBuff; | |
| UINT64 GetSize; | |
| UINT8 MaxOffset; | |
| MaxOffset = BROTLI_SCRATCH_MAX; | |
| GetSize = GetDecodedSizeOfBuf((UINT8 *)Source, MaxOffset - BROTLI_INFO_SIZE, MaxOffset); | |
| BroBuff.Buff = Scratch; | |
| BroBuff.BuffSize = (UINTN)GetSize; | |
| Status = BrotliDecompress( | |
| (VOID *)((UINT8 *)Source + BROTLI_SCRATCH_MAX), | |
| SourceSize - BROTLI_SCRATCH_MAX, | |
| Destination, | |
| DestSize, | |
| (VOID *)(&BroBuff) | |
| ); | |
| return Status; | |
| } |