1*0bfb2374SThiebaud Weksteen /* 2*0bfb2374SThiebaud Weksteen * Copyright 2012 IBM Corporation 3*0bfb2374SThiebaud Weksteen * 4*0bfb2374SThiebaud Weksteen * Author: Ashley Lai <ashleydlai@gmail.com> 5*0bfb2374SThiebaud Weksteen * Nayna Jain <nayna@linux.vnet.ibm.com> 6*0bfb2374SThiebaud Weksteen * 7*0bfb2374SThiebaud Weksteen * Maintained by: <tpmdd-devel@lists.sourceforge.net> 8*0bfb2374SThiebaud Weksteen * 9*0bfb2374SThiebaud Weksteen * Read the event log created by the firmware on PPC64 10*0bfb2374SThiebaud Weksteen * 11*0bfb2374SThiebaud Weksteen * This program is free software; you can redistribute it and/or 12*0bfb2374SThiebaud Weksteen * modify it under the terms of the GNU General Public License 13*0bfb2374SThiebaud Weksteen * as published by the Free Software Foundation; either version 14*0bfb2374SThiebaud Weksteen * 2 of the License, or (at your option) any later version. 15*0bfb2374SThiebaud Weksteen * 16*0bfb2374SThiebaud Weksteen */ 17*0bfb2374SThiebaud Weksteen 18*0bfb2374SThiebaud Weksteen #include <linux/slab.h> 19*0bfb2374SThiebaud Weksteen #include <linux/of.h> 20*0bfb2374SThiebaud Weksteen #include <linux/tpm_eventlog.h> 21*0bfb2374SThiebaud Weksteen 22*0bfb2374SThiebaud Weksteen #include "../tpm.h" 23*0bfb2374SThiebaud Weksteen 24*0bfb2374SThiebaud Weksteen int tpm_read_log_of(struct tpm_chip *chip) 25*0bfb2374SThiebaud Weksteen { 26*0bfb2374SThiebaud Weksteen struct device_node *np; 27*0bfb2374SThiebaud Weksteen const u32 *sizep; 28*0bfb2374SThiebaud Weksteen const u64 *basep; 29*0bfb2374SThiebaud Weksteen struct tpm_bios_log *log; 30*0bfb2374SThiebaud Weksteen u32 size; 31*0bfb2374SThiebaud Weksteen u64 base; 32*0bfb2374SThiebaud Weksteen 33*0bfb2374SThiebaud Weksteen log = &chip->log; 34*0bfb2374SThiebaud Weksteen if (chip->dev.parent && chip->dev.parent->of_node) 35*0bfb2374SThiebaud Weksteen np = chip->dev.parent->of_node; 36*0bfb2374SThiebaud Weksteen else 37*0bfb2374SThiebaud Weksteen return -ENODEV; 38*0bfb2374SThiebaud Weksteen 39*0bfb2374SThiebaud Weksteen if (of_property_read_bool(np, "powered-while-suspended")) 40*0bfb2374SThiebaud Weksteen chip->flags |= TPM_CHIP_FLAG_ALWAYS_POWERED; 41*0bfb2374SThiebaud Weksteen 42*0bfb2374SThiebaud Weksteen sizep = of_get_property(np, "linux,sml-size", NULL); 43*0bfb2374SThiebaud Weksteen basep = of_get_property(np, "linux,sml-base", NULL); 44*0bfb2374SThiebaud Weksteen if (sizep == NULL && basep == NULL) 45*0bfb2374SThiebaud Weksteen return -ENODEV; 46*0bfb2374SThiebaud Weksteen if (sizep == NULL || basep == NULL) 47*0bfb2374SThiebaud Weksteen return -EIO; 48*0bfb2374SThiebaud Weksteen 49*0bfb2374SThiebaud Weksteen /* 50*0bfb2374SThiebaud Weksteen * For both vtpm/tpm, firmware has log addr and log size in big 51*0bfb2374SThiebaud Weksteen * endian format. But in case of vtpm, there is a method called 52*0bfb2374SThiebaud Weksteen * sml-handover which is run during kernel init even before 53*0bfb2374SThiebaud Weksteen * device tree is setup. This sml-handover function takes care 54*0bfb2374SThiebaud Weksteen * of endianness and writes to sml-base and sml-size in little 55*0bfb2374SThiebaud Weksteen * endian format. For this reason, vtpm doesn't need conversion 56*0bfb2374SThiebaud Weksteen * but physical tpm needs the conversion. 57*0bfb2374SThiebaud Weksteen */ 58*0bfb2374SThiebaud Weksteen if (of_property_match_string(np, "compatible", "IBM,vtpm") < 0) { 59*0bfb2374SThiebaud Weksteen size = be32_to_cpup((__force __be32 *)sizep); 60*0bfb2374SThiebaud Weksteen base = be64_to_cpup((__force __be64 *)basep); 61*0bfb2374SThiebaud Weksteen } else { 62*0bfb2374SThiebaud Weksteen size = *sizep; 63*0bfb2374SThiebaud Weksteen base = *basep; 64*0bfb2374SThiebaud Weksteen } 65*0bfb2374SThiebaud Weksteen 66*0bfb2374SThiebaud Weksteen if (size == 0) { 67*0bfb2374SThiebaud Weksteen dev_warn(&chip->dev, "%s: Event log area empty\n", __func__); 68*0bfb2374SThiebaud Weksteen return -EIO; 69*0bfb2374SThiebaud Weksteen } 70*0bfb2374SThiebaud Weksteen 71*0bfb2374SThiebaud Weksteen log->bios_event_log = kmalloc(size, GFP_KERNEL); 72*0bfb2374SThiebaud Weksteen if (!log->bios_event_log) 73*0bfb2374SThiebaud Weksteen return -ENOMEM; 74*0bfb2374SThiebaud Weksteen 75*0bfb2374SThiebaud Weksteen log->bios_event_log_end = log->bios_event_log + size; 76*0bfb2374SThiebaud Weksteen 77*0bfb2374SThiebaud Weksteen memcpy(log->bios_event_log, __va(base), size); 78*0bfb2374SThiebaud Weksteen 79*0bfb2374SThiebaud Weksteen if (chip->flags & TPM_CHIP_FLAG_TPM2) 80*0bfb2374SThiebaud Weksteen return EFI_TCG2_EVENT_LOG_FORMAT_TCG_2; 81*0bfb2374SThiebaud Weksteen return EFI_TCG2_EVENT_LOG_FORMAT_TCG_1_2; 82*0bfb2374SThiebaud Weksteen } 83