#include "../common/global.h" #include "udev.h" #include "midr.h" #define _PATH_DEVICETREE_MODEL "/sys/firmware/devicetree/base/model" #define _PATH_CPUINFO "/proc/cpuinfo" //#define _PATH_CPUINFO "cpuinfo_debug" #define CPUINFO_CPU_IMPLEMENTER_STR "CPU implementer\t: " #define CPUINFO_CPU_ARCHITECTURE_STR "CPU architecture: " #define CPUINFO_CPU_VARIANT_STR "CPU variant\t: " #define CPUINFO_CPU_PART_STR "CPU part\t: " #define CPUINFO_CPU_REVISION_STR "CPU revision\t: " #define CPUINFO_HARDWARE_STR "Hardware\t: " #define CPUINFO_REVISION_STR "Revision\t: " #define CPUINFO_CPU_STRING "processor" long parse_cpuinfo_field(char* buf, char* field_str, int field_base) { char* tmp = strstr(buf, field_str); if(tmp == NULL) return -1; tmp += strlen(field_str); char* end; errno = 0; long ret = strtol(tmp, &end, field_base); if(errno != 0) { printWarn("strtol: %s:\n", strerror(errno)); return -1; } return ret; } // https://developer.arm.com/docs/ddi0595/h/aarch32-system-registers/midr // https://static.docs.arm.com/ddi0595/h/SysReg_xml_v86A-2020-06.pdf uint32_t get_midr_from_cpuinfo(uint32_t core, bool* success) { int filelen; char* buf; *success = true; if((buf = read_file(_PATH_CPUINFO, &filelen)) == NULL) { printWarn("read_file: %s: %s\n", _PATH_CPUINFO, strerror(errno)); *success = false; return 0; } char* tmp = strstr(buf, CPUINFO_CPU_STRING); uint32_t current_core = 0; while(core != current_core && tmp != NULL) { tmp++; current_core++; tmp = strstr(tmp, CPUINFO_CPU_STRING); } if(tmp == NULL) { *success = false; return 0; } uint32_t cpu_implementer; uint32_t cpu_architecture; uint32_t cpu_variant; uint32_t cpu_part; uint32_t cpu_revision; uint32_t midr = 0; long ret; if ((ret = parse_cpuinfo_field(tmp, CPUINFO_CPU_IMPLEMENTER_STR, 16)) < 0) { printBug("get_midr_from_cpuinfo: Failed parsing cpu_implementer\n"); *success = false; return 0; } cpu_implementer = (uint32_t) ret; if ((ret = parse_cpuinfo_field(tmp, CPUINFO_CPU_ARCHITECTURE_STR, 10)) < 0) { printBug("get_midr_from_cpuinfo: Failed parsing cpu_architecture\n"); *success = false; return 0; } cpu_architecture = (uint32_t) 0xF; // Why? if ((ret = parse_cpuinfo_field(tmp, CPUINFO_CPU_VARIANT_STR, 16)) < 0) { printBug("get_midr_from_cpuinfo: Failed parsing cpu_variant\n"); *success = false; return 0; } cpu_variant = (uint32_t) ret; if ((ret = parse_cpuinfo_field(tmp, CPUINFO_CPU_PART_STR, 16)) < 0) { printBug("get_midr_from_cpuinfo: Failed parsing cpu_part\n"); *success = false; return 0; } cpu_part = (uint32_t) ret; if ((ret = parse_cpuinfo_field(tmp, CPUINFO_CPU_REVISION_STR, 10)) < 0) { printBug("get_midr_from_cpuinfo: Failed parsing cpu_revision\n"); *success = false; return 0; } cpu_revision = (uint32_t) ret; midr = midr_set_implementer(midr, cpu_implementer); midr = midr_set_variant(midr, cpu_variant); midr = midr_set_architecture(midr, cpu_architecture); midr = midr_set_part(midr, cpu_part); midr = midr_set_revision(midr, cpu_revision); return midr; } char* get_field_from_cpuinfo(char* CPUINFO_FIELD) { int filelen; char* buf; if((buf = read_file(_PATH_CPUINFO, &filelen)) == NULL) { printWarn("read_file: %s: %s:\n", _PATH_CPUINFO, strerror(errno)); return NULL; } char* tmp1 = strstr(buf, CPUINFO_FIELD); if(tmp1 == NULL) return NULL; tmp1 = tmp1 + strlen(CPUINFO_FIELD); char* tmp2 = strstr(tmp1, "\n"); int strlen = (1 + (tmp2-tmp1)); char* hardware = emalloc(sizeof(char) * strlen); memset(hardware, 0, sizeof(char) * strlen); strncpy(hardware, tmp1, tmp2-tmp1); return hardware; } char* get_hardware_from_cpuinfo() { return get_field_from_cpuinfo(CPUINFO_HARDWARE_STR); } char* get_revision_from_cpuinfo() { return get_field_from_cpuinfo(CPUINFO_REVISION_STR); } bool is_raspberry_pi() { int filelen; char* buf; if((buf = read_file(_PATH_DEVICETREE_MODEL, &filelen)) == NULL) { return false; } char* tmp; if((tmp = strstr(buf, "Raspberry Pi")) == NULL) { return false; } return true; }