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
_get_field(const char * line)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
_get_cpuid(void)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 unsigned long 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
get_cpuid(char * buffer,size_t sz)84 int get_cpuid(char *buffer, size_t sz)
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 *
get_cpuid_str(struct perf_pmu * pmu __maybe_unused)101 get_cpuid_str(struct perf_pmu *pmu __maybe_unused)
102 {
103 return _get_cpuid();
104 }
105