2 * 842 Software Decompression
4 * Copyright (C) 2015 Dan Streetman, IBM Corp
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * See 842.h for details of the 842 compressed format.
19 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
20 #define MODULE_NAME "842_decompress"
23 #include "842_debugfs.h"
25 /* rolling fifo sizes */
26 #define I2_FIFO_SIZE (2 * (1 << I2_BITS))
27 #define I4_FIFO_SIZE (4 * (1 << I4_BITS))
28 #define I8_FIFO_SIZE (8 * (1 << I8_BITS))
30 static u8 decomp_ops[OPS_MAX][4] = {
68 #define beN_to_cpu(d, s) \
69 ((s) == 2 ? be16_to_cpu(get_unaligned((__be16 *)d)) : \
70 (s) == 4 ? be32_to_cpu(get_unaligned((__be32 *)d)) : \
71 (s) == 8 ? be64_to_cpu(get_unaligned((__be64 *)d)) : \
72 WARN(1, "pr_debug param err invalid size %x\n", s))
74 static int next_bits(struct sw842_param *p, u64 *d, u8 n);
76 static int __split_next_bits(struct sw842_param *p, u64 *d, u8 n, u8 s)
82 pr_debug("split_next_bits invalid n %u s %u\n", n, s);
86 ret = next_bits(p, &tmp, n - s);
89 ret = next_bits(p, d, s);
96 static int next_bits(struct sw842_param *p, u64 *d, u8 n)
98 u8 *in = p->in, b = p->bit, bits = b + n;
101 pr_debug("next_bits invalid n %u\n", n);
105 /* split this up if reading > 8 bytes, or if we're at the end of
106 * the input buffer and would read past the end
109 return __split_next_bits(p, d, n, 32);
110 else if (p->ilen < 8 && bits > 32 && bits <= 56)
111 return __split_next_bits(p, d, n, 16);
112 else if (p->ilen < 4 && bits > 16 && bits <= 24)
113 return __split_next_bits(p, d, n, 8);
115 if (DIV_ROUND_UP(bits, 8) > p->ilen)
119 *d = *in >> (8 - bits);
121 *d = be16_to_cpu(get_unaligned((__be16 *)in)) >> (16 - bits);
123 *d = be32_to_cpu(get_unaligned((__be32 *)in)) >> (32 - bits);
125 *d = be64_to_cpu(get_unaligned((__be64 *)in)) >> (64 - bits);
127 *d &= GENMASK_ULL(n - 1, 0);
133 p->ilen -= p->bit / 8;
140 static int do_data(struct sw842_param *p, u8 n)
148 ret = next_bits(p, &v, n * 8);
154 put_unaligned(cpu_to_be16((u16)v), (__be16 *)p->out);
157 put_unaligned(cpu_to_be32((u32)v), (__be32 *)p->out);
160 put_unaligned(cpu_to_be64((u64)v), (__be64 *)p->out);
172 static int __do_index(struct sw842_param *p, u8 size, u8 bits, u64 fsize)
174 u64 index, offset, total = round_down(p->out - p->ostart, 8);
177 ret = next_bits(p, &index, bits);
181 offset = index * size;
183 /* a ring buffer of fsize is used; correct the offset */
185 /* this is where the current fifo is */
186 u64 section = round_down(total, fsize);
187 /* the current pos in the fifo */
188 u64 pos = total - section;
190 /* if the offset is past/at the pos, we need to
191 * go back to the last fifo section
199 if (offset + size > total) {
200 pr_debug("index%x %lx points past end %lx\n", size,
201 (unsigned long)offset, (unsigned long)total);
205 pr_debug("index%x to %lx off %lx adjoff %lx tot %lx data %lx\n",
206 size, (unsigned long)index, (unsigned long)(index * size),
207 (unsigned long)offset, (unsigned long)total,
208 (unsigned long)beN_to_cpu(&p->ostart[offset], size));
210 memcpy(p->out, &p->ostart[offset], size);
217 static int do_index(struct sw842_param *p, u8 n)
221 return __do_index(p, 2, I2_BITS, I2_FIFO_SIZE);
223 return __do_index(p, 4, I4_BITS, I4_FIFO_SIZE);
225 return __do_index(p, 8, I8_BITS, I8_FIFO_SIZE);
231 static int do_op(struct sw842_param *p, u8 o)
238 for (i = 0; i < 4; i++) {
239 u8 op = decomp_ops[o][i];
241 pr_debug("op is %x\n", op);
243 switch (op & OP_ACTION) {
245 ret = do_data(p, op & OP_AMOUNT);
247 case OP_ACTION_INDEX:
248 ret = do_index(p, op & OP_AMOUNT);
253 pr_err("Interal error, invalid op %x\n", op);
261 if (sw842_template_counts)
262 atomic_inc(&template_count[o]);
270 * Decompress the 842-compressed buffer of length @ilen at @in
271 * to the output buffer @out, using no more than @olen bytes.
273 * The compressed buffer must be only a single 842-compressed buffer,
274 * with the standard format described in the comments in 842.h
275 * Processing will stop when the 842 "END" template is detected,
276 * not the end of the buffer.
278 * Returns: 0 on success, error on failure. The @olen parameter
279 * will contain the number of output bytes written on success, or
282 int sw842_decompress(const u8 *in, unsigned int ilen,
283 u8 *out, unsigned int *olen)
285 struct sw842_param p;
287 u64 op, rep, tmp, bytes, total;
302 ret = next_bits(&p, &op, OP_BITS);
306 pr_debug("template is %lx\n", (unsigned long)op);
310 ret = next_bits(&p, &rep, REPEAT_BITS);
314 if (p.out == out) /* no previous bytes */
320 if (rep * 8 > p.olen)
324 memcpy(p.out, p.out - 8, 8);
329 if (sw842_template_counts)
330 atomic_inc(&template_repeat_count);
341 if (sw842_template_counts)
342 atomic_inc(&template_zeros_count);
346 ret = next_bits(&p, &bytes, SHORT_DATA_BITS);
350 if (!bytes || bytes > SHORT_DATA_BITS_MAX)
353 while (bytes-- > 0) {
354 ret = next_bits(&p, &tmp, 8);
362 if (sw842_template_counts)
363 atomic_inc(&template_short_data_count);
367 if (sw842_template_counts)
368 atomic_inc(&template_end_count);
371 default: /* use template */
377 } while (op != OP_END);
380 * crc(0:31) is saved in compressed data starting with the
381 * next bit after End of stream template.
383 ret = next_bits(&p, &crc, CRC_BITS);
388 * Validate CRC saved in compressed data.
390 if (crc != (u64)crc32_be(0, out, total - p.olen)) {
391 pr_debug("CRC mismatch for decompression\n");
395 if (unlikely((total - p.olen) > UINT_MAX))
398 *olen = total - p.olen;
402 EXPORT_SYMBOL_GPL(sw842_decompress);
404 static int __init sw842_init(void)
406 if (sw842_template_counts)
407 sw842_debugfs_create();
411 module_init(sw842_init);
413 static void __exit sw842_exit(void)
415 if (sw842_template_counts)
416 sw842_debugfs_remove();
418 module_exit(sw842_exit);
420 MODULE_LICENSE("GPL");
421 MODULE_DESCRIPTION("Software 842 Decompressor");
422 MODULE_AUTHOR("Dan Streetman <ddstreet@ieee.org>");