1 /*
2 * CPU detection code, extracted from mmx.h
3 * (c)1997-99 by H. Dietz and R. Fisher
4 * Converted to C and improved by Fabrice Bellard.
5 *
6 * This file is part of Tvheadend.
7 *
8 * This program is free software: you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation, either version 3 of the License, or
11 * (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program. If not, see <http://www.gnu.org/licenses/>.
20 */
21 #include "config.h"
22 #include "tvheadend.h"
23 #include "FFdecsa.h"
24
25
26
27 typedef struct {
28 int (*get_internal_parallelism)(void);
29 int (*get_suggested_cluster_size)(void);
30 void *(*get_key_struct)(void);
31 void (*free_key_struct)(void *keys);
32 void (*set_control_words)(void *keys, const unsigned char *even, const unsigned char *odd);
33
34 void (*set_even_control_word)(void *keys, const unsigned char *even);
35 void (*set_odd_control_word)(void *keys, const unsigned char *odd);
36 int (*decrypt_packets)(void *keys, unsigned char **cluster);
37
38 } csafuncs_t;
39
40
41 #define MAKEFUNCS(x) \
42 extern int get_internal_parallelism_##x(void);\
43 extern int get_suggested_cluster_size_##x(void);\
44 extern void *get_key_struct_##x(void);\
45 extern void free_key_struct_##x(void *keys);\
46 extern void set_control_words_##x(void *keys, const unsigned char *even, const unsigned char *odd);\
47 extern void set_even_control_word_##x(void *keys, const unsigned char *even);\
48 extern void set_odd_control_word_##x(void *keys, const unsigned char *odd);\
49 extern int decrypt_packets_##x(void *keys, unsigned char **cluster);\
50 static csafuncs_t funcs_##x = { \
51 &get_internal_parallelism_##x,\
52 &get_suggested_cluster_size_##x,\
53 &get_key_struct_##x,\
54 &free_key_struct_##x,\
55 &set_control_words_##x,\
56 &set_even_control_word_##x,\
57 &set_odd_control_word_##x,\
58 &decrypt_packets_##x\
59 };
60
61 MAKEFUNCS(32int);
62 #ifdef CONFIG_MMX
63 MAKEFUNCS(64mmx);
64 #endif
65
66 #ifdef CONFIG_SSE2
67 MAKEFUNCS(128sse2);
68 #endif
69
70 static csafuncs_t current;
71
72
73
74
75 #if defined(__x86_64__)
76 # define REG_a "rax"
77 # define REG_b "rbx"
78 # define REG_c "rcx"
79 # define REG_d "rdx"
80 # define REG_D "rdi"
81 # define REG_S "rsi"
82 # define PTR_SIZE "8"
83 typedef int64_t x86_reg;
84
85 # define REG_SP "rsp"
86 # define REG_BP "rbp"
87 # define REGBP rbp
88 # define REGa rax
89 # define REGb rbx
90 # define REGc rcx
91 # define REGd rdx
92 # define REGSP rsp
93
94 #elif defined(__i386__)
95
96 # define REG_a "eax"
97 # define REG_b "ebx"
98 # define REG_c "ecx"
99 # define REG_d "edx"
100 # define REG_D "edi"
101 # define REG_S "esi"
102 # define PTR_SIZE "4"
103 typedef int32_t x86_reg;
104
105 # define REG_SP "esp"
106 # define REG_BP "ebp"
107 # define REGBP ebp
108 # define REGa eax
109 # define REGb ebx
110 # define REGc ecx
111 # define REGd edx
112 # define REGSP esp
113 #else
114 typedef int x86_reg;
115 #endif
116
117 #if defined(__i386__) || defined(__x86_64__)
118 static inline void
native_cpuid(unsigned int * eax,unsigned int * ebx,unsigned int * ecx,unsigned int * edx)119 native_cpuid(unsigned int *eax, unsigned int *ebx,
120 unsigned int *ecx, unsigned int *edx)
121 {
122 /* saving ebx is necessary for PIC compatibility */
123 asm volatile("mov %%"REG_b", %%"REG_S"\n\t"
124 "cpuid\n\t"
125 "xchg %%"REG_b", %%"REG_S
126 : "=a" (*eax),
127 "=S" (*ebx),
128 "=c" (*ecx),
129 "=d" (*edx)
130 : "0" (*eax), "2" (*ecx));
131 }
132 #endif
133
134 void
ffdecsa_init(void)135 ffdecsa_init(void)
136 {
137 current = funcs_32int;
138
139
140 #if defined(__i386__) || defined(__x86_64__)
141
142 unsigned int eax, ebx, ecx, edx;
143 unsigned int max_std_level, std_caps;
144
145 #if defined(__i386__)
146
147 x86_reg a, c;
148 __asm__ volatile (
149 /* See if CPUID instruction is supported ... */
150 /* ... Get copies of EFLAGS into eax and ecx */
151 "pushfl\n\t"
152 "pop %0\n\t"
153 "mov %0, %1\n\t"
154
155 /* ... Toggle the ID bit in one copy and store */
156 /* to the EFLAGS reg */
157 "xor $0x200000, %0\n\t"
158 "push %0\n\t"
159 "popfl\n\t"
160
161 /* ... Get the (hopefully modified) EFLAGS */
162 "pushfl\n\t"
163 "pop %0\n\t"
164 : "=a" (a), "=c" (c)
165 :
166 : "cc"
167 );
168
169 if (a != c) {
170 #endif
171 eax = ebx = ecx = edx = 0;
172 native_cpuid(&eax, &ebx, &ecx, &edx);
173 max_std_level = eax;
174
175 if(max_std_level >= 1){
176 eax = 1;
177 native_cpuid(&eax, &ebx, &ecx, &edx);
178 std_caps = edx;
179
180 #ifdef CONFIG_SSE2
181 if (std_caps & (1<<26)) {
182 current = funcs_128sse2;
183 tvhinfo(LS_CSA, "Using SSE2 128bit parallel descrambling");
184 return;
185 }
186 #endif
187
188 #ifdef CONFIG_MMX
189 if (std_caps & (1<<23)) {
190 current = funcs_64mmx;
191 tvhinfo(LS_CSA, "Using MMX 64bit parallel descrambling");
192 return;
193 }
194 #endif
195 }
196 #if defined(__i386__)
197 }
198 #endif
199 #endif
200
201 tvhinfo(LS_CSA, "Using 32bit parallel descrambling");
202 }
203
204
205 int
get_internal_parallelism(void)206 get_internal_parallelism(void)
207 {
208 return current.get_internal_parallelism();
209 }
210 int
get_suggested_cluster_size(void)211 get_suggested_cluster_size(void)
212 {
213 return current.get_suggested_cluster_size();
214 }
215
216 void *
get_key_struct(void)217 get_key_struct(void)
218 {
219 return current.get_key_struct();
220 }
221 void
free_key_struct(void * keys)222 free_key_struct(void *keys)
223 {
224 current.free_key_struct(keys);
225 }
226
227 void
set_even_control_word(void * keys,const unsigned char * even)228 set_even_control_word(void *keys, const unsigned char *even)
229 {
230 current.set_even_control_word(keys, even);
231 }
232
233 void
set_odd_control_word(void * keys,const unsigned char * odd)234 set_odd_control_word(void *keys, const unsigned char *odd)
235 {
236 current.set_odd_control_word(keys, odd);
237 }
238
239 int
decrypt_packets(void * keys,unsigned char ** cluster)240 decrypt_packets(void *keys, unsigned char **cluster)
241 {
242 return current.decrypt_packets(keys, cluster);
243 }
244