diff options
author | Masahiro Yamada <yamada.masahiro@socionext.com> | 2018-01-26 11:42:01 +0900 |
---|---|---|
committer | Masahiro Yamada <yamada.masahiro@socionext.com> | 2018-02-02 00:18:54 +0900 |
commit | c43d68510e309b8e8d152c158ec46450f14d72a6 (patch) | |
tree | 3c8f200dcc9ec93b069c2f84ae831f4eeb75612d /lib/zlib/tf_gunzip.c | |
parent | 221b1638aed1bedd7b17802d66c3288c07a60c85 (diff) |
zlib: add gunzip() support
This commit adds some more files to use zlib from TF.
To use zlib, ->zalloc and ->zfree hooks are needed. The implementation
depends on the system. For user-space, the libc provides malloc() and
friends. Unfortunately, ARM Trusted Firmware does not provide malloc()
or any concept of dynamic memory allocation.
I implemented very simple calloc() and free() for this. Stupidly,
zfree() never frees memory, but it works enough for this.
The purpose of using zlib is to implement gunzip() - this function
takes compressed data from in_buf, then dumps the decompressed data
to oub_buf. The work_buf is used for memory allocation during the
decompress. Upon exit, it updates in_buf and out_buf. If successful,
in_buf points to the end of input data, out_buf to the end of the
decompressed data.
To use this feature, you need to do:
- include lib/zlib/zlib.mk from your platform.mk
- add $(ZLIB_SOURCES) to your BL*_SOURCES
Signed-off-by: Masahiro Yamada <yamada.masahiro@socionext.com>
Diffstat (limited to 'lib/zlib/tf_gunzip.c')
-rw-r--r-- | lib/zlib/tf_gunzip.c | 101 |
1 files changed, 101 insertions, 0 deletions
diff --git a/lib/zlib/tf_gunzip.c b/lib/zlib/tf_gunzip.c new file mode 100644 index 00000000..f07c380a --- /dev/null +++ b/lib/zlib/tf_gunzip.c @@ -0,0 +1,101 @@ +/* + * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <assert.h> +#include <debug.h> +#include <errno.h> +#include <string.h> +#include <tf_gunzip.h> +#include <utils.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: %d byte input\n", stream.total_in); + VERBOSE("zlib: %d byte output\n", stream.total_out); + + *in_buf = (uintptr_t)stream.next_in; + *out_buf = (uintptr_t)stream.next_out; + + inflateEnd(&stream); + + return ret; +} |