in src/arm/linux/chipset.c [3618:3769]
struct cpuinfo_arm_chipset cpuinfo_arm_android_decode_chipset(
const struct cpuinfo_android_properties properties[restrict static 1],
uint32_t cores,
uint32_t max_cpu_freq_max)
{
struct cpuinfo_arm_chipset chipset = {
.vendor = cpuinfo_arm_chipset_vendor_unknown,
.series = cpuinfo_arm_chipset_series_unknown,
};
const bool tegra_platform = is_tegra(
properties->ro_board_platform,
properties->ro_board_platform + strnlen(properties->ro_board_platform, CPUINFO_BUILD_PROP_VALUE_MAX));
struct cpuinfo_arm_chipset chipsets[cpuinfo_android_chipset_property_max] = {
[cpuinfo_android_chipset_property_proc_cpuinfo_hardware] =
cpuinfo_arm_linux_decode_chipset_from_proc_cpuinfo_hardware(
properties->proc_cpuinfo_hardware, cores, max_cpu_freq_max, tegra_platform),
[cpuinfo_android_chipset_property_ro_product_board] =
cpuinfo_arm_android_decode_chipset_from_ro_product_board(
properties->ro_product_board, cores, max_cpu_freq_max),
[cpuinfo_android_chipset_property_ro_board_platform] =
cpuinfo_arm_android_decode_chipset_from_ro_board_platform(
properties->ro_board_platform, cores, max_cpu_freq_max),
[cpuinfo_android_chipset_property_ro_mediatek_platform] =
cpuinfo_arm_android_decode_chipset_from_ro_mediatek_platform(properties->ro_mediatek_platform),
[cpuinfo_android_chipset_property_ro_arch] =
cpuinfo_arm_android_decode_chipset_from_ro_arch(properties->ro_arch),
[cpuinfo_android_chipset_property_ro_chipname] =
cpuinfo_arm_android_decode_chipset_from_ro_chipname(properties->ro_chipname),
[cpuinfo_android_chipset_property_ro_hardware_chipname] =
cpuinfo_arm_android_decode_chipset_from_ro_chipname(properties->ro_hardware_chipname),
};
enum cpuinfo_arm_chipset_vendor vendor = cpuinfo_arm_chipset_vendor_unknown;
for (size_t i = 0; i < cpuinfo_android_chipset_property_max; i++) {
const enum cpuinfo_arm_chipset_vendor decoded_vendor = chipsets[i].vendor;
if (decoded_vendor != cpuinfo_arm_chipset_vendor_unknown) {
if (vendor == cpuinfo_arm_chipset_vendor_unknown) {
vendor = decoded_vendor;
} else if (vendor != decoded_vendor) {
/* Parsing different system properties produces different chipset vendors. This situation is rare. */
cpuinfo_log_error(
"chipset detection failed: different chipset vendors reported in different system properties");
goto finish;
}
}
}
if (vendor == cpuinfo_arm_chipset_vendor_unknown) {
cpuinfo_log_warning(
"chipset detection failed: none of the system properties matched known signatures");
goto finish;
}
/* Fix common bugs in reported chipsets */
for (size_t i = 0; i < cpuinfo_android_chipset_property_max; i++) {
cpuinfo_arm_fixup_chipset(&chipsets[i], cores, max_cpu_freq_max);
}
/*
* Propagate suffixes: consider all pairs of chipsets, if both chipsets in the pair are from the same series,
* and one's suffix is a prefix of another's chipset suffix, use the longest suffix.
*/
for (size_t i = 0; i < cpuinfo_android_chipset_property_max; i++) {
const size_t chipset_i_suffix_length = strnlen(chipsets[i].suffix, CPUINFO_ARM_CHIPSET_SUFFIX_MAX);
for (size_t j = 0; j < i; j++) {
if (chipsets[i].series == chipsets[j].series) {
const size_t chipset_j_suffix_length = strnlen(chipsets[j].suffix, CPUINFO_ARM_CHIPSET_SUFFIX_MAX);
if (chipset_i_suffix_length != chipset_j_suffix_length) {
const size_t common_prefix_length = (chipset_i_suffix_length < chipset_j_suffix_length) ?
chipset_i_suffix_length : chipset_j_suffix_length;
if (common_prefix_length == 0 ||
memcmp(chipsets[i].suffix, chipsets[j].suffix, common_prefix_length) == 0)
{
if (chipset_i_suffix_length > chipset_j_suffix_length) {
memcpy(chipsets[j].suffix, chipsets[i].suffix, chipset_i_suffix_length);
} else {
memcpy(chipsets[i].suffix, chipsets[j].suffix, chipset_j_suffix_length);
}
}
}
}
}
}
for (size_t i = 0; i < cpuinfo_android_chipset_property_max; i++) {
if (chipsets[i].series != cpuinfo_arm_chipset_series_unknown) {
if (chipset.series == cpuinfo_arm_chipset_series_unknown) {
chipset = chipsets[i];
} else if (chipsets[i].series != chipset.series || chipsets[i].model != chipset.model ||
strncmp(chipsets[i].suffix, chipset.suffix, CPUINFO_ARM_CHIPSET_SUFFIX_MAX) != 0)
{
cpuinfo_log_info(
"different chipsets reported in different system properties; "
"vendor-specific disambiguation heuristic would be used");
switch (vendor) {
case cpuinfo_arm_chipset_vendor_qualcomm:
return disambiguate_qualcomm_chipset(
&chipsets[cpuinfo_android_chipset_property_proc_cpuinfo_hardware],
&chipsets[cpuinfo_android_chipset_property_ro_product_board],
&chipsets[cpuinfo_android_chipset_property_ro_board_platform],
&chipsets[cpuinfo_android_chipset_property_ro_chipname],
&chipsets[cpuinfo_android_chipset_property_ro_hardware_chipname]);
case cpuinfo_arm_chipset_vendor_mediatek:
return disambiguate_mediatek_chipset(
&chipsets[cpuinfo_android_chipset_property_proc_cpuinfo_hardware],
&chipsets[cpuinfo_android_chipset_property_ro_product_board],
&chipsets[cpuinfo_android_chipset_property_ro_board_platform],
&chipsets[cpuinfo_android_chipset_property_ro_mediatek_platform],
&chipsets[cpuinfo_android_chipset_property_ro_chipname]);
case cpuinfo_arm_chipset_vendor_hisilicon:
return disambiguate_hisilicon_chipset(
&chipsets[cpuinfo_android_chipset_property_proc_cpuinfo_hardware],
&chipsets[cpuinfo_android_chipset_property_ro_product_board],
&chipsets[cpuinfo_android_chipset_property_ro_board_platform]);
case cpuinfo_arm_chipset_vendor_amlogic:
return disambiguate_amlogic_chipset(
&chipsets[cpuinfo_android_chipset_property_proc_cpuinfo_hardware],
&chipsets[cpuinfo_android_chipset_property_ro_board_platform]);
case cpuinfo_arm_chipset_vendor_marvell:
return disambiguate_marvell_chipset(
&chipsets[cpuinfo_android_chipset_property_proc_cpuinfo_hardware],
&chipsets[cpuinfo_android_chipset_property_ro_product_board],
&chipsets[cpuinfo_android_chipset_property_ro_chipname]);
case cpuinfo_arm_chipset_vendor_rockchip:
return disambiguate_rockchip_chipset(
&chipsets[cpuinfo_android_chipset_property_proc_cpuinfo_hardware],
&chipsets[cpuinfo_android_chipset_property_ro_product_board],
&chipsets[cpuinfo_android_chipset_property_ro_board_platform]);
case cpuinfo_arm_chipset_vendor_spreadtrum:
return disambiguate_spreadtrum_chipset(
&chipsets[cpuinfo_android_chipset_property_proc_cpuinfo_hardware],
&chipsets[cpuinfo_android_chipset_property_ro_product_board],
&chipsets[cpuinfo_android_chipset_property_ro_board_platform],
&chipsets[cpuinfo_android_chipset_property_ro_chipname]);
default:
cpuinfo_log_error(
"chipset detection failed: "
"could not disambiguate different chipsets reported in different system properties");
/* chipset variable contains valid, but inconsistent chipset information, overwrite it */
chipset = (struct cpuinfo_arm_chipset) {
.vendor = cpuinfo_arm_chipset_vendor_unknown,
.series = cpuinfo_arm_chipset_series_unknown,
};
goto finish;
}
}
}
}
finish:
return chipset;
}