2012-07-11 10:08:12 -05:00
/*
* Copyright ( C ) 2005 IBM Corporation
*
* Authors :
* Seiji Munetoh < munetoh @ jp . ibm . com >
* Stefan Berger < stefanb @ us . ibm . com >
* Reiner Sailer < sailer @ watson . ibm . com >
* Kylene Hall < kjhall @ us . ibm . com >
2016-11-14 05:00:54 -05:00
* Nayna Jain < nayna @ linux . vnet . ibm . com >
2012-07-11 10:08:12 -05:00
*
* Maintained by : < tpmdd - devel @ lists . sourceforge . net >
*
2016-11-14 05:00:52 -05:00
* Access to the event log extended by the TCG BIOS of PC platform
2012-07-11 10:08:12 -05:00
*
* 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 ; either version
* 2 of the License , or ( at your option ) any later version .
*
*/
# include <linux/seq_file.h>
# include <linux/fs.h>
# include <linux/security.h>
# include <linux/module.h>
# include <linux/slab.h>
2013-12-03 08:49:16 +08:00
# include <linux/acpi.h>
2012-07-11 10:08:12 -05:00
# include "tpm.h"
# include "tpm_eventlog.h"
struct acpi_tcpa {
struct acpi_table_header hdr ;
u16 platform_class ;
union {
struct client_hdr {
2012-11-21 13:56:45 -07:00
u32 log_max_len __packed ;
u64 log_start_addr __packed ;
2012-07-11 10:08:12 -05:00
} client ;
struct server_hdr {
u16 reserved ;
2012-11-21 13:56:45 -07:00
u64 log_max_len __packed ;
u64 log_start_addr __packed ;
2012-07-11 10:08:12 -05:00
} server ;
} ;
} ;
/* read binary bios log */
2016-11-14 05:00:54 -05:00
int tpm_read_log_acpi ( struct tpm_chip * chip )
2012-07-11 10:08:12 -05:00
{
struct acpi_tcpa * buff ;
acpi_status status ;
2012-09-04 11:18:21 -05:00
void __iomem * virt ;
2012-07-11 10:08:12 -05:00
u64 len , start ;
2016-11-14 05:00:52 -05:00
struct tpm_bios_log * log ;
2012-07-11 10:08:12 -05:00
2017-01-23 02:26:27 -05:00
if ( chip - > flags & TPM_CHIP_FLAG_TPM2 )
return - ENODEV ;
2016-11-14 05:00:52 -05:00
log = & chip - > log ;
2012-07-11 10:08:12 -05:00
2016-11-19 11:18:28 -07:00
/* Unfortuntely ACPI does not associate the event log with a specific
* TPM , like PPI . Thus all ACPI TPMs will read the same log .
*/
if ( ! chip - > acpi_dev_handle )
return - ENODEV ;
2012-07-11 10:08:12 -05:00
/* Find TCPA entry in RSDT (ACPI_LOGICAL_ADDRESSING) */
status = acpi_get_table ( ACPI_SIG_TCPA , 1 ,
( struct acpi_table_header * * ) & buff ) ;
2016-11-14 05:00:56 -05:00
if ( ACPI_FAILURE ( status ) )
2016-11-19 11:18:28 -07:00
return - ENODEV ;
2012-07-11 10:08:12 -05:00
switch ( buff - > platform_class ) {
case BIOS_SERVER :
len = buff - > server . log_max_len ;
start = buff - > server . log_start_addr ;
break ;
case BIOS_CLIENT :
default :
len = buff - > client . log_max_len ;
start = buff - > client . log_start_addr ;
break ;
}
if ( ! len ) {
2016-11-14 05:00:56 -05:00
dev_warn ( & chip - > dev , " %s: TCPA log area empty \n " , __func__ ) ;
2012-07-11 10:08:12 -05:00
return - EIO ;
}
/* malloc EventLog space */
log - > bios_event_log = kmalloc ( len , GFP_KERNEL ) ;
2016-11-14 05:00:56 -05:00
if ( ! log - > bios_event_log )
2012-07-11 10:08:12 -05:00
return - ENOMEM ;
log - > bios_event_log_end = log - > bios_event_log + len ;
2014-05-20 15:39:41 +08:00
virt = acpi_os_map_iomem ( start , len ) ;
2016-11-14 05:00:56 -05:00
if ( ! virt )
2016-11-14 05:00:52 -05:00
goto err ;
2012-07-11 10:08:12 -05:00
2012-09-04 11:18:21 -05:00
memcpy_fromio ( log - > bios_event_log , virt , len ) ;
2012-07-11 10:08:12 -05:00
2014-05-20 15:39:41 +08:00
acpi_os_unmap_iomem ( virt , len ) ;
2012-07-11 10:08:12 -05:00
return 0 ;
2016-11-14 05:00:52 -05:00
err :
kfree ( log - > bios_event_log ) ;
log - > bios_event_log = NULL ;
return - EIO ;
2012-07-11 10:08:12 -05:00
}