Branch data Line data Source code
1 : : // SPDX-License-Identifier: GPL-2.0
2 : : #ifdef STATIC
3 : : #define PREBOOT
4 : : /* Pre-boot environment: included */
5 : :
6 : : /* prevent inclusion of _LINUX_KERNEL_H in pre-boot environment: lots
7 : : * errors about console_printk etc... on ARM */
8 : : #define _LINUX_KERNEL_H
9 : :
10 : : #include "zlib_inflate/inftrees.c"
11 : : #include "zlib_inflate/inffast.c"
12 : : #include "zlib_inflate/inflate.c"
13 : : #ifdef CONFIG_ZLIB_DFLTCC
14 : : #include "zlib_dfltcc/dfltcc.c"
15 : : #include "zlib_dfltcc/dfltcc_inflate.c"
16 : : #endif
17 : :
18 : : #else /* STATIC */
19 : : /* initramfs et al: linked */
20 : :
21 : : #include <linux/zutil.h>
22 : :
23 : : #include "zlib_inflate/inftrees.h"
24 : : #include "zlib_inflate/inffast.h"
25 : : #include "zlib_inflate/inflate.h"
26 : :
27 : : #include "zlib_inflate/infutil.h"
28 : : #include <linux/decompress/inflate.h>
29 : :
30 : : #endif /* STATIC */
31 : :
32 : : #include <linux/decompress/mm.h>
33 : :
34 : : #define GZIP_IOBUF_SIZE (16*1024)
35 : :
36 : 0 : static long INIT nofill(void *buffer, unsigned long len)
37 : : {
38 : 0 : return -1;
39 : : }
40 : :
41 : : /* Included from initramfs et al code */
42 : 0 : STATIC int INIT __gunzip(unsigned char *buf, long len,
43 : : long (*fill)(void*, unsigned long),
44 : : long (*flush)(void*, unsigned long),
45 : : unsigned char *out_buf, long out_len,
46 : : long *pos,
47 : : void(*error)(char *x)) {
48 : 0 : u8 *zbuf;
49 : 0 : struct z_stream_s *strm;
50 : 0 : int rc;
51 : :
52 : 0 : rc = -1;
53 [ # # ]: 0 : if (flush) {
54 : 0 : out_len = 0x8000; /* 32 K */
55 : 0 : out_buf = malloc(out_len);
56 : : } else {
57 [ # # ]: 0 : if (!out_len)
58 : 0 : out_len = ((size_t)~0) - (size_t)out_buf; /* no limit */
59 : : }
60 [ # # ]: 0 : if (!out_buf) {
61 : 0 : error("Out of memory while allocating output buffer");
62 : 0 : goto gunzip_nomem1;
63 : : }
64 : :
65 [ # # ]: 0 : if (buf)
66 : : zbuf = buf;
67 : : else {
68 : 0 : zbuf = malloc(GZIP_IOBUF_SIZE);
69 : 0 : len = 0;
70 : : }
71 [ # # ]: 0 : if (!zbuf) {
72 : 0 : error("Out of memory while allocating input buffer");
73 : 0 : goto gunzip_nomem2;
74 : : }
75 : :
76 : 0 : strm = malloc(sizeof(*strm));
77 [ # # ]: 0 : if (strm == NULL) {
78 : 0 : error("Out of memory while allocating z_stream");
79 : 0 : goto gunzip_nomem3;
80 : : }
81 : :
82 [ # # ]: 0 : strm->workspace = malloc(flush ? zlib_inflate_workspacesize() :
83 : : #ifdef CONFIG_ZLIB_DFLTCC
84 : : /* Always allocate the full workspace for DFLTCC */
85 : : zlib_inflate_workspacesize());
86 : : #else
87 : : sizeof(struct inflate_state));
88 : : #endif
89 [ # # ]: 0 : if (strm->workspace == NULL) {
90 : 0 : error("Out of memory while allocating workspace");
91 : 0 : goto gunzip_nomem4;
92 : : }
93 : :
94 [ # # ]: 0 : if (!fill)
95 : 0 : fill = nofill;
96 : :
97 [ # # ]: 0 : if (len == 0)
98 : 0 : len = fill(zbuf, GZIP_IOBUF_SIZE);
99 : :
100 : : /* verify the gzip header */
101 [ # # ]: 0 : if (len < 10 ||
102 [ # # # # : 0 : zbuf[0] != 0x1f || zbuf[1] != 0x8b || zbuf[2] != 0x08) {
# # ]
103 [ # # ]: 0 : if (pos)
104 : 0 : *pos = 0;
105 : 0 : error("Not a gzip file");
106 : 0 : goto gunzip_5;
107 : : }
108 : :
109 : : /* skip over gzip header (1f,8b,08... 10 bytes total +
110 : : * possible asciz filename)
111 : : */
112 : 0 : strm->next_in = zbuf + 10;
113 : 0 : strm->avail_in = len - 10;
114 : : /* skip over asciz filename */
115 [ # # ]: 0 : if (zbuf[3] & 0x8) {
116 : 0 : do {
117 : : /*
118 : : * If the filename doesn't fit into the buffer,
119 : : * the file is very probably corrupt. Don't try
120 : : * to read more data.
121 : : */
122 [ # # ]: 0 : if (strm->avail_in == 0) {
123 : 0 : error("header error");
124 : 0 : goto gunzip_5;
125 : : }
126 : 0 : --strm->avail_in;
127 [ # # ]: 0 : } while (*strm->next_in++);
128 : : }
129 : :
130 : 0 : strm->next_out = out_buf;
131 : 0 : strm->avail_out = out_len;
132 : :
133 : 0 : rc = zlib_inflateInit2(strm, -MAX_WBITS);
134 : :
135 : : #ifdef CONFIG_ZLIB_DFLTCC
136 : : /* Always keep the window for DFLTCC */
137 : : #else
138 [ # # ]: 0 : if (!flush) {
139 : 0 : WS(strm)->inflate_state.wsize = 0;
140 : 0 : WS(strm)->inflate_state.window = NULL;
141 : : }
142 : : #endif
143 : :
144 [ # # ]: 0 : while (rc == Z_OK) {
145 [ # # ]: 0 : if (strm->avail_in == 0) {
146 : : /* TODO: handle case where both pos and fill are set */
147 : 0 : len = fill(zbuf, GZIP_IOBUF_SIZE);
148 [ # # ]: 0 : if (len < 0) {
149 : 0 : rc = -1;
150 : 0 : error("read error");
151 : 0 : break;
152 : : }
153 : 0 : strm->next_in = zbuf;
154 : 0 : strm->avail_in = len;
155 : : }
156 : 0 : rc = zlib_inflate(strm, 0);
157 : :
158 : : /* Write any data generated */
159 [ # # # # ]: 0 : if (flush && strm->next_out > out_buf) {
160 : 0 : long l = strm->next_out - out_buf;
161 [ # # ]: 0 : if (l != flush(out_buf, l)) {
162 : 0 : rc = -1;
163 : 0 : error("write error");
164 : 0 : break;
165 : : }
166 : 0 : strm->next_out = out_buf;
167 : 0 : strm->avail_out = out_len;
168 : : }
169 : :
170 : : /* after Z_FINISH, only Z_STREAM_END is "we unpacked it all" */
171 [ # # ]: 0 : if (rc == Z_STREAM_END) {
172 : : rc = 0;
173 : : break;
174 [ # # ]: 0 : } else if (rc != Z_OK) {
175 : 0 : error("uncompression error");
176 : 0 : rc = -1;
177 : : }
178 : : }
179 : :
180 : 0 : zlib_inflateEnd(strm);
181 [ # # ]: 0 : if (pos)
182 : : /* add + 8 to skip over trailer */
183 : 0 : *pos = strm->next_in - zbuf+8;
184 : :
185 : 0 : gunzip_5:
186 : 0 : free(strm->workspace);
187 : 0 : gunzip_nomem4:
188 : 0 : free(strm);
189 : 0 : gunzip_nomem3:
190 [ # # ]: 0 : if (!buf)
191 : 0 : free(zbuf);
192 : 0 : gunzip_nomem2:
193 [ # # ]: 0 : if (flush)
194 : 0 : free(out_buf);
195 : 0 : gunzip_nomem1:
196 : 0 : return rc; /* returns Z_OK (0) if successful */
197 : : }
198 : :
199 : : #ifndef PREBOOT
200 : 0 : STATIC int INIT gunzip(unsigned char *buf, long len,
201 : : long (*fill)(void*, unsigned long),
202 : : long (*flush)(void*, unsigned long),
203 : : unsigned char *out_buf,
204 : : long *pos,
205 : : void (*error)(char *x))
206 : : {
207 : 0 : return __gunzip(buf, len, fill, flush, out_buf, 0, pos, error);
208 : : }
209 : : #else
210 : : STATIC int INIT __decompress(unsigned char *buf, long len,
211 : : long (*fill)(void*, unsigned long),
212 : : long (*flush)(void*, unsigned long),
213 : : unsigned char *out_buf, long out_len,
214 : : long *pos,
215 : : void (*error)(char *x))
216 : : {
217 : : return __gunzip(buf, len, fill, flush, out_buf, out_len, pos, error);
218 : : }
219 : : #endif
|