coreboot/util/msrtool/msrutils.c
<<
>>
Prefs
   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
  26static 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
  43static 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
  78void 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
 113int msr_eq(const struct msr a, const struct msr b) {
 114        return a.hi == b.hi && a.lo == b.lo;
 115}
 116
 117struct 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
 131struct 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
 145void msr_and(struct msr *a, const struct msr b) {
 146        a->hi &= b.hi;
 147        a->lo &= b.lo;
 148}
 149
 150const 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
 162uint32_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
 178void 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
 194int 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 */
 233uint8_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
 261void 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 */
 298uint8_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}
 338
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.