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