/*设备文件系统调用tpm_open()打开TPM设备实例*/
int tpm_open(struct inode *inode, struct file *file)
{
int minor = iminor(inode);
struct tpm_chip *chip = NULL, *pos;
rcu_read_lock();
list_for_each_entry_rcu(pos, &tpm_chip_list, list) {
if (pos->vendor.miscdev.minor == minor) {
chip = pos;
get_device(chip->dev);
break;
}
}
rcu_read_unlock();
if (!chip)
return -ENODEV;
/*检测chip结构体中is_open字段的值,确定此TPM设备只能打开一次*/
if (test_and_set_bit(0, &chip->is_open)) {
dev_dbg(chip->dev, "Another process owns this TPM\n");
put_device(chip->dev);
return -EBUSY;
}
/*分配TPM驱动程序的数据缓存区空间*/
chip->data_buffer = kzalloc(TPM_BUFSIZE, GFP_KERNEL);
if (chip->data_buffer == NULL) {
/*设置tpm_chip结构体is_open字段值为0*/
clear_bit(0, &chip->is_open);
put_device(chip->dev);
return -ENOMEM;
}
atomic_set(&chip->data_pending, 0);
/将TPM设备实例放在文件结构的私有数据成员上*/
file->private_data = chip;
return 0;
}
/*设备文件系统调用tpm_release()释放tpm设备实例*/
int tpm_release(struct inode *inode, struct file *file)
{
struct tpm_chip *chip = file->private_data;
del_singleshot_timer_sync(&chip->user_read_timer);
flush_work_sync(&chip->work);
/*设置文件结构的私有数据成员值为NULL*/
file->private_data = NULL;
/*原子设置,使读写缓存区的互斥锁为0*/
atomic_set(&chip->data_pending, 0);
/*释放读写缓存区*/
kfree(chip->data_buffer);
/*设置TPM设备打开次数为0,tpm_chip结构体中的is_open字段表示TPM设备打开的次数*/
clear_bit(0, &chip->is_open);
/*将设备引用计算器的值减1*/
put_device(chip->dev);
return 0;
}
/*向TPM设备中发送数据,此函数通过TPM设备驱动程序库TDDL(TPM Device Driver Library)调用*/
ssize_t tpm_write(struct file *file, const char __user *buf,
size_t size, loff_t *off)
{
struct tpm_chip *chip = file->private_data;
size_t in_size = size, out_size;
/*当有TPM设备执行读操作时,不能有写操作*/
while (atomic_read(&chip->data_pending) != 0)
/*有读操作时,让写操作睡眠*/
msleep(TPM_TIMEOUT);
mutex_lock(&chip->buffer_mutex);
if (in_size > TPM_BUFSIZE)
in_size = TPM_BUFSIZE;
/*将TPM命令从用户空间拷贝到设备驱动程序数据的缓存区中,即chip->data_buffer中*/
if (copy_from_user
(chip->data_buffer, (void __user *) buf, in_size)) {
mutex_unlock(&chip->buffer_mutex);
return -EFAULT;
}
/*发送命令给对应的TPM设备执行,等待TPM设备执行完成,返回执行结果,发送命令和返回结果都是原子操作*/
out_size = tpm_transmit(chip, chip->data_buffer, TPM_BUFSIZE);
atomic_set(&chip->data_pending, out_size);
mutex_unlock(&chip->buffer_mutex);
/*设定读的定时,读操作需在此时间内读取命令执行结果*/
mod_timer(&chip->user_read_timer, jiffies + (60 * HZ));
return in_size;
}
/*从驱动程序数据缓存区读取命令执行的结果返回给用户,此函数也是由TPM设备驱动程序库TDDL调用*/
ssize_t tpm_read(struct file *file, char __user *buf,
size_t size, loff_t *off)
{
struct tpm_chip *chip = file->private_data;
ssize_t ret_size;
int rc;
del_singleshot_timer_sync(&chip->user_read_timer);
flush_work_sync(&chip->work);
/*原子操作,读取data_pending字段大小*/
ret_size = atomic_read(&chip->data_pending);
/*原子操作,设子data_pending字段中的值为0*/
atomic_set(&chip->data_pending, 0);
if (ret_size > 0) {
ssize_t orig_ret_size = ret_size;
if (size < ret_size)
ret_size = size;
mutex_lock(&chip->buffer_mutex);
/*将执行结果data_buffer中的值返回到用户空间的buf中*/
rc = copy_to_user(buf, chip->data_buffer, ret_size);
/*用0初始化data_buffer中的数据*/
memset(chip->data_buffer, 0, orig_ret_size);
if (rc)
ret_size = -EFAULT;
mutex_unlock(&chip->buffer_mutex);
}
/*返回命令执行结果的字节数*/
return ret_size;
}
/*注销tpm_chip结构体实例,释放其占用空间*/
void tpm_remove_hardware(struct device *dev)
{
struct tpm_chip *chip = dev_get_drvdata(dev);
if (chip == NULL) {
dev_err(dev, "No device data found\n");
return;
}
spin_lock(&driver_lock);
list_del_rcu(&chip->list);
spin_unlock(&driver_lock);
synchronize_rcu();
misc_deregister(&chip->vendor.miscdev);
sysfs_remove_group(&dev->kobj, chip->vendor.attr_group);
tpm_bios_log_teardown(chip->bios_dir);
/*device结构对象引用计数器减1*/
put_device(chip->dev);
}
/*保存TPM设备状态,以备需要时恢复*/
int tpm_pm_suspend(struct device *dev, pm_message_t pm_state)
{
struct tpm_chip *chip = dev_get_drvdata(dev);
struct tpm_cmd_t cmd;
int rc;
u8 dummy_hash[TPM_DIGEST_SIZE] = { 0 };
if (chip == NULL)
return -ENODEV;
if (tpm_suspend_pcr) {
cmd.header.in = pcrextend_header;
cmd.params.pcrextend_in.pcr_idx = cpu_to_be32(tpm_suspend_pcr);
memcpy(cmd.params.pcrextend_in.hash, dummy_hash,
TPM_DIGEST_SIZE);
rc = transmit_cmd(chip, &cmd, EXTEND_PCR_RESULT_SIZE,
"extending dummy pcr before suspend");
}
cmd.header.in = savestate_header;
rc = transmit_cmd(chip, &cmd, SAVESTATE_RESULT_SIZE,
"sending savestate before suspend");
return rc;
}
/*恢复TPM状态*/
int tpm_pm_resume(struct device *dev)
{
struct tpm_chip *chip = dev_get_drvdata(dev);
if (chip == NULL)
return -ENODEV;
return 0;
}
/*tpm_vendor_specific结构体中提供的释放TPM结构实例的操作*/
void tpm_dev_vendor_release(struct tpm_chip *chip)
{
if (chip->vendor.release)
chip->vendor.release(chip->dev);
clear_bit(chip->dev_num, dev_mask);
kfree(chip->vendor.miscdev.name);
}
/*一次注销所有与TPM设备驱动有关的实例对象并释放其占有的空间*/
void tpm_dev_release(struct device *dev)
{
struct tpm_chip *chip = dev_get_drvdata(dev);
tpm_dev_vendor_release(chip);
chip->release(dev);
kfree(chip);
}
/*注册tpm结构体实例并初始化*/
struct tpm_chip *tpm_register_hardware(struct device *dev,
const struct tpm_vendor_specific *entry)
{
#define DEVNAME_SIZE 7
char *devname;
struct tpm_chip *chip;
/*分配内存空间*/
chip = kzalloc(sizeof(*chip), GFP_KERNEL);
devname = kmalloc(DEVNAME_SIZE, GFP_KERNEL);
if (chip == NULL || devname == NULL)
goto out_free;
/*初始化互斥量*/
mutex_init(&chip->buffer_mutex);
mutex_init(&chip->tpm_mutex);
/*初始化tpm_chip结构实例链表*/
INIT_LIST_HEAD(&chip->list);
/*初始化工作队列*/
INIT_WORK(&chip->work, timeout_work);
/*设定用户读定时器的值*/
setup_timer(&chip->user_read_timer, user_reader_timeout,
(unsigned long)chip);
/*设置tpm_chip实例中vendor字段的值*/
memcpy(&chip->vendor, entry, sizeof(struct tpm_vendor_specific));
/*设定dev_num字段的值*/
chip->dev_num = find_first_zero_bit(dev_mask, TPM_NUM_DEVICES);
if (chip->dev_num >= TPM_NUM_DEVICES) {
dev_err(dev, "No available tpm device numbers\n");
goto out_free;
} else if (chip->dev_num == 0)
chip->vendor.miscdev.minor = TPM_MINOR;
else
chip->vendor.miscdev.minor = MISC_DYNAMIC_MINOR;
set_bit(chip->dev_num, dev_mask);
scnprintf(devname, DEVNAME_SIZE, "%s%d", "tpm", chip->dev_num);
chip->vendor.miscdev.name = devname;
chip->vendor.miscdev.parent = dev;
chip->dev = get_device(dev);
chip->release = dev->release;
dev->release = tpm_dev_release;
dev_set_drvdata(dev, chip);
if (misc_register(&chip->vendor.miscdev)) {
dev_err(chip->dev,
"unable to misc_register %s, minor %d\n",
chip->vendor.miscdev.name,
chip->vendor.miscdev.minor);
put_device(chip->dev);
return NULL;
}
if (sysfs_create_group(&dev->kobj, chip->vendor.attr_group)) {
misc_deregister(&chip->vendor.miscdev);
put_device(chip->dev);
return NULL;
}
chip->bios_dir = tpm_bios_log_setup(devname);
/*确保tpm_chip设备实例有效*/
spin_lock(&driver_lock);
list_add_rcu(&chip->list, &tpm_chip_list);
spin_unlock(&driver_lock);
return chip;
out_free:
/*注册失败,释放已经分配的空间*/
kfree(chip);
kfree(devname);
return NULL;
}