1 /** @file 2 3 Copyright (c) 2017, Linaro. All rights reserved. 4 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 <Library/BaseLib.h> 16 #include <Library/BaseMemoryLib.h> 17 #include <Library/ZLib.h> 18 19 #include "zlib.h" 20 21 #define CHUNK 32768 22 23 EFI_STATUS 24 GzipDecompress ( 25 IN VOID *CompressData, 26 IN UINTN *CompressDataLen, 27 IN VOID *UncompressData, 28 IN OUT UINTN *UncompressDataLen 29 ) 30 { 31 INTN ret; 32 INTN have; 33 unsigned char in[CHUNK]; 34 unsigned char out[CHUNK]; 35 UINTN comp_offset; 36 UINTN uncomp_offset; 37 UINTN left; 38 z_stream stream = { 0 }; 39 40 // Speed up the decompress 41 comp_offset = 0; 42 uncomp_offset = 0; 43 left = *CompressDataLen; 44 45 stream.zalloc = NULL; 46 stream.zfree = NULL; 47 stream.opaque = NULL; 48 stream.avail_in = CHUNK; 49 50 if (inflateInit2(&stream, MAX_WBITS + 16) != Z_OK) 51 { 52 return EFI_ABORTED; 53 } 54 do 55 { 56 /* decompress until deflate stream ends */ 57 if (left > CHUNK) 58 { 59 stream.avail_in = CHUNK; 60 left = left - CHUNK; 61 } 62 else 63 { 64 stream.avail_in = left; 65 left = 0; 66 } 67 if (stream.avail_in == 0) { 68 break; 69 } 70 stream.next_in = in; 71 CopyMem (in, CompressData + comp_offset, stream.avail_in); 72 comp_offset += stream.avail_in; 73 /* run inflate() on input until output buffer not full */ 74 do 75 { 76 stream.avail_out = CHUNK; 77 stream.next_out = out; 78 ret = inflate(&stream, Z_NO_FLUSH); 79 switch (ret) 80 { 81 case Z_NEED_DICT: 82 ret = Z_DATA_ERROR; /* and fall through */ 83 case Z_DATA_ERROR: 84 case Z_MEM_ERROR: 85 inflateEnd(&stream); 86 return ret; 87 } 88 have = CHUNK - stream.avail_out; 89 CopyMem (UncompressData + uncomp_offset, out, have); 90 uncomp_offset += have; 91 } while (stream.avail_out == 0); 92 /* done when inflate() says it's done */ 93 } while (ret != Z_STREAM_END); 94 inflateEnd(&stream); 95 *(unsigned char *)(UncompressData + uncomp_offset) = '\0'; 96 if (*CompressDataLen > stream.total_in) 97 { 98 *CompressDataLen = stream.total_in; 99 } 100 *UncompressDataLen = stream.total_out; 101 return EFI_SUCCESS; 102 } 103