0001
0002
0003
0004
0005
0006
0007
0008
0009
0010 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
0011 #define MODULE_NAME "842_decompress"
0012
0013 #include "842.h"
0014 #include "842_debugfs.h"
0015
0016
0017 #define I2_FIFO_SIZE (2 * (1 << I2_BITS))
0018 #define I4_FIFO_SIZE (4 * (1 << I4_BITS))
0019 #define I8_FIFO_SIZE (8 * (1 << I8_BITS))
0020
0021 static u8 decomp_ops[OPS_MAX][4] = {
0022 { D8, N0, N0, N0 },
0023 { D4, D2, I2, N0 },
0024 { D4, I2, D2, N0 },
0025 { D4, I2, I2, N0 },
0026 { D4, I4, N0, N0 },
0027 { D2, I2, D4, N0 },
0028 { D2, I2, D2, I2 },
0029 { D2, I2, I2, D2 },
0030 { D2, I2, I2, I2 },
0031 { D2, I2, I4, N0 },
0032 { I2, D2, D4, N0 },
0033 { I2, D4, I2, N0 },
0034 { I2, D2, I2, D2 },
0035 { I2, D2, I2, I2 },
0036 { I2, D2, I4, N0 },
0037 { I2, I2, D4, N0 },
0038 { I2, I2, D2, I2 },
0039 { I2, I2, I2, D2 },
0040 { I2, I2, I2, I2 },
0041 { I2, I2, I4, N0 },
0042 { I4, D4, N0, N0 },
0043 { I4, D2, I2, N0 },
0044 { I4, I2, D2, N0 },
0045 { I4, I2, I2, N0 },
0046 { I4, I4, N0, N0 },
0047 { I8, N0, N0, N0 }
0048 };
0049
0050 struct sw842_param {
0051 u8 *in;
0052 u8 bit;
0053 u64 ilen;
0054 u8 *out;
0055 u8 *ostart;
0056 u64 olen;
0057 };
0058
0059 #define beN_to_cpu(d, s) \
0060 ((s) == 2 ? be16_to_cpu(get_unaligned((__be16 *)d)) : \
0061 (s) == 4 ? be32_to_cpu(get_unaligned((__be32 *)d)) : \
0062 (s) == 8 ? be64_to_cpu(get_unaligned((__be64 *)d)) : \
0063 0)
0064
0065 static int next_bits(struct sw842_param *p, u64 *d, u8 n);
0066
0067 static int __split_next_bits(struct sw842_param *p, u64 *d, u8 n, u8 s)
0068 {
0069 u64 tmp = 0;
0070 int ret;
0071
0072 if (n <= s) {
0073 pr_debug("split_next_bits invalid n %u s %u\n", n, s);
0074 return -EINVAL;
0075 }
0076
0077 ret = next_bits(p, &tmp, n - s);
0078 if (ret)
0079 return ret;
0080 ret = next_bits(p, d, s);
0081 if (ret)
0082 return ret;
0083 *d |= tmp << s;
0084 return 0;
0085 }
0086
0087 static int next_bits(struct sw842_param *p, u64 *d, u8 n)
0088 {
0089 u8 *in = p->in, b = p->bit, bits = b + n;
0090
0091 if (n > 64) {
0092 pr_debug("next_bits invalid n %u\n", n);
0093 return -EINVAL;
0094 }
0095
0096
0097
0098
0099 if (bits > 64)
0100 return __split_next_bits(p, d, n, 32);
0101 else if (p->ilen < 8 && bits > 32 && bits <= 56)
0102 return __split_next_bits(p, d, n, 16);
0103 else if (p->ilen < 4 && bits > 16 && bits <= 24)
0104 return __split_next_bits(p, d, n, 8);
0105
0106 if (DIV_ROUND_UP(bits, 8) > p->ilen)
0107 return -EOVERFLOW;
0108
0109 if (bits <= 8)
0110 *d = *in >> (8 - bits);
0111 else if (bits <= 16)
0112 *d = be16_to_cpu(get_unaligned((__be16 *)in)) >> (16 - bits);
0113 else if (bits <= 32)
0114 *d = be32_to_cpu(get_unaligned((__be32 *)in)) >> (32 - bits);
0115 else
0116 *d = be64_to_cpu(get_unaligned((__be64 *)in)) >> (64 - bits);
0117
0118 *d &= GENMASK_ULL(n - 1, 0);
0119
0120 p->bit += n;
0121
0122 if (p->bit > 7) {
0123 p->in += p->bit / 8;
0124 p->ilen -= p->bit / 8;
0125 p->bit %= 8;
0126 }
0127
0128 return 0;
0129 }
0130
0131 static int do_data(struct sw842_param *p, u8 n)
0132 {
0133 u64 v;
0134 int ret;
0135
0136 if (n > p->olen)
0137 return -ENOSPC;
0138
0139 ret = next_bits(p, &v, n * 8);
0140 if (ret)
0141 return ret;
0142
0143 switch (n) {
0144 case 2:
0145 put_unaligned(cpu_to_be16((u16)v), (__be16 *)p->out);
0146 break;
0147 case 4:
0148 put_unaligned(cpu_to_be32((u32)v), (__be32 *)p->out);
0149 break;
0150 case 8:
0151 put_unaligned(cpu_to_be64((u64)v), (__be64 *)p->out);
0152 break;
0153 default:
0154 return -EINVAL;
0155 }
0156
0157 p->out += n;
0158 p->olen -= n;
0159
0160 return 0;
0161 }
0162
0163 static int __do_index(struct sw842_param *p, u8 size, u8 bits, u64 fsize)
0164 {
0165 u64 index, offset, total = round_down(p->out - p->ostart, 8);
0166 int ret;
0167
0168 ret = next_bits(p, &index, bits);
0169 if (ret)
0170 return ret;
0171
0172 offset = index * size;
0173
0174
0175 if (total > fsize) {
0176
0177 u64 section = round_down(total, fsize);
0178
0179 u64 pos = total - section;
0180
0181
0182
0183
0184 if (offset >= pos)
0185 section -= fsize;
0186
0187 offset += section;
0188 }
0189
0190 if (offset + size > total) {
0191 pr_debug("index%x %lx points past end %lx\n", size,
0192 (unsigned long)offset, (unsigned long)total);
0193 return -EINVAL;
0194 }
0195
0196 if (size != 2 && size != 4 && size != 8)
0197 WARN(1, "__do_index invalid size %x\n", size);
0198 else
0199 pr_debug("index%x to %lx off %lx adjoff %lx tot %lx data %lx\n",
0200 size, (unsigned long)index,
0201 (unsigned long)(index * size), (unsigned long)offset,
0202 (unsigned long)total,
0203 (unsigned long)beN_to_cpu(&p->ostart[offset], size));
0204
0205 memcpy(p->out, &p->ostart[offset], size);
0206 p->out += size;
0207 p->olen -= size;
0208
0209 return 0;
0210 }
0211
0212 static int do_index(struct sw842_param *p, u8 n)
0213 {
0214 switch (n) {
0215 case 2:
0216 return __do_index(p, 2, I2_BITS, I2_FIFO_SIZE);
0217 case 4:
0218 return __do_index(p, 4, I4_BITS, I4_FIFO_SIZE);
0219 case 8:
0220 return __do_index(p, 8, I8_BITS, I8_FIFO_SIZE);
0221 default:
0222 return -EINVAL;
0223 }
0224 }
0225
0226 static int do_op(struct sw842_param *p, u8 o)
0227 {
0228 int i, ret = 0;
0229
0230 if (o >= OPS_MAX)
0231 return -EINVAL;
0232
0233 for (i = 0; i < 4; i++) {
0234 u8 op = decomp_ops[o][i];
0235
0236 pr_debug("op is %x\n", op);
0237
0238 switch (op & OP_ACTION) {
0239 case OP_ACTION_DATA:
0240 ret = do_data(p, op & OP_AMOUNT);
0241 break;
0242 case OP_ACTION_INDEX:
0243 ret = do_index(p, op & OP_AMOUNT);
0244 break;
0245 case OP_ACTION_NOOP:
0246 break;
0247 default:
0248 pr_err("Internal error, invalid op %x\n", op);
0249 return -EINVAL;
0250 }
0251
0252 if (ret)
0253 return ret;
0254 }
0255
0256 if (sw842_template_counts)
0257 atomic_inc(&template_count[o]);
0258
0259 return 0;
0260 }
0261
0262
0263
0264
0265
0266
0267
0268
0269
0270
0271
0272
0273
0274
0275
0276
0277 int sw842_decompress(const u8 *in, unsigned int ilen,
0278 u8 *out, unsigned int *olen)
0279 {
0280 struct sw842_param p;
0281 int ret;
0282 u64 op, rep, tmp, bytes, total;
0283 u64 crc;
0284
0285 p.in = (u8 *)in;
0286 p.bit = 0;
0287 p.ilen = ilen;
0288 p.out = out;
0289 p.ostart = out;
0290 p.olen = *olen;
0291
0292 total = p.olen;
0293
0294 *olen = 0;
0295
0296 do {
0297 ret = next_bits(&p, &op, OP_BITS);
0298 if (ret)
0299 return ret;
0300
0301 pr_debug("template is %lx\n", (unsigned long)op);
0302
0303 switch (op) {
0304 case OP_REPEAT:
0305 ret = next_bits(&p, &rep, REPEAT_BITS);
0306 if (ret)
0307 return ret;
0308
0309 if (p.out == out)
0310 return -EINVAL;
0311
0312
0313 rep++;
0314
0315 if (rep * 8 > p.olen)
0316 return -ENOSPC;
0317
0318 while (rep-- > 0) {
0319 memcpy(p.out, p.out - 8, 8);
0320 p.out += 8;
0321 p.olen -= 8;
0322 }
0323
0324 if (sw842_template_counts)
0325 atomic_inc(&template_repeat_count);
0326
0327 break;
0328 case OP_ZEROS:
0329 if (8 > p.olen)
0330 return -ENOSPC;
0331
0332 memset(p.out, 0, 8);
0333 p.out += 8;
0334 p.olen -= 8;
0335
0336 if (sw842_template_counts)
0337 atomic_inc(&template_zeros_count);
0338
0339 break;
0340 case OP_SHORT_DATA:
0341 ret = next_bits(&p, &bytes, SHORT_DATA_BITS);
0342 if (ret)
0343 return ret;
0344
0345 if (!bytes || bytes > SHORT_DATA_BITS_MAX)
0346 return -EINVAL;
0347
0348 while (bytes-- > 0) {
0349 ret = next_bits(&p, &tmp, 8);
0350 if (ret)
0351 return ret;
0352 *p.out = (u8)tmp;
0353 p.out++;
0354 p.olen--;
0355 }
0356
0357 if (sw842_template_counts)
0358 atomic_inc(&template_short_data_count);
0359
0360 break;
0361 case OP_END:
0362 if (sw842_template_counts)
0363 atomic_inc(&template_end_count);
0364
0365 break;
0366 default:
0367 ret = do_op(&p, op);
0368 if (ret)
0369 return ret;
0370 break;
0371 }
0372 } while (op != OP_END);
0373
0374
0375
0376
0377
0378 ret = next_bits(&p, &crc, CRC_BITS);
0379 if (ret)
0380 return ret;
0381
0382
0383
0384
0385 if (crc != (u64)crc32_be(0, out, total - p.olen)) {
0386 pr_debug("CRC mismatch for decompression\n");
0387 return -EINVAL;
0388 }
0389
0390 if (unlikely((total - p.olen) > UINT_MAX))
0391 return -ENOSPC;
0392
0393 *olen = total - p.olen;
0394
0395 return 0;
0396 }
0397 EXPORT_SYMBOL_GPL(sw842_decompress);
0398
0399 static int __init sw842_init(void)
0400 {
0401 if (sw842_template_counts)
0402 sw842_debugfs_create();
0403
0404 return 0;
0405 }
0406 module_init(sw842_init);
0407
0408 static void __exit sw842_exit(void)
0409 {
0410 if (sw842_template_counts)
0411 sw842_debugfs_remove();
0412 }
0413 module_exit(sw842_exit);
0414
0415 MODULE_LICENSE("GPL");
0416 MODULE_DESCRIPTION("Software 842 Decompressor");
0417 MODULE_AUTHOR("Dan Streetman <ddstreet@ieee.org>");