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