2005-04-16 15:20:36 -07:00
/*
* Copyright ( C ) 2004 IBM Corporation
*
* Authors :
* Leendert van Doorn < leendert @ watson . ibm . com >
* Dave Safford < safford @ watson . ibm . com >
* Reiner Sailer < sailer @ watson . ibm . com >
* Kylene Hall < kjhall @ us . ibm . com >
*
2007-08-22 14:01:04 -07:00
* Maintained by : < tpmdd - devel @ lists . sourceforge . net >
2005-04-16 15:20:36 -07:00
*
* Device driver for TCG / TCPA TPM ( trusted platform module ) .
* Specifications at www . trustedcomputinggroup . org
*
* This program is free software ; you can redistribute it and / or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation , version 2 of the
* License .
*
*/
# include <linux/module.h>
# include <linux/delay.h>
# include <linux/fs.h>
2007-05-08 00:32:02 -07:00
# include <linux/mutex.h>
2006-10-18 13:55:46 -04:00
# include <linux/sched.h>
2005-04-16 15:20:36 -07:00
# include <linux/miscdevice.h>
2005-11-01 15:14:05 +00:00
# include <linux/platform_device.h>
2006-03-25 03:07:35 -08:00
# include <linux/io.h>
2009-02-02 15:23:44 -02:00
# include <linux/tpm.h>
2005-04-16 15:20:36 -07:00
2012-06-07 13:47:14 -05:00
enum tpm_const {
TPM_MINOR = 224 , /* officially assigned */
TPM_BUFSIZE = 4096 ,
TPM_NUM_DEVICES = 256 ,
2013-03-17 14:56:39 -07:00
TPM_RETRY = 50 , /* 5 seconds */
2012-06-07 13:47:14 -05:00
} ;
2005-06-23 22:01:48 -07:00
enum tpm_timeout {
TPM_TIMEOUT = 5 , /* msecs */
2013-03-17 14:56:39 -07:00
TPM_TIMEOUT_RETRY = 100 /* msecs */
2005-06-23 22:01:48 -07:00
} ;
2005-04-16 15:20:36 -07:00
/* TPM addresses */
2005-06-23 22:01:48 -07:00
enum tpm_addr {
2005-06-25 14:55:39 -07:00
TPM_SUPERIO_ADDR = 0x2E ,
2005-06-23 22:01:48 -07:00
TPM_ADDR = 0x4E ,
} ;
2013-03-17 14:56:39 -07:00
# define TPM_WARN_RETRY 0x800
2011-11-11 12:57:04 -05:00
# define TPM_WARN_DOING_SELFTEST 0x802
2012-01-17 22:07:30 -05:00
# define TPM_ERR_DEACTIVATED 0x6
# define TPM_ERR_DISABLED 0x7
2012-11-21 13:54:33 -07:00
# define TPM_ERR_INVALID_POSTINIT 38
2012-01-17 22:07:30 -05:00
2011-11-01 17:00:52 -02:00
# define TPM_HEADER_SIZE 10
2005-06-23 22:02:00 -07:00
extern ssize_t tpm_show_pubek ( struct device * , struct device_attribute * attr ,
char * ) ;
extern ssize_t tpm_show_pcrs ( struct device * , struct device_attribute * attr ,
char * ) ;
extern ssize_t tpm_show_caps ( struct device * , struct device_attribute * attr ,
char * ) ;
2006-04-22 02:37:50 -07:00
extern ssize_t tpm_show_caps_1_2 ( struct device * , struct device_attribute * attr ,
char * ) ;
2005-06-23 22:02:00 -07:00
extern ssize_t tpm_store_cancel ( struct device * , struct device_attribute * attr ,
const char * , size_t ) ;
2006-04-22 02:37:50 -07:00
extern ssize_t tpm_show_enabled ( struct device * , struct device_attribute * attr ,
char * ) ;
extern ssize_t tpm_show_active ( struct device * , struct device_attribute * attr ,
char * ) ;
extern ssize_t tpm_show_owned ( struct device * , struct device_attribute * attr ,
char * ) ;
extern ssize_t tpm_show_temp_deactivated ( struct device * ,
struct device_attribute * attr , char * ) ;
2011-03-30 12:13:25 -04:00
extern ssize_t tpm_show_durations ( struct device * ,
struct device_attribute * attr , char * ) ;
2011-03-30 12:13:28 -04:00
extern ssize_t tpm_show_timeouts ( struct device * ,
struct device_attribute * attr , char * ) ;
2005-04-16 15:20:36 -07:00
struct tpm_chip ;
struct tpm_vendor_specific {
2006-04-22 02:37:26 -07:00
const u8 req_complete_mask ;
const u8 req_complete_val ;
2013-01-22 13:52:35 -06:00
bool ( * req_canceled ) ( struct tpm_chip * chip , u8 status ) ;
2005-11-13 16:07:41 -08:00
void __iomem * iobase ; /* ioremapped address */
unsigned long base ; /* TPM base address */
2006-04-22 02:38:03 -07:00
int irq ;
2011-03-30 12:13:32 -04:00
int probed_irq ;
2006-04-22 02:38:03 -07:00
2005-11-13 16:07:41 -08:00
int region_size ;
int have_region ;
2005-04-16 15:20:36 -07:00
int ( * recv ) ( struct tpm_chip * , u8 * , size_t ) ;
int ( * send ) ( struct tpm_chip * , u8 * , size_t ) ;
void ( * cancel ) ( struct tpm_chip * ) ;
2005-10-30 15:03:23 -08:00
u8 ( * status ) ( struct tpm_chip * ) ;
2008-02-06 01:37:02 -08:00
void ( * release ) ( struct device * ) ;
2005-04-16 15:20:36 -07:00
struct miscdevice miscdev ;
2005-06-23 22:02:00 -07:00
struct attribute_group * attr_group ;
2006-04-22 02:38:03 -07:00
struct list_head list ;
int locality ;
2006-04-22 02:38:19 -07:00
unsigned long timeout_a , timeout_b , timeout_c , timeout_d ; /* jiffies */
2011-03-30 12:13:28 -04:00
bool timeout_adjusted ;
2006-04-22 02:38:19 -07:00
unsigned long duration [ 3 ] ; /* jiffies */
2011-03-30 12:13:25 -04:00
bool duration_adjusted ;
2012-12-05 11:36:20 -06:00
void * priv ;
2006-04-22 02:38:03 -07:00
wait_queue_head_t read_queue ;
wait_queue_head_t int_queue ;
2013-01-22 13:50:07 -06:00
u16 manufacturer_id ;
2005-04-16 15:20:36 -07:00
} ;
2012-12-05 11:36:20 -06:00
# define TPM_VPRIV(c) (c)->vendor.priv
2012-01-20 12:58:49 -05:00
# define TPM_VID_INTEL 0x8086
2013-01-22 13:52:35 -06:00
# define TPM_VID_WINBOND 0x1050
# define TPM_VID_STM 0x104A
2012-01-20 12:58:49 -05:00
2005-04-16 15:20:36 -07:00
struct tpm_chip {
2005-10-30 15:03:24 -08:00
struct device * dev ; /* Device stuff */
2005-04-16 15:20:36 -07:00
int dev_num ; /* /dev/tpm# */
2008-10-11 09:04:02 +11:00
unsigned long is_open ; /* only one allowed */
2005-04-16 15:20:36 -07:00
int time_expired ;
/* Data passed to and from the tpm via the read/write calls */
u8 * data_buffer ;
atomic_t data_pending ;
2007-05-08 00:32:02 -07:00
struct mutex buffer_mutex ;
2005-04-16 15:20:36 -07:00
struct timer_list user_read_timer ; /* user needs to claim result */
2005-11-13 16:07:43 -08:00
struct work_struct work ;
2007-05-08 00:32:02 -07:00
struct mutex tpm_mutex ; /* tpm is processing */
2005-04-16 15:20:36 -07:00
2006-04-22 02:37:15 -07:00
struct tpm_vendor_specific vendor ;
2005-04-16 15:20:36 -07:00
2006-01-08 01:03:15 -08:00
struct dentry * * bios_dir ;
2005-04-16 15:20:36 -07:00
struct list_head list ;
2008-02-06 01:37:02 -08:00
void ( * release ) ( struct device * ) ;
2005-04-16 15:20:36 -07:00
} ;
2006-04-22 02:38:03 -07:00
# define to_tpm_chip(n) container_of(n, struct tpm_chip, vendor)
2010-11-23 17:50:32 -05:00
static inline void tpm_chip_put ( struct tpm_chip * chip )
{
module_put ( chip - > dev - > driver - > owner ) ;
}
2005-06-25 14:55:39 -07:00
static inline int tpm_read_index ( int base , int index )
2005-04-16 15:20:36 -07:00
{
2005-06-25 14:55:39 -07:00
outb ( index , base ) ;
return inb ( base + 1 ) & 0xFF ;
2005-04-16 15:20:36 -07:00
}
2005-06-25 14:55:39 -07:00
static inline void tpm_write_index ( int base , int index , int value )
2005-04-16 15:20:36 -07:00
{
2005-06-25 14:55:39 -07:00
outb ( index , base ) ;
outb ( value & 0xFF , base + 1 ) ;
2005-04-16 15:20:36 -07:00
}
2009-02-02 15:23:43 -02:00
struct tpm_input_header {
__be16 tag ;
__be32 length ;
__be32 ordinal ;
2012-11-21 13:56:45 -07:00
} __packed ;
2009-02-02 15:23:43 -02:00
struct tpm_output_header {
__be16 tag ;
__be32 length ;
__be32 return_code ;
2012-11-21 13:56:45 -07:00
} __packed ;
2009-02-02 15:23:43 -02:00
struct stclear_flags_t {
__be16 tag ;
u8 deactivated ;
u8 disableForceClear ;
u8 physicalPresence ;
u8 physicalPresenceLock ;
u8 bGlobalLock ;
2012-11-21 13:56:45 -07:00
} __packed ;
2009-02-02 15:23:43 -02:00
struct tpm_version_t {
u8 Major ;
u8 Minor ;
u8 revMajor ;
u8 revMinor ;
2012-11-21 13:56:45 -07:00
} __packed ;
2009-02-02 15:23:43 -02:00
struct tpm_version_1_2_t {
__be16 tag ;
u8 Major ;
u8 Minor ;
u8 revMajor ;
u8 revMinor ;
2012-11-21 13:56:45 -07:00
} __packed ;
2009-02-02 15:23:43 -02:00
struct timeout_t {
__be32 a ;
__be32 b ;
__be32 c ;
__be32 d ;
2012-11-21 13:56:45 -07:00
} __packed ;
2009-02-02 15:23:43 -02:00
struct duration_t {
__be32 tpm_short ;
__be32 tpm_medium ;
__be32 tpm_long ;
2012-11-21 13:56:45 -07:00
} __packed ;
2009-02-02 15:23:43 -02:00
struct permanent_flags_t {
__be16 tag ;
u8 disable ;
u8 ownership ;
u8 deactivated ;
u8 readPubek ;
u8 disableOwnerClear ;
u8 allowMaintenance ;
u8 physicalPresenceLifetimeLock ;
u8 physicalPresenceHWEnable ;
u8 physicalPresenceCMDEnable ;
u8 CEKPUsed ;
u8 TPMpost ;
u8 TPMpostLock ;
u8 FIPS ;
u8 operator ;
u8 enableRevokeEK ;
u8 nvLocked ;
u8 readSRKPub ;
u8 tpmEstablished ;
u8 maintenanceDone ;
u8 disableFullDALogicInfo ;
2012-11-21 13:56:45 -07:00
} __packed ;
2009-02-02 15:23:43 -02:00
typedef union {
struct permanent_flags_t perm_flags ;
struct stclear_flags_t stclear_flags ;
bool owned ;
__be32 num_pcrs ;
struct tpm_version_t tpm_version ;
struct tpm_version_1_2_t tpm_version_1_2 ;
__be32 manufacturer_id ;
struct timeout_t timeout ;
struct duration_t duration ;
} cap_t ;
struct tpm_getcap_params_in {
__be32 cap ;
__be32 subcap_size ;
__be32 subcap ;
2012-11-21 13:56:45 -07:00
} __packed ;
2009-02-02 15:23:43 -02:00
struct tpm_getcap_params_out {
__be32 cap_size ;
cap_t cap ;
2012-11-21 13:56:45 -07:00
} __packed ;
2009-02-02 15:23:43 -02:00
struct tpm_readpubek_params_out {
u8 algorithm [ 4 ] ;
u8 encscheme [ 2 ] ;
u8 sigscheme [ 2 ] ;
2010-06-14 13:58:22 -03:00
__be32 paramsize ;
2009-02-02 15:23:43 -02:00
u8 parameters [ 12 ] ; /*assuming RSA*/
__be32 keysize ;
u8 modulus [ 256 ] ;
u8 checksum [ 20 ] ;
2012-11-21 13:56:45 -07:00
} __packed ;
2009-02-02 15:23:43 -02:00
typedef union {
struct tpm_input_header in ;
struct tpm_output_header out ;
} tpm_cmd_header ;
2009-02-02 15:23:44 -02:00
# define TPM_DIGEST_SIZE 20
struct tpm_pcrread_out {
u8 pcr_result [ TPM_DIGEST_SIZE ] ;
2012-11-21 13:56:45 -07:00
} __packed ;
2009-02-02 15:23:44 -02:00
struct tpm_pcrread_in {
__be32 pcr_idx ;
2012-11-21 13:56:45 -07:00
} __packed ;
2009-02-02 15:23:44 -02:00
struct tpm_pcrextend_in {
__be32 pcr_idx ;
u8 hash [ TPM_DIGEST_SIZE ] ;
2012-11-21 13:56:45 -07:00
} __packed ;
2009-02-02 15:23:44 -02:00
2012-06-07 13:47:14 -05:00
/* 128 bytes is an arbitrary cap. This could be as large as TPM_BUFSIZE - 18
* bytes , but 128 is still a relatively large number of random bytes and
* anything much bigger causes users of struct tpm_cmd_t to start getting
* compiler warnings about stack frame size . */
# define TPM_MAX_RNG_DATA 128
struct tpm_getrandom_out {
__be32 rng_data_len ;
u8 rng_data [ TPM_MAX_RNG_DATA ] ;
2012-11-21 13:56:45 -07:00
} __packed ;
2012-06-07 13:47:14 -05:00
struct tpm_getrandom_in {
__be32 num_bytes ;
2012-11-21 13:56:45 -07:00
} __packed ;
2012-06-07 13:47:14 -05:00
2012-11-21 13:54:33 -07:00
struct tpm_startup_in {
__be16 startup_type ;
} __packed ;
2009-02-02 15:23:43 -02:00
typedef union {
struct tpm_getcap_params_out getcap_out ;
struct tpm_readpubek_params_out readpubek_out ;
u8 readpubek_out_buffer [ sizeof ( struct tpm_readpubek_params_out ) ] ;
struct tpm_getcap_params_in getcap_in ;
2009-02-02 15:23:44 -02:00
struct tpm_pcrread_in pcrread_in ;
struct tpm_pcrread_out pcrread_out ;
struct tpm_pcrextend_in pcrextend_in ;
2012-06-07 13:47:14 -05:00
struct tpm_getrandom_in getrandom_in ;
struct tpm_getrandom_out getrandom_out ;
2012-11-21 13:54:33 -07:00
struct tpm_startup_in startup_in ;
2009-02-02 15:23:43 -02:00
} tpm_cmd_params ;
struct tpm_cmd_t {
tpm_cmd_header header ;
tpm_cmd_params params ;
2012-11-21 13:56:45 -07:00
} __packed ;
2009-02-02 15:23:43 -02:00
ssize_t tpm_getcap ( struct device * , __be32 , cap_t * , const char * ) ;
2005-04-16 15:20:36 -07:00
2011-11-11 12:57:02 -05:00
extern int tpm_get_timeouts ( struct tpm_chip * ) ;
2006-04-22 02:37:50 -07:00
extern void tpm_gen_interrupt ( struct tpm_chip * ) ;
2011-11-11 12:57:04 -05:00
extern int tpm_do_selftest ( struct tpm_chip * ) ;
2006-04-22 02:37:38 -07:00
extern unsigned long tpm_calc_ordinal_duration ( struct tpm_chip * , u32 ) ;
2006-04-22 02:37:26 -07:00
extern struct tpm_chip * tpm_register_hardware ( struct device * ,
const struct tpm_vendor_specific * ) ;
2005-04-16 15:20:36 -07:00
extern int tpm_open ( struct inode * , struct file * ) ;
extern int tpm_release ( struct inode * , struct file * ) ;
2008-10-11 09:04:39 +11:00
extern void tpm_dev_vendor_release ( struct tpm_chip * ) ;
2005-04-16 15:20:36 -07:00
extern ssize_t tpm_write ( struct file * , const char __user * , size_t ,
loff_t * ) ;
extern ssize_t tpm_read ( struct file * , char __user * , size_t , loff_t * ) ;
2005-10-30 15:03:24 -08:00
extern void tpm_remove_hardware ( struct device * ) ;
2012-07-06 19:09:01 +02:00
extern int tpm_pm_suspend ( struct device * ) ;
2005-10-30 15:03:25 -08:00
extern int tpm_pm_resume ( struct device * ) ;
2011-09-16 14:39:40 -03:00
extern int wait_for_tpm_stat ( struct tpm_chip * , u8 , unsigned long ,
2013-01-22 13:57:53 -06:00
wait_queue_head_t * , bool ) ;
2012-08-22 18:47:22 +08:00
# ifdef CONFIG_ACPI
2012-10-09 17:35:22 +08:00
extern int tpm_add_ppi ( struct kobject * ) ;
extern void tpm_remove_ppi ( struct kobject * ) ;
2012-08-22 18:47:22 +08:00
# else
2012-10-09 17:35:22 +08:00
static inline int tpm_add_ppi ( struct kobject * parent )
2012-08-22 18:47:22 +08:00
{
return 0 ;
}
2012-10-09 17:35:22 +08:00
static inline void tpm_remove_ppi ( struct kobject * parent )
{
}
2012-08-22 18:47:22 +08:00
# endif