1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <string.h>
4 #include <ctype.h>
5
6 #include "soc.h"
7 #include "socs.h"
8 #include "udev.h"
9 #include "../common/global.h"
10
11 #define min(a,b) (((a)<(b))?(a):(b))
12 #define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0]))
13
14 static char* soc_trademark_string[] = {
15 [SOC_VENDOR_SNAPDRAGON] = "Snapdragon ",
16 [SOC_VENDOR_MEDIATEK] = "MediaTek ",
17 [SOC_VENDOR_EXYNOS] = "Exynos ",
18 [SOC_VENDOR_KIRIN] = "Kirin ",
19 [SOC_VENDOR_BROADCOM] = "Broadcom BCM",
20 [SOC_VENDOR_APPLE] = "Apple "
21 };
22
23 static char* soc_rpi_string[] = {
24 "BCM2835",
25 "BCM2836",
26 "BCM2837",
27 "BCM2711"
28 };
29
fill_soc(struct system_on_chip * soc,char * soc_name,SOC soc_model,int32_t process)30 void fill_soc(struct system_on_chip* soc, char* soc_name, SOC soc_model, int32_t process) {
31 soc->soc_model = soc_model;
32 soc->soc_vendor = get_soc_vendor_from_soc(soc_model);
33 soc->process = process;
34 int len = strlen(soc_name) + strlen(soc_trademark_string[soc->soc_vendor]) + 1;
35 soc->soc_name = emalloc(sizeof(char) * len);
36 memset(soc->soc_name, 0, sizeof(char) * len);
37 sprintf(soc->soc_name, "%s%s", soc_trademark_string[soc->soc_vendor], soc_name);
38 }
39
match_soc(struct system_on_chip * soc,char * raw_name,char * expected_name,char * soc_name,SOC soc_model,int32_t process)40 bool match_soc(struct system_on_chip* soc, char* raw_name, char* expected_name, char* soc_name, SOC soc_model, int32_t process) {
41 if(strlen(raw_name) > strlen(expected_name))
42 return false;
43
44 int len = strlen(raw_name);
45 if(strncmp(raw_name, expected_name, len) != 0) {
46 return false;
47 }
48 else {
49 fill_soc(soc, soc_name, soc_model, process);
50 return true;
51 }
52 }
53
toupperstr(char * str)54 char* toupperstr(char* str) {
55 int len = strlen(str) + 1;
56 char* ret = emalloc(sizeof(char) * len);
57 memset(ret, 0, sizeof(char) * len);
58
59 for(int i=0; i < len; i++) {
60 ret[i] = toupper((unsigned char) str[i]);
61 }
62
63 return ret;
64 }
65
66 #define SOC_START if (false) {}
67 #define SOC_EQ(raw_name, expected_name, soc_name, soc_model, soc, process) \
68 else if (match_soc(soc, raw_name, expected_name, soc_name, soc_model, process)) return true;
69 #define SOC_END else { return false; }
70 // Exynos special define
71 #define SOC_EXY_EQ(raw_name, tmpsoc, soc_name, soc_model, soc, process) \
72 sprintf(tmpsoc, "exynos%s", soc_name); \
73 if (match_soc(soc, raw_name, tmpsoc, soc_name, soc_model, process)) return true; \
74 sprintf(tmpsoc, "universal%s", soc_name); \
75 if (match_soc(soc, raw_name, tmpsoc, soc_name, soc_model, process)) return true;
76
77 // https://en.wikipedia.org/wiki/Raspberry_Pi
78 // http://phonedb.net/index.php?m=processor&id=562&c=broadcom_bcm21663
79 // https://hwbot.org/hardware/processors#key=bcmxxx
match_broadcom(char * soc_name,struct system_on_chip * soc)80 bool match_broadcom(char* soc_name, struct system_on_chip* soc) {
81 char* tmp;
82
83 if((tmp = strstr(soc_name, "BCM")) == NULL)
84 return false;
85
86 SOC_START
87 SOC_EQ(tmp, "BCM2835", "2835", SOC_BCM_2835, soc, 65)
88 SOC_EQ(tmp, "BCM2836", "2836", SOC_BCM_2836, soc, 40)
89 SOC_EQ(tmp, "BCM2837", "2837", SOC_BCM_2837, soc, 40)
90 SOC_EQ(tmp, "BCM2837B0", "2837B0", SOC_BCM_2837B0, soc, 40)
91 SOC_EQ(tmp, "BCM2711", "2711", SOC_BCM_2711, soc, 28)
92 SOC_EQ(tmp, "BCM21553", "21553", SOC_BCM_21553, soc, 65)
93 SOC_EQ(tmp, "BCM21553-Thunderbird", "21553 Thunderbird", SOC_BCM_21553T, soc, 65)
94 SOC_EQ(tmp, "BCM21663", "21663", SOC_BCM_21663, soc, 40)
95 SOC_EQ(tmp, "BCM21664", "21664", SOC_BCM_21664, soc, 40)
96 SOC_EQ(tmp, "BCM28155", "28155", SOC_BCM_28155, soc, 40)
97 SOC_EQ(tmp, "BCM23550", "23550", SOC_BCM_23550, soc, 40)
98 SOC_EQ(tmp, "BCM28145", "28145", SOC_BCM_28145, soc, 40)
99 SOC_EQ(tmp, "BCM2157", "2157", SOC_BCM_2157, soc, 65)
100 SOC_EQ(tmp, "BCM21654", "21654", SOC_BCM_21654, soc, 40)
101 SOC_END
102 }
103
104 // https://www.techinsights.com/
105 // https://datasheetspdf.com/pdf-file/1316605/HiSilicon/Hi3660/1
match_hisilicon(char * soc_name,struct system_on_chip * soc)106 bool match_hisilicon(char* soc_name, struct system_on_chip* soc) {
107 char* tmp;
108
109 if((tmp = strstr(soc_name, "Hi")) == NULL)
110 return false;
111
112 SOC_START
113 SOC_EQ(tmp, "Hi3620GFC", "K3V2", SOC_HISILICON_3620, soc, 40)
114 //SOC_EQ(tmp, "?", "K3V2E", SOC_KIRIN, soc, ?)
115 //SOC_EQ(tmp, "?", "620", SOC_KIRIN, soc, 28)
116 //SOC_EQ(tmp, "?", "650", SOC_KIRIN, soc, 16)
117 //SOC_EQ(tmp, "?", "655", SOC_KIRIN, soc, 16)
118 //SOC_EQ(tmp, "?", "658", SOC_KIRIN, soc, 16)
119 //SOC_EQ(tmp, "?", "659", SOC_KIRIN, soc, 16)
120 //SOC_EQ(tmp, "?", "710", SOC_KIRIN, soc, 12)
121 //SOC_EQ(tmp, "?", "710A", SOC_KIRIN, soc, 12)
122 //SOC_EQ(tmp, "?", "710F", SOC_KIRIN, soc, 12)
123 //SOC_EQ(tmp, "?", "810", SOC_KIRIN, soc, 7)
124 //SOC_EQ(tmp, "?", "820", SOC_KIRIN, soc, 7)
125 //SOC_EQ(tmp, "?", "9000", SOC_KIRIN, soc, 5)
126 //SOC_EQ(tmp, "?", "9000E", SOC_KIRIN, soc, 5)
127 //SOC_EQ(tmp, "?", "910", SOC_KIRIN, soc, 28)
128 //SOC_EQ(tmp, "?", "910T", SOC_KIRIN, soc, 28)
129 SOC_EQ(tmp, "Hi3630", "920", SOC_HISILICON_3630, soc, 28)
130 //SOC_EQ(tmp, "?", "925", SOC_KIRIN, soc, 28)
131 //SOC_EQ(tmp, "?", "930", SOC_KIRIN, soc, ?)
132 //SOC_EQ(tmp, "?", "935", SOC_KIRIN, soc, ?)
133 SOC_EQ(tmp, "Hi3650", "950", SOC_HISILICON_3650, soc, 16)
134 //SOC_EQ(tmp, "?", "955", SOC_KIRIN, soc, ?)
135 SOC_EQ(tmp, "Hi3660", "960", SOC_HISILICON_3660, soc, 16)
136 //SOC_EQ(tmp, "?", "960S", SOC_KIRIN, soc, 16)
137 SOC_EQ(tmp, "Hi3670", "970", SOC_HISILICON_3670, soc, 10)
138 SOC_EQ(tmp, "Hi3680", "980", SOC_HISILICON_3680, soc, 7)
139 //SOC_EQ(tmp, "?", "985", SOC_KIRIN, soc, 7)
140 SOC_EQ(tmp, "Hi3690", "990", SOC_HISILICON_3690, soc, 7)
141 SOC_END
142 }
143
match_exynos(char * soc_name,struct system_on_chip * soc)144 bool match_exynos(char* soc_name, struct system_on_chip* soc) {
145 char* tmp;
146
147 if((tmp = strstr(soc_name, "universal")) != NULL);
148 else if((tmp = strstr(soc_name, "exynos")) != NULL);
149 else return false;
150
151 // Because exynos are recently using "exynosXXXX" instead
152 // of "universalXXXX" as codenames, SOC_EXY_EQ will check for
153 // both cases, since it seems that there are some SoCs that
154 // can appear with both codenames
155
156 // Used by SOC_EXY_EQ
157 char tmpsoc[14];
158
159 SOC_START
160 SOC_EXY_EQ(tmp, tmpsoc, "3475", SOC_EXYNOS_3475, soc, 28)
161 SOC_EXY_EQ(tmp, tmpsoc, "4210", SOC_EXYNOS_4210, soc, 45)
162 SOC_EXY_EQ(tmp, tmpsoc, "4212", SOC_EXYNOS_4212, soc, 32)
163 SOC_EXY_EQ(tmp, tmpsoc, "4412", SOC_EXYNOS_4412, soc, 32)
164 SOC_EXY_EQ(tmp, tmpsoc, "5250", SOC_EXYNOS_5250, soc, 32)
165 SOC_EXY_EQ(tmp, tmpsoc, "5410", SOC_EXYNOS_5410, soc, 28)
166 SOC_EXY_EQ(tmp, tmpsoc, "5420", SOC_EXYNOS_5420, soc, 28)
167 SOC_EXY_EQ(tmp, tmpsoc, "5422", SOC_EXYNOS_5422, soc, 28)
168 SOC_EXY_EQ(tmp, tmpsoc, "5430", SOC_EXYNOS_5430, soc, 20)
169 SOC_EXY_EQ(tmp, tmpsoc, "5433", SOC_EXYNOS_5433, soc, 20)
170 SOC_EXY_EQ(tmp, tmpsoc, "5260", SOC_EXYNOS_5260, soc, 28)
171 SOC_EXY_EQ(tmp, tmpsoc, "7270", SOC_EXYNOS_7270, soc, 14)
172 SOC_EXY_EQ(tmp, tmpsoc, "7420", SOC_EXYNOS_7420, soc, 14)
173 SOC_EXY_EQ(tmp, tmpsoc, "7570", SOC_EXYNOS_7570, soc, 14)
174 SOC_EXY_EQ(tmp, tmpsoc, "7570", SOC_EXYNOS_7570, soc, 14)
175 SOC_EXY_EQ(tmp, tmpsoc, "7870", SOC_EXYNOS_7870, soc, 14)
176 SOC_EXY_EQ(tmp, tmpsoc, "7870", SOC_EXYNOS_7870, soc, 14)
177 SOC_EXY_EQ(tmp, tmpsoc, "7872", SOC_EXYNOS_7872, soc, 14)
178 SOC_EXY_EQ(tmp, tmpsoc, "7880", SOC_EXYNOS_7880, soc, 14)
179 SOC_EXY_EQ(tmp, tmpsoc, "7884", SOC_EXYNOS_7884, soc, 14)
180 SOC_EXY_EQ(tmp, tmpsoc, "7885", SOC_EXYNOS_7885, soc, 14)
181 SOC_EXY_EQ(tmp, tmpsoc, "7904", SOC_EXYNOS_7904, soc, 14)
182 SOC_EXY_EQ(tmp, tmpsoc, "8890", SOC_EXYNOS_8890, soc, 14)
183 SOC_EXY_EQ(tmp, tmpsoc, "8895", SOC_EXYNOS_8895, soc, 10)
184 SOC_EXY_EQ(tmp, tmpsoc, "9110", SOC_EXYNOS_9110, soc, 14)
185 SOC_EXY_EQ(tmp, tmpsoc, "9609", SOC_EXYNOS_9609, soc, 10)
186 SOC_EXY_EQ(tmp, tmpsoc, "9610", SOC_EXYNOS_9610, soc, 10)
187 SOC_EXY_EQ(tmp, tmpsoc, "9611", SOC_EXYNOS_9611, soc, 10)
188 SOC_EXY_EQ(tmp, tmpsoc, "9810", SOC_EXYNOS_9810, soc, 10)
189 SOC_EXY_EQ(tmp, tmpsoc, "9820", SOC_EXYNOS_9820, soc, 8)
190 SOC_EXY_EQ(tmp, tmpsoc, "9825", SOC_EXYNOS_9825, soc, 7)
191 SOC_EXY_EQ(tmp, tmpsoc, "1080", SOC_EXYNOS_1080, soc, 5)
192 SOC_EXY_EQ(tmp, tmpsoc, "990", SOC_EXYNOS_990, soc, 7)
193 SOC_EXY_EQ(tmp, tmpsoc, "980", SOC_EXYNOS_980, soc, 8)
194 SOC_EXY_EQ(tmp, tmpsoc, "880", SOC_EXYNOS_880, soc, 8)
195 SOC_END
196 }
197
match_mediatek(char * soc_name,struct system_on_chip * soc)198 bool match_mediatek(char* soc_name, struct system_on_chip* soc) {
199 char* tmp;
200
201 if((tmp = strstr(soc_name, "MT")) == NULL)
202 return false;
203
204 SOC_START
205 // Dimensity //
206 SOC_EQ(tmp, "MT6889", "Dimensity 1000", SOC_MTK_MT6889, soc, 7)
207 SOC_EQ(tmp, "MT6885Z", "Dimensity 1000L", SOC_MTK_MT6885Z, soc, 7)
208 //SOC_EQ(tmp, "?", "Dimensity 700", SOC_MTK_, soc, 7)
209 SOC_EQ(tmp, "MT6853", "Dimensity 720", SOC_MTK_MT6853, soc, 7)
210 SOC_EQ(tmp, "MT6873", "Dimensity 800", SOC_MTK_MT6873, soc, 7)
211 SOC_EQ(tmp, "MT6875", "Dimensity 820", SOC_MTK_MT6875, soc, 7)
212 // Helio //
213 SOC_EQ(tmp, "MT6761D", "Helio A20", SOC_MTK_MT6761D, soc, 12)
214 SOC_EQ(tmp, "MT6761", "Helio A22", SOC_MTK_MT6761, soc, 12)
215 SOC_EQ(tmp, "MT6762D", "Helio A25", SOC_MTK_MT6762D, soc, 12)
216 //SOC_EQ(tmp, "?", "Helio G25", SOC_MTK_, soc, 12)
217 //SOC_EQ(tmp, "?", "Helio G35", SOC_MTK_, soc, 12)
218 //SOC_EQ(tmp, "?", "Helio G70", SOC_MTK_, soc, 12)
219 //SOC_EQ(tmp, "?", "Helio G80", SOC_MTK_, soc, 12)
220 //SOC_EQ(tmp, "?", "Helio G90", SOC_MTK_, soc, 12)
221 //SOC_EQ(tmp, "?", "Helio G90T", SOC_MTK_, soc, 12)
222 //SOC_EQ(tmp, "?", "Helio G95", SOC_MTK_, soc, 12)
223 SOC_EQ(tmp, "MT6755", "Helio P10", SOC_MTK_MT6755M, soc, 28)
224 SOC_EQ(tmp, "MT6755M", "Helio P10 M", SOC_MTK_MT6755M, soc, 28)
225 SOC_EQ(tmp, "MT6755T", "Helio P15", SOC_MTK_MT6755T, soc, 28)
226 SOC_EQ(tmp, "MT6757", "Helio P20", SOC_MTK_MT6757, soc, 16)
227 SOC_EQ(tmp, "MT6762", "Helio P22", SOC_MTK_MT6762, soc, 12)
228 SOC_EQ(tmp, "MT6763V", "Helio P23", SOC_MTK_MT6763V, soc, 16)
229 SOC_EQ(tmp, "MT6763T", "Helio P23", SOC_MTK_MT6763T, soc, 16)
230 SOC_EQ(tmp, "MT6757CD", "Helio P25", SOC_MTK_MT6757CD, soc, 16)
231 SOC_EQ(tmp, "MT6758", "Helio P30", SOC_MTK_MT6758, soc, 16)
232 SOC_EQ(tmp, "MT6765", "Helio P35", SOC_MTK_MT6765, soc, 12)
233 SOC_EQ(tmp, "MT6771", "Helio P60", SOC_MTK_MT6771, soc, 12)
234 SOC_EQ(tmp, "MT6768", "Helio P65", SOC_MTK_MT6768, soc, 12)
235 SOC_EQ(tmp, "MT6771T", "Helio P70", SOC_MTK_MT6771, soc, 12)
236 SOC_EQ(tmp, "MT6771V", "Helio P70", SOC_MTK_MT6771, soc, 12)
237 SOC_EQ(tmp, "MT6779", "Helio P90", SOC_MTK_MT6779, soc, 12)
238 //SOC_EQ(tmp, "?", "Helio P95", SOC_MTK_, soc, 12)
239 SOC_EQ(tmp, "MT6795", "Helio X10", SOC_MTK_MT6795, soc, 28)
240 SOC_EQ(tmp, "MT6795T", "Helio X10 T", SOC_MTK_MT6795, soc, 28)
241 SOC_EQ(tmp, "MT6797", "Helio X20", SOC_MTK_MT6797, soc, 20)
242 SOC_EQ(tmp, "MT6797M", "Helio X20 M", SOC_MTK_MT6797, soc, 20)
243 SOC_EQ(tmp, "MT6797D", "Helio X23", SOC_MTK_MT6797, soc, 20)
244 SOC_EQ(tmp, "MT6797T", "Helio X25", SOC_MTK_MT6797T, soc, 20)
245 SOC_EQ(tmp, "MT6797X", "Helio X27", SOC_MTK_MT6797X, soc, 20)
246 SOC_EQ(tmp, "MT6799", "Helio X30", SOC_MTK_MT6799, soc, 10)
247 // MT XXXX //
248 SOC_EQ(tmp, "MT6515", "MT6515", SOC_MTK_MT6515, soc, 40)
249 SOC_EQ(tmp, "MT6516", "MT6516", SOC_MTK_MT6516, soc, 65)
250 SOC_EQ(tmp, "MT6517", "MT6517", SOC_MTK_MT6517, soc, 40)
251 SOC_EQ(tmp, "MT6572", "MT6572", SOC_MTK_MT6572, soc, 28)
252 SOC_EQ(tmp, "MT6572M", "MT6572M", SOC_MTK_MT6572M, soc, 28)
253 SOC_EQ(tmp, "MT6573", "MT6573", SOC_MTK_MT6573, soc, 65)
254 SOC_EQ(tmp, "MT6575", "MT6575", SOC_MTK_MT6575, soc, 40)
255 SOC_EQ(tmp, "MT6577", "MT6577", SOC_MTK_MT6577, soc, 40)
256 SOC_EQ(tmp, "MT6577T", "MT6577T", SOC_MTK_MT6577T, soc, 40)
257 SOC_EQ(tmp, "MT6580", "MT6580", SOC_MTK_MT6580, soc, 28)
258 SOC_EQ(tmp, "MT6582", "MT6582", SOC_MTK_MT6582, soc, 28)
259 SOC_EQ(tmp, "MT6582M", "MT6582M", SOC_MTK_MT6582M, soc, 28)
260 SOC_EQ(tmp, "MT6589", "MT6589", SOC_MTK_MT6589, soc, 28)
261 SOC_EQ(tmp, "MT6589T", "MT6589T", SOC_MTK_MT6589T, soc, 28)
262 SOC_EQ(tmp, "MT6592", "MT6592", SOC_MTK_MT6592, soc, 28)
263 SOC_EQ(tmp, "MT6595", "MT6595", SOC_MTK_MT6595, soc, 28)
264 SOC_EQ(tmp, "MT6732", "MT6732", SOC_MTK_MT6732, soc, 28)
265 SOC_EQ(tmp, "MT6735", "MT6735", SOC_MTK_MT6735, soc, 28)
266 SOC_EQ(tmp, "MT6735M", "MT6735M", SOC_MTK_MT6735M, soc, 28)
267 SOC_EQ(tmp, "MT6735P", "MT6735P", SOC_MTK_MT6735P, soc, 28)
268 SOC_EQ(tmp, "MT6737", "MT6737", SOC_MTK_MT6737, soc, 28)
269 SOC_EQ(tmp, "MT6737M", "MT6737M", SOC_MTK_MT6737M, soc, 28)
270 SOC_EQ(tmp, "MT6737T", "MT6737T", SOC_MTK_MT6737T, soc, 28)
271 SOC_EQ(tmp, "MT6739", "MT6739", SOC_MTK_MT6739, soc, 28)
272 SOC_EQ(tmp, "MT6750", "MT6750", SOC_MTK_MT6750, soc, 28)
273 SOC_EQ(tmp, "MT6750S", "MT6750S", SOC_MTK_MT6750S, soc, 28)
274 SOC_EQ(tmp, "MT6750T", "MT6750T", SOC_MTK_MT6750T, soc, 28)
275 SOC_EQ(tmp, "MT6752", "MT6752", SOC_MTK_MT6752, soc, 28)
276 SOC_EQ(tmp, "MT6753", "MT6753", SOC_MTK_MT6753, soc, 28)
277 SOC_EQ(tmp, "MT6850", "MT6850", SOC_MTK_MT6850, soc, 28)
278 SOC_EQ(tmp, "MT8121", "MT8121", SOC_MTK_MT8121, soc, 40)
279 SOC_EQ(tmp, "MT8125", "MT8125", SOC_MTK_MT8125, soc, 40)
280 SOC_EQ(tmp, "MT8127", "MT8127", SOC_MTK_MT8127, soc, 32)
281 SOC_EQ(tmp, "MT8135", "MT8135", SOC_MTK_MT8135, soc, 28)
282 SOC_EQ(tmp, "MT8163A", "MT8163A", SOC_MTK_MT8163A, soc, 28)
283 SOC_EQ(tmp, "MT8163B", "MT8163B", SOC_MTK_MT8163B, soc, 28)
284 SOC_EQ(tmp, "MT8167B", "MT8167B", SOC_MTK_MT8167B, soc, 28)
285 SOC_EQ(tmp, "MT8173", "MT8173", SOC_MTK_MT8173, soc, 28)
286 SOC_EQ(tmp, "MT8176", "MT8176", SOC_MTK_MT8176, soc, 28)
287 SOC_EQ(tmp, "MT8321", "MT8321", SOC_MTK_MT8321, soc, 28)
288 SOC_EQ(tmp, "MT8382", "MT8382", SOC_MTK_MT8382, soc, 28)
289 SOC_EQ(tmp, "MT8581", "MT8581", SOC_MTK_MT8581, soc, 28)
290 SOC_EQ(tmp, "MT8735", "MT8735", SOC_MTK_MT8735, soc, 28)
291 SOC_EQ(tmp, "MT8765B", "MT8765B", SOC_MTK_MT8765B, soc, 28)
292 SOC_EQ(tmp, "MT8783", "MT8783", SOC_MTK_MT8783, soc, 28)
293 SOC_END
294 }
295
296 /*
297 * APQ: Application Processor Qualcomm
298 * MSM: Mobile Station Modem
299 * In a APQXXXX or MSMXXXX, the second digit represents:
300 * *------------------*
301 * | Value | Meaning |
302 * *------------------*
303 * | 0 | No modem |
304 * | 2 | HPSA+ |
305 * | 6 | CDMA |
306 * | 9 | LTE |
307 * *------------------*
308 * Ref: https://www.tomshardware.com/reviews/snapdragon-801-performance-xperia-z2,3777-2.html
309 * TWO-HEADED SNAPDRAGON TAKES FLIGHT By Linley Gwennap
310 *
311 * If Qualcomm official website reports the SoC name without the initial two or three SKU name,
312 * we assume APQ if second number is 0, or MSM if second number is different than 0
313 *
314 * All SoC names here have been retrieved from official Qualcomm resources. However, Linux kernel
315 * and Android may report the SoC with slightly different. Therefore, this function needs some
316 * rework (e.g, debug with http://specdevice.com/unmoderated.php?lang=en)
317 */
match_qualcomm(char * soc_name,struct system_on_chip * soc)318 bool match_qualcomm(char* soc_name, struct system_on_chip* soc) {
319 char* tmp;
320 char* soc_name_upper = toupperstr(soc_name);
321
322 if((tmp = strstr(soc_name_upper, "MSM")) != NULL);
323 else if((tmp = strstr(soc_name_upper, "SDM")) != NULL);
324 else if((tmp = strstr(soc_name_upper, "APQ")) != NULL);
325 else if((tmp = strstr(soc_name_upper, "SM")) != NULL);
326 else if((tmp = strstr(soc_name_upper, "QM")) != NULL);
327 else if((tmp = strstr(soc_name_upper, "QSD")) != NULL);
328 else return false;
329
330 SOC_START
331 // Snapdragon S1 //
332 SOC_EQ(tmp, "QSD8650", "S1", SOC_SNAPD_QSD8650, soc, 65)
333 SOC_EQ(tmp, "QSD8250", "S1", SOC_SNAPD_QSD8250, soc, 65)
334 SOC_EQ(tmp, "MSM7627", "S1", SOC_SNAPD_MSM7627, soc, 65)
335 SOC_EQ(tmp, "MSM7227", "S1", SOC_SNAPD_MSM7227, soc, 65)
336 SOC_EQ(tmp, "MSM7627A", "S1", SOC_SNAPD_MSM7627A, soc, 45)
337 SOC_EQ(tmp, "MSM7227A", "S1", SOC_SNAPD_MSM7227A, soc, 45)
338 SOC_EQ(tmp, "MSM7625", "S1", SOC_SNAPD_MSM7625, soc, 65)
339 SOC_EQ(tmp, "MSM7225", "S1", SOC_SNAPD_MSM7225, soc, 65)
340 SOC_EQ(tmp, "MSM7625A", "S1", SOC_SNAPD_MSM7625A, soc, 45)
341 SOC_EQ(tmp, "MSM7225A", "S1", SOC_SNAPD_MSM7225A, soc, 45)
342 // Snapdragon S2 //
343 SOC_EQ(tmp, "MSM8655", "S2", SOC_SNAPD_MSM8655, soc, 45)
344 SOC_EQ(tmp, "MSM8255", "S2", SOC_SNAPD_MSM8255, soc, 45)
345 SOC_EQ(tmp, "APQ8055", "S2", SOC_SNAPD_APQ8055, soc, 45)
346 SOC_EQ(tmp, "MSM7630", "S2", SOC_SNAPD_MSM7630, soc, 45)
347 SOC_EQ(tmp, "MSM7230", "S2", SOC_SNAPD_MSM7230, soc, 45)
348 // Snapdragon S3 //
349 SOC_EQ(tmp, "MSM8660", "S3", SOC_SNAPD_MSM8660, soc, 45)
350 SOC_EQ(tmp, "MSM8260", "S3", SOC_SNAPD_MSM8260, soc, 45)
351 SOC_EQ(tmp, "APQ8060", "S3", SOC_SNAPD_APQ8060, soc, 45)
352 // Snapdragon S4 //
353 SOC_EQ(tmp, "MSM8225", "S4 Play", SOC_SNAPD_MSM8225, soc, 45)
354 SOC_EQ(tmp, "MSM8625", "S4 Play", SOC_SNAPD_MSM8625, soc, 45)
355 SOC_EQ(tmp, "APQ8060A", "S4 Plus", SOC_SNAPD_APQ8060A, soc, 28)
356 SOC_EQ(tmp, "MSM8960", "S4 Plus", SOC_SNAPD_MSM8960, soc, 28)
357 SOC_EQ(tmp, "MSM8260A", "S4 Plus", SOC_SNAPD_MSM8260A, soc, 28)
358 SOC_EQ(tmp, "MSM8627", "S4 Plus", SOC_SNAPD_MSM8627, soc, 28)
359 SOC_EQ(tmp, "MSM8227", "S4 Plus", SOC_SNAPD_MSM8227, soc, 28)
360 SOC_EQ(tmp, "APQ8064", "S4 Pro", SOC_SNAPD_APQ8064, soc, 28)
361 SOC_EQ(tmp, "MSM8960T", "S4 Pro", SOC_SNAPD_MSM8960T, soc, 28)
362 // Snapdragon 2XX //
363 SOC_EQ(tmp, "MSM8110", "200", SOC_SNAPD_MSM8110, soc, 28)
364 SOC_EQ(tmp, "MSM8210", "200", SOC_SNAPD_MSM8210, soc, 28)
365 SOC_EQ(tmp, "MSM8610", "200", SOC_SNAPD_MSM8610, soc, 28)
366 SOC_EQ(tmp, "MSM8112", "200", SOC_SNAPD_MSM8112, soc, 28)
367 SOC_EQ(tmp, "MSM8212", "200", SOC_SNAPD_MSM8212, soc, 28)
368 SOC_EQ(tmp, "MSM8612", "200", SOC_SNAPD_MSM8612, soc, 28)
369 SOC_EQ(tmp, "MSM8225Q", "200", SOC_SNAPD_MSM8225Q, soc, 45)
370 SOC_EQ(tmp, "MSM8625Q", "200", SOC_SNAPD_MSM8625Q, soc, 45)
371 SOC_EQ(tmp, "MSM8208", "208", SOC_SNAPD_MSM8208, soc, 28)
372 SOC_EQ(tmp, "MSM8905", "205", SOC_SNAPD_MSM8905, soc, 28)
373 SOC_EQ(tmp, "MSM8909", "210 / 212", SOC_SNAPD_MSM8909, soc, 28) // In the future, we can differentiate them using frequency
374 SOC_EQ(tmp, "QM215", "215", SOC_SNAPD_QM215, soc, 28)
375 // Snapdragon 4XX //
376 SOC_EQ(tmp, "APQ8028", "400", SOC_SNAPD_APQ8028, soc, 28)
377 SOC_EQ(tmp, "MSM8228", "400", SOC_SNAPD_MSM8228, soc, 28)
378 SOC_EQ(tmp, "MSM8628", "400", SOC_SNAPD_MSM8628, soc, 28)
379 SOC_EQ(tmp, "MSM8928", "400", SOC_SNAPD_MSM8928, soc, 28)
380 SOC_EQ(tmp, "MSM8926", "400", SOC_SNAPD_MSM8926, soc, 28)
381 SOC_EQ(tmp, "APQ8030AB", "400", SOC_SNAPD_APQ8030AB, soc, 28)
382 SOC_EQ(tmp, "MSM8226", "400", SOC_SNAPD_MSM8226, soc, 28)
383 SOC_EQ(tmp, "MSM8230AB", "400", SOC_SNAPD_MSM8230AB, soc, 28)
384 SOC_EQ(tmp, "MSM8626", "400", SOC_SNAPD_MSM8626, soc, 28)
385 SOC_EQ(tmp, "MSM8630", "400", SOC_SNAPD_MSM8630, soc, 28)
386 SOC_EQ(tmp, "MSM8630AB", "400", SOC_SNAPD_MSM8630AB, soc, 28)
387 SOC_EQ(tmp, "MSM8930", "400", SOC_SNAPD_MSM8930, soc, 28)
388 SOC_EQ(tmp, "MSM8930AB", "400", SOC_SNAPD_MSM8930AB, soc, 28)
389 SOC_EQ(tmp, "MSM8916", "410 / 412", SOC_SNAPD_MSM8916, soc, 28)
390 SOC_EQ(tmp, "MSM8929", "415", SOC_SNAPD_MSM8929, soc, 28)
391 SOC_EQ(tmp, "MSM8917", "425", SOC_SNAPD_MSM8917, soc, 28)
392 SOC_EQ(tmp, "MSM8920", "427", SOC_SNAPD_MSM8920, soc, 28)
393 SOC_EQ(tmp, "SDM429", "429", SOC_SNAPD_SDM429, soc, 12)
394 SOC_EQ(tmp, "MSM8937", "430", SOC_SNAPD_MSM8937, soc, 28)
395 SOC_EQ(tmp, "MSM8940", "435", SOC_SNAPD_MSM8940, soc, 28)
396 SOC_EQ(tmp, "SDM439", "439", SOC_SNAPD_SDM439, soc, 12)
397 SOC_EQ(tmp, "SDM450", "450", SOC_SNAPD_SDM450, soc, 14)
398 SOC_EQ(tmp, "SM4250-AA", "460", SOC_SNAPD_SM4250_AA, soc, 11)
399 // Snapdragon 6XX //
400 SOC_EQ(tmp, "APQ8064T", "600", SOC_SNAPD_APQ8064T, soc, 28)
401 SOC_EQ(tmp, "APQ8064M", "600", SOC_SNAPD_APQ8064M, soc, 28)
402 SOC_EQ(tmp, "MSM8936", "610", SOC_SNAPD_MSM8936, soc, 28)
403 SOC_EQ(tmp, "MSM8939", "615 / 616", SOC_SNAPD_MSM8939, soc, 28)
404 SOC_EQ(tmp, "MSM8952", "617", SOC_SNAPD_MSM8952, soc, 28)
405 SOC_EQ(tmp, "MSM8953", "625", SOC_SNAPD_MSM8953, soc, 14)
406 SOC_EQ(tmp, "MSM8953 PRO", "626", SOC_SNAPD_MSM8953_PRO, soc, 14)
407 SOC_EQ(tmp, "SDM630", "630", SOC_SNAPD_SDM630, soc, 14)
408 SOC_EQ(tmp, "SDM632", "632", SOC_SNAPD_SDM632, soc, 14)
409 SOC_EQ(tmp, "SDM636", "636", SOC_SNAPD_SDM636, soc, 14)
410 SOC_EQ(tmp, "MSM8956", "650", SOC_SNAPD_MSM8956, soc, 28)
411 SOC_EQ(tmp, "MSM8976", "652", SOC_SNAPD_MSM8976, soc, 28)
412 SOC_EQ(tmp, "MSM8976 PRO", "653", SOC_SNAPD_MSM8976_PRO, soc, 28)
413 SOC_EQ(tmp, "SDM660", "660", SOC_SNAPD_SDM660, soc, 14)
414 SOC_EQ(tmp, "SM6115", "662", SOC_SNAPD_SM6115, soc, 11)
415 SOC_EQ(tmp, "SM6125", "665", SOC_SNAPD_SM6125, soc, 11)
416 SOC_EQ(tmp, "SDM670", "670", SOC_SNAPD_SDM670, soc, 10)
417 SOC_EQ(tmp, "SM6150", "675", SOC_SNAPD_SM6150, soc, 11)
418 SOC_EQ(tmp, "SM6350", "690", SOC_SNAPD_SM6350, soc, 8)
419 // Snapdragon 7XX //
420 SOC_EQ(tmp, "SDM710", "710", SOC_SNAPD_SDM710, soc, 10)
421 SOC_EQ(tmp, "SDM712", "712", SOC_SNAPD_SDM712, soc, 10)
422 SOC_EQ(tmp, "SM7125", "720G", SOC_SNAPD_SM7125, soc, 8)
423 SOC_EQ(tmp, "SM7150-AA", "730", SOC_SNAPD_SM7150_AA, soc, 8)
424 SOC_EQ(tmp, "SM7150-AB", "730G", SOC_SNAPD_SM7150_AB, soc, 8)
425 SOC_EQ(tmp, "SM7150-AC", "732G", SOC_SNAPD_SM7150_AC, soc, 8)
426 SOC_EQ(tmp, "SM7225", "750G", SOC_SNAPD_SM7225, soc, 8)
427 SOC_EQ(tmp, "SM7250-AA", "765", SOC_SNAPD_SM7250_AA, soc, 7)
428 SOC_EQ(tmp, "SM7250-AB", "765G", SOC_SNAPD_SM7250_AB, soc, 7)
429 SOC_EQ(tmp, "SM7250-AC", "768G", SOC_SNAPD_SM7250_AC, soc, 7)
430 // Snapdragon 8XX //
431 SOC_EQ(tmp, "MSM8974AA", "800", SOC_SNAPD_MSM8974AA, soc, 28)
432 SOC_EQ(tmp, "MSM8974AB", "800", SOC_SNAPD_MSM8974AB, soc, 28)
433 SOC_EQ(tmp, "MSM8974AC", "800", SOC_SNAPD_MSM8974AC, soc, 28)
434 SOC_EQ(tmp, "MSM8974PRO-AB", "801", SOC_SNAPD_MSM8974PRO_AB, soc, 28)
435 SOC_EQ(tmp, "MSM8974PRO-AC", "801", SOC_SNAPD_MSM8974PRO_AC, soc, 28)
436 SOC_EQ(tmp, "APQ8084", "805", SOC_SNAPD_APQ8084, soc, 28)
437 SOC_EQ(tmp, "MSM8992", "808", SOC_SNAPD_MSM8992, soc, 20)
438 SOC_EQ(tmp, "MSM8994", "810", SOC_SNAPD_MSM8994, soc, 20)
439 SOC_EQ(tmp, "MSM8996", "820", SOC_SNAPD_MSM8996, soc, 14)
440 SOC_EQ(tmp, "MSM8996 PRO A", "821", SOC_SNAPD_MSM8996_PRO_A, soc, 14)
441 SOC_EQ(tmp, "MSM8998", "835", SOC_SNAPD_MSM8998, soc, 10)
442 SOC_EQ(tmp, "APQ8098", "835", SOC_SNAPD_APQ8098, soc, 10)
443 SOC_EQ(tmp, "SDM845", "845", SOC_SNAPD_SDM845, soc, 10)
444 SOC_EQ(tmp, "SDM850", "850", SOC_SNAPD_SDM850, soc, 10)
445 SOC_EQ(tmp, "SM8150", "855", SOC_SNAPD_SM8150, soc, 7)
446 SOC_EQ(tmp, "SM8150-AC", "855+", SOC_SNAPD_SM8150_AC, soc, 7)
447 SOC_EQ(tmp, "SM8250", "865", SOC_SNAPD_SM8250, soc, 7)
448 SOC_EQ(tmp, "SM8250-AB", "865+", SOC_SNAPD_SM8250_AB, soc, 7)
449 SOC_EQ(tmp, "SM8350", "888", SOC_SNAPD_SM8350, soc, 5)
450 SOC_END
451 }
452
match_special(char * soc_name,struct system_on_chip * soc)453 bool match_special(char* soc_name, struct system_on_chip* soc) {
454 char* tmp;
455
456 // Xiaomi hides Redmi Note 8/8T under "Qualcomm Technologies, Inc TRINKET"
457 if((tmp = strstr(soc_name, "TRINKET")) != NULL) {
458 fill_soc(soc, "665", SOC_SNAPD_SM6125, 11);
459 return true;
460 }
461
462 // Snapdragon 730 reported as "Qualcomm Technologies, Inc. SDMMAGPIE"
463 if((tmp = strstr(soc_name, "SDMMAGPIE")) != NULL) {
464 fill_soc(soc, "730", SOC_SNAPD_SM7150_AA, 8);
465 return true;
466 }
467
468 return false;
469 }
470
parse_soc_from_string(struct system_on_chip * soc)471 struct system_on_chip* parse_soc_from_string(struct system_on_chip* soc) {
472 char* raw_name = soc->raw_name;
473
474 if(match_special(raw_name, soc))
475 return soc;
476
477 if (match_qualcomm(raw_name, soc))
478 return soc;
479
480 if(match_mediatek(raw_name, soc))
481 return soc;
482
483 if(match_exynos(raw_name, soc))
484 return soc;
485
486 if(match_hisilicon(raw_name, soc))
487 return soc;
488
489 match_broadcom(raw_name, soc);
490
491 return soc;
492 }
493
494 #ifdef __ANDROID__
495 #include <sys/system_properties.h>
496
android_property_get(const char * key,char * value)497 static inline int android_property_get(const char* key, char* value) {
498 return __system_property_get(key, value);
499 }
500
guess_soc_from_android(struct system_on_chip * soc)501 struct system_on_chip* guess_soc_from_android(struct system_on_chip* soc) {
502 char tmp[100];
503 int property_len = 0;
504
505 property_len = android_property_get("ro.mediatek.platform", (char *) &tmp);
506 if(property_len > 0) {
507 soc->raw_name = emalloc(sizeof(char) * (property_len + 1));
508 strncpy(soc->raw_name, tmp, property_len + 1);
509 soc->raw_name[property_len] = '\0';
510 soc->soc_vendor = SOC_VENDOR_UNKNOWN;
511 return parse_soc_from_string(soc);
512 }
513
514 property_len = android_property_get("ro.product.board", (char *) &tmp);
515 if(property_len > 0) {
516 soc->raw_name = emalloc(sizeof(char) * (property_len + 1));
517 strncpy(soc->raw_name, tmp, property_len + 1);
518 soc->raw_name[property_len] = '\0';
519 soc->soc_vendor = SOC_VENDOR_UNKNOWN;
520 return parse_soc_from_string(soc);
521 }
522
523 return soc;
524 }
525 #endif
526
guess_soc_from_cpuinfo(struct system_on_chip * soc)527 struct system_on_chip* guess_soc_from_cpuinfo(struct system_on_chip* soc) {
528 char* tmp = get_hardware_from_cpuinfo();
529
530 if(tmp != NULL) {
531 soc->raw_name = tmp;
532 return parse_soc_from_string(soc);
533 }
534
535 return soc;
536 }
537
hex2int(char c)538 int hex2int(char c) {
539 if (c >= '0' && c <= '9')
540 return c - '0';
541 if (c >= 'A' && c <= 'F')
542 return c - 'A' + 10;
543 if (c >= 'a' && c <= 'f')
544 return c - 'a' + 10;
545
546 return -1;
547 }
548
549 // https://www.raspberrypi.org/documentation/hardware/raspberrypi/revision-codes/README.md
guess_soc_raspbery_pi(struct system_on_chip * soc)550 struct system_on_chip* guess_soc_raspbery_pi(struct system_on_chip* soc) {
551 char* revision = get_revision_from_cpuinfo();
552
553 if(revision == NULL) {
554 printWarn("[RPi] Couldn't find revision field in cpuinfo");
555 return soc;
556 }
557
558 if(strlen(revision) != 6) {
559 printWarn("[RPi] Found invalid RPi revision code: '%s'", revision);
560 return soc;
561 }
562
563 int arr_size = ARRAY_SIZE(soc_rpi_string);
564 int pppp = hex2int(revision[2]);
565 if(pppp == -1) {
566 printErr("[RPi] Found invalid RPi PPPP code: %s", revision[2]);
567 return soc;
568 }
569
570 if(pppp > arr_size) {
571 printErr("[RPi] Found invalid RPi PPPP code: %d while max is %d", pppp, arr_size);
572 return soc;
573 }
574
575 char* soc_raw_name = soc_rpi_string[pppp];
576 /*int soc_len = strlen(soc_raw_name);
577 soc->raw_name = emalloc(sizeof(char) * (soc_len + 1));
578 strncpy(soc->raw_name, soc_raw_name, soc_len + 1);*/
579
580 match_broadcom(soc_raw_name, soc);
581 return soc;
582 }
583
get_soc()584 struct system_on_chip* get_soc() {
585 struct system_on_chip* soc = emalloc(sizeof(struct system_on_chip));
586 soc->raw_name = NULL;
587 soc->soc_vendor = SOC_VENDOR_UNKNOWN;
588 soc->process = UNKNOWN;
589
590 #ifdef __linux__
591 bool isRPi = is_raspberry_pi();
592 if(isRPi) {
593 soc = guess_soc_raspbery_pi(soc);
594 if(soc->soc_vendor == SOC_VENDOR_UNKNOWN) {
595 printWarn("SoC detection failed using revision code");
596 }
597 else {
598 return soc;
599 }
600 }
601
602 soc = guess_soc_from_cpuinfo(soc);
603 if(soc->soc_vendor == SOC_VENDOR_UNKNOWN) {
604 if(soc->raw_name != NULL)
605 printWarn("SoC detection failed using /proc/cpuinfo: Found '%s' string", soc->raw_name);
606 else
607 printWarn("SoC detection failed using /proc/cpuinfo: No string found");
608 #ifdef __ANDROID__
609 soc = guess_soc_from_android(soc);
610 if(soc->raw_name == NULL)
611 printWarn("SoC detection failed using Android: No string found");
612 else if(soc->soc_vendor == SOC_VENDOR_UNKNOWN)
613 printWarn("SoC detection failed using Android: Found '%s' string", soc->raw_name);
614 #endif // ifdef __ANDROID__
615 }
616 #elif defined __APPLE__ || __MACH__
617 fill_soc(soc, "M1", SOC_APPLE_M1, 5);
618 #endif // ifdef __linux__
619
620 if(soc->raw_name == NULL) {
621 soc->raw_name = emalloc(sizeof(char) * (strlen(STRING_UNKNOWN)+1));
622 snprintf(soc->raw_name, strlen(STRING_UNKNOWN)+1, STRING_UNKNOWN);
623 }
624
625 return soc;
626 }
627
get_soc_name(struct system_on_chip * soc)628 char* get_soc_name(struct system_on_chip* soc) {
629 if(soc->soc_vendor == SOC_VENDOR_UNKNOWN)
630 return soc->raw_name;
631 return soc->soc_name;
632 }
633
get_soc_vendor(struct system_on_chip * soc)634 VENDOR get_soc_vendor(struct system_on_chip* soc) {
635 return soc->soc_vendor;
636 }
637
get_str_process(struct system_on_chip * soc)638 char* get_str_process(struct system_on_chip* soc) {
639 char* str;
640
641 if(soc->process == UNKNOWN) {
642 str = emalloc(sizeof(char) * (strlen(STRING_UNKNOWN)+1));
643 snprintf(str, strlen(STRING_UNKNOWN)+1, STRING_UNKNOWN);
644 }
645 else {
646 str = emalloc(sizeof(char) * 5);
647 memset(str, 0, sizeof(char) * 5);
648 snprintf(str, 5, "%dnm", soc->process);
649 }
650 return str;
651 }
652