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