uboot/drivers/tpm/tpm.c
<<
>>
Prefs
   1/*
   2 * Copyright (C) 2011 Infineon Technologies
   3 *
   4 * Authors:
   5 * Peter Huewe <huewe.external@infineon.com>
   6 *
   7 * Description:
   8 * Device driver for TCG/TCPA TPM (trusted platform module).
   9 * Specifications at www.trustedcomputinggroup.org
  10 *
  11 * It is based on the Linux kernel driver tpm.c from Leendert van
  12 * Dorn, Dave Safford, Reiner Sailer, and Kyleen Hall.
  13 *
  14 * Version: 2.1.1
  15 *
  16 * See file CREDITS for list of people who contributed to this
  17 * project.
  18 *
  19 * This program is free software; you can redistribute it and/or
  20 * modify it under the terms of the GNU General Public License as
  21 * published by the Free Software Foundation, version 2 of the
  22 * License.
  23 *
  24 * This program is distributed in the hope that it will be useful,
  25 * but WITHOUT ANY WARRANTY; without even the implied warranty of
  26 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  27 * GNU General Public License for more details.
  28 *
  29 * You should have received a copy of the GNU General Public License
  30 * along with this program; if not, write to the Free Software
  31 * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
  32 * MA 02111-1307 USA
  33 */
  34
  35#include <config.h>
  36#include <common.h>
  37#include <linux/compiler.h>
  38#include <fdtdec.h>
  39#include <i2c.h>
  40#include <tpm.h>
  41#include <asm-generic/errno.h>
  42#include <linux/types.h>
  43#include <linux/unaligned/be_byteshift.h>
  44
  45#include "tpm_private.h"
  46
  47DECLARE_GLOBAL_DATA_PTR;
  48
  49/* TPM configuration */
  50struct tpm {
  51        int i2c_bus;
  52        int slave_addr;
  53        char inited;
  54        int old_bus;
  55} tpm;
  56
  57/* Global structure for tpm chip data */
  58static struct tpm_chip g_chip;
  59
  60enum tpm_duration {
  61        TPM_SHORT = 0,
  62        TPM_MEDIUM = 1,
  63        TPM_LONG = 2,
  64        TPM_UNDEFINED,
  65};
  66
  67/* Extended error numbers from linux (see errno.h) */
  68#define ECANCELED       125     /* Operation Canceled */
  69
  70/* Timer frequency. Corresponds to msec timer resolution*/
  71#define HZ              1000
  72
  73#define TPM_MAX_ORDINAL                 243
  74#define TPM_MAX_PROTECTED_ORDINAL       12
  75#define TPM_PROTECTED_ORDINAL_MASK      0xFF
  76
  77#define TPM_CMD_COUNT_BYTE      2
  78#define TPM_CMD_ORDINAL_BYTE    6
  79
  80/*
  81 * Array with one entry per ordinal defining the maximum amount
  82 * of time the chip could take to return the result.  The ordinal
  83 * designation of short, medium or long is defined in a table in
  84 * TCG Specification TPM Main Part 2 TPM Structures Section 17. The
  85 * values of the SHORT, MEDIUM, and LONG durations are retrieved
  86 * from the chip during initialization with a call to tpm_get_timeouts.
  87 */
  88static const u8 tpm_protected_ordinal_duration[TPM_MAX_PROTECTED_ORDINAL] = {
  89        TPM_UNDEFINED,          /* 0 */
  90        TPM_UNDEFINED,
  91        TPM_UNDEFINED,
  92        TPM_UNDEFINED,
  93        TPM_UNDEFINED,
  94        TPM_UNDEFINED,          /* 5 */
  95        TPM_UNDEFINED,
  96        TPM_UNDEFINED,
  97        TPM_UNDEFINED,
  98        TPM_UNDEFINED,
  99        TPM_SHORT,              /* 10 */
 100        TPM_SHORT,
 101};
 102
 103static const u8 tpm_ordinal_duration[TPM_MAX_ORDINAL] = {
 104        TPM_UNDEFINED,          /* 0 */
 105        TPM_UNDEFINED,
 106        TPM_UNDEFINED,
 107        TPM_UNDEFINED,
 108        TPM_UNDEFINED,
 109        TPM_UNDEFINED,          /* 5 */
 110        TPM_UNDEFINED,
 111        TPM_UNDEFINED,
 112        TPM_UNDEFINED,
 113        TPM_UNDEFINED,
 114        TPM_SHORT,              /* 10 */
 115        TPM_SHORT,
 116        TPM_MEDIUM,
 117        TPM_LONG,
 118        TPM_LONG,
 119        TPM_MEDIUM,             /* 15 */
 120        TPM_SHORT,
 121        TPM_SHORT,
 122        TPM_MEDIUM,
 123        TPM_LONG,
 124        TPM_SHORT,              /* 20 */
 125        TPM_SHORT,
 126        TPM_MEDIUM,
 127        TPM_MEDIUM,
 128        TPM_MEDIUM,
 129        TPM_SHORT,              /* 25 */
 130        TPM_SHORT,
 131        TPM_MEDIUM,
 132        TPM_SHORT,
 133        TPM_SHORT,
 134        TPM_MEDIUM,             /* 30 */
 135        TPM_LONG,
 136        TPM_MEDIUM,
 137        TPM_SHORT,
 138        TPM_SHORT,
 139        TPM_SHORT,              /* 35 */
 140        TPM_MEDIUM,
 141        TPM_MEDIUM,
 142        TPM_UNDEFINED,
 143        TPM_UNDEFINED,
 144        TPM_MEDIUM,             /* 40 */
 145        TPM_LONG,
 146        TPM_MEDIUM,
 147        TPM_SHORT,
 148        TPM_SHORT,
 149        TPM_SHORT,              /* 45 */
 150        TPM_SHORT,
 151        TPM_SHORT,
 152        TPM_SHORT,
 153        TPM_LONG,
 154        TPM_MEDIUM,             /* 50 */
 155        TPM_MEDIUM,
 156        TPM_UNDEFINED,
 157        TPM_UNDEFINED,
 158        TPM_UNDEFINED,
 159        TPM_UNDEFINED,          /* 55 */
 160        TPM_UNDEFINED,
 161        TPM_UNDEFINED,
 162        TPM_UNDEFINED,
 163        TPM_UNDEFINED,
 164        TPM_MEDIUM,             /* 60 */
 165        TPM_MEDIUM,
 166        TPM_MEDIUM,
 167        TPM_SHORT,
 168        TPM_SHORT,
 169        TPM_MEDIUM,             /* 65 */
 170        TPM_UNDEFINED,
 171        TPM_UNDEFINED,
 172        TPM_UNDEFINED,
 173        TPM_UNDEFINED,
 174        TPM_SHORT,              /* 70 */
 175        TPM_SHORT,
 176        TPM_UNDEFINED,
 177        TPM_UNDEFINED,
 178        TPM_UNDEFINED,
 179        TPM_UNDEFINED,          /* 75 */
 180        TPM_UNDEFINED,
 181        TPM_UNDEFINED,
 182        TPM_UNDEFINED,
 183        TPM_UNDEFINED,
 184        TPM_LONG,               /* 80 */
 185        TPM_UNDEFINED,
 186        TPM_MEDIUM,
 187        TPM_LONG,
 188        TPM_SHORT,
 189        TPM_UNDEFINED,          /* 85 */
 190        TPM_UNDEFINED,
 191        TPM_UNDEFINED,
 192        TPM_UNDEFINED,
 193        TPM_UNDEFINED,
 194        TPM_SHORT,              /* 90 */
 195        TPM_SHORT,
 196        TPM_SHORT,
 197        TPM_SHORT,
 198        TPM_SHORT,
 199        TPM_UNDEFINED,          /* 95 */
 200        TPM_UNDEFINED,
 201        TPM_UNDEFINED,
 202        TPM_UNDEFINED,
 203        TPM_UNDEFINED,
 204        TPM_MEDIUM,             /* 100 */
 205        TPM_SHORT,
 206        TPM_SHORT,
 207        TPM_UNDEFINED,
 208        TPM_UNDEFINED,
 209        TPM_UNDEFINED,          /* 105 */
 210        TPM_UNDEFINED,
 211        TPM_UNDEFINED,
 212        TPM_UNDEFINED,
 213        TPM_UNDEFINED,
 214        TPM_SHORT,              /* 110 */
 215        TPM_SHORT,
 216        TPM_SHORT,
 217        TPM_SHORT,
 218        TPM_SHORT,
 219        TPM_SHORT,              /* 115 */
 220        TPM_SHORT,
 221        TPM_SHORT,
 222        TPM_UNDEFINED,
 223        TPM_UNDEFINED,
 224        TPM_LONG,               /* 120 */
 225        TPM_LONG,
 226        TPM_MEDIUM,
 227        TPM_UNDEFINED,
 228        TPM_SHORT,
 229        TPM_SHORT,              /* 125 */
 230        TPM_SHORT,
 231        TPM_LONG,
 232        TPM_SHORT,
 233        TPM_SHORT,
 234        TPM_SHORT,              /* 130 */
 235        TPM_MEDIUM,
 236        TPM_UNDEFINED,
 237        TPM_SHORT,
 238        TPM_MEDIUM,
 239        TPM_UNDEFINED,          /* 135 */
 240        TPM_UNDEFINED,
 241        TPM_UNDEFINED,
 242        TPM_UNDEFINED,
 243        TPM_UNDEFINED,
 244        TPM_SHORT,              /* 140 */
 245        TPM_SHORT,
 246        TPM_UNDEFINED,
 247        TPM_UNDEFINED,
 248        TPM_UNDEFINED,
 249        TPM_UNDEFINED,          /* 145 */
 250        TPM_UNDEFINED,
 251        TPM_UNDEFINED,
 252        TPM_UNDEFINED,
 253        TPM_UNDEFINED,
 254        TPM_SHORT,              /* 150 */
 255        TPM_MEDIUM,
 256        TPM_MEDIUM,
 257        TPM_SHORT,
 258        TPM_SHORT,
 259        TPM_UNDEFINED,          /* 155 */
 260        TPM_UNDEFINED,
 261        TPM_UNDEFINED,
 262        TPM_UNDEFINED,
 263        TPM_UNDEFINED,
 264        TPM_SHORT,              /* 160 */
 265        TPM_SHORT,
 266        TPM_SHORT,
 267        TPM_SHORT,
 268        TPM_UNDEFINED,
 269        TPM_UNDEFINED,          /* 165 */
 270        TPM_UNDEFINED,
 271        TPM_UNDEFINED,
 272        TPM_UNDEFINED,
 273        TPM_UNDEFINED,
 274        TPM_LONG,               /* 170 */
 275        TPM_UNDEFINED,
 276        TPM_UNDEFINED,
 277        TPM_UNDEFINED,
 278        TPM_UNDEFINED,
 279        TPM_UNDEFINED,          /* 175 */
 280        TPM_UNDEFINED,
 281        TPM_UNDEFINED,
 282        TPM_UNDEFINED,
 283        TPM_UNDEFINED,
 284        TPM_MEDIUM,             /* 180 */
 285        TPM_SHORT,
 286        TPM_MEDIUM,
 287        TPM_MEDIUM,
 288        TPM_MEDIUM,
 289        TPM_MEDIUM,             /* 185 */
 290        TPM_SHORT,
 291        TPM_UNDEFINED,
 292        TPM_UNDEFINED,
 293        TPM_UNDEFINED,
 294        TPM_UNDEFINED,          /* 190 */
 295        TPM_UNDEFINED,
 296        TPM_UNDEFINED,
 297        TPM_UNDEFINED,
 298        TPM_UNDEFINED,
 299        TPM_UNDEFINED,          /* 195 */
 300        TPM_UNDEFINED,
 301        TPM_UNDEFINED,
 302        TPM_UNDEFINED,
 303        TPM_UNDEFINED,
 304        TPM_SHORT,              /* 200 */
 305        TPM_UNDEFINED,
 306        TPM_UNDEFINED,
 307        TPM_UNDEFINED,
 308        TPM_SHORT,
 309        TPM_SHORT,              /* 205 */
 310        TPM_SHORT,
 311        TPM_SHORT,
 312        TPM_SHORT,
 313        TPM_SHORT,
 314        TPM_MEDIUM,             /* 210 */
 315        TPM_UNDEFINED,
 316        TPM_MEDIUM,
 317        TPM_MEDIUM,
 318        TPM_MEDIUM,
 319        TPM_UNDEFINED,          /* 215 */
 320        TPM_MEDIUM,
 321        TPM_UNDEFINED,
 322        TPM_UNDEFINED,
 323        TPM_SHORT,
 324        TPM_SHORT,              /* 220 */
 325        TPM_SHORT,
 326        TPM_SHORT,
 327        TPM_SHORT,
 328        TPM_SHORT,
 329        TPM_UNDEFINED,          /* 225 */
 330        TPM_UNDEFINED,
 331        TPM_UNDEFINED,
 332        TPM_UNDEFINED,
 333        TPM_UNDEFINED,
 334        TPM_SHORT,              /* 230 */
 335        TPM_LONG,
 336        TPM_MEDIUM,
 337        TPM_UNDEFINED,
 338        TPM_UNDEFINED,
 339        TPM_UNDEFINED,          /* 235 */
 340        TPM_UNDEFINED,
 341        TPM_UNDEFINED,
 342        TPM_UNDEFINED,
 343        TPM_UNDEFINED,
 344        TPM_SHORT,              /* 240 */
 345        TPM_UNDEFINED,
 346        TPM_MEDIUM,
 347};
 348
 349/* Returns max number of milliseconds to wait */
 350static unsigned long tpm_calc_ordinal_duration(struct tpm_chip *chip,
 351                u32 ordinal)
 352{
 353        int duration_idx = TPM_UNDEFINED;
 354        int duration = 0;
 355
 356        if (ordinal < TPM_MAX_ORDINAL) {
 357                duration_idx = tpm_ordinal_duration[ordinal];
 358        } else if ((ordinal & TPM_PROTECTED_ORDINAL_MASK) <
 359                        TPM_MAX_PROTECTED_ORDINAL) {
 360                duration_idx = tpm_protected_ordinal_duration[
 361                                ordinal & TPM_PROTECTED_ORDINAL_MASK];
 362        }
 363
 364        if (duration_idx != TPM_UNDEFINED)
 365                duration = chip->vendor.duration[duration_idx];
 366
 367        if (duration <= 0)
 368                return 2 * 60 * HZ; /* Two minutes timeout */
 369        else
 370                return duration;
 371}
 372
 373static ssize_t tpm_transmit(const unsigned char *buf, size_t bufsiz)
 374{
 375        ssize_t rc;
 376        u32 count, ordinal;
 377        unsigned long start, stop;
 378
 379        struct tpm_chip *chip = &g_chip;
 380
 381        /* switch endianess: big->little */
 382        count = get_unaligned_be32(buf + TPM_CMD_COUNT_BYTE);
 383        ordinal = get_unaligned_be32(buf + TPM_CMD_ORDINAL_BYTE);
 384
 385        if (count == 0) {
 386                error("no data\n");
 387                return -ENODATA;
 388        }
 389        if (count > bufsiz) {
 390                error("invalid count value %x %zx\n", count, bufsiz);
 391                return -E2BIG;
 392        }
 393
 394        rc = chip->vendor.send(chip, (u8 *)buf, count);
 395        if (rc < 0) {
 396                error("tpm_transmit: tpm_send: error %zd\n", rc);
 397                goto out;
 398        }
 399
 400        if (chip->vendor.irq)
 401                goto out_recv;
 402
 403        start = get_timer(0);
 404        stop = tpm_calc_ordinal_duration(chip, ordinal);
 405        do {
 406                debug("waiting for status...\n");
 407                u8 status = chip->vendor.status(chip);
 408                if ((status & chip->vendor.req_complete_mask) ==
 409                    chip->vendor.req_complete_val) {
 410                        debug("...got it;\n");
 411                        goto out_recv;
 412                }
 413
 414                if (status == chip->vendor.req_canceled) {
 415                        error("Operation Canceled\n");
 416                        rc = -ECANCELED;
 417                        goto out;
 418                }
 419                udelay(TPM_TIMEOUT * 1000);
 420        } while (get_timer(start) < stop);
 421
 422        chip->vendor.cancel(chip);
 423        error("Operation Timed out\n");
 424        rc = -ETIME;
 425        goto out;
 426
 427out_recv:
 428        debug("out_recv: reading response...\n");
 429        rc = chip->vendor.recv(chip, (u8 *)buf, TPM_BUFSIZE);
 430        if (rc < 0)
 431                error("tpm_transmit: tpm_recv: error %zd\n", rc);
 432
 433out:
 434        return rc;
 435}
 436
 437static int tpm_open(uint32_t dev_addr)
 438{
 439        int rc;
 440        if (g_chip.is_open)
 441                return -EBUSY;
 442        rc = tpm_vendor_init(dev_addr);
 443        if (rc < 0)
 444                g_chip.is_open = 0;
 445        return rc;
 446}
 447
 448static void tpm_close(void)
 449{
 450        if (g_chip.is_open) {
 451                tpm_vendor_cleanup(&g_chip);
 452                g_chip.is_open = 0;
 453        }
 454}
 455
 456static int tpm_select(void)
 457{
 458        int ret;
 459
 460        tpm.old_bus = i2c_get_bus_num();
 461        if (tpm.old_bus != tpm.i2c_bus) {
 462                ret = i2c_set_bus_num(tpm.i2c_bus);
 463                if (ret) {
 464                        debug("%s: Fail to set i2c bus %d\n", __func__,
 465                              tpm.i2c_bus);
 466                        return -1;
 467                }
 468        }
 469        return 0;
 470}
 471
 472static int tpm_deselect(void)
 473{
 474        int ret;
 475
 476        if (tpm.old_bus != i2c_get_bus_num()) {
 477                ret = i2c_set_bus_num(tpm.old_bus);
 478                if (ret) {
 479                        debug("%s: Fail to restore i2c bus %d\n",
 480                              __func__, tpm.old_bus);
 481                        return -1;
 482                }
 483        }
 484        tpm.old_bus = -1;
 485        return 0;
 486}
 487
 488/**
 489 * Decode TPM configuration.
 490 *
 491 * @param dev   Returns a configuration of TPM device
 492 * @return 0 if ok, -1 on error
 493 */
 494static int tpm_decode_config(struct tpm *dev)
 495{
 496#ifdef CONFIG_OF_CONTROL
 497        const void *blob = gd->fdt_blob;
 498        int node, parent;
 499        int i2c_bus;
 500
 501        node = fdtdec_next_compatible(blob, 0, COMPAT_INFINEON_SLB9635_TPM);
 502        if (node < 0) {
 503                node = fdtdec_next_compatible(blob, 0,
 504                                COMPAT_INFINEON_SLB9645_TPM);
 505        }
 506        if (node < 0) {
 507                debug("%s: Node not found\n", __func__);
 508                return -1;
 509        }
 510        parent = fdt_parent_offset(blob, node);
 511        if (parent < 0) {
 512                debug("%s: Cannot find node parent\n", __func__);
 513                return -1;
 514        }
 515        i2c_bus = i2c_get_bus_num_fdt(parent);
 516        if (i2c_bus < 0)
 517                return -1;
 518        dev->i2c_bus = i2c_bus;
 519        dev->slave_addr = fdtdec_get_addr(blob, node, "reg");
 520#else
 521        dev->i2c_bus = CONFIG_TPM_TIS_I2C_BUS_NUMBER;
 522        dev->slave_addr = CONFIG_TPM_TIS_I2C_SLAVE_ADDRESS;
 523#endif
 524        return 0;
 525}
 526
 527struct tpm_chip *tpm_register_hardware(const struct tpm_vendor_specific *entry)
 528{
 529        struct tpm_chip *chip;
 530
 531        /* Driver specific per-device data */
 532        chip = &g_chip;
 533        memcpy(&chip->vendor, entry, sizeof(struct tpm_vendor_specific));
 534        chip->is_open = 1;
 535
 536        return chip;
 537}
 538
 539int tis_init(void)
 540{
 541        if (tpm.inited)
 542                return 0;
 543
 544        if (tpm_decode_config(&tpm))
 545                return -1;
 546
 547        if (tpm_select())
 548                return -1;
 549
 550        /*
 551         * Probe TPM twice; the first probing might fail because TPM is asleep,
 552         * and the probing can wake up TPM.
 553         */
 554        if (i2c_probe(tpm.slave_addr) && i2c_probe(tpm.slave_addr)) {
 555                debug("%s: fail to probe i2c addr 0x%x\n", __func__,
 556                      tpm.slave_addr);
 557                return -1;
 558        }
 559
 560        tpm_deselect();
 561
 562        tpm.inited = 1;
 563
 564        return 0;
 565}
 566
 567int tis_open(void)
 568{
 569        int rc;
 570
 571        if (!tpm.inited)
 572                return -1;
 573
 574        if (tpm_select())
 575                return -1;
 576
 577        rc = tpm_open(tpm.slave_addr);
 578
 579        tpm_deselect();
 580
 581        return rc;
 582}
 583
 584int tis_close(void)
 585{
 586        if (!tpm.inited)
 587                return -1;
 588
 589        if (tpm_select())
 590                return -1;
 591
 592        tpm_close();
 593
 594        tpm_deselect();
 595
 596        return 0;
 597}
 598
 599int tis_sendrecv(const uint8_t *sendbuf, size_t sbuf_size,
 600                uint8_t *recvbuf, size_t *rbuf_len)
 601{
 602        int len;
 603        uint8_t buf[4096];
 604
 605        if (!tpm.inited)
 606                return -1;
 607
 608        if (sizeof(buf) < sbuf_size)
 609                return -1;
 610
 611        memcpy(buf, sendbuf, sbuf_size);
 612
 613        if (tpm_select())
 614                return -1;
 615
 616        len = tpm_transmit(buf, sbuf_size);
 617
 618        tpm_deselect();
 619
 620        if (len < 10) {
 621                *rbuf_len = 0;
 622                return -1;
 623        }
 624
 625        memcpy(recvbuf, buf, len);
 626        *rbuf_len = len;
 627
 628        return 0;
 629}
 630