1 /* 2 * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved. 3 * 4 * SPDX-License-Identifier: BSD-3-Clause 5 */ 6 7 #include <assert.h> 8 #include <errno.h> 9 #include <string.h> 10 11 #include <common/debug.h> 12 #include <lib/utils.h> 13 #include <tf_gunzip.h> 14 15 #include "zutil.h" 16 17 /* 18 * memory allocated by malloc() is supposed to be aligned for any built-in type 19 */ 20 #define ZALLOC_ALIGNMENT sizeof(void *) 21 22 static uintptr_t zalloc_start; 23 static uintptr_t zalloc_end; 24 static uintptr_t zalloc_current; 25 26 static void * ZLIB_INTERNAL zcalloc(void *opaque, unsigned int items, 27 unsigned int size) 28 { 29 uintptr_t p, p_end; 30 31 size *= items; 32 33 p = round_up(zalloc_current, ZALLOC_ALIGNMENT); 34 p_end = p + size; 35 36 if (p_end > zalloc_end) 37 return NULL; 38 39 memset((void *)p, 0, size); 40 41 zalloc_current = p_end; 42 43 return (void *)p; 44 } 45 46 static void ZLIB_INTERNAL zfree(void *opaque, void *ptr) 47 { 48 } 49 50 /* 51 * gunzip - decompress gzip data 52 * @in_buf: source of compressed input. Upon exit, the end of input. 53 * @in_len: length of in_buf 54 * @out_buf: destination of decompressed output. Upon exit, the end of output. 55 * @out_len: length of out_buf 56 * @work_buf: workspace 57 * @work_len: length of workspace 58 */ 59 int gunzip(uintptr_t *in_buf, size_t in_len, uintptr_t *out_buf, 60 size_t out_len, uintptr_t work_buf, size_t work_len) 61 { 62 z_stream stream; 63 int zret, ret; 64 65 zalloc_start = work_buf; 66 zalloc_end = work_buf + work_len; 67 zalloc_current = zalloc_start; 68 69 stream.next_in = (typeof(stream.next_in))*in_buf; 70 stream.avail_in = in_len; 71 stream.next_out = (typeof(stream.next_out))*out_buf; 72 stream.avail_out = out_len; 73 stream.zalloc = zcalloc; 74 stream.zfree = zfree; 75 stream.opaque = (voidpf)0; 76 77 zret = inflateInit(&stream); 78 if (zret != Z_OK) { 79 ERROR("zlib: inflate init failed (ret = %d)\n", zret); 80 return (zret == Z_MEM_ERROR) ? -ENOMEM : -EIO; 81 } 82 83 zret = inflate(&stream, Z_NO_FLUSH); 84 if (zret == Z_STREAM_END) { 85 ret = 0; 86 } else { 87 if (stream.msg) 88 ERROR("%s\n", stream.msg); 89 ERROR("zlib: inflate failed (ret = %d)\n", zret); 90 ret = (zret == Z_MEM_ERROR) ? -ENOMEM : -EIO; 91 } 92 93 VERBOSE("zlib: %lu byte input\n", stream.total_in); 94 VERBOSE("zlib: %lu byte output\n", stream.total_out); 95 96 *in_buf = (uintptr_t)stream.next_in; 97 *out_buf = (uintptr_t)stream.next_out; 98 99 inflateEnd(&stream); 100 101 return ret; 102 } 103