• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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