124fa0402a9b6a537e87e38341e78b7da86486846Lasse Collin/* 224fa0402a9b6a537e87e38341e78b7da86486846Lasse Collin * Branch/Call/Jump (BCJ) filter decoders 324fa0402a9b6a537e87e38341e78b7da86486846Lasse Collin * 424fa0402a9b6a537e87e38341e78b7da86486846Lasse Collin * Authors: Lasse Collin <lasse.collin@tukaani.org> 524fa0402a9b6a537e87e38341e78b7da86486846Lasse Collin * Igor Pavlov <http://7-zip.org/> 624fa0402a9b6a537e87e38341e78b7da86486846Lasse Collin * 724fa0402a9b6a537e87e38341e78b7da86486846Lasse Collin * This file has been put into the public domain. 824fa0402a9b6a537e87e38341e78b7da86486846Lasse Collin * You can do whatever you want with this file. 924fa0402a9b6a537e87e38341e78b7da86486846Lasse Collin */ 1024fa0402a9b6a537e87e38341e78b7da86486846Lasse Collin 1124fa0402a9b6a537e87e38341e78b7da86486846Lasse Collin#include "xz_private.h" 1224fa0402a9b6a537e87e38341e78b7da86486846Lasse Collin 1324fa0402a9b6a537e87e38341e78b7da86486846Lasse Collin/* 1424fa0402a9b6a537e87e38341e78b7da86486846Lasse Collin * The rest of the file is inside this ifdef. It makes things a little more 1524fa0402a9b6a537e87e38341e78b7da86486846Lasse Collin * convenient when building without support for any BCJ filters. 1624fa0402a9b6a537e87e38341e78b7da86486846Lasse Collin */ 1724fa0402a9b6a537e87e38341e78b7da86486846Lasse Collin#ifdef XZ_DEC_BCJ 1824fa0402a9b6a537e87e38341e78b7da86486846Lasse Collin 1924fa0402a9b6a537e87e38341e78b7da86486846Lasse Collinstruct xz_dec_bcj { 2024fa0402a9b6a537e87e38341e78b7da86486846Lasse Collin /* Type of the BCJ filter being used */ 2124fa0402a9b6a537e87e38341e78b7da86486846Lasse Collin enum { 2224fa0402a9b6a537e87e38341e78b7da86486846Lasse Collin BCJ_X86 = 4, /* x86 or x86-64 */ 2324fa0402a9b6a537e87e38341e78b7da86486846Lasse Collin BCJ_POWERPC = 5, /* Big endian only */ 2424fa0402a9b6a537e87e38341e78b7da86486846Lasse Collin BCJ_IA64 = 6, /* Big or little endian */ 2524fa0402a9b6a537e87e38341e78b7da86486846Lasse Collin BCJ_ARM = 7, /* Little endian only */ 2624fa0402a9b6a537e87e38341e78b7da86486846Lasse Collin BCJ_ARMTHUMB = 8, /* Little endian only */ 2724fa0402a9b6a537e87e38341e78b7da86486846Lasse Collin BCJ_SPARC = 9 /* Big or little endian */ 2824fa0402a9b6a537e87e38341e78b7da86486846Lasse Collin } type; 2924fa0402a9b6a537e87e38341e78b7da86486846Lasse Collin 3024fa0402a9b6a537e87e38341e78b7da86486846Lasse Collin /* 3124fa0402a9b6a537e87e38341e78b7da86486846Lasse Collin * Return value of the next filter in the chain. We need to preserve 3224fa0402a9b6a537e87e38341e78b7da86486846Lasse Collin * this information across calls, because we must not call the next 3324fa0402a9b6a537e87e38341e78b7da86486846Lasse Collin * filter anymore once it has returned XZ_STREAM_END. 3424fa0402a9b6a537e87e38341e78b7da86486846Lasse Collin */ 3524fa0402a9b6a537e87e38341e78b7da86486846Lasse Collin enum xz_ret ret; 3624fa0402a9b6a537e87e38341e78b7da86486846Lasse Collin 3724fa0402a9b6a537e87e38341e78b7da86486846Lasse Collin /* True if we are operating in single-call mode. */ 3824fa0402a9b6a537e87e38341e78b7da86486846Lasse Collin bool single_call; 3924fa0402a9b6a537e87e38341e78b7da86486846Lasse Collin 4024fa0402a9b6a537e87e38341e78b7da86486846Lasse Collin /* 4124fa0402a9b6a537e87e38341e78b7da86486846Lasse Collin * Absolute position relative to the beginning of the uncompressed 4224fa0402a9b6a537e87e38341e78b7da86486846Lasse Collin * data (in a single .xz Block). We care only about the lowest 32 4324fa0402a9b6a537e87e38341e78b7da86486846Lasse Collin * bits so this doesn't need to be uint64_t even with big files. 4424fa0402a9b6a537e87e38341e78b7da86486846Lasse Collin */ 4524fa0402a9b6a537e87e38341e78b7da86486846Lasse Collin uint32_t pos; 4624fa0402a9b6a537e87e38341e78b7da86486846Lasse Collin 4724fa0402a9b6a537e87e38341e78b7da86486846Lasse Collin /* x86 filter state */ 4824fa0402a9b6a537e87e38341e78b7da86486846Lasse Collin uint32_t x86_prev_mask; 4924fa0402a9b6a537e87e38341e78b7da86486846Lasse Collin 5024fa0402a9b6a537e87e38341e78b7da86486846Lasse Collin /* Temporary space to hold the variables from struct xz_buf */ 5124fa0402a9b6a537e87e38341e78b7da86486846Lasse Collin uint8_t *out; 5224fa0402a9b6a537e87e38341e78b7da86486846Lasse Collin size_t out_pos; 5324fa0402a9b6a537e87e38341e78b7da86486846Lasse Collin size_t out_size; 5424fa0402a9b6a537e87e38341e78b7da86486846Lasse Collin 5524fa0402a9b6a537e87e38341e78b7da86486846Lasse Collin struct { 5624fa0402a9b6a537e87e38341e78b7da86486846Lasse Collin /* Amount of already filtered data in the beginning of buf */ 5724fa0402a9b6a537e87e38341e78b7da86486846Lasse Collin size_t filtered; 5824fa0402a9b6a537e87e38341e78b7da86486846Lasse Collin 5924fa0402a9b6a537e87e38341e78b7da86486846Lasse Collin /* Total amount of data currently stored in buf */ 6024fa0402a9b6a537e87e38341e78b7da86486846Lasse Collin size_t size; 6124fa0402a9b6a537e87e38341e78b7da86486846Lasse Collin 6224fa0402a9b6a537e87e38341e78b7da86486846Lasse Collin /* 6324fa0402a9b6a537e87e38341e78b7da86486846Lasse Collin * Buffer to hold a mix of filtered and unfiltered data. This 6424fa0402a9b6a537e87e38341e78b7da86486846Lasse Collin * needs to be big enough to hold Alignment + 2 * Look-ahead: 6524fa0402a9b6a537e87e38341e78b7da86486846Lasse Collin * 6624fa0402a9b6a537e87e38341e78b7da86486846Lasse Collin * Type Alignment Look-ahead 6724fa0402a9b6a537e87e38341e78b7da86486846Lasse Collin * x86 1 4 6824fa0402a9b6a537e87e38341e78b7da86486846Lasse Collin * PowerPC 4 0 6924fa0402a9b6a537e87e38341e78b7da86486846Lasse Collin * IA-64 16 0 7024fa0402a9b6a537e87e38341e78b7da86486846Lasse Collin * ARM 4 0 7124fa0402a9b6a537e87e38341e78b7da86486846Lasse Collin * ARM-Thumb 2 2 7224fa0402a9b6a537e87e38341e78b7da86486846Lasse Collin * SPARC 4 0 7324fa0402a9b6a537e87e38341e78b7da86486846Lasse Collin */ 7424fa0402a9b6a537e87e38341e78b7da86486846Lasse Collin uint8_t buf[16]; 7524fa0402a9b6a537e87e38341e78b7da86486846Lasse Collin } temp; 7624fa0402a9b6a537e87e38341e78b7da86486846Lasse Collin}; 7724fa0402a9b6a537e87e38341e78b7da86486846Lasse Collin 7824fa0402a9b6a537e87e38341e78b7da86486846Lasse Collin#ifdef XZ_DEC_X86 7924fa0402a9b6a537e87e38341e78b7da86486846Lasse Collin/* 8024fa0402a9b6a537e87e38341e78b7da86486846Lasse Collin * This is used to test the most significant byte of a memory address 8124fa0402a9b6a537e87e38341e78b7da86486846Lasse Collin * in an x86 instruction. 8224fa0402a9b6a537e87e38341e78b7da86486846Lasse Collin */ 8324fa0402a9b6a537e87e38341e78b7da86486846Lasse Collinstatic inline int bcj_x86_test_msbyte(uint8_t b) 8424fa0402a9b6a537e87e38341e78b7da86486846Lasse Collin{ 8524fa0402a9b6a537e87e38341e78b7da86486846Lasse Collin return b == 0x00 || b == 0xFF; 8624fa0402a9b6a537e87e38341e78b7da86486846Lasse Collin} 8724fa0402a9b6a537e87e38341e78b7da86486846Lasse Collin 8824fa0402a9b6a537e87e38341e78b7da86486846Lasse Collinstatic size_t bcj_x86(struct xz_dec_bcj *s, uint8_t *buf, size_t size) 8924fa0402a9b6a537e87e38341e78b7da86486846Lasse Collin{ 9024fa0402a9b6a537e87e38341e78b7da86486846Lasse Collin static const bool mask_to_allowed_status[8] 9124fa0402a9b6a537e87e38341e78b7da86486846Lasse Collin = { true, true, true, false, true, false, false, false }; 9224fa0402a9b6a537e87e38341e78b7da86486846Lasse Collin 9324fa0402a9b6a537e87e38341e78b7da86486846Lasse Collin static const uint8_t mask_to_bit_num[8] = { 0, 1, 2, 2, 3, 3, 3, 3 }; 9424fa0402a9b6a537e87e38341e78b7da86486846Lasse Collin 9524fa0402a9b6a537e87e38341e78b7da86486846Lasse Collin size_t i; 9624fa0402a9b6a537e87e38341e78b7da86486846Lasse Collin size_t prev_pos = (size_t)-1; 9724fa0402a9b6a537e87e38341e78b7da86486846Lasse Collin uint32_t prev_mask = s->x86_prev_mask; 9824fa0402a9b6a537e87e38341e78b7da86486846Lasse Collin uint32_t src; 9924fa0402a9b6a537e87e38341e78b7da86486846Lasse Collin uint32_t dest; 10024fa0402a9b6a537e87e38341e78b7da86486846Lasse Collin uint32_t j; 10124fa0402a9b6a537e87e38341e78b7da86486846Lasse Collin uint8_t b; 10224fa0402a9b6a537e87e38341e78b7da86486846Lasse Collin 10324fa0402a9b6a537e87e38341e78b7da86486846Lasse Collin if (size <= 4) 10424fa0402a9b6a537e87e38341e78b7da86486846Lasse Collin return 0; 10524fa0402a9b6a537e87e38341e78b7da86486846Lasse Collin 10624fa0402a9b6a537e87e38341e78b7da86486846Lasse Collin size -= 4; 10724fa0402a9b6a537e87e38341e78b7da86486846Lasse Collin for (i = 0; i < size; ++i) { 10824fa0402a9b6a537e87e38341e78b7da86486846Lasse Collin if ((buf[i] & 0xFE) != 0xE8) 10924fa0402a9b6a537e87e38341e78b7da86486846Lasse Collin continue; 11024fa0402a9b6a537e87e38341e78b7da86486846Lasse Collin 11124fa0402a9b6a537e87e38341e78b7da86486846Lasse Collin prev_pos = i - prev_pos; 11224fa0402a9b6a537e87e38341e78b7da86486846Lasse Collin if (prev_pos > 3) { 11324fa0402a9b6a537e87e38341e78b7da86486846Lasse Collin prev_mask = 0; 11424fa0402a9b6a537e87e38341e78b7da86486846Lasse Collin } else { 11524fa0402a9b6a537e87e38341e78b7da86486846Lasse Collin prev_mask = (prev_mask << (prev_pos - 1)) & 7; 11624fa0402a9b6a537e87e38341e78b7da86486846Lasse Collin if (prev_mask != 0) { 11724fa0402a9b6a537e87e38341e78b7da86486846Lasse Collin b = buf[i + 4 - mask_to_bit_num[prev_mask]]; 11824fa0402a9b6a537e87e38341e78b7da86486846Lasse Collin if (!mask_to_allowed_status[prev_mask] 11924fa0402a9b6a537e87e38341e78b7da86486846Lasse Collin || bcj_x86_test_msbyte(b)) { 12024fa0402a9b6a537e87e38341e78b7da86486846Lasse Collin prev_pos = i; 12124fa0402a9b6a537e87e38341e78b7da86486846Lasse Collin prev_mask = (prev_mask << 1) | 1; 12224fa0402a9b6a537e87e38341e78b7da86486846Lasse Collin continue; 12324fa0402a9b6a537e87e38341e78b7da86486846Lasse Collin } 12424fa0402a9b6a537e87e38341e78b7da86486846Lasse Collin } 12524fa0402a9b6a537e87e38341e78b7da86486846Lasse Collin } 12624fa0402a9b6a537e87e38341e78b7da86486846Lasse Collin 12724fa0402a9b6a537e87e38341e78b7da86486846Lasse Collin prev_pos = i; 12824fa0402a9b6a537e87e38341e78b7da86486846Lasse Collin 12924fa0402a9b6a537e87e38341e78b7da86486846Lasse Collin if (bcj_x86_test_msbyte(buf[i + 4])) { 13024fa0402a9b6a537e87e38341e78b7da86486846Lasse Collin src = get_unaligned_le32(buf + i + 1); 13124fa0402a9b6a537e87e38341e78b7da86486846Lasse Collin while (true) { 13224fa0402a9b6a537e87e38341e78b7da86486846Lasse Collin dest = src - (s->pos + (uint32_t)i + 5); 13324fa0402a9b6a537e87e38341e78b7da86486846Lasse Collin if (prev_mask == 0) 13424fa0402a9b6a537e87e38341e78b7da86486846Lasse Collin break; 13524fa0402a9b6a537e87e38341e78b7da86486846Lasse Collin 13624fa0402a9b6a537e87e38341e78b7da86486846Lasse Collin j = mask_to_bit_num[prev_mask] * 8; 13724fa0402a9b6a537e87e38341e78b7da86486846Lasse Collin b = (uint8_t)(dest >> (24 - j)); 13824fa0402a9b6a537e87e38341e78b7da86486846Lasse Collin if (!bcj_x86_test_msbyte(b)) 13924fa0402a9b6a537e87e38341e78b7da86486846Lasse Collin break; 14024fa0402a9b6a537e87e38341e78b7da86486846Lasse Collin 14124fa0402a9b6a537e87e38341e78b7da86486846Lasse Collin src = dest ^ (((uint32_t)1 << (32 - j)) - 1); 14224fa0402a9b6a537e87e38341e78b7da86486846Lasse Collin } 14324fa0402a9b6a537e87e38341e78b7da86486846Lasse Collin 14424fa0402a9b6a537e87e38341e78b7da86486846Lasse Collin dest &= 0x01FFFFFF; 14524fa0402a9b6a537e87e38341e78b7da86486846Lasse Collin dest |= (uint32_t)0 - (dest & 0x01000000); 14624fa0402a9b6a537e87e38341e78b7da86486846Lasse Collin put_unaligned_le32(dest, buf + i + 1); 14724fa0402a9b6a537e87e38341e78b7da86486846Lasse Collin i += 4; 14824fa0402a9b6a537e87e38341e78b7da86486846Lasse Collin } else { 14924fa0402a9b6a537e87e38341e78b7da86486846Lasse Collin prev_mask = (prev_mask << 1) | 1; 15024fa0402a9b6a537e87e38341e78b7da86486846Lasse Collin } 15124fa0402a9b6a537e87e38341e78b7da86486846Lasse Collin } 15224fa0402a9b6a537e87e38341e78b7da86486846Lasse Collin 15324fa0402a9b6a537e87e38341e78b7da86486846Lasse Collin prev_pos = i - prev_pos; 15424fa0402a9b6a537e87e38341e78b7da86486846Lasse Collin s->x86_prev_mask = prev_pos > 3 ? 0 : prev_mask << (prev_pos - 1); 15524fa0402a9b6a537e87e38341e78b7da86486846Lasse Collin return i; 15624fa0402a9b6a537e87e38341e78b7da86486846Lasse Collin} 15724fa0402a9b6a537e87e38341e78b7da86486846Lasse Collin#endif 15824fa0402a9b6a537e87e38341e78b7da86486846Lasse Collin 15924fa0402a9b6a537e87e38341e78b7da86486846Lasse Collin#ifdef XZ_DEC_POWERPC 16024fa0402a9b6a537e87e38341e78b7da86486846Lasse Collinstatic size_t bcj_powerpc(struct xz_dec_bcj *s, uint8_t *buf, size_t size) 16124fa0402a9b6a537e87e38341e78b7da86486846Lasse Collin{ 16224fa0402a9b6a537e87e38341e78b7da86486846Lasse Collin size_t i; 16324fa0402a9b6a537e87e38341e78b7da86486846Lasse Collin uint32_t instr; 16424fa0402a9b6a537e87e38341e78b7da86486846Lasse Collin 16524fa0402a9b6a537e87e38341e78b7da86486846Lasse Collin for (i = 0; i + 4 <= size; i += 4) { 16624fa0402a9b6a537e87e38341e78b7da86486846Lasse Collin instr = get_unaligned_be32(buf + i); 16724fa0402a9b6a537e87e38341e78b7da86486846Lasse Collin if ((instr & 0xFC000003) == 0x48000001) { 16824fa0402a9b6a537e87e38341e78b7da86486846Lasse Collin instr &= 0x03FFFFFC; 16924fa0402a9b6a537e87e38341e78b7da86486846Lasse Collin instr -= s->pos + (uint32_t)i; 17024fa0402a9b6a537e87e38341e78b7da86486846Lasse Collin instr &= 0x03FFFFFC; 17124fa0402a9b6a537e87e38341e78b7da86486846Lasse Collin instr |= 0x48000001; 17224fa0402a9b6a537e87e38341e78b7da86486846Lasse Collin put_unaligned_be32(instr, buf + i); 17324fa0402a9b6a537e87e38341e78b7da86486846Lasse Collin } 17424fa0402a9b6a537e87e38341e78b7da86486846Lasse Collin } 17524fa0402a9b6a537e87e38341e78b7da86486846Lasse Collin 17624fa0402a9b6a537e87e38341e78b7da86486846Lasse Collin return i; 17724fa0402a9b6a537e87e38341e78b7da86486846Lasse Collin} 17824fa0402a9b6a537e87e38341e78b7da86486846Lasse Collin#endif 17924fa0402a9b6a537e87e38341e78b7da86486846Lasse Collin 18024fa0402a9b6a537e87e38341e78b7da86486846Lasse Collin#ifdef XZ_DEC_IA64 18124fa0402a9b6a537e87e38341e78b7da86486846Lasse Collinstatic size_t bcj_ia64(struct xz_dec_bcj *s, uint8_t *buf, size_t size) 18224fa0402a9b6a537e87e38341e78b7da86486846Lasse Collin{ 18324fa0402a9b6a537e87e38341e78b7da86486846Lasse Collin static const uint8_t branch_table[32] = { 18424fa0402a9b6a537e87e38341e78b7da86486846Lasse Collin 0, 0, 0, 0, 0, 0, 0, 0, 18524fa0402a9b6a537e87e38341e78b7da86486846Lasse Collin 0, 0, 0, 0, 0, 0, 0, 0, 18624fa0402a9b6a537e87e38341e78b7da86486846Lasse Collin 4, 4, 6, 6, 0, 0, 7, 7, 18724fa0402a9b6a537e87e38341e78b7da86486846Lasse Collin 4, 4, 0, 0, 4, 4, 0, 0 18824fa0402a9b6a537e87e38341e78b7da86486846Lasse Collin }; 18924fa0402a9b6a537e87e38341e78b7da86486846Lasse Collin 19024fa0402a9b6a537e87e38341e78b7da86486846Lasse Collin /* 19124fa0402a9b6a537e87e38341e78b7da86486846Lasse Collin * The local variables take a little bit stack space, but it's less 19224fa0402a9b6a537e87e38341e78b7da86486846Lasse Collin * than what LZMA2 decoder takes, so it doesn't make sense to reduce 19324fa0402a9b6a537e87e38341e78b7da86486846Lasse Collin * stack usage here without doing that for the LZMA2 decoder too. 19424fa0402a9b6a537e87e38341e78b7da86486846Lasse Collin */ 19524fa0402a9b6a537e87e38341e78b7da86486846Lasse Collin 19624fa0402a9b6a537e87e38341e78b7da86486846Lasse Collin /* Loop counters */ 19724fa0402a9b6a537e87e38341e78b7da86486846Lasse Collin size_t i; 19824fa0402a9b6a537e87e38341e78b7da86486846Lasse Collin size_t j; 19924fa0402a9b6a537e87e38341e78b7da86486846Lasse Collin 20024fa0402a9b6a537e87e38341e78b7da86486846Lasse Collin /* Instruction slot (0, 1, or 2) in the 128-bit instruction word */ 20124fa0402a9b6a537e87e38341e78b7da86486846Lasse Collin uint32_t slot; 20224fa0402a9b6a537e87e38341e78b7da86486846Lasse Collin 20324fa0402a9b6a537e87e38341e78b7da86486846Lasse Collin /* Bitwise offset of the instruction indicated by slot */ 20424fa0402a9b6a537e87e38341e78b7da86486846Lasse Collin uint32_t bit_pos; 20524fa0402a9b6a537e87e38341e78b7da86486846Lasse Collin 20624fa0402a9b6a537e87e38341e78b7da86486846Lasse Collin /* bit_pos split into byte and bit parts */ 20724fa0402a9b6a537e87e38341e78b7da86486846Lasse Collin uint32_t byte_pos; 20824fa0402a9b6a537e87e38341e78b7da86486846Lasse Collin uint32_t bit_res; 20924fa0402a9b6a537e87e38341e78b7da86486846Lasse Collin 21024fa0402a9b6a537e87e38341e78b7da86486846Lasse Collin /* Address part of an instruction */ 21124fa0402a9b6a537e87e38341e78b7da86486846Lasse Collin uint32_t addr; 21224fa0402a9b6a537e87e38341e78b7da86486846Lasse Collin 21324fa0402a9b6a537e87e38341e78b7da86486846Lasse Collin /* Mask used to detect which instructions to convert */ 21424fa0402a9b6a537e87e38341e78b7da86486846Lasse Collin uint32_t mask; 21524fa0402a9b6a537e87e38341e78b7da86486846Lasse Collin 21624fa0402a9b6a537e87e38341e78b7da86486846Lasse Collin /* 41-bit instruction stored somewhere in the lowest 48 bits */ 21724fa0402a9b6a537e87e38341e78b7da86486846Lasse Collin uint64_t instr; 21824fa0402a9b6a537e87e38341e78b7da86486846Lasse Collin 21924fa0402a9b6a537e87e38341e78b7da86486846Lasse Collin /* Instruction normalized with bit_res for easier manipulation */ 22024fa0402a9b6a537e87e38341e78b7da86486846Lasse Collin uint64_t norm; 22124fa0402a9b6a537e87e38341e78b7da86486846Lasse Collin 22224fa0402a9b6a537e87e38341e78b7da86486846Lasse Collin for (i = 0; i + 16 <= size; i += 16) { 22324fa0402a9b6a537e87e38341e78b7da86486846Lasse Collin mask = branch_table[buf[i] & 0x1F]; 22424fa0402a9b6a537e87e38341e78b7da86486846Lasse Collin for (slot = 0, bit_pos = 5; slot < 3; ++slot, bit_pos += 41) { 22524fa0402a9b6a537e87e38341e78b7da86486846Lasse Collin if (((mask >> slot) & 1) == 0) 22624fa0402a9b6a537e87e38341e78b7da86486846Lasse Collin continue; 22724fa0402a9b6a537e87e38341e78b7da86486846Lasse Collin 22824fa0402a9b6a537e87e38341e78b7da86486846Lasse Collin byte_pos = bit_pos >> 3; 22924fa0402a9b6a537e87e38341e78b7da86486846Lasse Collin bit_res = bit_pos & 7; 23024fa0402a9b6a537e87e38341e78b7da86486846Lasse Collin instr = 0; 23124fa0402a9b6a537e87e38341e78b7da86486846Lasse Collin for (j = 0; j < 6; ++j) 23224fa0402a9b6a537e87e38341e78b7da86486846Lasse Collin instr |= (uint64_t)(buf[i + j + byte_pos]) 23324fa0402a9b6a537e87e38341e78b7da86486846Lasse Collin << (8 * j); 23424fa0402a9b6a537e87e38341e78b7da86486846Lasse Collin 23524fa0402a9b6a537e87e38341e78b7da86486846Lasse Collin norm = instr >> bit_res; 23624fa0402a9b6a537e87e38341e78b7da86486846Lasse Collin 23724fa0402a9b6a537e87e38341e78b7da86486846Lasse Collin if (((norm >> 37) & 0x0F) == 0x05 23824fa0402a9b6a537e87e38341e78b7da86486846Lasse Collin && ((norm >> 9) & 0x07) == 0) { 23924fa0402a9b6a537e87e38341e78b7da86486846Lasse Collin addr = (norm >> 13) & 0x0FFFFF; 24024fa0402a9b6a537e87e38341e78b7da86486846Lasse Collin addr |= ((uint32_t)(norm >> 36) & 1) << 20; 24124fa0402a9b6a537e87e38341e78b7da86486846Lasse Collin addr <<= 4; 24224fa0402a9b6a537e87e38341e78b7da86486846Lasse Collin addr -= s->pos + (uint32_t)i; 24324fa0402a9b6a537e87e38341e78b7da86486846Lasse Collin addr >>= 4; 24424fa0402a9b6a537e87e38341e78b7da86486846Lasse Collin 24524fa0402a9b6a537e87e38341e78b7da86486846Lasse Collin norm &= ~((uint64_t)0x8FFFFF << 13); 24624fa0402a9b6a537e87e38341e78b7da86486846Lasse Collin norm |= (uint64_t)(addr & 0x0FFFFF) << 13; 24724fa0402a9b6a537e87e38341e78b7da86486846Lasse Collin norm |= (uint64_t)(addr & 0x100000) 24824fa0402a9b6a537e87e38341e78b7da86486846Lasse Collin << (36 - 20); 24924fa0402a9b6a537e87e38341e78b7da86486846Lasse Collin 25024fa0402a9b6a537e87e38341e78b7da86486846Lasse Collin instr &= (1 << bit_res) - 1; 25124fa0402a9b6a537e87e38341e78b7da86486846Lasse Collin instr |= norm << bit_res; 25224fa0402a9b6a537e87e38341e78b7da86486846Lasse Collin 25324fa0402a9b6a537e87e38341e78b7da86486846Lasse Collin for (j = 0; j < 6; j++) 25424fa0402a9b6a537e87e38341e78b7da86486846Lasse Collin buf[i + j + byte_pos] 25524fa0402a9b6a537e87e38341e78b7da86486846Lasse Collin = (uint8_t)(instr >> (8 * j)); 25624fa0402a9b6a537e87e38341e78b7da86486846Lasse Collin } 25724fa0402a9b6a537e87e38341e78b7da86486846Lasse Collin } 25824fa0402a9b6a537e87e38341e78b7da86486846Lasse Collin } 25924fa0402a9b6a537e87e38341e78b7da86486846Lasse Collin 26024fa0402a9b6a537e87e38341e78b7da86486846Lasse Collin return i; 26124fa0402a9b6a537e87e38341e78b7da86486846Lasse Collin} 26224fa0402a9b6a537e87e38341e78b7da86486846Lasse Collin#endif 26324fa0402a9b6a537e87e38341e78b7da86486846Lasse Collin 26424fa0402a9b6a537e87e38341e78b7da86486846Lasse Collin#ifdef XZ_DEC_ARM 26524fa0402a9b6a537e87e38341e78b7da86486846Lasse Collinstatic size_t bcj_arm(struct xz_dec_bcj *s, uint8_t *buf, size_t size) 26624fa0402a9b6a537e87e38341e78b7da86486846Lasse Collin{ 26724fa0402a9b6a537e87e38341e78b7da86486846Lasse Collin size_t i; 26824fa0402a9b6a537e87e38341e78b7da86486846Lasse Collin uint32_t addr; 26924fa0402a9b6a537e87e38341e78b7da86486846Lasse Collin 27024fa0402a9b6a537e87e38341e78b7da86486846Lasse Collin for (i = 0; i + 4 <= size; i += 4) { 27124fa0402a9b6a537e87e38341e78b7da86486846Lasse Collin if (buf[i + 3] == 0xEB) { 27224fa0402a9b6a537e87e38341e78b7da86486846Lasse Collin addr = (uint32_t)buf[i] | ((uint32_t)buf[i + 1] << 8) 27324fa0402a9b6a537e87e38341e78b7da86486846Lasse Collin | ((uint32_t)buf[i + 2] << 16); 27424fa0402a9b6a537e87e38341e78b7da86486846Lasse Collin addr <<= 2; 27524fa0402a9b6a537e87e38341e78b7da86486846Lasse Collin addr -= s->pos + (uint32_t)i + 8; 27624fa0402a9b6a537e87e38341e78b7da86486846Lasse Collin addr >>= 2; 27724fa0402a9b6a537e87e38341e78b7da86486846Lasse Collin buf[i] = (uint8_t)addr; 27824fa0402a9b6a537e87e38341e78b7da86486846Lasse Collin buf[i + 1] = (uint8_t)(addr >> 8); 27924fa0402a9b6a537e87e38341e78b7da86486846Lasse Collin buf[i + 2] = (uint8_t)(addr >> 16); 28024fa0402a9b6a537e87e38341e78b7da86486846Lasse Collin } 28124fa0402a9b6a537e87e38341e78b7da86486846Lasse Collin } 28224fa0402a9b6a537e87e38341e78b7da86486846Lasse Collin 28324fa0402a9b6a537e87e38341e78b7da86486846Lasse Collin return i; 28424fa0402a9b6a537e87e38341e78b7da86486846Lasse Collin} 28524fa0402a9b6a537e87e38341e78b7da86486846Lasse Collin#endif 28624fa0402a9b6a537e87e38341e78b7da86486846Lasse Collin 28724fa0402a9b6a537e87e38341e78b7da86486846Lasse Collin#ifdef XZ_DEC_ARMTHUMB 28824fa0402a9b6a537e87e38341e78b7da86486846Lasse Collinstatic size_t bcj_armthumb(struct xz_dec_bcj *s, uint8_t *buf, size_t size) 28924fa0402a9b6a537e87e38341e78b7da86486846Lasse Collin{ 29024fa0402a9b6a537e87e38341e78b7da86486846Lasse Collin size_t i; 29124fa0402a9b6a537e87e38341e78b7da86486846Lasse Collin uint32_t addr; 29224fa0402a9b6a537e87e38341e78b7da86486846Lasse Collin 29324fa0402a9b6a537e87e38341e78b7da86486846Lasse Collin for (i = 0; i + 4 <= size; i += 2) { 29424fa0402a9b6a537e87e38341e78b7da86486846Lasse Collin if ((buf[i + 1] & 0xF8) == 0xF0 29524fa0402a9b6a537e87e38341e78b7da86486846Lasse Collin && (buf[i + 3] & 0xF8) == 0xF8) { 29624fa0402a9b6a537e87e38341e78b7da86486846Lasse Collin addr = (((uint32_t)buf[i + 1] & 0x07) << 19) 29724fa0402a9b6a537e87e38341e78b7da86486846Lasse Collin | ((uint32_t)buf[i] << 11) 29824fa0402a9b6a537e87e38341e78b7da86486846Lasse Collin | (((uint32_t)buf[i + 3] & 0x07) << 8) 29924fa0402a9b6a537e87e38341e78b7da86486846Lasse Collin | (uint32_t)buf[i + 2]; 30024fa0402a9b6a537e87e38341e78b7da86486846Lasse Collin addr <<= 1; 30124fa0402a9b6a537e87e38341e78b7da86486846Lasse Collin addr -= s->pos + (uint32_t)i + 4; 30224fa0402a9b6a537e87e38341e78b7da86486846Lasse Collin addr >>= 1; 30324fa0402a9b6a537e87e38341e78b7da86486846Lasse Collin buf[i + 1] = (uint8_t)(0xF0 | ((addr >> 19) & 0x07)); 30424fa0402a9b6a537e87e38341e78b7da86486846Lasse Collin buf[i] = (uint8_t)(addr >> 11); 30524fa0402a9b6a537e87e38341e78b7da86486846Lasse Collin buf[i + 3] = (uint8_t)(0xF8 | ((addr >> 8) & 0x07)); 30624fa0402a9b6a537e87e38341e78b7da86486846Lasse Collin buf[i + 2] = (uint8_t)addr; 30724fa0402a9b6a537e87e38341e78b7da86486846Lasse Collin i += 2; 30824fa0402a9b6a537e87e38341e78b7da86486846Lasse Collin } 30924fa0402a9b6a537e87e38341e78b7da86486846Lasse Collin } 31024fa0402a9b6a537e87e38341e78b7da86486846Lasse Collin 31124fa0402a9b6a537e87e38341e78b7da86486846Lasse Collin return i; 31224fa0402a9b6a537e87e38341e78b7da86486846Lasse Collin} 31324fa0402a9b6a537e87e38341e78b7da86486846Lasse Collin#endif 31424fa0402a9b6a537e87e38341e78b7da86486846Lasse Collin 31524fa0402a9b6a537e87e38341e78b7da86486846Lasse Collin#ifdef XZ_DEC_SPARC 31624fa0402a9b6a537e87e38341e78b7da86486846Lasse Collinstatic size_t bcj_sparc(struct xz_dec_bcj *s, uint8_t *buf, size_t size) 31724fa0402a9b6a537e87e38341e78b7da86486846Lasse Collin{ 31824fa0402a9b6a537e87e38341e78b7da86486846Lasse Collin size_t i; 31924fa0402a9b6a537e87e38341e78b7da86486846Lasse Collin uint32_t instr; 32024fa0402a9b6a537e87e38341e78b7da86486846Lasse Collin 32124fa0402a9b6a537e87e38341e78b7da86486846Lasse Collin for (i = 0; i + 4 <= size; i += 4) { 32224fa0402a9b6a537e87e38341e78b7da86486846Lasse Collin instr = get_unaligned_be32(buf + i); 32324fa0402a9b6a537e87e38341e78b7da86486846Lasse Collin if ((instr >> 22) == 0x100 || (instr >> 22) == 0x1FF) { 32424fa0402a9b6a537e87e38341e78b7da86486846Lasse Collin instr <<= 2; 32524fa0402a9b6a537e87e38341e78b7da86486846Lasse Collin instr -= s->pos + (uint32_t)i; 32624fa0402a9b6a537e87e38341e78b7da86486846Lasse Collin instr >>= 2; 32724fa0402a9b6a537e87e38341e78b7da86486846Lasse Collin instr = ((uint32_t)0x40000000 - (instr & 0x400000)) 32824fa0402a9b6a537e87e38341e78b7da86486846Lasse Collin | 0x40000000 | (instr & 0x3FFFFF); 32924fa0402a9b6a537e87e38341e78b7da86486846Lasse Collin put_unaligned_be32(instr, buf + i); 33024fa0402a9b6a537e87e38341e78b7da86486846Lasse Collin } 33124fa0402a9b6a537e87e38341e78b7da86486846Lasse Collin } 33224fa0402a9b6a537e87e38341e78b7da86486846Lasse Collin 33324fa0402a9b6a537e87e38341e78b7da86486846Lasse Collin return i; 33424fa0402a9b6a537e87e38341e78b7da86486846Lasse Collin} 33524fa0402a9b6a537e87e38341e78b7da86486846Lasse Collin#endif 33624fa0402a9b6a537e87e38341e78b7da86486846Lasse Collin 33724fa0402a9b6a537e87e38341e78b7da86486846Lasse Collin/* 33824fa0402a9b6a537e87e38341e78b7da86486846Lasse Collin * Apply the selected BCJ filter. Update *pos and s->pos to match the amount 33924fa0402a9b6a537e87e38341e78b7da86486846Lasse Collin * of data that got filtered. 34024fa0402a9b6a537e87e38341e78b7da86486846Lasse Collin * 34124fa0402a9b6a537e87e38341e78b7da86486846Lasse Collin * NOTE: This is implemented as a switch statement to avoid using function 34224fa0402a9b6a537e87e38341e78b7da86486846Lasse Collin * pointers, which could be problematic in the kernel boot code, which must 34324fa0402a9b6a537e87e38341e78b7da86486846Lasse Collin * avoid pointers to static data (at least on x86). 34424fa0402a9b6a537e87e38341e78b7da86486846Lasse Collin */ 34524fa0402a9b6a537e87e38341e78b7da86486846Lasse Collinstatic void bcj_apply(struct xz_dec_bcj *s, 34624fa0402a9b6a537e87e38341e78b7da86486846Lasse Collin uint8_t *buf, size_t *pos, size_t size) 34724fa0402a9b6a537e87e38341e78b7da86486846Lasse Collin{ 34824fa0402a9b6a537e87e38341e78b7da86486846Lasse Collin size_t filtered; 34924fa0402a9b6a537e87e38341e78b7da86486846Lasse Collin 35024fa0402a9b6a537e87e38341e78b7da86486846Lasse Collin buf += *pos; 35124fa0402a9b6a537e87e38341e78b7da86486846Lasse Collin size -= *pos; 35224fa0402a9b6a537e87e38341e78b7da86486846Lasse Collin 35324fa0402a9b6a537e87e38341e78b7da86486846Lasse Collin switch (s->type) { 35424fa0402a9b6a537e87e38341e78b7da86486846Lasse Collin#ifdef XZ_DEC_X86 35524fa0402a9b6a537e87e38341e78b7da86486846Lasse Collin case BCJ_X86: 35624fa0402a9b6a537e87e38341e78b7da86486846Lasse Collin filtered = bcj_x86(s, buf, size); 35724fa0402a9b6a537e87e38341e78b7da86486846Lasse Collin break; 35824fa0402a9b6a537e87e38341e78b7da86486846Lasse Collin#endif 35924fa0402a9b6a537e87e38341e78b7da86486846Lasse Collin#ifdef XZ_DEC_POWERPC 36024fa0402a9b6a537e87e38341e78b7da86486846Lasse Collin case BCJ_POWERPC: 36124fa0402a9b6a537e87e38341e78b7da86486846Lasse Collin filtered = bcj_powerpc(s, buf, size); 36224fa0402a9b6a537e87e38341e78b7da86486846Lasse Collin break; 36324fa0402a9b6a537e87e38341e78b7da86486846Lasse Collin#endif 36424fa0402a9b6a537e87e38341e78b7da86486846Lasse Collin#ifdef XZ_DEC_IA64 36524fa0402a9b6a537e87e38341e78b7da86486846Lasse Collin case BCJ_IA64: 36624fa0402a9b6a537e87e38341e78b7da86486846Lasse Collin filtered = bcj_ia64(s, buf, size); 36724fa0402a9b6a537e87e38341e78b7da86486846Lasse Collin break; 36824fa0402a9b6a537e87e38341e78b7da86486846Lasse Collin#endif 36924fa0402a9b6a537e87e38341e78b7da86486846Lasse Collin#ifdef XZ_DEC_ARM 37024fa0402a9b6a537e87e38341e78b7da86486846Lasse Collin case BCJ_ARM: 37124fa0402a9b6a537e87e38341e78b7da86486846Lasse Collin filtered = bcj_arm(s, buf, size); 37224fa0402a9b6a537e87e38341e78b7da86486846Lasse Collin break; 37324fa0402a9b6a537e87e38341e78b7da86486846Lasse Collin#endif 37424fa0402a9b6a537e87e38341e78b7da86486846Lasse Collin#ifdef XZ_DEC_ARMTHUMB 37524fa0402a9b6a537e87e38341e78b7da86486846Lasse Collin case BCJ_ARMTHUMB: 37624fa0402a9b6a537e87e38341e78b7da86486846Lasse Collin filtered = bcj_armthumb(s, buf, size); 37724fa0402a9b6a537e87e38341e78b7da86486846Lasse Collin break; 37824fa0402a9b6a537e87e38341e78b7da86486846Lasse Collin#endif 37924fa0402a9b6a537e87e38341e78b7da86486846Lasse Collin#ifdef XZ_DEC_SPARC 38024fa0402a9b6a537e87e38341e78b7da86486846Lasse Collin case BCJ_SPARC: 38124fa0402a9b6a537e87e38341e78b7da86486846Lasse Collin filtered = bcj_sparc(s, buf, size); 38224fa0402a9b6a537e87e38341e78b7da86486846Lasse Collin break; 38324fa0402a9b6a537e87e38341e78b7da86486846Lasse Collin#endif 38424fa0402a9b6a537e87e38341e78b7da86486846Lasse Collin default: 38524fa0402a9b6a537e87e38341e78b7da86486846Lasse Collin /* Never reached but silence compiler warnings. */ 38624fa0402a9b6a537e87e38341e78b7da86486846Lasse Collin filtered = 0; 38724fa0402a9b6a537e87e38341e78b7da86486846Lasse Collin break; 38824fa0402a9b6a537e87e38341e78b7da86486846Lasse Collin } 38924fa0402a9b6a537e87e38341e78b7da86486846Lasse Collin 39024fa0402a9b6a537e87e38341e78b7da86486846Lasse Collin *pos += filtered; 39124fa0402a9b6a537e87e38341e78b7da86486846Lasse Collin s->pos += filtered; 39224fa0402a9b6a537e87e38341e78b7da86486846Lasse Collin} 39324fa0402a9b6a537e87e38341e78b7da86486846Lasse Collin 39424fa0402a9b6a537e87e38341e78b7da86486846Lasse Collin/* 39524fa0402a9b6a537e87e38341e78b7da86486846Lasse Collin * Flush pending filtered data from temp to the output buffer. 39624fa0402a9b6a537e87e38341e78b7da86486846Lasse Collin * Move the remaining mixture of possibly filtered and unfiltered 39724fa0402a9b6a537e87e38341e78b7da86486846Lasse Collin * data to the beginning of temp. 39824fa0402a9b6a537e87e38341e78b7da86486846Lasse Collin */ 39924fa0402a9b6a537e87e38341e78b7da86486846Lasse Collinstatic void bcj_flush(struct xz_dec_bcj *s, struct xz_buf *b) 40024fa0402a9b6a537e87e38341e78b7da86486846Lasse Collin{ 40124fa0402a9b6a537e87e38341e78b7da86486846Lasse Collin size_t copy_size; 40224fa0402a9b6a537e87e38341e78b7da86486846Lasse Collin 40324fa0402a9b6a537e87e38341e78b7da86486846Lasse Collin copy_size = min_t(size_t, s->temp.filtered, b->out_size - b->out_pos); 40424fa0402a9b6a537e87e38341e78b7da86486846Lasse Collin memcpy(b->out + b->out_pos, s->temp.buf, copy_size); 40524fa0402a9b6a537e87e38341e78b7da86486846Lasse Collin b->out_pos += copy_size; 40624fa0402a9b6a537e87e38341e78b7da86486846Lasse Collin 40724fa0402a9b6a537e87e38341e78b7da86486846Lasse Collin s->temp.filtered -= copy_size; 40824fa0402a9b6a537e87e38341e78b7da86486846Lasse Collin s->temp.size -= copy_size; 40924fa0402a9b6a537e87e38341e78b7da86486846Lasse Collin memmove(s->temp.buf, s->temp.buf + copy_size, s->temp.size); 41024fa0402a9b6a537e87e38341e78b7da86486846Lasse Collin} 41124fa0402a9b6a537e87e38341e78b7da86486846Lasse Collin 41224fa0402a9b6a537e87e38341e78b7da86486846Lasse Collin/* 41324fa0402a9b6a537e87e38341e78b7da86486846Lasse Collin * The BCJ filter functions are primitive in sense that they process the 41424fa0402a9b6a537e87e38341e78b7da86486846Lasse Collin * data in chunks of 1-16 bytes. To hide this issue, this function does 41524fa0402a9b6a537e87e38341e78b7da86486846Lasse Collin * some buffering. 41624fa0402a9b6a537e87e38341e78b7da86486846Lasse Collin */ 41724fa0402a9b6a537e87e38341e78b7da86486846Lasse CollinXZ_EXTERN enum xz_ret xz_dec_bcj_run(struct xz_dec_bcj *s, 41824fa0402a9b6a537e87e38341e78b7da86486846Lasse Collin struct xz_dec_lzma2 *lzma2, 41924fa0402a9b6a537e87e38341e78b7da86486846Lasse Collin struct xz_buf *b) 42024fa0402a9b6a537e87e38341e78b7da86486846Lasse Collin{ 42124fa0402a9b6a537e87e38341e78b7da86486846Lasse Collin size_t out_start; 42224fa0402a9b6a537e87e38341e78b7da86486846Lasse Collin 42324fa0402a9b6a537e87e38341e78b7da86486846Lasse Collin /* 42424fa0402a9b6a537e87e38341e78b7da86486846Lasse Collin * Flush pending already filtered data to the output buffer. Return 42524fa0402a9b6a537e87e38341e78b7da86486846Lasse Collin * immediatelly if we couldn't flush everything, or if the next 42624fa0402a9b6a537e87e38341e78b7da86486846Lasse Collin * filter in the chain had already returned XZ_STREAM_END. 42724fa0402a9b6a537e87e38341e78b7da86486846Lasse Collin */ 42824fa0402a9b6a537e87e38341e78b7da86486846Lasse Collin if (s->temp.filtered > 0) { 42924fa0402a9b6a537e87e38341e78b7da86486846Lasse Collin bcj_flush(s, b); 43024fa0402a9b6a537e87e38341e78b7da86486846Lasse Collin if (s->temp.filtered > 0) 43124fa0402a9b6a537e87e38341e78b7da86486846Lasse Collin return XZ_OK; 43224fa0402a9b6a537e87e38341e78b7da86486846Lasse Collin 43324fa0402a9b6a537e87e38341e78b7da86486846Lasse Collin if (s->ret == XZ_STREAM_END) 43424fa0402a9b6a537e87e38341e78b7da86486846Lasse Collin return XZ_STREAM_END; 43524fa0402a9b6a537e87e38341e78b7da86486846Lasse Collin } 43624fa0402a9b6a537e87e38341e78b7da86486846Lasse Collin 43724fa0402a9b6a537e87e38341e78b7da86486846Lasse Collin /* 43824fa0402a9b6a537e87e38341e78b7da86486846Lasse Collin * If we have more output space than what is currently pending in 43924fa0402a9b6a537e87e38341e78b7da86486846Lasse Collin * temp, copy the unfiltered data from temp to the output buffer 44024fa0402a9b6a537e87e38341e78b7da86486846Lasse Collin * and try to fill the output buffer by decoding more data from the 44124fa0402a9b6a537e87e38341e78b7da86486846Lasse Collin * next filter in the chain. Apply the BCJ filter on the new data 44224fa0402a9b6a537e87e38341e78b7da86486846Lasse Collin * in the output buffer. If everything cannot be filtered, copy it 44324fa0402a9b6a537e87e38341e78b7da86486846Lasse Collin * to temp and rewind the output buffer position accordingly. 4449c1f8594df4814ebfd6822ca3c9444fb3445888dLasse Collin * 4459c1f8594df4814ebfd6822ca3c9444fb3445888dLasse Collin * This needs to be always run when temp.size == 0 to handle a special 4469c1f8594df4814ebfd6822ca3c9444fb3445888dLasse Collin * case where the output buffer is full and the next filter has no 4479c1f8594df4814ebfd6822ca3c9444fb3445888dLasse Collin * more output coming but hasn't returned XZ_STREAM_END yet. 44824fa0402a9b6a537e87e38341e78b7da86486846Lasse Collin */ 4499c1f8594df4814ebfd6822ca3c9444fb3445888dLasse Collin if (s->temp.size < b->out_size - b->out_pos || s->temp.size == 0) { 45024fa0402a9b6a537e87e38341e78b7da86486846Lasse Collin out_start = b->out_pos; 45124fa0402a9b6a537e87e38341e78b7da86486846Lasse Collin memcpy(b->out + b->out_pos, s->temp.buf, s->temp.size); 45224fa0402a9b6a537e87e38341e78b7da86486846Lasse Collin b->out_pos += s->temp.size; 45324fa0402a9b6a537e87e38341e78b7da86486846Lasse Collin 45424fa0402a9b6a537e87e38341e78b7da86486846Lasse Collin s->ret = xz_dec_lzma2_run(lzma2, b); 45524fa0402a9b6a537e87e38341e78b7da86486846Lasse Collin if (s->ret != XZ_STREAM_END 45624fa0402a9b6a537e87e38341e78b7da86486846Lasse Collin && (s->ret != XZ_OK || s->single_call)) 45724fa0402a9b6a537e87e38341e78b7da86486846Lasse Collin return s->ret; 45824fa0402a9b6a537e87e38341e78b7da86486846Lasse Collin 45924fa0402a9b6a537e87e38341e78b7da86486846Lasse Collin bcj_apply(s, b->out, &out_start, b->out_pos); 46024fa0402a9b6a537e87e38341e78b7da86486846Lasse Collin 46124fa0402a9b6a537e87e38341e78b7da86486846Lasse Collin /* 46224fa0402a9b6a537e87e38341e78b7da86486846Lasse Collin * As an exception, if the next filter returned XZ_STREAM_END, 46324fa0402a9b6a537e87e38341e78b7da86486846Lasse Collin * we can do that too, since the last few bytes that remain 46424fa0402a9b6a537e87e38341e78b7da86486846Lasse Collin * unfiltered are meant to remain unfiltered. 46524fa0402a9b6a537e87e38341e78b7da86486846Lasse Collin */ 46624fa0402a9b6a537e87e38341e78b7da86486846Lasse Collin if (s->ret == XZ_STREAM_END) 46724fa0402a9b6a537e87e38341e78b7da86486846Lasse Collin return XZ_STREAM_END; 46824fa0402a9b6a537e87e38341e78b7da86486846Lasse Collin 46924fa0402a9b6a537e87e38341e78b7da86486846Lasse Collin s->temp.size = b->out_pos - out_start; 47024fa0402a9b6a537e87e38341e78b7da86486846Lasse Collin b->out_pos -= s->temp.size; 47124fa0402a9b6a537e87e38341e78b7da86486846Lasse Collin memcpy(s->temp.buf, b->out + b->out_pos, s->temp.size); 4729c1f8594df4814ebfd6822ca3c9444fb3445888dLasse Collin 4739c1f8594df4814ebfd6822ca3c9444fb3445888dLasse Collin /* 4749c1f8594df4814ebfd6822ca3c9444fb3445888dLasse Collin * If there wasn't enough input to the next filter to fill 4759c1f8594df4814ebfd6822ca3c9444fb3445888dLasse Collin * the output buffer with unfiltered data, there's no point 4769c1f8594df4814ebfd6822ca3c9444fb3445888dLasse Collin * to try decoding more data to temp. 4779c1f8594df4814ebfd6822ca3c9444fb3445888dLasse Collin */ 4789c1f8594df4814ebfd6822ca3c9444fb3445888dLasse Collin if (b->out_pos + s->temp.size < b->out_size) 4799c1f8594df4814ebfd6822ca3c9444fb3445888dLasse Collin return XZ_OK; 48024fa0402a9b6a537e87e38341e78b7da86486846Lasse Collin } 48124fa0402a9b6a537e87e38341e78b7da86486846Lasse Collin 48224fa0402a9b6a537e87e38341e78b7da86486846Lasse Collin /* 4839c1f8594df4814ebfd6822ca3c9444fb3445888dLasse Collin * We have unfiltered data in temp. If the output buffer isn't full 4849c1f8594df4814ebfd6822ca3c9444fb3445888dLasse Collin * yet, try to fill the temp buffer by decoding more data from the 4859c1f8594df4814ebfd6822ca3c9444fb3445888dLasse Collin * next filter. Apply the BCJ filter on temp. Then we hopefully can 4869c1f8594df4814ebfd6822ca3c9444fb3445888dLasse Collin * fill the actual output buffer by copying filtered data from temp. 4879c1f8594df4814ebfd6822ca3c9444fb3445888dLasse Collin * A mix of filtered and unfiltered data may be left in temp; it will 4889c1f8594df4814ebfd6822ca3c9444fb3445888dLasse Collin * be taken care on the next call to this function. 48924fa0402a9b6a537e87e38341e78b7da86486846Lasse Collin */ 4909c1f8594df4814ebfd6822ca3c9444fb3445888dLasse Collin if (b->out_pos < b->out_size) { 49124fa0402a9b6a537e87e38341e78b7da86486846Lasse Collin /* Make b->out{,_pos,_size} temporarily point to s->temp. */ 49224fa0402a9b6a537e87e38341e78b7da86486846Lasse Collin s->out = b->out; 49324fa0402a9b6a537e87e38341e78b7da86486846Lasse Collin s->out_pos = b->out_pos; 49424fa0402a9b6a537e87e38341e78b7da86486846Lasse Collin s->out_size = b->out_size; 49524fa0402a9b6a537e87e38341e78b7da86486846Lasse Collin b->out = s->temp.buf; 49624fa0402a9b6a537e87e38341e78b7da86486846Lasse Collin b->out_pos = s->temp.size; 49724fa0402a9b6a537e87e38341e78b7da86486846Lasse Collin b->out_size = sizeof(s->temp.buf); 49824fa0402a9b6a537e87e38341e78b7da86486846Lasse Collin 49924fa0402a9b6a537e87e38341e78b7da86486846Lasse Collin s->ret = xz_dec_lzma2_run(lzma2, b); 50024fa0402a9b6a537e87e38341e78b7da86486846Lasse Collin 50124fa0402a9b6a537e87e38341e78b7da86486846Lasse Collin s->temp.size = b->out_pos; 50224fa0402a9b6a537e87e38341e78b7da86486846Lasse Collin b->out = s->out; 50324fa0402a9b6a537e87e38341e78b7da86486846Lasse Collin b->out_pos = s->out_pos; 50424fa0402a9b6a537e87e38341e78b7da86486846Lasse Collin b->out_size = s->out_size; 50524fa0402a9b6a537e87e38341e78b7da86486846Lasse Collin 50624fa0402a9b6a537e87e38341e78b7da86486846Lasse Collin if (s->ret != XZ_OK && s->ret != XZ_STREAM_END) 50724fa0402a9b6a537e87e38341e78b7da86486846Lasse Collin return s->ret; 50824fa0402a9b6a537e87e38341e78b7da86486846Lasse Collin 50924fa0402a9b6a537e87e38341e78b7da86486846Lasse Collin bcj_apply(s, s->temp.buf, &s->temp.filtered, s->temp.size); 51024fa0402a9b6a537e87e38341e78b7da86486846Lasse Collin 51124fa0402a9b6a537e87e38341e78b7da86486846Lasse Collin /* 51224fa0402a9b6a537e87e38341e78b7da86486846Lasse Collin * If the next filter returned XZ_STREAM_END, we mark that 51324fa0402a9b6a537e87e38341e78b7da86486846Lasse Collin * everything is filtered, since the last unfiltered bytes 51424fa0402a9b6a537e87e38341e78b7da86486846Lasse Collin * of the stream are meant to be left as is. 51524fa0402a9b6a537e87e38341e78b7da86486846Lasse Collin */ 51624fa0402a9b6a537e87e38341e78b7da86486846Lasse Collin if (s->ret == XZ_STREAM_END) 51724fa0402a9b6a537e87e38341e78b7da86486846Lasse Collin s->temp.filtered = s->temp.size; 51824fa0402a9b6a537e87e38341e78b7da86486846Lasse Collin 51924fa0402a9b6a537e87e38341e78b7da86486846Lasse Collin bcj_flush(s, b); 52024fa0402a9b6a537e87e38341e78b7da86486846Lasse Collin if (s->temp.filtered > 0) 52124fa0402a9b6a537e87e38341e78b7da86486846Lasse Collin return XZ_OK; 52224fa0402a9b6a537e87e38341e78b7da86486846Lasse Collin } 52324fa0402a9b6a537e87e38341e78b7da86486846Lasse Collin 52424fa0402a9b6a537e87e38341e78b7da86486846Lasse Collin return s->ret; 52524fa0402a9b6a537e87e38341e78b7da86486846Lasse Collin} 52624fa0402a9b6a537e87e38341e78b7da86486846Lasse Collin 52724fa0402a9b6a537e87e38341e78b7da86486846Lasse CollinXZ_EXTERN struct xz_dec_bcj *xz_dec_bcj_create(bool single_call) 52824fa0402a9b6a537e87e38341e78b7da86486846Lasse Collin{ 52924fa0402a9b6a537e87e38341e78b7da86486846Lasse Collin struct xz_dec_bcj *s = kmalloc(sizeof(*s), GFP_KERNEL); 53024fa0402a9b6a537e87e38341e78b7da86486846Lasse Collin if (s != NULL) 53124fa0402a9b6a537e87e38341e78b7da86486846Lasse Collin s->single_call = single_call; 53224fa0402a9b6a537e87e38341e78b7da86486846Lasse Collin 53324fa0402a9b6a537e87e38341e78b7da86486846Lasse Collin return s; 53424fa0402a9b6a537e87e38341e78b7da86486846Lasse Collin} 53524fa0402a9b6a537e87e38341e78b7da86486846Lasse Collin 53624fa0402a9b6a537e87e38341e78b7da86486846Lasse CollinXZ_EXTERN enum xz_ret xz_dec_bcj_reset(struct xz_dec_bcj *s, uint8_t id) 53724fa0402a9b6a537e87e38341e78b7da86486846Lasse Collin{ 53824fa0402a9b6a537e87e38341e78b7da86486846Lasse Collin switch (id) { 53924fa0402a9b6a537e87e38341e78b7da86486846Lasse Collin#ifdef XZ_DEC_X86 54024fa0402a9b6a537e87e38341e78b7da86486846Lasse Collin case BCJ_X86: 54124fa0402a9b6a537e87e38341e78b7da86486846Lasse Collin#endif 54224fa0402a9b6a537e87e38341e78b7da86486846Lasse Collin#ifdef XZ_DEC_POWERPC 54324fa0402a9b6a537e87e38341e78b7da86486846Lasse Collin case BCJ_POWERPC: 54424fa0402a9b6a537e87e38341e78b7da86486846Lasse Collin#endif 54524fa0402a9b6a537e87e38341e78b7da86486846Lasse Collin#ifdef XZ_DEC_IA64 54624fa0402a9b6a537e87e38341e78b7da86486846Lasse Collin case BCJ_IA64: 54724fa0402a9b6a537e87e38341e78b7da86486846Lasse Collin#endif 54824fa0402a9b6a537e87e38341e78b7da86486846Lasse Collin#ifdef XZ_DEC_ARM 54924fa0402a9b6a537e87e38341e78b7da86486846Lasse Collin case BCJ_ARM: 55024fa0402a9b6a537e87e38341e78b7da86486846Lasse Collin#endif 55124fa0402a9b6a537e87e38341e78b7da86486846Lasse Collin#ifdef XZ_DEC_ARMTHUMB 55224fa0402a9b6a537e87e38341e78b7da86486846Lasse Collin case BCJ_ARMTHUMB: 55324fa0402a9b6a537e87e38341e78b7da86486846Lasse Collin#endif 55424fa0402a9b6a537e87e38341e78b7da86486846Lasse Collin#ifdef XZ_DEC_SPARC 55524fa0402a9b6a537e87e38341e78b7da86486846Lasse Collin case BCJ_SPARC: 55624fa0402a9b6a537e87e38341e78b7da86486846Lasse Collin#endif 55724fa0402a9b6a537e87e38341e78b7da86486846Lasse Collin break; 55824fa0402a9b6a537e87e38341e78b7da86486846Lasse Collin 55924fa0402a9b6a537e87e38341e78b7da86486846Lasse Collin default: 56024fa0402a9b6a537e87e38341e78b7da86486846Lasse Collin /* Unsupported Filter ID */ 56124fa0402a9b6a537e87e38341e78b7da86486846Lasse Collin return XZ_OPTIONS_ERROR; 56224fa0402a9b6a537e87e38341e78b7da86486846Lasse Collin } 56324fa0402a9b6a537e87e38341e78b7da86486846Lasse Collin 56424fa0402a9b6a537e87e38341e78b7da86486846Lasse Collin s->type = id; 56524fa0402a9b6a537e87e38341e78b7da86486846Lasse Collin s->ret = XZ_OK; 56624fa0402a9b6a537e87e38341e78b7da86486846Lasse Collin s->pos = 0; 56724fa0402a9b6a537e87e38341e78b7da86486846Lasse Collin s->x86_prev_mask = 0; 56824fa0402a9b6a537e87e38341e78b7da86486846Lasse Collin s->temp.filtered = 0; 56924fa0402a9b6a537e87e38341e78b7da86486846Lasse Collin s->temp.size = 0; 57024fa0402a9b6a537e87e38341e78b7da86486846Lasse Collin 57124fa0402a9b6a537e87e38341e78b7da86486846Lasse Collin return XZ_OK; 57224fa0402a9b6a537e87e38341e78b7da86486846Lasse Collin} 57324fa0402a9b6a537e87e38341e78b7da86486846Lasse Collin 57424fa0402a9b6a537e87e38341e78b7da86486846Lasse Collin#endif 575