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
zcalloc(void * opaque,unsigned int items,unsigned int size)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
zfree(void * opaque,void * ptr)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 */
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)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