// SPDX-License-Identifier: GPL-2.0-or-later /* * 842 Software Decompression * * Copyright (C) 2015 Dan Streetman, IBM Corp * * See 842.h for details of the 842 compressed format.
*/
if (n > 64) {
pr_debug("next_bits invalid n %u\n", n); return -EINVAL;
}
/* split this up if reading > 8 bytes, or if we're at the end of * the input buffer and would read past the end
*/ if (bits > 64) return __split_next_bits(p, d, n, 32); elseif (p->ilen < 8 && bits > 32 && bits <= 56) return __split_next_bits(p, d, n, 16); elseif (p->ilen < 4 && bits > 16 && bits <= 24) return __split_next_bits(p, d, n, 8);
if (DIV_ROUND_UP(bits, 8) > p->ilen) return -EOVERFLOW;
ret = next_bits(p, &index, bits); if (ret) return ret;
offset = index * size;
/* a ring buffer of fsize is used; correct the offset */ if (total > fsize) { /* this is where the current fifo is */
u64 section = round_down(total, fsize); /* the current pos in the fifo */
u64 pos = total - section;
/* if the offset is past/at the pos, we need to * go back to the last fifo section
*/ if (offset >= pos)
section -= fsize;
offset += section;
}
if (offset + size > total) {
pr_debug("index%x %lx points past end %lx\n", size,
(unsignedlong)offset, (unsignedlong)total); return -EINVAL;
}
if (size != 2 && size != 4 && size != 8)
WARN(1, "__do_index invalid size %x\n", size); else
pr_debug("index%x to %lx off %lx adjoff %lx tot %lx data %lx\n",
size, (unsignedlong)index,
(unsignedlong)(index * size), (unsignedlong)offset,
(unsignedlong)total,
(unsignedlong)beN_to_cpu(&p->ostart[offset], size));
staticint do_op(struct sw842_param *p, u8 o)
{ int i, ret = 0;
if (o >= OPS_MAX) return -EINVAL;
for (i = 0; i < 4; i++) {
u8 op = decomp_ops[o][i];
pr_debug("op is %x\n", op);
switch (op & OP_ACTION) { case OP_ACTION_DATA:
ret = do_data(p, op & OP_AMOUNT); break; case OP_ACTION_INDEX:
ret = do_index(p, op & OP_AMOUNT); break; case OP_ACTION_NOOP: break; default:
pr_err("Internal error, invalid op %x\n", op); return -EINVAL;
}
if (ret) return ret;
}
if (sw842_template_counts)
atomic_inc(&template_count[o]);
return 0;
}
/** * sw842_decompress * * Decompress the 842-compressed buffer of length @ilen at @in * to the output buffer @out, using no more than @olen bytes. * * The compressed buffer must be only a single 842-compressed buffer, * with the standard format described in the comments in 842.h * Processing will stop when the 842 "END" template is detected, * not the end of the buffer. * * Returns: 0 on success, error on failure. The @olen parameter * will contain the number of output bytes written on success, or * 0 on error.
*/ int sw842_decompress(const u8 *in, unsignedint ilen,
u8 *out, unsignedint *olen)
{ struct sw842_param p; int ret;
u64 op, rep, tmp, bytes, total;
u64 crc;
if (sw842_template_counts)
atomic_inc(&template_repeat_count);
break; case OP_ZEROS: if (8 > p.olen) return -ENOSPC;
memset(p.out, 0, 8);
p.out += 8;
p.olen -= 8;
if (sw842_template_counts)
atomic_inc(&template_zeros_count);
break; case OP_SHORT_DATA:
ret = next_bits(&p, &bytes, SHORT_DATA_BITS); if (ret) return ret;
if (!bytes || bytes > SHORT_DATA_BITS_MAX) return -EINVAL;
while (bytes-- > 0) {
ret = next_bits(&p, &tmp, 8); if (ret) return ret;
*p.out = (u8)tmp;
p.out++;
p.olen--;
}
if (sw842_template_counts)
atomic_inc(&template_short_data_count);
break; case OP_END: if (sw842_template_counts)
atomic_inc(&template_end_count);
break; default: /* use template */
ret = do_op(&p, op); if (ret) return ret; break;
}
} while (op != OP_END);
/* * crc(0:31) is saved in compressed data starting with the * next bit after End of stream template.
*/
ret = next_bits(&p, &crc, CRC_BITS); if (ret) return ret;
/* * Validate CRC saved in compressed data.
*/ if (crc != (u64)crc32_be(0, out, total - p.olen)) {
pr_debug("CRC mismatch for decompression\n"); return -EINVAL;
}
if (unlikely((total - p.olen) > UINT_MAX)) return -ENOSPC;
*olen = total - p.olen;
return 0;
}
EXPORT_SYMBOL_GPL(sw842_decompress);
staticint __init sw842_init(void)
{ if (sw842_template_counts)
sw842_debugfs_create();
return 0;
}
module_init(sw842_init);
staticvoid __exit sw842_exit(void)
{ if (sw842_template_counts)
sw842_debugfs_remove();
}
module_exit(sw842_exit);
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.