/ util / msrtool / msrutils.c
msrutils.c
  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  
  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  
 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  
 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  
 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  
118  int msr_eq(const struct msr a, const struct msr b) {
119  	return a.hi == b.hi && a.lo == b.lo;
120  }
121  
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  
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  
150  void msr_and(struct msr *a, const struct msr b) {
151  	a->hi &= b.hi;
152  	a->lo &= b.lo;
153  }
154  
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  
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  
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  
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   */
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  
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 coreboot@coreboot.org. 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   */
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 coreboot@coreboot.org. 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  }