1 // SPDX-License-Identifier: GPL-2.0-only 2 /* 3 * Implementation of get_cpuid(). 4 * 5 * Author: Nikita Shubin <n.shubin@yadro.com> 6 */ 7 8 #include <stdio.h> 9 #include <stdlib.h> 10 #include <api/fs/fs.h> 11 #include <errno.h> 12 #include "../../util/debug.h" 13 #include "../../util/header.h" 14 15 #define CPUINFO_MVEN "mvendorid" 16 #define CPUINFO_MARCH "marchid" 17 #define CPUINFO_MIMP "mimpid" 18 #define CPUINFO "/proc/cpuinfo" 19 20 static char *_get_field(const char *line) 21 { 22 char *line2, *nl; 23 24 line2 = strrchr(line, ' '); 25 if (!line2) 26 return NULL; 27 28 line2++; 29 nl = strrchr(line, '\n'); 30 if (!nl) 31 return NULL; 32 33 return strndup(line2, nl - line2); 34 } 35 36 static char *_get_cpuid(void) 37 { 38 char *line = NULL; 39 char *mvendorid = NULL; 40 char *marchid = NULL; 41 char *mimpid = NULL; 42 char *cpuid = NULL; 43 int read; 44 size_t line_sz; 45 FILE *cpuinfo; 46 47 cpuinfo = fopen(CPUINFO, "r"); 48 if (cpuinfo == NULL) 49 return cpuid; 50 51 while ((read = getline(&line, &line_sz, cpuinfo)) != -1) { 52 if (!strncmp(line, CPUINFO_MVEN, strlen(CPUINFO_MVEN))) { 53 mvendorid = _get_field(line); 54 if (!mvendorid) 55 goto free; 56 } else if (!strncmp(line, CPUINFO_MARCH, strlen(CPUINFO_MARCH))) { 57 marchid = _get_field(line); 58 if (!marchid) 59 goto free; 60 } else if (!strncmp(line, CPUINFO_MIMP, strlen(CPUINFO_MIMP))) { 61 mimpid = _get_field(line); 62 if (!mimpid) 63 goto free; 64 65 break; 66 } 67 } 68 69 if (!mvendorid || !marchid || !mimpid) 70 goto free; 71 72 if (asprintf(&cpuid, "%s-%s-%s", mvendorid, marchid, mimpid) < 0) 73 cpuid = NULL; 74 75 free: 76 fclose(cpuinfo); 77 free(mvendorid); 78 free(marchid); 79 free(mimpid); 80 81 return cpuid; 82 } 83 84 int get_cpuid(char *buffer, size_t sz, struct perf_cpu cpu __maybe_unused) 85 { 86 char *cpuid = _get_cpuid(); 87 int ret = 0; 88 89 if (sz < strlen(cpuid)) { 90 ret = -EINVAL; 91 goto free; 92 } 93 94 scnprintf(buffer, sz, "%s", cpuid); 95 free: 96 free(cpuid); 97 return ret; 98 } 99 100 char * 101 get_cpuid_str(struct perf_cpu cpu __maybe_unused) 102 { 103 return _get_cpuid(); 104 } 105