2012-08-14 18:35:32 -05:00
/*
* Copyright 2012 IBM Corporation
*
2014-12-04 21:01:51 -06:00
* Author : Ashley Lai < ashleydlai @ gmail . com >
2016-11-14 05:00:54 -05:00
* Nayna Jain < nayna @ linux . vnet . ibm . com >
2012-08-14 18:35:32 -05:00
*
* Maintained by : < tpmdd - devel @ lists . sourceforge . net >
*
* Read the event log created by the firmware on PPC64
*
* 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/slab.h>
# include <linux/of.h>
2017-09-20 10:13:36 +02:00
# include <linux/tpm_eventlog.h>
2012-08-14 18:35:32 -05:00
# include "tpm.h"
2016-11-14 05:00:54 -05:00
int tpm_read_log_of ( struct tpm_chip * chip )
2012-08-14 18:35:32 -05:00
{
struct device_node * np ;
const u32 * sizep ;
2015-06-17 18:17:09 -04:00
const u64 * basep ;
2016-11-14 05:00:52 -05:00
struct tpm_bios_log * log ;
2017-01-23 02:26:26 -05:00
u32 size ;
u64 base ;
2012-08-14 18:35:32 -05:00
2016-11-14 05:00:52 -05:00
log = & chip - > log ;
2016-11-19 11:18:28 -07:00
if ( chip - > dev . parent & & chip - > dev . parent - > of_node )
2016-11-14 05:00:55 -05:00
np = chip - > dev . parent - > of_node ;
2016-11-15 13:27:22 +00:00
else
2012-08-14 18:35:32 -05:00
return - ENODEV ;
2017-06-27 12:27:24 +02:00
if ( of_property_read_bool ( np , " powered-while-suspended " ) )
chip - > flags | = TPM_CHIP_FLAG_ALWAYS_POWERED ;
2012-08-14 18:35:32 -05:00
sizep = of_get_property ( np , " linux,sml-size " , NULL ) ;
2016-11-19 11:18:28 -07:00
basep = of_get_property ( np , " linux,sml-base " , NULL ) ;
if ( sizep = = NULL & & basep = = NULL )
return - ENODEV ;
if ( sizep = = NULL | | basep = = NULL )
2016-11-14 05:00:56 -05:00
return - EIO ;
2017-01-23 02:26:26 -05:00
/*
* For both vtpm / tpm , firmware has log addr and log size in big
* endian format . But in case of vtpm , there is a method called
* sml - handover which is run during kernel init even before
* device tree is setup . This sml - handover function takes care
* of endianness and writes to sml - base and sml - size in little
* endian format . For this reason , vtpm doesn ' t need conversion
* but physical tpm needs the conversion .
*/
if ( of_property_match_string ( np , " compatible " , " IBM,vtpm " ) < 0 ) {
size = be32_to_cpup ( sizep ) ;
base = be64_to_cpup ( basep ) ;
} else {
size = * sizep ;
base = * basep ;
}
if ( size = = 0 ) {
2016-11-14 05:00:56 -05:00
dev_warn ( & chip - > dev , " %s: Event log area empty \n " , __func__ ) ;
return - EIO ;
2012-08-14 18:35:32 -05:00
}
2017-01-23 02:26:26 -05:00
log - > bios_event_log = kmalloc ( size , GFP_KERNEL ) ;
2016-11-14 05:00:56 -05:00
if ( ! log - > bios_event_log )
2012-08-14 18:35:32 -05:00
return - ENOMEM ;
2017-01-23 02:26:26 -05:00
log - > bios_event_log_end = log - > bios_event_log + size ;
2012-08-14 18:35:32 -05:00
2017-01-23 02:26:26 -05:00
memcpy ( log - > bios_event_log , __va ( base ) , size ) ;
2012-08-14 18:35:32 -05:00
2017-09-20 10:13:40 +02:00
if ( chip - > flags & TPM_CHIP_FLAG_TPM2 )
return EFI_TCG2_EVENT_LOG_FORMAT_TCG_2 ;
return EFI_TCG2_EVENT_LOG_FORMAT_TCG_1_2 ;
2012-08-14 18:35:32 -05:00
}