xref: /aosp_15_r20/external/coreboot/util/msrtool/msrutils.c (revision b9411a12aaaa7e1e6a6fb7c5e057f44ee179a49c)
1 /* SPDX-License-Identifier: GPL-2.0-only */
2 
3 #include <stdio.h>
4 #include <string.h>
5 #include <stdlib.h>
6 
7 #include "msrtool.h"
8 
print_bitdef(FILE * f,const struct msrbits * mb,const char * tail)9 static void print_bitdef(FILE *f, const struct msrbits *mb, const char *tail) {
10 	uint8_t endbit;
11 	if (!reserved && 0 == strcmp(mb->name, "RSVD"))
12 		return;
13 	if (1 == mb->size)
14 		fprintf(f, "# %5d", mb->start);
15 	else {
16 		endbit = mb->start - mb->size + 1;
17 		fprintf(f, "# %*d:%d", endbit < 10 ? 3 : 2, mb->start, endbit);
18 	}
19 	if (0 == strcmp(mb->name, "RSVD"))
20 		fprintf(f, " [%s]", mb->desc);
21 	else
22 		fprintf(f, " %s %s", mb->name, mb->desc);
23 	fprintf(f, "%s", tail);
24 }
25 
print_bitval(FILE * f,const struct msrbits * mb,const struct msr val)26 static void print_bitval(FILE *f, const struct msrbits *mb, const struct msr val) {
27 	uint8_t i;
28 	struct msr tmp, mask = MSR1(1);
29 	const struct msrbitvalues *mbv = mb->bitval;
30 	while (mbv->text && !msr_eq(mbv->value, val))
31 		mbv++;
32 	switch (mb->present) {
33 	case PRESENT_BIN:
34 		mask = msr_shl(mask, mb->size - 1);
35 		for (i = 0; i < mb->size; i++) {
36 			memcpy(&tmp, &val, sizeof(val));
37 			msr_and(&tmp, mask);
38 			fprintf(f, "%d", (tmp.hi || tmp.lo) ? 1 : 0);
39 			mask = msr_shr(mask, 1);
40 		}
41 		break;
42 	case PRESENT_DEC:
43 		fprintf(f, "%d", val.lo);
44 		break;
45 	case PRESENT_OCT:
46 		fprintf(f, "0%o", val.lo);
47 		break;
48 	case PRESENT_HEX:
49 		hexprint(f, val, mb->size);
50 		break;
51 	case PRESENT_HEXDEC:
52 		hexprint(f, val, mb->size);
53 		fprintf(f, " %d", val.lo);
54 		break;
55 	case PRESENT_STR:
56 		strprint(f, val, mb->size);
57 		break;
58 	}
59 	if (mbv->text)
60 		fprintf(f, ": %s", mbv->text);
61 	fprintf(f, "\n");
62 }
63 
hexprint(FILE * f,const struct msr val,const uint8_t bits)64 void hexprint(FILE *f, const struct msr val, const uint8_t bits) {
65 	if (bits <= 4)
66 		fprintf(f, "0x%01x", val.lo & 0xf);
67 	else if (bits <= 8)
68 		fprintf(f, "0x%02x", val.lo & 0xff);
69 	else if (bits <= 12)
70 		fprintf(f, "0x%03x", val.lo & 0xfff);
71 	else if (bits <= 16)
72 		fprintf(f, "0x%04x", val.lo & 0xffff);
73 	else if (bits <= 20)
74 		fprintf(f, "0x%05x", val.lo & 0xfffff);
75 	else if (bits <= 24)
76 		fprintf(f, "0x%06x", val.lo & 0xffffff);
77 	else if (bits <= 28)
78 		fprintf(f, "0x%07x", val.lo & 0xfffffff);
79 	else if (bits <= 32)
80 		fprintf(f, "0x%08x", val.lo);
81 	else if (bits <= 36)
82 		fprintf(f, "0x%01x%08x", val.hi & 0xf, val.lo);
83 	else if (bits <= 40)
84 		fprintf(f, "0x%02x%08x", val.hi & 0xff, val.lo);
85 	else if (bits <= 44)
86 		fprintf(f, "0x%03x%08x", val.hi & 0xfff, val.lo);
87 	else if (bits <= 48)
88 		fprintf(f, "0x%04x%08x", val.hi & 0xffff, val.lo);
89 	else if (bits <= 52)
90 		fprintf(f, "0x%05x%08x", val.hi & 0xfffff, val.lo);
91 	else if (bits <= 56)
92 		fprintf(f, "0x%06x%08x", val.hi & 0xffffff, val.lo);
93 	else if (bits <= 60)
94 		fprintf(f, "0x%07x%08x", val.hi & 0xfffffff, val.lo);
95 	else
96 		fprintf(f, "0x%08x%08x", val.hi, val.lo);
97 }
98 
strprint(FILE * f,const struct msr val,const uint8_t bits)99 void strprint(FILE *f, const struct msr val, const uint8_t bits) {
100 	if (bits > 56)
101 		fputc(val.hi, f);
102 	if (bits > 48)
103 		fputc(val.hi >> 8, f);
104 	if (bits > 40)
105 		fputc(val.hi >> 16, f);
106 	if (bits > 32)
107 		fputc(val.hi >> 24, f);
108 	if (bits > 24)
109 		fputc(val.lo, f);
110 	if (bits > 16)
111 		fputc(val.lo >> 8, f);
112 	if (bits > 8)
113 		fputc(val.lo >> 16, f);
114 	if (bits > 0)
115 		fputc(val.lo >> 24, f);
116 }
117 
msr_eq(const struct msr a,const struct msr b)118 int msr_eq(const struct msr a, const struct msr b) {
119 	return a.hi == b.hi && a.lo == b.lo;
120 }
121 
msr_shl(const struct msr a,const uint8_t bits)122 struct msr msr_shl(const struct msr a, const uint8_t bits) {
123 	struct msr ret;
124 
125 	ret.hi = bits < 32 ? a.hi << bits : 0;
126 	ret.lo = bits < 32 ? a.lo << bits : 0;
127 
128 	if (bits < 32)
129 		ret.hi |= bits ? a.lo >> (32 - bits) : 0;
130 	else
131 		ret.hi |= a.lo << (bits - 32);
132 
133 	return ret;
134 }
135 
msr_shr(const struct msr a,const uint8_t bits)136 struct msr msr_shr(const struct msr a, const uint8_t bits) {
137 	struct msr ret;
138 
139 	ret.hi = bits < 32 ? a.hi >> bits : 0;
140 	ret.lo = bits < 32 ? a.lo >> bits : 0;
141 
142 	if (bits < 32)
143 		ret.lo |= bits ? a.hi << (32 - bits) : 0;
144 	else
145 		ret.lo |= a.hi >> (bits - 32);
146 
147 	return ret;
148 }
149 
msr_and(struct msr * a,const struct msr b)150 void msr_and(struct msr *a, const struct msr b) {
151 	a->hi &= b.hi;
152 	a->lo &= b.lo;
153 }
154 
findmsrdef(const uint32_t addr)155 const struct msrdef *findmsrdef(const uint32_t addr) {
156 	uint8_t t;
157 	const struct msrdef *m;
158 	if (!targets)
159 		return NULL;
160 	for (t = 0; t < targets_found; t++)
161 		for (m = targets[t]->msrs; !MSR_ISEOT(*m); m++)
162 			if (addr == m->addr)
163 				return m;
164 	return NULL;
165 }
166 
msraddrbyname(const char * name)167 uint32_t msraddrbyname(const char *name) {
168 	uint8_t t;
169 	const uint32_t addr = strtoul(name, NULL, 16);
170 	const struct msrdef *m;
171 	if (!targets)
172 		return addr;
173 	for (t = 0; t < targets_found; t++)
174 		for (m = targets[t]->msrs; !MSR_ISEOT(*m); m++) {
175 			if (addr == m->addr)
176 				return m->addr;
177 			if (!strcasecmp(name, m->symbol))
178 				return m->addr;
179 		}
180 	return addr;
181 }
182 
dumpmsrdefs(const struct targetdef * t)183 void dumpmsrdefs(const struct targetdef *t) {
184 	const struct msrdef *m;
185 	const struct msrbits *mb;
186 	if (NULL == t)
187 		return;
188 	printf("# %s MSRs:\n", t->name);
189 	for (m = t->msrs; !MSR_ISEOT(*m); m++) {
190 		if (t->msrs != m)
191 			printf("\n");
192 		printf("# %s\n", m->symbol);
193 		for (mb = m->bits; mb->size; mb++)
194 			print_bitdef(stdout, mb, "\n");
195 		printf("0x%08x\n", m->addr);
196 	}
197 }
198 
dumpmsrdefsvals(FILE * f,const struct targetdef * t,const uint8_t cpu)199 int dumpmsrdefsvals(FILE *f, const struct targetdef *t, const uint8_t cpu) {
200 	struct msr val = MSR1(0);
201 	const struct msrdef *m;
202 	const struct msrbits *mb;
203 	if (NULL == t)
204 		return 1;
205 	fprintf(f, "# %s MSRs:\n", t->name);
206 	for (m = t->msrs; !MSR_ISEOT(*m); m++) {
207 		if (t->msrs != m)
208 			fprintf(f, "\n");
209 		if (!sys->rdmsr(cpu, m->addr, &val))
210 			return 1;
211 		fprintf(f, "# %s\n", m->symbol);
212 		for (mb = m->bits; mb->size; mb++)
213 			print_bitdef(f, mb, "\n");
214 		fprintf(f, "0x%08x 0x%08x%08x\n", m->addr, val.hi, val.lo);
215 	}
216 	return 0;
217 }
218 
219 /**
220  * Parse a hexadecimal string into an MSR value.
221  *
222  * Leading 0x or 0X is optional, the string is always parsed as hexadecimal.
223  * Any non-hexadecimal character except ' ' can separate the high 32 bits and
224  * the low 32 bits. If there is such a separator, high and low values do not
225  * need to be zero padded. If there is no separator, the last <=8 digits are
226  * the low 32 bits and any characters before them are the high 32 bits.
227  * When there is no separator and less than eight digits, the high 32 bits
228  * are set to 0.
229  * Parsing fails when there is a separator and it is followed by another
230  * non-hexadecimal character.
231  *
232  * @param str The string to parse. The string must be writable but will be
233  * restored before return.
234  * @param msr Pointer to the struct msr where the value will be stored.
235  * @param endptr If endptr is not NULL, *endptr will point to after the MSR.
236  * @return 1 on success, 0 on parse failure. msr is unchanged on failure.
237  */
str2msr(char * str,struct msr * msr,char ** endptr)238 uint8_t str2msr(char *str, struct msr *msr, char **endptr) {
239 	char c;
240 	size_t len, lo;
241 	if (0 == strncmp(str, "0x", 2) || 0 == strncmp(str, "0X", 2))
242 		str += 2;
243 	len = strspn(str, HEXCHARS);
244 	if (len <= 8 && (0 == str[len] || ' ' == str[len])) {
245 		msr->hi = 0;
246 		lo = 0;
247 	} else if (len <= 8) {
248 		lo = len + strcspn(str + len, HEXCHARS);
249 		if (0 == len && 0 == strspn(str + lo, HEXCHARS))
250 			return 0;
251 		c = str[len];
252 		str[len] = 0;
253 		msr->hi = strtoul(str, NULL, 16);
254 		str[len] = c;
255 	} else {
256 		lo = len - 8;
257 		c = str[lo];
258 		str[lo] = 0;
259 		msr->hi = strtoul(str, NULL, 16);
260 		str[lo] = c;
261 	}
262 	msr->lo = strtoul(str + lo, endptr, 16);
263 	return 1;
264 }
265 
decodemsr(const uint8_t cpu,const uint32_t addr,const struct msr val)266 void decodemsr(const uint8_t cpu, const uint32_t addr, const struct msr val) {
267 	struct msr bitval, mask;
268 	const struct msrdef *m = findmsrdef(addr);
269 	const struct msrbits *mb;
270 
271 	if (NULL != m)
272 		printf("# %s ", m->symbol);
273 	printf("0x%08x = 0x%08x%08x\n", addr, val.hi, val.lo);
274 	if (NULL == m) {
275 		fprintf(stderr, "Sorry - no definition exists for this MSR! Please add it and send a signed-off\n");
276 		fprintf(stderr, "patch to [email protected]. Thanks for your help!\n");
277 		return;
278 	}
279 
280 	for (mb = m->bits; mb->size; mb++) {
281 		if (!reserved && 0 == strcmp(mb->name, "RSVD"))
282 			continue;
283 		print_bitdef(stdout, mb, " = ");
284 		mask.hi = mask.lo = 0xffffffff;
285 		mask = msr_shr(mask, 64 - mb->size);
286 		bitval = msr_shr(val, mb->start - mb->size + 1);
287 		msr_and(&bitval, mask);
288 		print_bitval(stdout, mb, bitval);
289 	}
290 }
291 
292 /**
293  * Compare two MSR values and print any differences with field definitions and
294  * both old and new values decoded.
295  *
296  * @param f Output stream.
297  * @param addr MSR address.
298  * @param a Left value.
299  * @param b Right value.
300  * @return 1 when a and b differ, 0 when they are equal or only reserved bits
301  * differ and processing of reserved bits was not requested (with -r).
302  */
diff_msr(FILE * f,const uint32_t addr,const struct msr a,const struct msr b)303 uint8_t diff_msr(FILE *f, const uint32_t addr, const struct msr a, const struct msr b) {
304 	uint8_t ret = 0, first = 1;
305 	struct msr aval, bval, mask;
306 	const struct msrdef *m = findmsrdef(addr);
307 	const struct msrbits *mb;
308 
309 	if (a.hi == b.hi && a.lo == b.lo)
310 		return 0;
311 
312 	if (NULL == m) {
313 		fprintf(stderr, "MSR 0x%08x has no definition! Please add it and send a Signed-off-by patch\n", addr);
314 		fprintf(stderr, "to [email protected]. Thank you for your help!\n");
315 		return 1;
316 	}
317 
318 	for (mb = m->bits; mb->size; mb++) {
319 		if (!reserved && 0 == strcmp(mb->name, "RSVD"))
320 			continue;
321 		mask.hi = mask.lo = 0xffffffff;
322 		mask = msr_shr(mask, 64 - mb->size);
323 		aval = msr_shr(a, mb->start - mb->size + 1);
324 		bval = msr_shr(b, mb->start - mb->size + 1);
325 		msr_and(&aval, mask);
326 		msr_and(&bval, mask);
327 		if (msr_eq(aval, bval))
328 			continue;
329 		if (first) {
330 			fprintf(f, "# %s\n", m->symbol);
331 			fprintf(f, "-0x%08x 0x%08x%08x\n", addr, a.hi, a.lo);
332 			fprintf(f, "+0x%08x 0x%08x%08x\n", addr, b.hi, b.lo);
333 			first = 0;
334 			ret = 1;
335 		}
336 		print_bitdef(f, mb, "\n-");
337 		print_bitval(f, mb, aval);
338 		fprintf(f, "+");
339 		print_bitval(f, mb, bval);
340 	}
341 	return ret;
342 }
343