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