diff options
Diffstat (limited to 'lib/zlib/tf_gunzip.c')
-rw-r--r-- | lib/zlib/tf_gunzip.c | 115 |
1 files changed, 115 insertions, 0 deletions
diff --git a/lib/zlib/tf_gunzip.c b/lib/zlib/tf_gunzip.c new file mode 100644 index 0000000..3ac80bc --- /dev/null +++ b/lib/zlib/tf_gunzip.c @@ -0,0 +1,115 @@ +/* + * Copyright (c) 2018-2021, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <assert.h> +#include <errno.h> +#include <string.h> + +#include <common/debug.h> +#include <common/tf_crc32.h> +#include <lib/utils.h> +#include <tf_gunzip.h> + +#include "zutil.h" + +/* + * memory allocated by malloc() is supposed to be aligned for any built-in type + */ +#define ZALLOC_ALIGNMENT sizeof(void *) + +static uintptr_t zalloc_start; +static uintptr_t zalloc_end; +static uintptr_t zalloc_current; + +static void * ZLIB_INTERNAL zcalloc(void *opaque, unsigned int items, + unsigned int size) +{ + uintptr_t p, p_end; + + size *= items; + + p = round_up(zalloc_current, ZALLOC_ALIGNMENT); + p_end = p + size; + + if (p_end > zalloc_end) + return NULL; + + memset((void *)p, 0, size); + + zalloc_current = p_end; + + return (void *)p; +} + +static void ZLIB_INTERNAL zfree(void *opaque, void *ptr) +{ +} + +/* + * gunzip - decompress gzip data + * @in_buf: source of compressed input. Upon exit, the end of input. + * @in_len: length of in_buf + * @out_buf: destination of decompressed output. Upon exit, the end of output. + * @out_len: length of out_buf + * @work_buf: workspace + * @work_len: length of workspace + */ +int gunzip(uintptr_t *in_buf, size_t in_len, uintptr_t *out_buf, + size_t out_len, uintptr_t work_buf, size_t work_len) +{ + z_stream stream; + int zret, ret; + + zalloc_start = work_buf; + zalloc_end = work_buf + work_len; + zalloc_current = zalloc_start; + + stream.next_in = (typeof(stream.next_in))*in_buf; + stream.avail_in = in_len; + stream.next_out = (typeof(stream.next_out))*out_buf; + stream.avail_out = out_len; + stream.zalloc = zcalloc; + stream.zfree = zfree; + stream.opaque = (voidpf)0; + + zret = inflateInit(&stream); + if (zret != Z_OK) { + ERROR("zlib: inflate init failed (ret = %d)\n", zret); + return (zret == Z_MEM_ERROR) ? -ENOMEM : -EIO; + } + + zret = inflate(&stream, Z_NO_FLUSH); + if (zret == Z_STREAM_END) { + ret = 0; + } else { + if (stream.msg) + ERROR("%s\n", stream.msg); + ERROR("zlib: inflate failed (ret = %d)\n", zret); + ret = (zret == Z_MEM_ERROR) ? -ENOMEM : -EIO; + } + + VERBOSE("zlib: %lu byte input\n", stream.total_in); + VERBOSE("zlib: %lu byte output\n", stream.total_out); + + *in_buf = (uintptr_t)stream.next_in; + *out_buf = (uintptr_t)stream.next_out; + + inflateEnd(&stream); + + return ret; +} + +/* Wrapper function to calculate CRC + * @crc: previous accumulated CRC + * @buf: buffer base address + * @size: size of the buffer + * + * Return calculated CRC32 value + */ +uint32_t tf_crc32(uint32_t crc, const unsigned char *buf, size_t size) +{ + return (uint32_t)crc32((unsigned long)crc, buf, size); +} |