2019-05-27 08:55:01 +02:00
// SPDX-License-Identifier: GPL-2.0-or-later
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
*/
# 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>
2017-09-20 10:13:36 +02:00
# include <linux/tpm_eventlog.h>
2012-07-11 10:08:12 -05:00
2018-04-12 12:13:48 +02:00
# include "../tpm.h"
2018-04-12 12:13:50 +02:00
# include "common.h"
2012-07-11 10:08:12 -05:00
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 ;
2020-07-06 19:58:07 -04:00
struct acpi_table_tpm2 * tbl ;
struct acpi_tpm2_phy * tpm2_phy ;
int format ;
2017-01-23 02:26:27 -05:00
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 ;
2020-07-06 19:58:07 -04:00
if ( chip - > flags & TPM_CHIP_FLAG_TPM2 ) {
status = acpi_get_table ( " TPM2 " , 1 ,
( struct acpi_table_header * * ) & tbl ) ;
if ( ACPI_FAILURE ( status ) )
return - ENODEV ;
if ( tbl - > header . length <
sizeof ( * tbl ) + sizeof ( struct acpi_tpm2_phy ) )
return - ENODEV ;
tpm2_phy = ( void * ) tbl + sizeof ( * tbl ) ;
len = tpm2_phy - > log_area_minimum_length ;
start = tpm2_phy - > log_area_start_address ;
if ( ! start | | ! len )
return - ENODEV ;
format = EFI_TCG2_EVENT_LOG_FORMAT_TCG_2 ;
} else {
/* Find TCPA entry in RSDT (ACPI_LOGICAL_ADDRESSING) */
status = acpi_get_table ( ACPI_SIG_TCPA , 1 ,
( struct acpi_table_header * * ) & buff ) ;
if ( ACPI_FAILURE ( status ) )
return - ENODEV ;
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 ;
}
format = EFI_TCG2_EVENT_LOG_FORMAT_TCG_1_2 ;
2012-07-11 10:08:12 -05:00
}
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 ) ;
2020-07-06 19:58:07 -04:00
return format ;
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
}