18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later 28c2ecf20Sopenharmony_ci/* 38c2ecf20Sopenharmony_ci * Copyright 2012 IBM Corporation 48c2ecf20Sopenharmony_ci * 58c2ecf20Sopenharmony_ci * Author: Ashley Lai <ashleydlai@gmail.com> 68c2ecf20Sopenharmony_ci * Nayna Jain <nayna@linux.vnet.ibm.com> 78c2ecf20Sopenharmony_ci * 88c2ecf20Sopenharmony_ci * Maintained by: <tpmdd-devel@lists.sourceforge.net> 98c2ecf20Sopenharmony_ci * 108c2ecf20Sopenharmony_ci * Read the event log created by the firmware on PPC64 118c2ecf20Sopenharmony_ci */ 128c2ecf20Sopenharmony_ci 138c2ecf20Sopenharmony_ci#include <linux/slab.h> 148c2ecf20Sopenharmony_ci#include <linux/of.h> 158c2ecf20Sopenharmony_ci#include <linux/tpm_eventlog.h> 168c2ecf20Sopenharmony_ci 178c2ecf20Sopenharmony_ci#include "../tpm.h" 188c2ecf20Sopenharmony_ci#include "common.h" 198c2ecf20Sopenharmony_ci 208c2ecf20Sopenharmony_ciint tpm_read_log_of(struct tpm_chip *chip) 218c2ecf20Sopenharmony_ci{ 228c2ecf20Sopenharmony_ci struct device_node *np; 238c2ecf20Sopenharmony_ci const u32 *sizep; 248c2ecf20Sopenharmony_ci const u64 *basep; 258c2ecf20Sopenharmony_ci struct tpm_bios_log *log; 268c2ecf20Sopenharmony_ci u32 size; 278c2ecf20Sopenharmony_ci u64 base; 288c2ecf20Sopenharmony_ci 298c2ecf20Sopenharmony_ci log = &chip->log; 308c2ecf20Sopenharmony_ci if (chip->dev.parent && chip->dev.parent->of_node) 318c2ecf20Sopenharmony_ci np = chip->dev.parent->of_node; 328c2ecf20Sopenharmony_ci else 338c2ecf20Sopenharmony_ci return -ENODEV; 348c2ecf20Sopenharmony_ci 358c2ecf20Sopenharmony_ci if (of_property_read_bool(np, "powered-while-suspended")) 368c2ecf20Sopenharmony_ci chip->flags |= TPM_CHIP_FLAG_ALWAYS_POWERED; 378c2ecf20Sopenharmony_ci 388c2ecf20Sopenharmony_ci sizep = of_get_property(np, "linux,sml-size", NULL); 398c2ecf20Sopenharmony_ci basep = of_get_property(np, "linux,sml-base", NULL); 408c2ecf20Sopenharmony_ci if (sizep == NULL && basep == NULL) 418c2ecf20Sopenharmony_ci return -ENODEV; 428c2ecf20Sopenharmony_ci if (sizep == NULL || basep == NULL) 438c2ecf20Sopenharmony_ci return -EIO; 448c2ecf20Sopenharmony_ci 458c2ecf20Sopenharmony_ci /* 468c2ecf20Sopenharmony_ci * For both vtpm/tpm, firmware has log addr and log size in big 478c2ecf20Sopenharmony_ci * endian format. But in case of vtpm, there is a method called 488c2ecf20Sopenharmony_ci * sml-handover which is run during kernel init even before 498c2ecf20Sopenharmony_ci * device tree is setup. This sml-handover function takes care 508c2ecf20Sopenharmony_ci * of endianness and writes to sml-base and sml-size in little 518c2ecf20Sopenharmony_ci * endian format. For this reason, vtpm doesn't need conversion 528c2ecf20Sopenharmony_ci * but physical tpm needs the conversion. 538c2ecf20Sopenharmony_ci */ 548c2ecf20Sopenharmony_ci if (of_property_match_string(np, "compatible", "IBM,vtpm") < 0 && 558c2ecf20Sopenharmony_ci of_property_match_string(np, "compatible", "IBM,vtpm20") < 0) { 568c2ecf20Sopenharmony_ci size = be32_to_cpup((__force __be32 *)sizep); 578c2ecf20Sopenharmony_ci base = be64_to_cpup((__force __be64 *)basep); 588c2ecf20Sopenharmony_ci } else { 598c2ecf20Sopenharmony_ci size = *sizep; 608c2ecf20Sopenharmony_ci base = *basep; 618c2ecf20Sopenharmony_ci } 628c2ecf20Sopenharmony_ci 638c2ecf20Sopenharmony_ci if (size == 0) { 648c2ecf20Sopenharmony_ci dev_warn(&chip->dev, "%s: Event log area empty\n", __func__); 658c2ecf20Sopenharmony_ci return -EIO; 668c2ecf20Sopenharmony_ci } 678c2ecf20Sopenharmony_ci 688c2ecf20Sopenharmony_ci log->bios_event_log = kmemdup(__va(base), size, GFP_KERNEL); 698c2ecf20Sopenharmony_ci if (!log->bios_event_log) 708c2ecf20Sopenharmony_ci return -ENOMEM; 718c2ecf20Sopenharmony_ci 728c2ecf20Sopenharmony_ci log->bios_event_log_end = log->bios_event_log + size; 738c2ecf20Sopenharmony_ci 748c2ecf20Sopenharmony_ci if (chip->flags & TPM_CHIP_FLAG_TPM2) 758c2ecf20Sopenharmony_ci return EFI_TCG2_EVENT_LOG_FORMAT_TCG_2; 768c2ecf20Sopenharmony_ci return EFI_TCG2_EVENT_LOG_FORMAT_TCG_1_2; 778c2ecf20Sopenharmony_ci} 78