diff --git a/src/arm/api.h b/src/arm/api.h index 48b99ddc..469c84bd 100644 --- a/src/arm/api.h +++ b/src/arm/api.h @@ -28,6 +28,7 @@ enum cpuinfo_arm_chipset_vendor { cpuinfo_arm_chipset_vendor_spreadtrum, cpuinfo_arm_chipset_vendor_telechips, cpuinfo_arm_chipset_vendor_texas_instruments, + cpuinfo_arm_chipset_vendor_unisoc, cpuinfo_arm_chipset_vendor_wondermedia, cpuinfo_arm_chipset_vendor_max, }; @@ -62,6 +63,7 @@ enum cpuinfo_arm_chipset_series { cpuinfo_arm_chipset_series_spreadtrum_sc, cpuinfo_arm_chipset_series_telechips_tcc, cpuinfo_arm_chipset_series_texas_instruments_omap, + cpuinfo_arm_chipset_series_unisoc_t, cpuinfo_arm_chipset_series_wondermedia_wm, cpuinfo_arm_chipset_series_max, }; diff --git a/src/arm/linux/api.h b/src/arm/linux/api.h index 1c09f827..2e849431 100644 --- a/src/arm/linux/api.h +++ b/src/arm/linux/api.h @@ -314,7 +314,7 @@ CPUINFO_INTERNAL bool cpuinfo_arm_linux_parse_proc_cpuinfo( struct cpuinfo_arm_isa isa[restrict static 1]); #endif -#ifdef __ANDROID__ +#if defined(__ANDROID__) CPUINFO_INTERNAL struct cpuinfo_arm_chipset cpuinfo_arm_android_decode_chipset( const struct cpuinfo_android_properties properties[restrict static 1], diff --git a/src/arm/linux/chipset.c b/src/arm/linux/chipset.c index 180f1a69..e70e6ede 100644 --- a/src/arm/linux/chipset.c +++ b/src/arm/linux/chipset.c @@ -84,6 +84,7 @@ static enum cpuinfo_arm_chipset_vendor chipset_series_vendor[cpuinfo_arm_chipset [cpuinfo_arm_chipset_series_spreadtrum_sc] = cpuinfo_arm_chipset_vendor_spreadtrum, [cpuinfo_arm_chipset_series_telechips_tcc] = cpuinfo_arm_chipset_vendor_telechips, [cpuinfo_arm_chipset_series_texas_instruments_omap] = cpuinfo_arm_chipset_vendor_texas_instruments, + [cpuinfo_arm_chipset_series_unisoc_t] = cpuinfo_arm_chipset_vendor_unisoc, [cpuinfo_arm_chipset_series_wondermedia_wm] = cpuinfo_arm_chipset_vendor_wondermedia, }; @@ -865,6 +866,64 @@ static bool match_sc( return true; } +/** + * Tries to match, case-sentitively, /Unisoc T\d{3,4}/ signature for Unisoc T chipset. + * If match successful, extracts model information into \p chipset argument. + * + * @param start - start of the platform identifier (/proc/cpuinfo Hardware string, ro.product.board, + * ro.board.platform, or ro.chipname) to match. + * @param end - end of the platform identifier (/proc/cpuinfo Hardware string, ro.product.board, + * ro.board.platform, or ro.chipname) to match. + * @param[out] chipset - location where chipset information will be stored upon a successful match. + * + * @returns true if signature matched, false otherwise. + */ +static bool match_t( + const char* start, const char* end, + struct cpuinfo_arm_chipset chipset[restrict static 1]) +{ + /* Expect 11-12 symbols: "Unisoc T" (8 symbols) + 3-4-digit model number */ + const size_t length = end - start; + switch (length) { + case 11: + case 12: + break; + default: + return false; + } + + /* Check that string starts with "Unisoc T". The first four characters are loaded as 32-bit little endian word */ + const uint32_t expected_unis = load_u32le(start); + if (expected_unis != UINT32_C(0x73696E55) /* "sinU" = reverse("Unis") */) { + return false; + } + + /* The next four characters are loaded as 32-bit little endian word */ + const uint32_t expected_oc_t = load_u32le(start + 4); + if (expected_oc_t != UINT32_C(0x5420636F) /* "T co" = reverse("oc T") */) { + return false; + } + + /* Validate and parse 3-4 digit model number */ + uint32_t model = 0; + for (uint32_t i = 8; i < length; i++) { + const uint32_t digit = (uint32_t) (uint8_t) start[i] - '0'; + if (digit >= 10) { + /* Not really a digit */ + return false; + } + model = model * 10 + digit; + } + + *chipset = (struct cpuinfo_arm_chipset) { + .vendor = cpuinfo_arm_chipset_vendor_unisoc, + .series = cpuinfo_arm_chipset_series_unisoc_t, + .model = model, + }; + return true; +} + + /** * Tries to match /lc\d{4}[a-z]?$/ signature for Leadcore LC chipsets. * If match successful, extracts model information into \p chipset argument. @@ -879,7 +938,7 @@ static bool match_lc( const char* start, const char* end, struct cpuinfo_arm_chipset chipset[restrict static 1]) { - /* Expect at 6-7 symbols: "lc" (2 symbols) + 4-digit model number + optional 1-letter suffix */ + /* Expect 6-7 symbols: "lc" (2 symbols) + 4-digit model number + optional 1-letter suffix */ const size_t length = end - start; switch (length) { case 6: @@ -2342,6 +2401,16 @@ struct cpuinfo_arm_chipset cpuinfo_arm_linux_decode_chipset_from_proc_cpuinfo_ha cpuinfo_log_debug( "matched Spreadtrum SC signature in /proc/cpuinfo Hardware string \"%.*s\"", (int) hardware_length, hardware); + + return chipset; + } + + /* Check Unisoc T signature */ + if (match_t(hardware, hardware_end, &chipset)) { + cpuinfo_log_debug( + "matched Unisoc T signature in /proc/cpuinfo Hardware string \"%.*s\"", + (int) hardware_length, hardware); + return chipset; } @@ -3405,6 +3474,7 @@ static const char* chipset_vendor_string[cpuinfo_arm_chipset_vendor_max] = { [cpuinfo_arm_chipset_vendor_spreadtrum] = "Spreadtrum", [cpuinfo_arm_chipset_vendor_telechips] = "Telechips", [cpuinfo_arm_chipset_vendor_texas_instruments] = "Texas Instruments", + [cpuinfo_arm_chipset_vendor_unisoc] = "Unisoc", [cpuinfo_arm_chipset_vendor_wondermedia] = "WonderMedia", }; @@ -3439,6 +3509,7 @@ static const char* chipset_series_string[cpuinfo_arm_chipset_series_max] = { [cpuinfo_arm_chipset_series_spreadtrum_sc] = "SC", [cpuinfo_arm_chipset_series_telechips_tcc] = "TCC", [cpuinfo_arm_chipset_series_texas_instruments_omap] = "OMAP", + [cpuinfo_arm_chipset_series_unisoc_t] = "T", [cpuinfo_arm_chipset_series_wondermedia_wm] = "WM", }; @@ -3472,7 +3543,7 @@ void cpuinfo_arm_chipset_to_string( } } -#ifdef __ANDROID__ +#if defined(__ANDROID__) static inline struct cpuinfo_arm_chipset disambiguate_qualcomm_chipset( const struct cpuinfo_arm_chipset proc_cpuinfo_hardware_chipset[restrict static 1], const struct cpuinfo_arm_chipset ro_product_board_chipset[restrict static 1],