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
20static 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
36static 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
75free:
76	fclose(cpuinfo);
77	free(mvendorid);
78	free(marchid);
79	free(mimpid);
80
81	return cpuid;
82}
83
84int 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);
95free:
96	free(cpuid);
97	return ret;
98}
99
100char *
101get_cpuid_str(struct perf_pmu *pmu __maybe_unused)
102{
103	return _get_cpuid();
104}
105