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