^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) * Branch/Call/Jump (BCJ) filter decoders
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) * Authors: Lasse Collin <lasse.collin@tukaani.org>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) * Igor Pavlov <https://7-zip.org/>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) * This file has been put into the public domain.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) * You can do whatever you want with this file.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) #include "xz_private.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) * The rest of the file is inside this ifdef. It makes things a little more
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) * convenient when building without support for any BCJ filters.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) #ifdef XZ_DEC_BCJ
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) struct xz_dec_bcj {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) /* Type of the BCJ filter being used */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) enum {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) BCJ_X86 = 4, /* x86 or x86-64 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) BCJ_POWERPC = 5, /* Big endian only */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) BCJ_IA64 = 6, /* Big or little endian */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) BCJ_ARM = 7, /* Little endian only */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) BCJ_ARMTHUMB = 8, /* Little endian only */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) BCJ_SPARC = 9 /* Big or little endian */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) } type;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) * Return value of the next filter in the chain. We need to preserve
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) * this information across calls, because we must not call the next
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) * filter anymore once it has returned XZ_STREAM_END.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) enum xz_ret ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) /* True if we are operating in single-call mode. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) bool single_call;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) * Absolute position relative to the beginning of the uncompressed
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) * data (in a single .xz Block). We care only about the lowest 32
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) * bits so this doesn't need to be uint64_t even with big files.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) uint32_t pos;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) /* x86 filter state */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) uint32_t x86_prev_mask;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) /* Temporary space to hold the variables from struct xz_buf */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) uint8_t *out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) size_t out_pos;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) size_t out_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) struct {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) /* Amount of already filtered data in the beginning of buf */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) size_t filtered;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) /* Total amount of data currently stored in buf */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) size_t size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) * Buffer to hold a mix of filtered and unfiltered data. This
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) * needs to be big enough to hold Alignment + 2 * Look-ahead:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) * Type Alignment Look-ahead
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) * x86 1 4
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) * PowerPC 4 0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) * IA-64 16 0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) * ARM 4 0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) * ARM-Thumb 2 2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) * SPARC 4 0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) uint8_t buf[16];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) } temp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) #ifdef XZ_DEC_X86
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) * This is used to test the most significant byte of a memory address
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) * in an x86 instruction.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) static inline int bcj_x86_test_msbyte(uint8_t b)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) return b == 0x00 || b == 0xFF;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) static size_t bcj_x86(struct xz_dec_bcj *s, uint8_t *buf, size_t size)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) static const bool mask_to_allowed_status[8]
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) = { true, true, true, false, true, false, false, false };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) static const uint8_t mask_to_bit_num[8] = { 0, 1, 2, 2, 3, 3, 3, 3 };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) size_t i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) size_t prev_pos = (size_t)-1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) uint32_t prev_mask = s->x86_prev_mask;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) uint32_t src;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) uint32_t dest;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) uint32_t j;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) uint8_t b;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) if (size <= 4)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) size -= 4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) for (i = 0; i < size; ++i) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) if ((buf[i] & 0xFE) != 0xE8)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) prev_pos = i - prev_pos;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) if (prev_pos > 3) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) prev_mask = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) prev_mask = (prev_mask << (prev_pos - 1)) & 7;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) if (prev_mask != 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) b = buf[i + 4 - mask_to_bit_num[prev_mask]];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) if (!mask_to_allowed_status[prev_mask]
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) || bcj_x86_test_msbyte(b)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) prev_pos = i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) prev_mask = (prev_mask << 1) | 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) prev_pos = i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) if (bcj_x86_test_msbyte(buf[i + 4])) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) src = get_unaligned_le32(buf + i + 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) while (true) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) dest = src - (s->pos + (uint32_t)i + 5);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) if (prev_mask == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) j = mask_to_bit_num[prev_mask] * 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) b = (uint8_t)(dest >> (24 - j));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) if (!bcj_x86_test_msbyte(b))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) src = dest ^ (((uint32_t)1 << (32 - j)) - 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) dest &= 0x01FFFFFF;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) dest |= (uint32_t)0 - (dest & 0x01000000);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) put_unaligned_le32(dest, buf + i + 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) i += 4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) prev_mask = (prev_mask << 1) | 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) prev_pos = i - prev_pos;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) s->x86_prev_mask = prev_pos > 3 ? 0 : prev_mask << (prev_pos - 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) return i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) #ifdef XZ_DEC_POWERPC
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) static size_t bcj_powerpc(struct xz_dec_bcj *s, uint8_t *buf, size_t size)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) size_t i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) uint32_t instr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) for (i = 0; i + 4 <= size; i += 4) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) instr = get_unaligned_be32(buf + i);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) if ((instr & 0xFC000003) == 0x48000001) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) instr &= 0x03FFFFFC;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) instr -= s->pos + (uint32_t)i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) instr &= 0x03FFFFFC;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) instr |= 0x48000001;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) put_unaligned_be32(instr, buf + i);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) return i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) #ifdef XZ_DEC_IA64
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) static size_t bcj_ia64(struct xz_dec_bcj *s, uint8_t *buf, size_t size)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) static const uint8_t branch_table[32] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) 0, 0, 0, 0, 0, 0, 0, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) 0, 0, 0, 0, 0, 0, 0, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) 4, 4, 6, 6, 0, 0, 7, 7,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) 4, 4, 0, 0, 4, 4, 0, 0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) * The local variables take a little bit stack space, but it's less
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) * than what LZMA2 decoder takes, so it doesn't make sense to reduce
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) * stack usage here without doing that for the LZMA2 decoder too.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) /* Loop counters */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) size_t i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) size_t j;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) /* Instruction slot (0, 1, or 2) in the 128-bit instruction word */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) uint32_t slot;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) /* Bitwise offset of the instruction indicated by slot */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) uint32_t bit_pos;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) /* bit_pos split into byte and bit parts */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) uint32_t byte_pos;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) uint32_t bit_res;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) /* Address part of an instruction */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) uint32_t addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) /* Mask used to detect which instructions to convert */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) uint32_t mask;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) /* 41-bit instruction stored somewhere in the lowest 48 bits */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) uint64_t instr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) /* Instruction normalized with bit_res for easier manipulation */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) uint64_t norm;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) for (i = 0; i + 16 <= size; i += 16) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) mask = branch_table[buf[i] & 0x1F];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) for (slot = 0, bit_pos = 5; slot < 3; ++slot, bit_pos += 41) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) if (((mask >> slot) & 1) == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) byte_pos = bit_pos >> 3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) bit_res = bit_pos & 7;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) instr = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) for (j = 0; j < 6; ++j)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) instr |= (uint64_t)(buf[i + j + byte_pos])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) << (8 * j);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) norm = instr >> bit_res;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) if (((norm >> 37) & 0x0F) == 0x05
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) && ((norm >> 9) & 0x07) == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) addr = (norm >> 13) & 0x0FFFFF;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) addr |= ((uint32_t)(norm >> 36) & 1) << 20;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) addr <<= 4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) addr -= s->pos + (uint32_t)i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) addr >>= 4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) norm &= ~((uint64_t)0x8FFFFF << 13);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) norm |= (uint64_t)(addr & 0x0FFFFF) << 13;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) norm |= (uint64_t)(addr & 0x100000)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) << (36 - 20);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) instr &= (1 << bit_res) - 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) instr |= norm << bit_res;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) for (j = 0; j < 6; j++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) buf[i + j + byte_pos]
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) = (uint8_t)(instr >> (8 * j));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) return i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) #ifdef XZ_DEC_ARM
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) static size_t bcj_arm(struct xz_dec_bcj *s, uint8_t *buf, size_t size)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) size_t i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) uint32_t addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) for (i = 0; i + 4 <= size; i += 4) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) if (buf[i + 3] == 0xEB) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) addr = (uint32_t)buf[i] | ((uint32_t)buf[i + 1] << 8)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) | ((uint32_t)buf[i + 2] << 16);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) addr <<= 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) addr -= s->pos + (uint32_t)i + 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) addr >>= 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) buf[i] = (uint8_t)addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) buf[i + 1] = (uint8_t)(addr >> 8);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) buf[i + 2] = (uint8_t)(addr >> 16);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) return i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) #ifdef XZ_DEC_ARMTHUMB
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) static size_t bcj_armthumb(struct xz_dec_bcj *s, uint8_t *buf, size_t size)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) size_t i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) uint32_t addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) for (i = 0; i + 4 <= size; i += 2) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) if ((buf[i + 1] & 0xF8) == 0xF0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) && (buf[i + 3] & 0xF8) == 0xF8) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) addr = (((uint32_t)buf[i + 1] & 0x07) << 19)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) | ((uint32_t)buf[i] << 11)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) | (((uint32_t)buf[i + 3] & 0x07) << 8)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) | (uint32_t)buf[i + 2];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) addr <<= 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) addr -= s->pos + (uint32_t)i + 4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) addr >>= 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) buf[i + 1] = (uint8_t)(0xF0 | ((addr >> 19) & 0x07));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) buf[i] = (uint8_t)(addr >> 11);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) buf[i + 3] = (uint8_t)(0xF8 | ((addr >> 8) & 0x07));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) buf[i + 2] = (uint8_t)addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) i += 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) return i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) #ifdef XZ_DEC_SPARC
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) static size_t bcj_sparc(struct xz_dec_bcj *s, uint8_t *buf, size_t size)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) size_t i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) uint32_t instr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) for (i = 0; i + 4 <= size; i += 4) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) instr = get_unaligned_be32(buf + i);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) if ((instr >> 22) == 0x100 || (instr >> 22) == 0x1FF) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) instr <<= 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) instr -= s->pos + (uint32_t)i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) instr >>= 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) instr = ((uint32_t)0x40000000 - (instr & 0x400000))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) | 0x40000000 | (instr & 0x3FFFFF);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) put_unaligned_be32(instr, buf + i);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) return i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) * Apply the selected BCJ filter. Update *pos and s->pos to match the amount
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) * of data that got filtered.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) * NOTE: This is implemented as a switch statement to avoid using function
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) * pointers, which could be problematic in the kernel boot code, which must
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) * avoid pointers to static data (at least on x86).
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) static void bcj_apply(struct xz_dec_bcj *s,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) uint8_t *buf, size_t *pos, size_t size)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) size_t filtered;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350) buf += *pos;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351) size -= *pos;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) switch (s->type) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) #ifdef XZ_DEC_X86
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) case BCJ_X86:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356) filtered = bcj_x86(s, buf, size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359) #ifdef XZ_DEC_POWERPC
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) case BCJ_POWERPC:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361) filtered = bcj_powerpc(s, buf, size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364) #ifdef XZ_DEC_IA64
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365) case BCJ_IA64:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366) filtered = bcj_ia64(s, buf, size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369) #ifdef XZ_DEC_ARM
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370) case BCJ_ARM:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371) filtered = bcj_arm(s, buf, size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374) #ifdef XZ_DEC_ARMTHUMB
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375) case BCJ_ARMTHUMB:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376) filtered = bcj_armthumb(s, buf, size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379) #ifdef XZ_DEC_SPARC
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380) case BCJ_SPARC:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381) filtered = bcj_sparc(s, buf, size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385) /* Never reached but silence compiler warnings. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386) filtered = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390) *pos += filtered;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391) s->pos += filtered;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395) * Flush pending filtered data from temp to the output buffer.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396) * Move the remaining mixture of possibly filtered and unfiltered
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397) * data to the beginning of temp.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399) static void bcj_flush(struct xz_dec_bcj *s, struct xz_buf *b)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401) size_t copy_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403) copy_size = min_t(size_t, s->temp.filtered, b->out_size - b->out_pos);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404) memcpy(b->out + b->out_pos, s->temp.buf, copy_size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405) b->out_pos += copy_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407) s->temp.filtered -= copy_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408) s->temp.size -= copy_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409) memmove(s->temp.buf, s->temp.buf + copy_size, s->temp.size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413) * The BCJ filter functions are primitive in sense that they process the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414) * data in chunks of 1-16 bytes. To hide this issue, this function does
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415) * some buffering.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417) XZ_EXTERN enum xz_ret xz_dec_bcj_run(struct xz_dec_bcj *s,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418) struct xz_dec_lzma2 *lzma2,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419) struct xz_buf *b)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 421) size_t out_start;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 422)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 424) * Flush pending already filtered data to the output buffer. Return
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 425) * immediatelly if we couldn't flush everything, or if the next
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 426) * filter in the chain had already returned XZ_STREAM_END.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 427) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 428) if (s->temp.filtered > 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 429) bcj_flush(s, b);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 430) if (s->temp.filtered > 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 431) return XZ_OK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 432)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 433) if (s->ret == XZ_STREAM_END)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 434) return XZ_STREAM_END;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 435) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 436)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 437) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 438) * If we have more output space than what is currently pending in
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 439) * temp, copy the unfiltered data from temp to the output buffer
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 440) * and try to fill the output buffer by decoding more data from the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 441) * next filter in the chain. Apply the BCJ filter on the new data
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 442) * in the output buffer. If everything cannot be filtered, copy it
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 443) * to temp and rewind the output buffer position accordingly.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 444) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 445) * This needs to be always run when temp.size == 0 to handle a special
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 446) * case where the output buffer is full and the next filter has no
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 447) * more output coming but hasn't returned XZ_STREAM_END yet.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 448) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 449) if (s->temp.size < b->out_size - b->out_pos || s->temp.size == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 450) out_start = b->out_pos;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 451) memcpy(b->out + b->out_pos, s->temp.buf, s->temp.size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 452) b->out_pos += s->temp.size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 453)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 454) s->ret = xz_dec_lzma2_run(lzma2, b);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 455) if (s->ret != XZ_STREAM_END
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 456) && (s->ret != XZ_OK || s->single_call))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 457) return s->ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 458)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 459) bcj_apply(s, b->out, &out_start, b->out_pos);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 460)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 461) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 462) * As an exception, if the next filter returned XZ_STREAM_END,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 463) * we can do that too, since the last few bytes that remain
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 464) * unfiltered are meant to remain unfiltered.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 465) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 466) if (s->ret == XZ_STREAM_END)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 467) return XZ_STREAM_END;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 468)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 469) s->temp.size = b->out_pos - out_start;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 470) b->out_pos -= s->temp.size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 471) memcpy(s->temp.buf, b->out + b->out_pos, s->temp.size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 472)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 473) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 474) * If there wasn't enough input to the next filter to fill
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 475) * the output buffer with unfiltered data, there's no point
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 476) * to try decoding more data to temp.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 477) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 478) if (b->out_pos + s->temp.size < b->out_size)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 479) return XZ_OK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 480) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 481)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 482) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 483) * We have unfiltered data in temp. If the output buffer isn't full
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 484) * yet, try to fill the temp buffer by decoding more data from the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 485) * next filter. Apply the BCJ filter on temp. Then we hopefully can
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 486) * fill the actual output buffer by copying filtered data from temp.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 487) * A mix of filtered and unfiltered data may be left in temp; it will
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 488) * be taken care on the next call to this function.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 489) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 490) if (b->out_pos < b->out_size) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 491) /* Make b->out{,_pos,_size} temporarily point to s->temp. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 492) s->out = b->out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 493) s->out_pos = b->out_pos;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 494) s->out_size = b->out_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 495) b->out = s->temp.buf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 496) b->out_pos = s->temp.size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 497) b->out_size = sizeof(s->temp.buf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 498)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 499) s->ret = xz_dec_lzma2_run(lzma2, b);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 500)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 501) s->temp.size = b->out_pos;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 502) b->out = s->out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 503) b->out_pos = s->out_pos;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 504) b->out_size = s->out_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 505)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 506) if (s->ret != XZ_OK && s->ret != XZ_STREAM_END)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 507) return s->ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 508)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 509) bcj_apply(s, s->temp.buf, &s->temp.filtered, s->temp.size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 510)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 511) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 512) * If the next filter returned XZ_STREAM_END, we mark that
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 513) * everything is filtered, since the last unfiltered bytes
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 514) * of the stream are meant to be left as is.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 515) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 516) if (s->ret == XZ_STREAM_END)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 517) s->temp.filtered = s->temp.size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 518)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 519) bcj_flush(s, b);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 520) if (s->temp.filtered > 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 521) return XZ_OK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 522) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 523)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 524) return s->ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 525) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 526)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 527) XZ_EXTERN struct xz_dec_bcj *xz_dec_bcj_create(bool single_call)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 528) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 529) struct xz_dec_bcj *s = kmalloc(sizeof(*s), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 530) if (s != NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 531) s->single_call = single_call;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 532)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 533) return s;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 534) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 535)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 536) XZ_EXTERN enum xz_ret xz_dec_bcj_reset(struct xz_dec_bcj *s, uint8_t id)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 537) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 538) switch (id) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 539) #ifdef XZ_DEC_X86
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 540) case BCJ_X86:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 541) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 542) #ifdef XZ_DEC_POWERPC
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 543) case BCJ_POWERPC:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 544) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 545) #ifdef XZ_DEC_IA64
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 546) case BCJ_IA64:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 547) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 548) #ifdef XZ_DEC_ARM
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 549) case BCJ_ARM:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 550) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 551) #ifdef XZ_DEC_ARMTHUMB
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 552) case BCJ_ARMTHUMB:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 553) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 554) #ifdef XZ_DEC_SPARC
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 555) case BCJ_SPARC:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 556) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 557) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 558)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 559) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 560) /* Unsupported Filter ID */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 561) return XZ_OPTIONS_ERROR;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 562) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 563)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 564) s->type = id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 565) s->ret = XZ_OK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 566) s->pos = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 567) s->x86_prev_mask = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 568) s->temp.filtered = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 569) s->temp.size = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 570)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 571) return XZ_OK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 572) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 573)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 574) #endif