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