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
GzipDecompress(IN VOID * CompressData,IN UINTN * CompressDataLen,IN VOID * UncompressData,IN OUT UINTN * UncompressDataLen)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