Files
xen/tools/firmware/rombios/32bit/tcgbios/tpm_drivers.c
T
Ian Campbell 443701ef0c Replace FSF street address with canonical URL
As recommended in http://www.gnu.org/licenses/gpl-howto.en.html.

This is the result of:
$ git grep -El Mass\|Temple\|Franklin | xargs ./fsf.pl

Where fsf.pl is:
    #!/usr/bin/perl -w -pi.bak -0777
    my $repl = 'If not, see <http://www.gnu.org/licenses/>.';
    my $br = qr/(?:\s*\n\s*(?:[\*\#]|\/\/|\.\\" )?\s*|\s+)/;

    my $inwt = qr/[Ii]f${br}not,${br}write${br}(?:to${br})?the${br}Free${br}Software${br}Foundation,(?:${br}Inc\.,)?/;

    my $mass = qr/675${br}Mass${br}Ave,?${br}Cambridge,?${br}MA${br}02139,?${br}USA,?\.?/;
    my $franklin = qr/51${br}Franklin${br}St(?:reet)?(?:,${br}| - )Fifth${br}Floor,?${br}Boston,?${br}MA,?${br}02110-1301,?${br}USA,?\.?/;
    my $temple = qr/59${br}Temple${br}Place(?:,${br}| - )Suite${br}330,?${br}Boston,?${br}MA,?${br}021110?-1307,?${br}USA,?\.?/;

    s|$inwt$br$mass|$repl|m;
    s|$inwt$br$franklin|$repl|m;
    s|$inwt$br$temple|$repl|m;

The only remaining mentions of these addresses are in COPYING files which I
haven't touched.

Some of the changed files are imports from elsewhere, however
filtering them out is tricky, I think it is tolerable to have these
files be modified here and then perhaps reverted on the next sync,
since it's only 1-2 lines and obvious what is going on.

Signed-off-by: Ian Campbell <ian.campbell@citrix.com>
2015-07-29 11:14:07 +01:00

196 lines
4.9 KiB
C

/*
* Implementation of the TCG BIOS extension according to the specification
* described in
* https://www.trustedcomputinggroup.org/specs/PCClient/TCG_PCClientImplementationforBIOS_1-20_1-00.pdf
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; If not, see <http://www.gnu.org/licenses/>.
*
* Copyright (C) IBM Corporation, 2006
*
* Author: Stefan Berger <stefanb@us.ibm.com>
*/
#include "rombios_compat.h"
#include "util.h"
#include "tpm_drivers.h"
#include "tcgbios.h"
#define STS_VALID (1 << 7) /* 0x80 */
#define STS_COMMAND_READY (1 << 6) /* 0x40 */
#define STS_TPM_GO (1 << 5) /* 0x20 */
#define STS_DATA_AVAILABLE (1 << 4) /* 0x10 */
#define STS_EXPECT (1 << 3) /* 0x08 */
#define STS_RESPONSE_RETRY (1 << 1) /* 0x02 */
#define ACCESS_TPM_REG_VALID_STS (1 << 7) /* 0x80 */
#define ACCESS_ACTIVE_LOCALITY (1 << 5) /* 0x20 */
#define ACCESS_BEEN_SEIZED (1 << 4) /* 0x10 */
#define ACCESS_SEIZE (1 << 3) /* 0x08 */
#define ACCESS_PENDING_REQUEST (1 << 2) /* 0x04 */
#define ACCESS_REQUEST_USE (1 << 1) /* 0x02 */
#define ACCESS_TPM_ESTABLISHMENT (1 << 0) /* 0x01 */
static uint32_t tis_wait_sts(uint8_t *addr, uint32_t time,
uint8_t mask, uint8_t expect)
{
uint32_t rc = 0;
while (time > 0) {
uint8_t sts = mmio_readb(&addr[TPM_STS]);
if ((sts & mask) == expect) {
rc = 1;
break;
}
mssleep(1);
time--;
}
return rc;
}
static uint32_t tis_activate(uint32_t baseaddr)
{
uint32_t rc = 1;
uint8_t *tis_addr = (uint8_t*)baseaddr;
uint8_t acc;
/* request access to locality */
tis_addr[TPM_ACCESS] = ACCESS_REQUEST_USE;
acc = mmio_readb(&tis_addr[TPM_ACCESS]);
if ((acc & ACCESS_ACTIVE_LOCALITY) != 0) {
tis_addr[TPM_STS] = STS_COMMAND_READY;
rc = tis_wait_sts(tis_addr, 100,
STS_COMMAND_READY, STS_COMMAND_READY);
}
return rc;
}
static uint32_t tis_ready(uint32_t baseaddr)
{
uint32_t rc = 0;
uint8_t *tis_addr = (uint8_t*)baseaddr;
tis_addr[TPM_STS] = STS_COMMAND_READY;
rc = tis_wait_sts(tis_addr, 100, STS_COMMAND_READY, STS_COMMAND_READY);
return rc;
}
static uint32_t tis_senddata(uint32_t baseaddr, unsigned char *data, uint32_t len)
{
uint32_t rc = 0;
uint8_t *tis_addr = (uint8_t*)baseaddr;
uint32_t offset = 0;
uint32_t end = 0;
do {
uint16_t burst = 0;
uint32_t ctr = 0;
while (burst == 0 && ctr < 2000) {
burst = mmio_readw((uint16_t *)&tis_addr[TPM_STS+1]);
if (burst == 0) {
mssleep(1);
ctr++;
}
}
if (burst == 0) {
rc = TCG_RESPONSE_TIMEOUT;
break;
}
while (1) {
tis_addr[TPM_DATA_FIFO] = data[offset];
offset++;
burst--;
if (burst == 0 || offset == len) {
break;
}
}
if (offset == len) {
end = 1;
}
} while (end == 0);
return rc;
}
static uint32_t tis_readresp(uint32_t baseaddr, unsigned char *buffer, uint32_t len)
{
uint32_t rc = 0;
uint32_t offset = 0;
uint8_t *tis_addr = (uint8_t*)baseaddr;
uint32_t sts;
while (offset < len) {
buffer[offset] = mmio_readb(&tis_addr[TPM_DATA_FIFO]);
offset++;
sts = mmio_readb(&tis_addr[TPM_STS]);
/* data left ? */
if ((sts & STS_DATA_AVAILABLE) == 0) {
break;
}
}
return rc;
}
static uint32_t tis_waitdatavalid(uint32_t baseaddr)
{
uint8_t *tis_addr = (uint8_t*)baseaddr;
uint32_t rc = 0;
if (tis_wait_sts(tis_addr, 1000, STS_VALID, STS_VALID) == 0) {
rc = TCG_NO_RESPONSE;
}
return rc;
}
static uint32_t tis_waitrespready(uint32_t baseaddr, uint32_t timeout)
{
uint32_t rc = 0;
uint8_t *tis_addr = (uint8_t*)baseaddr;
tis_addr[TPM_STS] = STS_TPM_GO;
if (tis_wait_sts(tis_addr, timeout,
STS_DATA_AVAILABLE, STS_DATA_AVAILABLE) == 0) {
rc = TCG_NO_RESPONSE;
}
return rc;
}
/* if device is not there, return '0', '1' otherwise */
static uint32_t tis_probe(uint32_t baseaddr)
{
uint32_t rc = 0;
uint8_t *tis_addr = (uint8_t*)baseaddr;
uint32_t didvid = mmio_readl((uint32_t *)&tis_addr[TPM_DID_VID]);
if ((didvid != 0) && (didvid != 0xffffffff)) {
rc = 1;
}
return rc;
}
struct tpm_driver tpm_drivers[TPM_NUM_DRIVERS] = {
{
.baseaddr = TPM_TIS_BASE_ADDRESS,
.activate = tis_activate,
.ready = tis_ready,
.senddata = tis_senddata,
.readresp = tis_readresp,
.waitdatavalid = tis_waitdatavalid,
.waitrespready = tis_waitrespready,
.probe = tis_probe,
},
};