in src/arm/linux/chipset.c [2226:2438]
struct cpuinfo_arm_chipset cpuinfo_arm_linux_decode_chipset_from_proc_cpuinfo_hardware(
const char hardware[restrict static CPUINFO_HARDWARE_VALUE_MAX],
uint32_t cores, uint32_t max_cpu_freq_max, bool is_tegra)
{
struct cpuinfo_arm_chipset chipset;
const size_t hardware_length = strnlen(hardware, CPUINFO_HARDWARE_VALUE_MAX);
const char* hardware_end = hardware + hardware_length;
if (is_tegra) {
/*
* Nvidia Tegra-specific path: compare /proc/cpuinfo Hardware string to
* tabulated Hardware values for popular chipsets/devices with Tegra chipsets.
* This path is only used when ro.board.platform indicates a Tegra chipset
* (albeit does not indicate which exactly Tegra chipset).
*/
for (size_t i = 0; i < CPUINFO_COUNT_OF(tegra_hardware_map_entries); i++) {
if (strncmp(tegra_hardware_map_entries[i].platform, hardware, hardware_length) == 0 &&
tegra_hardware_map_entries[i].platform[hardware_length] == 0)
{
cpuinfo_log_debug(
"found /proc/cpuinfo Hardware string \"%.*s\" in Nvidia Tegra chipset table",
(int) hardware_length, hardware);
/* Create chipset name from entry */
return (struct cpuinfo_arm_chipset) {
.vendor = chipset_series_vendor[tegra_hardware_map_entries[i].series],
.series = (enum cpuinfo_arm_chipset_series) tegra_hardware_map_entries[i].series,
.model = tegra_hardware_map_entries[i].model,
.suffix = {
[0] = tegra_hardware_map_entries[i].suffix,
},
};
}
}
} else {
/* Generic path: consider all other vendors */
bool word_start = true;
for (const char* pos = hardware; pos != hardware_end; pos++) {
const char c = *pos;
switch (c) {
case ' ':
case '\t':
case ',':
word_start = true;
break;
default:
if (word_start && is_ascii_alphabetic(c)) {
/* Check Qualcomm MSM/APQ signature */
if (match_msm_apq(pos, hardware_end, &chipset)) {
cpuinfo_log_debug(
"matched Qualcomm MSM/APQ signature in /proc/cpuinfo Hardware string \"%.*s\"",
(int) hardware_length, hardware);
return chipset;
}
/* Check SDMxxx (Qualcomm Snapdragon) signature */
if (match_sdm(pos, hardware_end, &chipset)) {
cpuinfo_log_debug(
"matched Qualcomm SDM signature in /proc/cpuinfo Hardware string \"%.*s\"",
(int) hardware_length, hardware);
return chipset;
}
/* Check SMxxxx (Qualcomm Snapdragon) signature */
if (match_sm(pos, hardware_end, &chipset)) {
cpuinfo_log_debug(
"matched Qualcomm SM signature in /proc/cpuinfo Hardware string \"%.*s\"",
(int) hardware_length, hardware);
return chipset;
}
/* Check MediaTek MT signature */
if (match_mt(pos, hardware_end, true, &chipset)) {
cpuinfo_log_debug(
"matched MediaTek MT signature in /proc/cpuinfo Hardware string \"%.*s\"",
(int) hardware_length, hardware);
return chipset;
}
/* Check HiSilicon Kirin signature */
if (match_kirin(pos, hardware_end, &chipset)) {
cpuinfo_log_debug(
"matched HiSilicon Kirin signature in /proc/cpuinfo Hardware string \"%.*s\"",
(int) hardware_length, hardware);
return chipset;
}
/* Check Rockchip RK signature */
if (match_rk(pos, hardware_end, &chipset)) {
cpuinfo_log_debug(
"matched Rockchip RK signature in /proc/cpuinfo Hardware string \"%.*s\"",
(int) hardware_length, hardware);
return chipset;
}
}
word_start = false;
break;
}
}
/* Check Samsung Exynos signature */
if (match_samsung_exynos(hardware, hardware_end, &chipset)) {
cpuinfo_log_debug(
"matched Samsung Exynos signature in /proc/cpuinfo Hardware string \"%.*s\"",
(int) hardware_length, hardware);
return chipset;
}
/* Check universalXXXX (Samsung Exynos) signature */
if (match_universal(hardware, hardware_end, &chipset)) {
cpuinfo_log_debug(
"matched UNIVERSAL (Samsung Exynos) signature in /proc/cpuinfo Hardware string \"%.*s\"",
(int) hardware_length, hardware);
return chipset;
}
#if CPUINFO_ARCH_ARM
/* Match /SMDK(4410|4x12)$/ */
if (match_and_parse_smdk(hardware, hardware_end, cores, &chipset)) {
cpuinfo_log_debug(
"matched SMDK (Samsung Exynos) signature in /proc/cpuinfo Hardware string \"%.*s\"",
(int) hardware_length, hardware);
return chipset;
}
#endif
/* Check Spreadtrum SC signature */
if (match_sc(hardware, hardware_end, &chipset)) {
cpuinfo_log_debug(
"matched Spreadtrum SC signature in /proc/cpuinfo Hardware string \"%.*s\"",
(int) hardware_length, hardware);
return chipset;
}
#if CPUINFO_ARCH_ARM
/* Check Marvell PXA signature */
if (match_pxa(hardware, hardware_end, &chipset)) {
cpuinfo_log_debug(
"matched Marvell PXA signature in /proc/cpuinfo Hardware string \"%.*s\"",
(int) hardware_length, hardware);
return chipset;
}
#endif
/* Match /sun\d+i/ signature and map to Allwinner chipset name */
if (match_and_parse_sunxi(hardware, hardware_end, cores, &chipset)) {
cpuinfo_log_debug(
"matched sunxi (Allwinner Ax) signature in /proc/cpuinfo Hardware string \"%.*s\"",
(int) hardware_length, hardware);
return chipset;
}
/* Check Broadcom BCM signature */
if (match_bcm(hardware, hardware_end, &chipset)) {
cpuinfo_log_debug(
"matched Broadcom BCM signature in /proc/cpuinfo Hardware string \"%.*s\"",
(int) hardware_length, hardware);
return chipset;
}
#if CPUINFO_ARCH_ARM
/* Check Texas Instruments OMAP signature */
if (match_omap(hardware, hardware_end, &chipset)) {
cpuinfo_log_debug(
"matched Texas Instruments OMAP signature in /proc/cpuinfo Hardware string \"%.*s\"",
(int) hardware_length, hardware);
return chipset;
}
/* Check WonderMedia WMT signature and decode chipset from frequency and number of cores */
if (match_and_parse_wmt(hardware, hardware_end, cores, max_cpu_freq_max, &chipset)) {
cpuinfo_log_debug(
"matched WonderMedia WMT signature in /proc/cpuinfo Hardware string \"%.*s\"",
(int) hardware_length, hardware);
return chipset;
}
#endif
/* Check Telechips TCC signature */
if (match_tcc(hardware, hardware_end, &chipset)) {
cpuinfo_log_debug(
"matched Telechips TCC signature in /proc/cpuinfo Hardware string \"%.*s\"",
(int) hardware_length, hardware);
return chipset;
}
/* Compare to tabulated Hardware values for popular chipsets/devices which can't be otherwise detected */
for (size_t i = 0; i < CPUINFO_COUNT_OF(special_hardware_map_entries); i++) {
if (strncmp(special_hardware_map_entries[i].platform, hardware, hardware_length) == 0 &&
special_hardware_map_entries[i].platform[hardware_length] == 0)
{
cpuinfo_log_debug(
"found /proc/cpuinfo Hardware string \"%.*s\" in special chipset table",
(int) hardware_length, hardware);
/* Create chipset name from entry */
return (struct cpuinfo_arm_chipset) {
.vendor = chipset_series_vendor[special_hardware_map_entries[i].series],
.series = (enum cpuinfo_arm_chipset_series) special_hardware_map_entries[i].series,
.model = special_hardware_map_entries[i].model,
.suffix = {
[0] = special_hardware_map_entries[i].suffix,
},
};
}
}
}
return (struct cpuinfo_arm_chipset) {
.vendor = cpuinfo_arm_chipset_vendor_unknown,
.series = cpuinfo_arm_chipset_series_unknown,
};
}