From 3b54f62d625934d4c4e3b2240395cbae3534ee16 Mon Sep 17 00:00:00 2001 From: Dr-Noob Date: Sat, 11 Mar 2023 12:00:30 +0100 Subject: [PATCH] [v1.03][ARM] Use SID to improve Allwinner SoC detection. Should help with #173 --- src/arm/soc.c | 89 ++++++++++++++++++++++++++++++++------------------ src/arm/socs.h | 1 + src/arm/udev.h | 2 ++ 3 files changed, 61 insertions(+), 31 deletions(-) diff --git a/src/arm/soc.c b/src/arm/soc.c index ee650a7..1838233 100644 --- a/src/arm/soc.c +++ b/src/arm/soc.c @@ -68,6 +68,50 @@ char* toupperstr(char* str) { return ret; } +uint32_t get_sid_from_nvmem(char* buf) { + uint32_t sid = 0; + sid += (unsigned char) buf[0] * 1<<0; + sid += (unsigned char) buf[1] * 1<<8; + sid += (unsigned char) buf[2] * 1<<16; + sid += (unsigned char) buf[3] * 1<<24; + return sid; +} + +// Security ID (SID) is an identifier that can help with SoC detection +// in Allwinner SoCs (https://linux-sunxi.org/SID_Register_Guide#Security_ID) +// SIDs list: +// - https://linux-sunxi.org/SID_Register_Guide#Currently_known_SID.27s +// - https://github.com/Dr-Noob/cpufetch/issues/173 +bool get_sunxisoc_from_sid(struct system_on_chip* soc, char* raw_name, uint32_t sid) { + typedef struct { + uint32_t sid; + struct system_on_chip soc; + } sidToSoC; + + sidToSoC socFromSid[] = { + // H2+ + {0x02c00042, {SOC_ALLWINNER_H2PLUS, SOC_VENDOR_ALLWINNER, 40, "H2+", raw_name} }, + // H3 + {0x02c00142, {SOC_ALLWINNER_H3, SOC_VENDOR_ALLWINNER, 40, "H3", raw_name} }, + {0x02c00181, {SOC_ALLWINNER_H3, SOC_VENDOR_ALLWINNER, 40, "H3", raw_name} }, + {0x02c00081, {SOC_ALLWINNER_H3, SOC_VENDOR_ALLWINNER, 40, "H3", raw_name} }, + // Unknown + {0x00000000, {UNKNOWN, SOC_VENDOR_UNKNOWN, -1, "", raw_name} } + }; + + int index = 0; + while(socFromSid[index].sid != 0x0) { + if(socFromSid[index].sid == sid) { + fill_soc(soc, socFromSid[index].soc.soc_name, socFromSid[index].soc.soc_model, socFromSid[index].soc.process); + return true; + } + index++; + } + + printErr("SID was found but it does not match any known SIDs: %08x\n", sid); + return false; +} + #define SOC_START if (false) {} #define SOC_EQ(raw_name, expected_name, soc_name, soc_model, soc, process) \ else if (match_soc(soc, raw_name, expected_name, soc_name, soc_model, process)) return true; @@ -468,39 +512,22 @@ bool match_allwinner(char* soc_name, struct system_on_chip* soc) { return false; SOC_START - // A series 32 bits + // SoCs we can detect just with with the name SOC_EQ(tmp, "sun4i", "A10", SOC_ALLWINNER_A10, soc, 55) - SOC_EQ(tmp, "sun5i", "A13", SOC_ALLWINNER_A13, soc, 55) - SOC_EQ(tmp, "sun5i", "A10s", SOC_ALLWINNER_A10S, soc, 55) - SOC_EQ(tmp, "sun7i", "A20", SOC_ALLWINNER_A20, soc, 40) - SOC_EQ(tmp, "sun8i", "A23", SOC_ALLWINNER_A23, soc, 40) SOC_EQ(tmp, "sun6i", "A31", SOC_ALLWINNER_A31, soc, 40) - SOC_EQ(tmp, "sun6i", "A31s", SOC_ALLWINNER_A31S, soc, 40) - SOC_EQ(tmp, "sun8i", "A33", SOC_ALLWINNER_A33, soc, 40) - SOC_EQ(tmp, "sun8i", "A40", SOC_ALLWINNER_A40, soc, 40) - SOC_EQ(tmp, "sun8i", "A50", SOC_ALLWINNER_A50, soc, 28) - SOC_EQ(tmp, "sun9i", "A80", SOC_ALLWINNER_A80, soc, 28) - SOC_EQ(tmp, "sun8i", "A83T", SOC_ALLWINNER_A83T, soc, 28) - - // H series 32 bits - SOC_EQ(tmp, "sun8i", "H2+", SOC_ALLWINNER_HZP, soc, 40) - SOC_EQ(tmp, "sun8i", "H3", SOC_ALLWINNER_H3, soc, 40) - SOC_EQ(tmp, "sun8i", "H8", SOC_ALLWINNER_H8, soc, 28) - - // H series 64 bits - SOC_EQ(tmp, "sun50i", "H5", SOC_ALLWINNER_H5, soc, 40) - SOC_EQ(tmp, "sun50i", "H6", SOC_ALLWINNER_H6, soc, 28) - SOC_EQ(tmp, "sun50i", "H616", SOC_ALLWINNER_H616, soc, 28) - - // R series 32 bits - SOC_EQ(tmp, "sun5i", "R8", SOC_ALLWINNER_R8, soc, 55) - SOC_EQ(tmp, "sun8i", "R16", SOC_ALLWINNER_R16, soc, 40) - SOC_EQ(tmp, "sun8i", "R40", SOC_ALLWINNER_R40, soc, 40) - SOC_EQ(tmp, "sun8i", "R58", SOC_ALLWINNER_R58, soc, 28) - - // R series 64 bits - SOC_EQ(tmp, "sun50i", "R329", SOC_ALLWINNER_R328, soc, 28) - SOC_END + SOC_EQ(tmp, "sun7i", "A20", SOC_ALLWINNER_A20, soc, 40) + else { + // sun5i/sun8i/sun9i/sun50i will fall here + // We need SID to actually distingish between the exact model + int filelen; + char* sid_nvmem = read_file(_PATH_SUNXI_NVMEM, &filelen); + if(sid_nvmem == NULL) { + printWarn("read_file: %s: %s\n", _PATH_SUNXI_NVMEM, strerror(errno)); + return false; + } + uint32_t sid = get_sid_from_nvmem(sid_nvmem); + return get_sunxisoc_from_sid(soc, soc_name, sid); + } } bool match_special(char* soc_name, struct system_on_chip* soc) { diff --git a/src/arm/socs.h b/src/arm/socs.h index 6a3c1b9..e73bf88 100644 --- a/src/arm/socs.h +++ b/src/arm/socs.h @@ -273,6 +273,7 @@ enum { SOC_ALLWINNER_A80, SOC_ALLWINNER_A83T, SOC_ALLWINNER_HZP, + SOC_ALLWINNER_H2PLUS, SOC_ALLWINNER_H3, SOC_ALLWINNER_H8, SOC_ALLWINNER_H5, diff --git a/src/arm/udev.h b/src/arm/udev.h index e6ef072..b379658 100644 --- a/src/arm/udev.h +++ b/src/arm/udev.h @@ -3,6 +3,8 @@ #include "../common/udev.h" +#define _PATH_SUNXI_NVMEM "/sys/bus/nvmem/devices/sunxi-sid0/nvmem" + #define UNKNOWN -1 int get_ncores_from_cpuinfo(void); uint32_t get_midr_from_cpuinfo(uint32_t core, bool* success);