TPM_NUM_MASK_ENTRIES = TPM_NUM_DEVICES / (8 * sizeof(int))
};
- /* PCI configuration addresses */
-enum tpm_pci_config_addr {
- PCI_GEN_PMCON_1 = 0xA0,
- PCI_GEN1_DEC = 0xE4,
- PCI_LPC_EN = 0xE6,
- PCI_GEN2_DEC = 0xEC
-};
-
-enum tpm_config {
- TPM_LOCK_REG = 0x0D,
- TPM_INTERUPT_REG = 0x0A,
- TPM_BASE_ADDR_LO = 0x08,
- TPM_BASE_ADDR_HI = 0x09,
- TPM_UNLOCK_VALUE = 0x55,
- TPM_LOCK_VALUE = 0xAA,
- TPM_DISABLE_INTERUPT_VALUE = 0x00
-};
-
-
static LIST_HEAD(tpm_chip_list);
static DEFINE_SPINLOCK(driver_lock);
static int dev_mask[TPM_NUM_MASK_ENTRIES];
up(&chip->buffer_mutex);
}
-/*
- * Initialize the LPC bus and enable the TPM ports
- */
-int tpm_lpc_bus_init(struct pci_dev *pci_dev, u16 base)
-{
- u32 lpcenable, tmp;
- int is_lpcm = 0;
-
- switch (pci_dev->vendor) {
- case PCI_VENDOR_ID_INTEL:
- switch (pci_dev->device) {
- case PCI_DEVICE_ID_INTEL_82801CA_12:
- case PCI_DEVICE_ID_INTEL_82801DB_12:
- is_lpcm = 1;
- break;
- }
- /* init ICH (enable LPC) */
- pci_read_config_dword(pci_dev, PCI_GEN1_DEC, &lpcenable);
- lpcenable |= 0x20000000;
- pci_write_config_dword(pci_dev, PCI_GEN1_DEC, lpcenable);
-
- if (is_lpcm) {
- pci_read_config_dword(pci_dev, PCI_GEN1_DEC,
- &lpcenable);
- if ((lpcenable & 0x20000000) == 0) {
- dev_err(&pci_dev->dev,
- "cannot enable LPC\n");
- return -ENODEV;
- }
- }
-
- /* initialize TPM registers */
- pci_read_config_dword(pci_dev, PCI_GEN2_DEC, &tmp);
-
- if (!is_lpcm)
- tmp = (tmp & 0xFFFF0000) | (base & 0xFFF0);
- else
- tmp =
- (tmp & 0xFFFF0000) | (base & 0xFFF0) |
- 0x00000001;
-
- pci_write_config_dword(pci_dev, PCI_GEN2_DEC, tmp);
-
- if (is_lpcm) {
- pci_read_config_dword(pci_dev, PCI_GEN_PMCON_1,
- &tmp);
- tmp |= 0x00000004; /* enable CLKRUN */
- pci_write_config_dword(pci_dev, PCI_GEN_PMCON_1,
- tmp);
- }
- break;
- case PCI_VENDOR_ID_AMD:
- /* nothing yet */
- break;
- }
-
- tpm_write_index(TPM_LOCK_REG, TPM_UNLOCK_VALUE);
- tpm_write_index(TPM_INTERUPT_REG, TPM_DISABLE_INTERUPT_VALUE);
- tpm_write_index(TPM_BASE_ADDR_LO, base);
- tpm_write_index(TPM_BASE_ADDR_HI, (base & 0xFF00) >> 8);
- tpm_write_index(TPM_LOCK_REG, TPM_LOCK_VALUE);
-
- return 0;
-}
-
-EXPORT_SYMBOL_GPL(tpm_lpc_bus_init);
-
/*
* Internal kernel interface to transmit TPM commands
*/
static ssize_t tpm_transmit(struct tpm_chip *chip, const char *buf,
size_t bufsiz)
{
- ssize_t len;
+ ssize_t rc;
u32 count;
- __be32 *native_size;
unsigned long stop;
- native_size = (__force __be32 *) (buf + 2);
- count = be32_to_cpu(*native_size);
+ count = be32_to_cpu(*((__be32 *) (buf + 2)));
if (count == 0)
return -ENODATA;
down(&chip->tpm_mutex);
- if ((len = chip->vendor->send(chip, (u8 *) buf, count)) < 0) {
+ if ((rc = chip->vendor->send(chip, (u8 *) buf, count)) < 0) {
dev_err(&chip->pci_dev->dev,
- "tpm_transmit: tpm_send: error %zd\n", len);
- return len;
+ "tpm_transmit: tpm_send: error %zd\n", rc);
+ goto out;
}
stop = jiffies + 2 * 60 * HZ;
chip->vendor->req_complete_val) {
goto out_recv;
}
- msleep(TPM_TIMEOUT); /* CHECK */
+
+ if ((status == chip->vendor->req_canceled)) {
+ dev_err(&chip->pci_dev->dev, "Operation Canceled\n");
+ rc = -ECANCELED;
+ goto out;
+ }
+
+ msleep(TPM_TIMEOUT); /* CHECK */
rmb();
} while (time_before(jiffies, stop));
chip->vendor->cancel(chip);
- dev_err(&chip->pci_dev->dev, "Time expired\n");
- up(&chip->tpm_mutex);
- return -EIO;
+ dev_err(&chip->pci_dev->dev, "Operation Timed out\n");
+ rc = -ETIME;
+ goto out;
out_recv:
- len = chip->vendor->recv(chip, (u8 *) buf, bufsiz);
- if (len < 0)
+ rc = chip->vendor->recv(chip, (u8 *) buf, bufsiz);
+ if (rc < 0)
dev_err(&chip->pci_dev->dev,
- "tpm_transmit: tpm_recv: error %zd\n", len);
+ "tpm_transmit: tpm_recv: error %zd\n", rc);
+out:
up(&chip->tpm_mutex);
- return len;
+ return rc;
}
#define TPM_DIGEST_SIZE 20
0, 0, 0, 0 /* PCR index */
};
-static ssize_t show_pcrs(struct device *dev, struct device_attribute *attr, char *buf)
+ssize_t tpm_show_pcrs(struct device *dev, struct device_attribute *attr,
+ char *buf)
{
u8 data[READ_PCR_RESULT_SIZE];
ssize_t len;
- int i, j, index, num_pcrs;
+ int i, j, num_pcrs;
+ __be32 index;
char *str = buf;
struct tpm_chip *chip =
memcpy(data, cap_pcr, sizeof(cap_pcr));
if ((len = tpm_transmit(chip, data, sizeof(data)))
- < CAP_PCR_RESULT_SIZE)
- return len;
+ < CAP_PCR_RESULT_SIZE) {
+ dev_dbg(&chip->pci_dev->dev, "A TPM error (%d) occurred "
+ "attempting to determine the number of PCRS\n",
+ be32_to_cpu(*((__be32 *) (data + 6))));
+ return 0;
+ }
- num_pcrs = be32_to_cpu(*((__force __be32 *) (data + 14)));
+ num_pcrs = be32_to_cpu(*((__be32 *) (data + 14)));
for (i = 0; i < num_pcrs; i++) {
memcpy(data, pcrread, sizeof(pcrread));
index = cpu_to_be32(i);
memcpy(data + 10, &index, 4);
if ((len = tpm_transmit(chip, data, sizeof(data)))
- < READ_PCR_RESULT_SIZE)
- return len;
+ < READ_PCR_RESULT_SIZE){
+ dev_dbg(&chip->pci_dev->dev, "A TPM error (%d) occurred"
+ " attempting to read PCR %d of %d\n",
+ be32_to_cpu(*((__be32 *) (data + 6))), i, num_pcrs);
+ goto out;
+ }
str += sprintf(str, "PCR-%02d: ", i);
for (j = 0; j < TPM_DIGEST_SIZE; j++)
str += sprintf(str, "%02X ", *(data + 10 + j));
str += sprintf(str, "\n");
}
+out:
return str - buf;
}
-
-static DEVICE_ATTR(pcrs, S_IRUGO, show_pcrs, NULL);
+EXPORT_SYMBOL_GPL(tpm_show_pcrs);
#define READ_PUBEK_RESULT_SIZE 314
static const u8 readpubek[] = {
0, 0, 0, 124, /* TPM_ORD_ReadPubek */
};
-static ssize_t show_pubek(struct device *dev, struct device_attribute *attr, char *buf)
+ssize_t tpm_show_pubek(struct device *dev, struct device_attribute *attr,
+ char *buf)
{
u8 *data;
ssize_t len;
- __be32 *native_val;
- int i;
+ int i, rc;
char *str = buf;
struct tpm_chip *chip =
if ((len = tpm_transmit(chip, data, READ_PUBEK_RESULT_SIZE)) <
READ_PUBEK_RESULT_SIZE) {
- rc = len;
+ dev_dbg(&chip->pci_dev->dev, "A TPM error (%d) occurred "
+ "attempting to read the PUBEK\n",
+ be32_to_cpu(*((__be32 *) (data + 6))));
+ rc = 0;
goto out;
}
ignore checksum 20 bytes
*/
- native_val = (__force __be32 *) (data + 34);
-
str +=
sprintf(str,
"Algorithm: %02X %02X %02X %02X\nEncscheme: %02X %02X\n"
data[15], data[16], data[17], data[22], data[23],
data[24], data[25], data[26], data[27], data[28],
data[29], data[30], data[31], data[32], data[33],
- be32_to_cpu(*native_val)
- );
+ be32_to_cpu(*((__be32 *) (data + 34))));
for (i = 0; i < 256; i++) {
- str += sprintf(str, "%02X ", data[i + 39]);
+ str += sprintf(str, "%02X ", data[i + 38]);
if ((i + 1) % 16 == 0)
str += sprintf(str, "\n");
}
return rc;
}
-static DEVICE_ATTR(pubek, S_IRUGO, show_pubek, NULL);
+EXPORT_SYMBOL_GPL(tpm_show_pubek);
#define CAP_VER_RESULT_SIZE 18
static const u8 cap_version[] = {
0, 0, 1, 3
};
-static ssize_t show_caps(struct device *dev, struct device_attribute *attr, char *buf)
+ssize_t tpm_show_caps(struct device *dev, struct device_attribute *attr,
+ char *buf)
{
u8 data[sizeof(cap_manufacturer)];
ssize_t len;
return len;
str += sprintf(str, "Manufacturer: 0x%x\n",
- be32_to_cpu(*(data + 14)));
+ be32_to_cpu(*((__be32 *) (data + 14))));
memcpy(data, cap_version, sizeof(cap_version));
return str - buf;
}
+EXPORT_SYMBOL_GPL(tpm_show_caps);
+
+ssize_t tpm_store_cancel(struct device *dev, struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct tpm_chip *chip = dev_get_drvdata(dev);
+ if (chip == NULL)
+ return 0;
+
+ chip->vendor->cancel(chip);
+ return count;
+}
+EXPORT_SYMBOL_GPL(tpm_store_cancel);
-static DEVICE_ATTR(caps, S_IRUGO, show_caps, NULL);
/*
* Device file system interface to the TPM
int tpm_release(struct inode *inode, struct file *file)
{
struct tpm_chip *chip = file->private_data;
-
- file->private_data = NULL;
spin_lock(&driver_lock);
+ file->private_data = NULL;
chip->num_opens--;
del_singleshot_timer_sync(&chip->user_read_timer);
atomic_set(&chip->data_pending, 0);
-
pci_dev_put(chip->pci_dev);
+ kfree(chip->data_buffer);
+ spin_unlock(&driver_lock);
return 0;
}
pci_set_drvdata(pci_dev, NULL);
misc_deregister(&chip->vendor->miscdev);
+ kfree(chip->vendor->miscdev.name);
- device_remove_file(&pci_dev->dev, &dev_attr_pubek);
- device_remove_file(&pci_dev->dev, &dev_attr_pcrs);
- device_remove_file(&pci_dev->dev, &dev_attr_caps);
+ sysfs_remove_group(&pci_dev->dev.kobj, chip->vendor->attr_group);
pci_disable_device(pci_dev);
if (chip == NULL)
return -ENODEV;
- spin_lock(&driver_lock);
- tpm_lpc_bus_init(pci_dev, chip->vendor->base);
- spin_unlock(&driver_lock);
-
return 0;
}
int tpm_register_hardware(struct pci_dev *pci_dev,
struct tpm_vendor_specific *entry)
{
- char devname[7];
+#define DEVNAME_SIZE 7
+
+ char *devname;
struct tpm_chip *chip;
int i, j;
else
chip->vendor->miscdev.minor = MISC_DYNAMIC_MINOR;
- snprintf(devname, sizeof(devname), "%s%d", "tpm", chip->dev_num);
+ devname = kmalloc(DEVNAME_SIZE, GFP_KERNEL);
+ scnprintf(devname, DEVNAME_SIZE, "%s%d", "tpm", chip->dev_num);
chip->vendor->miscdev.name = devname;
chip->vendor->miscdev.dev = &(pci_dev->dev);
return -ENODEV;
}
+ spin_lock(&driver_lock);
+
pci_set_drvdata(pci_dev, chip);
list_add(&chip->list, &tpm_chip_list);
- device_create_file(&pci_dev->dev, &dev_attr_pubek);
- device_create_file(&pci_dev->dev, &dev_attr_pcrs);
- device_create_file(&pci_dev->dev, &dev_attr_caps);
+ spin_unlock(&driver_lock);
+
+ sysfs_create_group(&pci_dev->dev.kobj, chip->vendor->attr_group);
return 0;
}