Merge tag 'powerpc-5.14-4' of git://git.kernel.org/pub/scm/linux/kernel/git/powerpc...
[linux-2.6-microblaze.git] / lib / 842 / 842_decompress.c
1 // SPDX-License-Identifier: GPL-2.0-or-later
2 /*
3  * 842 Software Decompression
4  *
5  * Copyright (C) 2015 Dan Streetman, IBM Corp
6  *
7  * See 842.h for details of the 842 compressed format.
8  */
9
10 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
11 #define MODULE_NAME "842_decompress"
12
13 #include "842.h"
14 #include "842_debugfs.h"
15
16 /* rolling fifo sizes */
17 #define I2_FIFO_SIZE    (2 * (1 << I2_BITS))
18 #define I4_FIFO_SIZE    (4 * (1 << I4_BITS))
19 #define I8_FIFO_SIZE    (8 * (1 << I8_BITS))
20
21 static u8 decomp_ops[OPS_MAX][4] = {
22         { D8, N0, N0, N0 },
23         { D4, D2, I2, N0 },
24         { D4, I2, D2, N0 },
25         { D4, I2, I2, N0 },
26         { D4, I4, N0, N0 },
27         { D2, I2, D4, N0 },
28         { D2, I2, D2, I2 },
29         { D2, I2, I2, D2 },
30         { D2, I2, I2, I2 },
31         { D2, I2, I4, N0 },
32         { I2, D2, D4, N0 },
33         { I2, D4, I2, N0 },
34         { I2, D2, I2, D2 },
35         { I2, D2, I2, I2 },
36         { I2, D2, I4, N0 },
37         { I2, I2, D4, N0 },
38         { I2, I2, D2, I2 },
39         { I2, I2, I2, D2 },
40         { I2, I2, I2, I2 },
41         { I2, I2, I4, N0 },
42         { I4, D4, N0, N0 },
43         { I4, D2, I2, N0 },
44         { I4, I2, D2, N0 },
45         { I4, I2, I2, N0 },
46         { I4, I4, N0, N0 },
47         { I8, N0, N0, N0 }
48 };
49
50 struct sw842_param {
51         u8 *in;
52         u8 bit;
53         u64 ilen;
54         u8 *out;
55         u8 *ostart;
56         u64 olen;
57 };
58
59 #define beN_to_cpu(d, s)                                        \
60         ((s) == 2 ? be16_to_cpu(get_unaligned((__be16 *)d)) :   \
61          (s) == 4 ? be32_to_cpu(get_unaligned((__be32 *)d)) :   \
62          (s) == 8 ? be64_to_cpu(get_unaligned((__be64 *)d)) :   \
63          0)
64
65 static int next_bits(struct sw842_param *p, u64 *d, u8 n);
66
67 static int __split_next_bits(struct sw842_param *p, u64 *d, u8 n, u8 s)
68 {
69         u64 tmp = 0;
70         int ret;
71
72         if (n <= s) {
73                 pr_debug("split_next_bits invalid n %u s %u\n", n, s);
74                 return -EINVAL;
75         }
76
77         ret = next_bits(p, &tmp, n - s);
78         if (ret)
79                 return ret;
80         ret = next_bits(p, d, s);
81         if (ret)
82                 return ret;
83         *d |= tmp << s;
84         return 0;
85 }
86
87 static int next_bits(struct sw842_param *p, u64 *d, u8 n)
88 {
89         u8 *in = p->in, b = p->bit, bits = b + n;
90
91         if (n > 64) {
92                 pr_debug("next_bits invalid n %u\n", n);
93                 return -EINVAL;
94         }
95
96         /* split this up if reading > 8 bytes, or if we're at the end of
97          * the input buffer and would read past the end
98          */
99         if (bits > 64)
100                 return __split_next_bits(p, d, n, 32);
101         else if (p->ilen < 8 && bits > 32 && bits <= 56)
102                 return __split_next_bits(p, d, n, 16);
103         else if (p->ilen < 4 && bits > 16 && bits <= 24)
104                 return __split_next_bits(p, d, n, 8);
105
106         if (DIV_ROUND_UP(bits, 8) > p->ilen)
107                 return -EOVERFLOW;
108
109         if (bits <= 8)
110                 *d = *in >> (8 - bits);
111         else if (bits <= 16)
112                 *d = be16_to_cpu(get_unaligned((__be16 *)in)) >> (16 - bits);
113         else if (bits <= 32)
114                 *d = be32_to_cpu(get_unaligned((__be32 *)in)) >> (32 - bits);
115         else
116                 *d = be64_to_cpu(get_unaligned((__be64 *)in)) >> (64 - bits);
117
118         *d &= GENMASK_ULL(n - 1, 0);
119
120         p->bit += n;
121
122         if (p->bit > 7) {
123                 p->in += p->bit / 8;
124                 p->ilen -= p->bit / 8;
125                 p->bit %= 8;
126         }
127
128         return 0;
129 }
130
131 static int do_data(struct sw842_param *p, u8 n)
132 {
133         u64 v;
134         int ret;
135
136         if (n > p->olen)
137                 return -ENOSPC;
138
139         ret = next_bits(p, &v, n * 8);
140         if (ret)
141                 return ret;
142
143         switch (n) {
144         case 2:
145                 put_unaligned(cpu_to_be16((u16)v), (__be16 *)p->out);
146                 break;
147         case 4:
148                 put_unaligned(cpu_to_be32((u32)v), (__be32 *)p->out);
149                 break;
150         case 8:
151                 put_unaligned(cpu_to_be64((u64)v), (__be64 *)p->out);
152                 break;
153         default:
154                 return -EINVAL;
155         }
156
157         p->out += n;
158         p->olen -= n;
159
160         return 0;
161 }
162
163 static int __do_index(struct sw842_param *p, u8 size, u8 bits, u64 fsize)
164 {
165         u64 index, offset, total = round_down(p->out - p->ostart, 8);
166         int ret;
167
168         ret = next_bits(p, &index, bits);
169         if (ret)
170                 return ret;
171
172         offset = index * size;
173
174         /* a ring buffer of fsize is used; correct the offset */
175         if (total > fsize) {
176                 /* this is where the current fifo is */
177                 u64 section = round_down(total, fsize);
178                 /* the current pos in the fifo */
179                 u64 pos = total - section;
180
181                 /* if the offset is past/at the pos, we need to
182                  * go back to the last fifo section
183                  */
184                 if (offset >= pos)
185                         section -= fsize;
186
187                 offset += section;
188         }
189
190         if (offset + size > total) {
191                 pr_debug("index%x %lx points past end %lx\n", size,
192                          (unsigned long)offset, (unsigned long)total);
193                 return -EINVAL;
194         }
195
196         if (size != 2 && size != 4 && size != 8)
197                 WARN(1, "__do_index invalid size %x\n", size);
198         else
199                 pr_debug("index%x to %lx off %lx adjoff %lx tot %lx data %lx\n",
200                          size, (unsigned long)index,
201                          (unsigned long)(index * size), (unsigned long)offset,
202                          (unsigned long)total,
203                          (unsigned long)beN_to_cpu(&p->ostart[offset], size));
204
205         memcpy(p->out, &p->ostart[offset], size);
206         p->out += size;
207         p->olen -= size;
208
209         return 0;
210 }
211
212 static int do_index(struct sw842_param *p, u8 n)
213 {
214         switch (n) {
215         case 2:
216                 return __do_index(p, 2, I2_BITS, I2_FIFO_SIZE);
217         case 4:
218                 return __do_index(p, 4, I4_BITS, I4_FIFO_SIZE);
219         case 8:
220                 return __do_index(p, 8, I8_BITS, I8_FIFO_SIZE);
221         default:
222                 return -EINVAL;
223         }
224 }
225
226 static int do_op(struct sw842_param *p, u8 o)
227 {
228         int i, ret = 0;
229
230         if (o >= OPS_MAX)
231                 return -EINVAL;
232
233         for (i = 0; i < 4; i++) {
234                 u8 op = decomp_ops[o][i];
235
236                 pr_debug("op is %x\n", op);
237
238                 switch (op & OP_ACTION) {
239                 case OP_ACTION_DATA:
240                         ret = do_data(p, op & OP_AMOUNT);
241                         break;
242                 case OP_ACTION_INDEX:
243                         ret = do_index(p, op & OP_AMOUNT);
244                         break;
245                 case OP_ACTION_NOOP:
246                         break;
247                 default:
248                         pr_err("Internal error, invalid op %x\n", op);
249                         return -EINVAL;
250                 }
251
252                 if (ret)
253                         return ret;
254         }
255
256         if (sw842_template_counts)
257                 atomic_inc(&template_count[o]);
258
259         return 0;
260 }
261
262 /**
263  * sw842_decompress
264  *
265  * Decompress the 842-compressed buffer of length @ilen at @in
266  * to the output buffer @out, using no more than @olen bytes.
267  *
268  * The compressed buffer must be only a single 842-compressed buffer,
269  * with the standard format described in the comments in 842.h
270  * Processing will stop when the 842 "END" template is detected,
271  * not the end of the buffer.
272  *
273  * Returns: 0 on success, error on failure.  The @olen parameter
274  * will contain the number of output bytes written on success, or
275  * 0 on error.
276  */
277 int sw842_decompress(const u8 *in, unsigned int ilen,
278                      u8 *out, unsigned int *olen)
279 {
280         struct sw842_param p;
281         int ret;
282         u64 op, rep, tmp, bytes, total;
283         u64 crc;
284
285         p.in = (u8 *)in;
286         p.bit = 0;
287         p.ilen = ilen;
288         p.out = out;
289         p.ostart = out;
290         p.olen = *olen;
291
292         total = p.olen;
293
294         *olen = 0;
295
296         do {
297                 ret = next_bits(&p, &op, OP_BITS);
298                 if (ret)
299                         return ret;
300
301                 pr_debug("template is %lx\n", (unsigned long)op);
302
303                 switch (op) {
304                 case OP_REPEAT:
305                         ret = next_bits(&p, &rep, REPEAT_BITS);
306                         if (ret)
307                                 return ret;
308
309                         if (p.out == out) /* no previous bytes */
310                                 return -EINVAL;
311
312                         /* copy rep + 1 */
313                         rep++;
314
315                         if (rep * 8 > p.olen)
316                                 return -ENOSPC;
317
318                         while (rep-- > 0) {
319                                 memcpy(p.out, p.out - 8, 8);
320                                 p.out += 8;
321                                 p.olen -= 8;
322                         }
323
324                         if (sw842_template_counts)
325                                 atomic_inc(&template_repeat_count);
326
327                         break;
328                 case OP_ZEROS:
329                         if (8 > p.olen)
330                                 return -ENOSPC;
331
332                         memset(p.out, 0, 8);
333                         p.out += 8;
334                         p.olen -= 8;
335
336                         if (sw842_template_counts)
337                                 atomic_inc(&template_zeros_count);
338
339                         break;
340                 case OP_SHORT_DATA:
341                         ret = next_bits(&p, &bytes, SHORT_DATA_BITS);
342                         if (ret)
343                                 return ret;
344
345                         if (!bytes || bytes > SHORT_DATA_BITS_MAX)
346                                 return -EINVAL;
347
348                         while (bytes-- > 0) {
349                                 ret = next_bits(&p, &tmp, 8);
350                                 if (ret)
351                                         return ret;
352                                 *p.out = (u8)tmp;
353                                 p.out++;
354                                 p.olen--;
355                         }
356
357                         if (sw842_template_counts)
358                                 atomic_inc(&template_short_data_count);
359
360                         break;
361                 case OP_END:
362                         if (sw842_template_counts)
363                                 atomic_inc(&template_end_count);
364
365                         break;
366                 default: /* use template */
367                         ret = do_op(&p, op);
368                         if (ret)
369                                 return ret;
370                         break;
371                 }
372         } while (op != OP_END);
373
374         /*
375          * crc(0:31) is saved in compressed data starting with the
376          * next bit after End of stream template.
377          */
378         ret = next_bits(&p, &crc, CRC_BITS);
379         if (ret)
380                 return ret;
381
382         /*
383          * Validate CRC saved in compressed data.
384          */
385         if (crc != (u64)crc32_be(0, out, total - p.olen)) {
386                 pr_debug("CRC mismatch for decompression\n");
387                 return -EINVAL;
388         }
389
390         if (unlikely((total - p.olen) > UINT_MAX))
391                 return -ENOSPC;
392
393         *olen = total - p.olen;
394
395         return 0;
396 }
397 EXPORT_SYMBOL_GPL(sw842_decompress);
398
399 static int __init sw842_init(void)
400 {
401         if (sw842_template_counts)
402                 sw842_debugfs_create();
403
404         return 0;
405 }
406 module_init(sw842_init);
407
408 static void __exit sw842_exit(void)
409 {
410         if (sw842_template_counts)
411                 sw842_debugfs_remove();
412 }
413 module_exit(sw842_exit);
414
415 MODULE_LICENSE("GPL");
416 MODULE_DESCRIPTION("Software 842 Decompressor");
417 MODULE_AUTHOR("Dan Streetman <ddstreet@ieee.org>");