Home | History | Annotate | Download | only in ZLib
      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