tpm: Move eventlog files to a subdirectory
authorThiebaud Weksteen <tweek@google.com>
Thu, 12 Apr 2018 10:13:48 +0000 (12:13 +0200)
committerJarkko Sakkinen <jarkko.sakkinen@linux.intel.com>
Wed, 9 May 2018 11:45:46 +0000 (14:45 +0300)
Signed-off-by: Thiebaud Weksteen <tweek@google.com>
Suggested-by: Jarkko Sakkinen <jarkko.sakkinen@linux.intel.com>
Reviewed-by: Jarkko Sakkinen <jarkko.sakkinen@linux.intel.com>
Tested-by: Jarkko Sakkinen <jarkko.sakkinen@linux.intel.com>
Signed-off-by: Jarkko Sakkinen <jarkko.sakkinen@linux.intel.com>
drivers/char/tpm/Makefile
drivers/char/tpm/eventlog/acpi.c [new file with mode: 0644]
drivers/char/tpm/eventlog/efi.c [new file with mode: 0644]
drivers/char/tpm/eventlog/of.c [new file with mode: 0644]
drivers/char/tpm/eventlog/tpm1.c [new file with mode: 0644]
drivers/char/tpm/eventlog/tpm2.c [new file with mode: 0644]
drivers/char/tpm/tpm1_eventlog.c [deleted file]
drivers/char/tpm/tpm2_eventlog.c [deleted file]
drivers/char/tpm/tpm_eventlog_acpi.c [deleted file]
drivers/char/tpm/tpm_eventlog_efi.c [deleted file]
drivers/char/tpm/tpm_eventlog_of.c [deleted file]

index acd758381c58ba37f992b8b0f7fcff48e202092c..5dcf5bd35a3d27aa8100970476f141dfe02aa60a 100644 (file)
@@ -4,11 +4,11 @@
 #
 obj-$(CONFIG_TCG_TPM) += tpm.o
 tpm-y := tpm-interface.o tpm-dev.o tpm-sysfs.o tpm-chip.o tpm2-cmd.o \
-        tpm-dev-common.o tpmrm-dev.o tpm1_eventlog.o tpm2_eventlog.o \
+        tpm-dev-common.o tpmrm-dev.o eventlog/tpm1.o eventlog/tpm2.o \
          tpm2-space.o
-tpm-$(CONFIG_ACPI) += tpm_ppi.o tpm_eventlog_acpi.o
-tpm-$(CONFIG_EFI) += tpm_eventlog_efi.o
-tpm-$(CONFIG_OF) += tpm_eventlog_of.o
+tpm-$(CONFIG_ACPI) += tpm_ppi.o eventlog/acpi.o
+tpm-$(CONFIG_EFI) += eventlog/efi.o
+tpm-$(CONFIG_OF) += eventlog/of.o
 obj-$(CONFIG_TCG_TIS_CORE) += tpm_tis_core.o
 obj-$(CONFIG_TCG_TIS) += tpm_tis.o
 obj-$(CONFIG_TCG_TIS_SPI) += tpm_tis_spi.o
diff --git a/drivers/char/tpm/eventlog/acpi.c b/drivers/char/tpm/eventlog/acpi.c
new file mode 100644 (file)
index 0000000..8476be2
--- /dev/null
@@ -0,0 +1,112 @@
+/*
+ * 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>
+ *     Nayna Jain <nayna@linux.vnet.ibm.com>
+ *
+ * Maintained by: <tpmdd-devel@lists.sourceforge.net>
+ *
+ * Access to the event log extended by the TCG BIOS of PC platform
+ *
+ * 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/seq_file.h>
+#include <linux/fs.h>
+#include <linux/security.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/acpi.h>
+#include <linux/tpm_eventlog.h>
+
+#include "../tpm.h"
+
+struct acpi_tcpa {
+       struct acpi_table_header hdr;
+       u16 platform_class;
+       union {
+               struct client_hdr {
+                       u32 log_max_len __packed;
+                       u64 log_start_addr __packed;
+               } client;
+               struct server_hdr {
+                       u16 reserved;
+                       u64 log_max_len __packed;
+                       u64 log_start_addr __packed;
+               } server;
+       };
+};
+
+/* read binary bios log */
+int tpm_read_log_acpi(struct tpm_chip *chip)
+{
+       struct acpi_tcpa *buff;
+       acpi_status status;
+       void __iomem *virt;
+       u64 len, start;
+       struct tpm_bios_log *log;
+
+       if (chip->flags & TPM_CHIP_FLAG_TPM2)
+               return -ENODEV;
+
+       log = &chip->log;
+
+       /* 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;
+
+       /* 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;
+       }
+       if (!len) {
+               dev_warn(&chip->dev, "%s: TCPA log area empty\n", __func__);
+               return -EIO;
+       }
+
+       /* malloc EventLog space */
+       log->bios_event_log = kmalloc(len, GFP_KERNEL);
+       if (!log->bios_event_log)
+               return -ENOMEM;
+
+       log->bios_event_log_end = log->bios_event_log + len;
+
+       virt = acpi_os_map_iomem(start, len);
+       if (!virt)
+               goto err;
+
+       memcpy_fromio(log->bios_event_log, virt, len);
+
+       acpi_os_unmap_iomem(virt, len);
+       return EFI_TCG2_EVENT_LOG_FORMAT_TCG_1_2;
+
+err:
+       kfree(log->bios_event_log);
+       log->bios_event_log = NULL;
+       return -EIO;
+
+}
diff --git a/drivers/char/tpm/eventlog/efi.c b/drivers/char/tpm/eventlog/efi.c
new file mode 100644 (file)
index 0000000..e1593c5
--- /dev/null
@@ -0,0 +1,66 @@
+/*
+ * Copyright (C) 2017 Google
+ *
+ * Authors:
+ *      Thiebaud Weksteen <tweek@google.com>
+ *
+ * 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/efi.h>
+#include <linux/tpm_eventlog.h>
+
+#include "../tpm.h"
+
+/* read binary bios log from EFI configuration table */
+int tpm_read_log_efi(struct tpm_chip *chip)
+{
+
+       struct linux_efi_tpm_eventlog *log_tbl;
+       struct tpm_bios_log *log;
+       u32 log_size;
+       u8 tpm_log_version;
+
+       if (!(chip->flags & TPM_CHIP_FLAG_TPM2))
+               return -ENODEV;
+
+       if (efi.tpm_log == EFI_INVALID_TABLE_ADDR)
+               return -ENODEV;
+
+       log = &chip->log;
+
+       log_tbl = memremap(efi.tpm_log, sizeof(*log_tbl), MEMREMAP_WB);
+       if (!log_tbl) {
+               pr_err("Could not map UEFI TPM log table !\n");
+               return -ENOMEM;
+       }
+
+       log_size = log_tbl->size;
+       memunmap(log_tbl);
+
+       log_tbl = memremap(efi.tpm_log, sizeof(*log_tbl) + log_size,
+                          MEMREMAP_WB);
+       if (!log_tbl) {
+               pr_err("Could not map UEFI TPM log table payload!\n");
+               return -ENOMEM;
+       }
+
+       /* malloc EventLog space */
+       log->bios_event_log = kmalloc(log_size, GFP_KERNEL);
+       if (!log->bios_event_log)
+               goto err_memunmap;
+       memcpy(log->bios_event_log, log_tbl->log, log_size);
+       log->bios_event_log_end = log->bios_event_log + log_size;
+
+       tpm_log_version = log_tbl->version;
+       memunmap(log_tbl);
+       return tpm_log_version;
+
+err_memunmap:
+       memunmap(log_tbl);
+       return -ENOMEM;
+}
diff --git a/drivers/char/tpm/eventlog/of.c b/drivers/char/tpm/eventlog/of.c
new file mode 100644 (file)
index 0000000..e1ec532
--- /dev/null
@@ -0,0 +1,82 @@
+/*
+ * Copyright 2012 IBM Corporation
+ *
+ * Author: Ashley Lai <ashleydlai@gmail.com>
+ *         Nayna Jain <nayna@linux.vnet.ibm.com>
+ *
+ * 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>
+#include <linux/tpm_eventlog.h>
+
+#include "../tpm.h"
+
+int tpm_read_log_of(struct tpm_chip *chip)
+{
+       struct device_node *np;
+       const u32 *sizep;
+       const u64 *basep;
+       struct tpm_bios_log *log;
+       u32 size;
+       u64 base;
+
+       log = &chip->log;
+       if (chip->dev.parent && chip->dev.parent->of_node)
+               np = chip->dev.parent->of_node;
+       else
+               return -ENODEV;
+
+       if (of_property_read_bool(np, "powered-while-suspended"))
+               chip->flags |= TPM_CHIP_FLAG_ALWAYS_POWERED;
+
+       sizep = of_get_property(np, "linux,sml-size", NULL);
+       basep = of_get_property(np, "linux,sml-base", NULL);
+       if (sizep == NULL && basep == NULL)
+               return -ENODEV;
+       if (sizep == NULL || basep == NULL)
+               return -EIO;
+
+       /*
+        * 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((__force __be32 *)sizep);
+               base = be64_to_cpup((__force __be64 *)basep);
+       } else {
+               size = *sizep;
+               base = *basep;
+       }
+
+       if (size == 0) {
+               dev_warn(&chip->dev, "%s: Event log area empty\n", __func__);
+               return -EIO;
+       }
+
+       log->bios_event_log = kmalloc(size, GFP_KERNEL);
+       if (!log->bios_event_log)
+               return -ENOMEM;
+
+       log->bios_event_log_end = log->bios_event_log + size;
+
+       memcpy(log->bios_event_log, __va(base), size);
+
+       if (chip->flags & TPM_CHIP_FLAG_TPM2)
+               return EFI_TCG2_EVENT_LOG_FORMAT_TCG_2;
+       return EFI_TCG2_EVENT_LOG_FORMAT_TCG_1_2;
+}
diff --git a/drivers/char/tpm/eventlog/tpm1.c b/drivers/char/tpm/eventlog/tpm1.c
new file mode 100644 (file)
index 0000000..d6aea3c
--- /dev/null
@@ -0,0 +1,476 @@
+/*
+ * Copyright (C) 2005, 2012 IBM Corporation
+ *
+ * Authors:
+ *     Kent Yoder <key@linux.vnet.ibm.com>
+ *     Seiji Munetoh <munetoh@jp.ibm.com>
+ *     Stefan Berger <stefanb@us.ibm.com>
+ *     Reiner Sailer <sailer@watson.ibm.com>
+ *     Kylene Hall <kjhall@us.ibm.com>
+ *     Nayna Jain <nayna@linux.vnet.ibm.com>
+ *
+ * Maintained by: <tpmdd-devel@lists.sourceforge.net>
+ *
+ * Access to the event log created by a system's firmware / BIOS
+ *
+ * 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/seq_file.h>
+#include <linux/efi.h>
+#include <linux/fs.h>
+#include <linux/security.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/tpm_eventlog.h>
+
+#include "../tpm.h"
+
+
+static const char* tcpa_event_type_strings[] = {
+       "PREBOOT",
+       "POST CODE",
+       "",
+       "NO ACTION",
+       "SEPARATOR",
+       "ACTION",
+       "EVENT TAG",
+       "S-CRTM Contents",
+       "S-CRTM Version",
+       "CPU Microcode",
+       "Platform Config Flags",
+       "Table of Devices",
+       "Compact Hash",
+       "IPL",
+       "IPL Partition Data",
+       "Non-Host Code",
+       "Non-Host Config",
+       "Non-Host Info"
+};
+
+static const char* tcpa_pc_event_id_strings[] = {
+       "",
+       "SMBIOS",
+       "BIS Certificate",
+       "POST BIOS ",
+       "ESCD ",
+       "CMOS",
+       "NVRAM",
+       "Option ROM",
+       "Option ROM config",
+       "",
+       "Option ROM microcode ",
+       "S-CRTM Version",
+       "S-CRTM Contents ",
+       "POST Contents ",
+       "Table of Devices",
+};
+
+/* returns pointer to start of pos. entry of tcg log */
+static void *tpm_bios_measurements_start(struct seq_file *m, loff_t *pos)
+{
+       loff_t i;
+       struct tpm_chip *chip = m->private;
+       struct tpm_bios_log *log = &chip->log;
+       void *addr = log->bios_event_log;
+       void *limit = log->bios_event_log_end;
+       struct tcpa_event *event;
+       u32 converted_event_size;
+       u32 converted_event_type;
+
+
+       /* read over *pos measurements */
+       for (i = 0; i < *pos; i++) {
+               event = addr;
+
+               converted_event_size =
+                   do_endian_conversion(event->event_size);
+               converted_event_type =
+                   do_endian_conversion(event->event_type);
+
+               if ((addr + sizeof(struct tcpa_event)) < limit) {
+                       if ((converted_event_type == 0) &&
+                           (converted_event_size == 0))
+                               return NULL;
+                       addr += (sizeof(struct tcpa_event) +
+                                converted_event_size);
+               }
+       }
+
+       /* now check if current entry is valid */
+       if ((addr + sizeof(struct tcpa_event)) >= limit)
+               return NULL;
+
+       event = addr;
+
+       converted_event_size = do_endian_conversion(event->event_size);
+       converted_event_type = do_endian_conversion(event->event_type);
+
+       if (((converted_event_type == 0) && (converted_event_size == 0))
+           || ((addr + sizeof(struct tcpa_event) + converted_event_size)
+               >= limit))
+               return NULL;
+
+       return addr;
+}
+
+static void *tpm_bios_measurements_next(struct seq_file *m, void *v,
+                                       loff_t *pos)
+{
+       struct tcpa_event *event = v;
+       struct tpm_chip *chip = m->private;
+       struct tpm_bios_log *log = &chip->log;
+       void *limit = log->bios_event_log_end;
+       u32 converted_event_size;
+       u32 converted_event_type;
+
+       converted_event_size = do_endian_conversion(event->event_size);
+
+       v += sizeof(struct tcpa_event) + converted_event_size;
+
+       /* now check if current entry is valid */
+       if ((v + sizeof(struct tcpa_event)) >= limit)
+               return NULL;
+
+       event = v;
+
+       converted_event_size = do_endian_conversion(event->event_size);
+       converted_event_type = do_endian_conversion(event->event_type);
+
+       if (((converted_event_type == 0) && (converted_event_size == 0)) ||
+           ((v + sizeof(struct tcpa_event) + converted_event_size) >= limit))
+               return NULL;
+
+       (*pos)++;
+       return v;
+}
+
+static void tpm_bios_measurements_stop(struct seq_file *m, void *v)
+{
+}
+
+static int get_event_name(char *dest, struct tcpa_event *event,
+                       unsigned char * event_entry)
+{
+       const char *name = "";
+       /* 41 so there is room for 40 data and 1 nul */
+       char data[41] = "";
+       int i, n_len = 0, d_len = 0;
+       struct tcpa_pc_event *pc_event;
+
+       switch (do_endian_conversion(event->event_type)) {
+       case PREBOOT:
+       case POST_CODE:
+       case UNUSED:
+       case NO_ACTION:
+       case SCRTM_CONTENTS:
+       case SCRTM_VERSION:
+       case CPU_MICROCODE:
+       case PLATFORM_CONFIG_FLAGS:
+       case TABLE_OF_DEVICES:
+       case COMPACT_HASH:
+       case IPL:
+       case IPL_PARTITION_DATA:
+       case NONHOST_CODE:
+       case NONHOST_CONFIG:
+       case NONHOST_INFO:
+               name = tcpa_event_type_strings[do_endian_conversion
+                                               (event->event_type)];
+               n_len = strlen(name);
+               break;
+       case SEPARATOR:
+       case ACTION:
+               if (MAX_TEXT_EVENT >
+                   do_endian_conversion(event->event_size)) {
+                       name = event_entry;
+                       n_len = do_endian_conversion(event->event_size);
+               }
+               break;
+       case EVENT_TAG:
+               pc_event = (struct tcpa_pc_event *)event_entry;
+
+               /* ToDo Row data -> Base64 */
+
+               switch (do_endian_conversion(pc_event->event_id)) {
+               case SMBIOS:
+               case BIS_CERT:
+               case CMOS:
+               case NVRAM:
+               case OPTION_ROM_EXEC:
+               case OPTION_ROM_CONFIG:
+               case S_CRTM_VERSION:
+                       name = tcpa_pc_event_id_strings[do_endian_conversion
+                                                       (pc_event->event_id)];
+                       n_len = strlen(name);
+                       break;
+               /* hash data */
+               case POST_BIOS_ROM:
+               case ESCD:
+               case OPTION_ROM_MICROCODE:
+               case S_CRTM_CONTENTS:
+               case POST_CONTENTS:
+                       name = tcpa_pc_event_id_strings[do_endian_conversion
+                                                       (pc_event->event_id)];
+                       n_len = strlen(name);
+                       for (i = 0; i < 20; i++)
+                               d_len += sprintf(&data[2*i], "%02x",
+                                               pc_event->event_data[i]);
+                       break;
+               default:
+                       break;
+               }
+       default:
+               break;
+       }
+
+       return snprintf(dest, MAX_TEXT_EVENT, "[%.*s%.*s]",
+                       n_len, name, d_len, data);
+
+}
+
+static int tpm_binary_bios_measurements_show(struct seq_file *m, void *v)
+{
+       struct tcpa_event *event = v;
+       struct tcpa_event temp_event;
+       char *temp_ptr;
+       int i;
+
+       memcpy(&temp_event, event, sizeof(struct tcpa_event));
+
+       /* convert raw integers for endianness */
+       temp_event.pcr_index = do_endian_conversion(event->pcr_index);
+       temp_event.event_type = do_endian_conversion(event->event_type);
+       temp_event.event_size = do_endian_conversion(event->event_size);
+
+       temp_ptr = (char *) &temp_event;
+
+       for (i = 0; i < (sizeof(struct tcpa_event) - 1) ; i++)
+               seq_putc(m, temp_ptr[i]);
+
+       temp_ptr = (char *) v;
+
+       for (i = (sizeof(struct tcpa_event) - 1);
+            i < (sizeof(struct tcpa_event) + temp_event.event_size); i++)
+               seq_putc(m, temp_ptr[i]);
+
+       return 0;
+
+}
+
+static int tpm_bios_measurements_release(struct inode *inode,
+                                        struct file *file)
+{
+       struct seq_file *seq = (struct seq_file *)file->private_data;
+       struct tpm_chip *chip = (struct tpm_chip *)seq->private;
+
+       put_device(&chip->dev);
+
+       return seq_release(inode, file);
+}
+
+static int tpm_ascii_bios_measurements_show(struct seq_file *m, void *v)
+{
+       int len = 0;
+       char *eventname;
+       struct tcpa_event *event = v;
+       unsigned char *event_entry =
+           (unsigned char *)(v + sizeof(struct tcpa_event));
+
+       eventname = kmalloc(MAX_TEXT_EVENT, GFP_KERNEL);
+       if (!eventname) {
+               printk(KERN_ERR "%s: ERROR - No Memory for event name\n ",
+                      __func__);
+               return -EFAULT;
+       }
+
+       /* 1st: PCR */
+       seq_printf(m, "%2d ", do_endian_conversion(event->pcr_index));
+
+       /* 2nd: SHA1 */
+       seq_printf(m, "%20phN", event->pcr_value);
+
+       /* 3rd: event type identifier */
+       seq_printf(m, " %02x", do_endian_conversion(event->event_type));
+
+       len += get_event_name(eventname, event, event_entry);
+
+       /* 4th: eventname <= max + \'0' delimiter */
+       seq_printf(m, " %s\n", eventname);
+
+       kfree(eventname);
+       return 0;
+}
+
+static const struct seq_operations tpm_ascii_b_measurements_seqops = {
+       .start = tpm_bios_measurements_start,
+       .next = tpm_bios_measurements_next,
+       .stop = tpm_bios_measurements_stop,
+       .show = tpm_ascii_bios_measurements_show,
+};
+
+static const struct seq_operations tpm_binary_b_measurements_seqops = {
+       .start = tpm_bios_measurements_start,
+       .next = tpm_bios_measurements_next,
+       .stop = tpm_bios_measurements_stop,
+       .show = tpm_binary_bios_measurements_show,
+};
+
+static int tpm_bios_measurements_open(struct inode *inode,
+                                           struct file *file)
+{
+       int err;
+       struct seq_file *seq;
+       struct tpm_chip_seqops *chip_seqops;
+       const struct seq_operations *seqops;
+       struct tpm_chip *chip;
+
+       inode_lock(inode);
+       if (!inode->i_private) {
+               inode_unlock(inode);
+               return -ENODEV;
+       }
+       chip_seqops = (struct tpm_chip_seqops *)inode->i_private;
+       seqops = chip_seqops->seqops;
+       chip = chip_seqops->chip;
+       get_device(&chip->dev);
+       inode_unlock(inode);
+
+       /* now register seq file */
+       err = seq_open(file, seqops);
+       if (!err) {
+               seq = file->private_data;
+               seq->private = chip;
+       }
+
+       return err;
+}
+
+static const struct file_operations tpm_bios_measurements_ops = {
+       .owner = THIS_MODULE,
+       .open = tpm_bios_measurements_open,
+       .read = seq_read,
+       .llseek = seq_lseek,
+       .release = tpm_bios_measurements_release,
+};
+
+static int tpm_read_log(struct tpm_chip *chip)
+{
+       int rc;
+
+       if (chip->log.bios_event_log != NULL) {
+               dev_dbg(&chip->dev,
+                       "%s: ERROR - event log already initialized\n",
+                       __func__);
+               return -EFAULT;
+       }
+
+       rc = tpm_read_log_acpi(chip);
+       if (rc != -ENODEV)
+               return rc;
+
+       rc = tpm_read_log_efi(chip);
+       if (rc != -ENODEV)
+               return rc;
+
+       return tpm_read_log_of(chip);
+}
+
+/*
+ * tpm_bios_log_setup() - Read the event log from the firmware
+ * @chip: TPM chip to use.
+ *
+ * If an event log is found then the securityfs files are setup to
+ * export it to userspace, otherwise nothing is done.
+ *
+ * Returns -ENODEV if the firmware has no event log or securityfs is not
+ * supported.
+ */
+int tpm_bios_log_setup(struct tpm_chip *chip)
+{
+       const char *name = dev_name(&chip->dev);
+       unsigned int cnt;
+       int log_version;
+       int rc = 0;
+
+       rc = tpm_read_log(chip);
+       if (rc < 0)
+               return rc;
+       log_version = rc;
+
+       cnt = 0;
+       chip->bios_dir[cnt] = securityfs_create_dir(name, NULL);
+       /* NOTE: securityfs_create_dir can return ENODEV if securityfs is
+        * compiled out. The caller should ignore the ENODEV return code.
+        */
+       if (IS_ERR(chip->bios_dir[cnt]))
+               goto err;
+       cnt++;
+
+       chip->bin_log_seqops.chip = chip;
+       if (log_version == EFI_TCG2_EVENT_LOG_FORMAT_TCG_2)
+               chip->bin_log_seqops.seqops =
+                       &tpm2_binary_b_measurements_seqops;
+       else
+               chip->bin_log_seqops.seqops =
+                       &tpm_binary_b_measurements_seqops;
+
+
+       chip->bios_dir[cnt] =
+           securityfs_create_file("binary_bios_measurements",
+                                  0440, chip->bios_dir[0],
+                                  (void *)&chip->bin_log_seqops,
+                                  &tpm_bios_measurements_ops);
+       if (IS_ERR(chip->bios_dir[cnt]))
+               goto err;
+       cnt++;
+
+       if (!(chip->flags & TPM_CHIP_FLAG_TPM2)) {
+
+               chip->ascii_log_seqops.chip = chip;
+               chip->ascii_log_seqops.seqops =
+                       &tpm_ascii_b_measurements_seqops;
+
+               chip->bios_dir[cnt] =
+                       securityfs_create_file("ascii_bios_measurements",
+                                              0440, chip->bios_dir[0],
+                                              (void *)&chip->ascii_log_seqops,
+                                              &tpm_bios_measurements_ops);
+               if (IS_ERR(chip->bios_dir[cnt]))
+                       goto err;
+               cnt++;
+       }
+
+       return 0;
+
+err:
+       rc = PTR_ERR(chip->bios_dir[cnt]);
+       chip->bios_dir[cnt] = NULL;
+       tpm_bios_log_teardown(chip);
+       return rc;
+}
+
+void tpm_bios_log_teardown(struct tpm_chip *chip)
+{
+       int i;
+       struct inode *inode;
+
+       /* securityfs_remove currently doesn't take care of handling sync
+        * between removal and opening of pseudo files. To handle this, a
+        * workaround is added by making i_private = NULL here during removal
+        * and to check it during open(), both within inode_lock()/unlock().
+        * This design ensures that open() either safely gets kref or fails.
+        */
+       for (i = (TPM_NUM_EVENT_LOG_FILES - 1); i >= 0; i--) {
+               if (chip->bios_dir[i]) {
+                       inode = d_inode(chip->bios_dir[i]);
+                       inode_lock(inode);
+                       inode->i_private = NULL;
+                       inode_unlock(inode);
+                       securityfs_remove(chip->bios_dir[i]);
+               }
+       }
+}
diff --git a/drivers/char/tpm/eventlog/tpm2.c b/drivers/char/tpm/eventlog/tpm2.c
new file mode 100644 (file)
index 0000000..f0723fa
--- /dev/null
@@ -0,0 +1,209 @@
+/*
+ * Copyright (C) 2016 IBM Corporation
+ *
+ * Authors:
+ *      Nayna Jain <nayna@linux.vnet.ibm.com>
+ *
+ * Access to TPM 2.0 event log as written by Firmware.
+ * It assumes that writer of event log has followed TCG Specification
+ * for Family "2.0" and written the event data in little endian.
+ * With that, it doesn't need any endian conversion for structure
+ * content.
+ *
+ * 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/seq_file.h>
+#include <linux/fs.h>
+#include <linux/security.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/tpm_eventlog.h>
+
+#include "../tpm.h"
+
+/*
+ * calc_tpm2_event_size() - calculate the event size, where event
+ * is an entry in the TPM 2.0 event log. The event is of type Crypto
+ * Agile Log Entry Format as defined in TCG EFI Protocol Specification
+ * Family "2.0".
+
+ * @event: event whose size is to be calculated.
+ * @event_header: the first event in the event log.
+ *
+ * Returns size of the event. If it is an invalid event, returns 0.
+ */
+static int calc_tpm2_event_size(struct tcg_pcr_event2 *event,
+                               struct tcg_pcr_event *event_header)
+{
+       struct tcg_efi_specid_event *efispecid;
+       struct tcg_event_field *event_field;
+       void *marker;
+       void *marker_start;
+       u32 halg_size;
+       size_t size;
+       u16 halg;
+       int i;
+       int j;
+
+       marker = event;
+       marker_start = marker;
+       marker = marker + sizeof(event->pcr_idx) + sizeof(event->event_type)
+               + sizeof(event->count);
+
+       efispecid = (struct tcg_efi_specid_event *)event_header->event;
+
+       /* Check if event is malformed. */
+       if (event->count > efispecid->num_algs)
+               return 0;
+
+       for (i = 0; i < event->count; i++) {
+               halg_size = sizeof(event->digests[i].alg_id);
+               memcpy(&halg, marker, halg_size);
+               marker = marker + halg_size;
+               for (j = 0; j < efispecid->num_algs; j++) {
+                       if (halg == efispecid->digest_sizes[j].alg_id) {
+                               marker +=
+                                       efispecid->digest_sizes[j].digest_size;
+                               break;
+                       }
+               }
+               /* Algorithm without known length. Such event is unparseable. */
+               if (j == efispecid->num_algs)
+                       return 0;
+       }
+
+       event_field = (struct tcg_event_field *)marker;
+       marker = marker + sizeof(event_field->event_size)
+               + event_field->event_size;
+       size = marker - marker_start;
+
+       if ((event->event_type == 0) && (event_field->event_size == 0))
+               return 0;
+
+       return size;
+}
+
+static void *tpm2_bios_measurements_start(struct seq_file *m, loff_t *pos)
+{
+       struct tpm_chip *chip = m->private;
+       struct tpm_bios_log *log = &chip->log;
+       void *addr = log->bios_event_log;
+       void *limit = log->bios_event_log_end;
+       struct tcg_pcr_event *event_header;
+       struct tcg_pcr_event2 *event;
+       size_t size;
+       int i;
+
+       event_header = addr;
+       size = sizeof(struct tcg_pcr_event) - sizeof(event_header->event)
+               + event_header->event_size;
+
+       if (*pos == 0) {
+               if (addr + size < limit) {
+                       if ((event_header->event_type == 0) &&
+                           (event_header->event_size == 0))
+                               return NULL;
+                       return SEQ_START_TOKEN;
+               }
+       }
+
+       if (*pos > 0) {
+               addr += size;
+               event = addr;
+               size = calc_tpm2_event_size(event, event_header);
+               if ((addr + size >=  limit) || (size == 0))
+                       return NULL;
+       }
+
+       for (i = 0; i < (*pos - 1); i++) {
+               event = addr;
+               size = calc_tpm2_event_size(event, event_header);
+
+               if ((addr + size >= limit) || (size == 0))
+                       return NULL;
+               addr += size;
+       }
+
+       return addr;
+}
+
+static void *tpm2_bios_measurements_next(struct seq_file *m, void *v,
+                                        loff_t *pos)
+{
+       struct tcg_pcr_event *event_header;
+       struct tcg_pcr_event2 *event;
+       struct tpm_chip *chip = m->private;
+       struct tpm_bios_log *log = &chip->log;
+       void *limit = log->bios_event_log_end;
+       size_t event_size;
+       void *marker;
+
+       event_header = log->bios_event_log;
+
+       if (v == SEQ_START_TOKEN) {
+               event_size = sizeof(struct tcg_pcr_event) -
+                       sizeof(event_header->event) + event_header->event_size;
+               marker = event_header;
+       } else {
+               event = v;
+               event_size = calc_tpm2_event_size(event, event_header);
+               if (event_size == 0)
+                       return NULL;
+               marker = event;
+       }
+
+       marker = marker + event_size;
+       if (marker >= limit)
+               return NULL;
+       v = marker;
+       event = v;
+
+       event_size = calc_tpm2_event_size(event, event_header);
+       if (((v + event_size) >= limit) || (event_size == 0))
+               return NULL;
+
+       (*pos)++;
+       return v;
+}
+
+static void tpm2_bios_measurements_stop(struct seq_file *m, void *v)
+{
+}
+
+static int tpm2_binary_bios_measurements_show(struct seq_file *m, void *v)
+{
+       struct tpm_chip *chip = m->private;
+       struct tpm_bios_log *log = &chip->log;
+       struct tcg_pcr_event *event_header = log->bios_event_log;
+       struct tcg_pcr_event2 *event = v;
+       void *temp_ptr;
+       size_t size;
+
+       if (v == SEQ_START_TOKEN) {
+               size = sizeof(struct tcg_pcr_event) -
+                       sizeof(event_header->event) + event_header->event_size;
+
+               temp_ptr = event_header;
+
+               if (size > 0)
+                       seq_write(m, temp_ptr, size);
+       } else {
+               size = calc_tpm2_event_size(event, event_header);
+               temp_ptr = event;
+               if (size > 0)
+                       seq_write(m, temp_ptr, size);
+       }
+
+       return 0;
+}
+
+const struct seq_operations tpm2_binary_b_measurements_seqops = {
+       .start = tpm2_bios_measurements_start,
+       .next = tpm2_bios_measurements_next,
+       .stop = tpm2_bios_measurements_stop,
+       .show = tpm2_binary_bios_measurements_show,
+};
diff --git a/drivers/char/tpm/tpm1_eventlog.c b/drivers/char/tpm/tpm1_eventlog.c
deleted file mode 100644 (file)
index add798b..0000000
+++ /dev/null
@@ -1,476 +0,0 @@
-/*
- * Copyright (C) 2005, 2012 IBM Corporation
- *
- * Authors:
- *     Kent Yoder <key@linux.vnet.ibm.com>
- *     Seiji Munetoh <munetoh@jp.ibm.com>
- *     Stefan Berger <stefanb@us.ibm.com>
- *     Reiner Sailer <sailer@watson.ibm.com>
- *     Kylene Hall <kjhall@us.ibm.com>
- *     Nayna Jain <nayna@linux.vnet.ibm.com>
- *
- * Maintained by: <tpmdd-devel@lists.sourceforge.net>
- *
- * Access to the event log created by a system's firmware / BIOS
- *
- * 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/seq_file.h>
-#include <linux/efi.h>
-#include <linux/fs.h>
-#include <linux/security.h>
-#include <linux/module.h>
-#include <linux/slab.h>
-#include <linux/tpm_eventlog.h>
-
-#include "tpm.h"
-
-
-static const char* tcpa_event_type_strings[] = {
-       "PREBOOT",
-       "POST CODE",
-       "",
-       "NO ACTION",
-       "SEPARATOR",
-       "ACTION",
-       "EVENT TAG",
-       "S-CRTM Contents",
-       "S-CRTM Version",
-       "CPU Microcode",
-       "Platform Config Flags",
-       "Table of Devices",
-       "Compact Hash",
-       "IPL",
-       "IPL Partition Data",
-       "Non-Host Code",
-       "Non-Host Config",
-       "Non-Host Info"
-};
-
-static const char* tcpa_pc_event_id_strings[] = {
-       "",
-       "SMBIOS",
-       "BIS Certificate",
-       "POST BIOS ",
-       "ESCD ",
-       "CMOS",
-       "NVRAM",
-       "Option ROM",
-       "Option ROM config",
-       "",
-       "Option ROM microcode ",
-       "S-CRTM Version",
-       "S-CRTM Contents ",
-       "POST Contents ",
-       "Table of Devices",
-};
-
-/* returns pointer to start of pos. entry of tcg log */
-static void *tpm_bios_measurements_start(struct seq_file *m, loff_t *pos)
-{
-       loff_t i;
-       struct tpm_chip *chip = m->private;
-       struct tpm_bios_log *log = &chip->log;
-       void *addr = log->bios_event_log;
-       void *limit = log->bios_event_log_end;
-       struct tcpa_event *event;
-       u32 converted_event_size;
-       u32 converted_event_type;
-
-
-       /* read over *pos measurements */
-       for (i = 0; i < *pos; i++) {
-               event = addr;
-
-               converted_event_size =
-                   do_endian_conversion(event->event_size);
-               converted_event_type =
-                   do_endian_conversion(event->event_type);
-
-               if ((addr + sizeof(struct tcpa_event)) < limit) {
-                       if ((converted_event_type == 0) &&
-                           (converted_event_size == 0))
-                               return NULL;
-                       addr += (sizeof(struct tcpa_event) +
-                                converted_event_size);
-               }
-       }
-
-       /* now check if current entry is valid */
-       if ((addr + sizeof(struct tcpa_event)) >= limit)
-               return NULL;
-
-       event = addr;
-
-       converted_event_size = do_endian_conversion(event->event_size);
-       converted_event_type = do_endian_conversion(event->event_type);
-
-       if (((converted_event_type == 0) && (converted_event_size == 0))
-           || ((addr + sizeof(struct tcpa_event) + converted_event_size)
-               >= limit))
-               return NULL;
-
-       return addr;
-}
-
-static void *tpm_bios_measurements_next(struct seq_file *m, void *v,
-                                       loff_t *pos)
-{
-       struct tcpa_event *event = v;
-       struct tpm_chip *chip = m->private;
-       struct tpm_bios_log *log = &chip->log;
-       void *limit = log->bios_event_log_end;
-       u32 converted_event_size;
-       u32 converted_event_type;
-
-       converted_event_size = do_endian_conversion(event->event_size);
-
-       v += sizeof(struct tcpa_event) + converted_event_size;
-
-       /* now check if current entry is valid */
-       if ((v + sizeof(struct tcpa_event)) >= limit)
-               return NULL;
-
-       event = v;
-
-       converted_event_size = do_endian_conversion(event->event_size);
-       converted_event_type = do_endian_conversion(event->event_type);
-
-       if (((converted_event_type == 0) && (converted_event_size == 0)) ||
-           ((v + sizeof(struct tcpa_event) + converted_event_size) >= limit))
-               return NULL;
-
-       (*pos)++;
-       return v;
-}
-
-static void tpm_bios_measurements_stop(struct seq_file *m, void *v)
-{
-}
-
-static int get_event_name(char *dest, struct tcpa_event *event,
-                       unsigned char * event_entry)
-{
-       const char *name = "";
-       /* 41 so there is room for 40 data and 1 nul */
-       char data[41] = "";
-       int i, n_len = 0, d_len = 0;
-       struct tcpa_pc_event *pc_event;
-
-       switch (do_endian_conversion(event->event_type)) {
-       case PREBOOT:
-       case POST_CODE:
-       case UNUSED:
-       case NO_ACTION:
-       case SCRTM_CONTENTS:
-       case SCRTM_VERSION:
-       case CPU_MICROCODE:
-       case PLATFORM_CONFIG_FLAGS:
-       case TABLE_OF_DEVICES:
-       case COMPACT_HASH:
-       case IPL:
-       case IPL_PARTITION_DATA:
-       case NONHOST_CODE:
-       case NONHOST_CONFIG:
-       case NONHOST_INFO:
-               name = tcpa_event_type_strings[do_endian_conversion
-                                               (event->event_type)];
-               n_len = strlen(name);
-               break;
-       case SEPARATOR:
-       case ACTION:
-               if (MAX_TEXT_EVENT >
-                   do_endian_conversion(event->event_size)) {
-                       name = event_entry;
-                       n_len = do_endian_conversion(event->event_size);
-               }
-               break;
-       case EVENT_TAG:
-               pc_event = (struct tcpa_pc_event *)event_entry;
-
-               /* ToDo Row data -> Base64 */
-
-               switch (do_endian_conversion(pc_event->event_id)) {
-               case SMBIOS:
-               case BIS_CERT:
-               case CMOS:
-               case NVRAM:
-               case OPTION_ROM_EXEC:
-               case OPTION_ROM_CONFIG:
-               case S_CRTM_VERSION:
-                       name = tcpa_pc_event_id_strings[do_endian_conversion
-                                                       (pc_event->event_id)];
-                       n_len = strlen(name);
-                       break;
-               /* hash data */
-               case POST_BIOS_ROM:
-               case ESCD:
-               case OPTION_ROM_MICROCODE:
-               case S_CRTM_CONTENTS:
-               case POST_CONTENTS:
-                       name = tcpa_pc_event_id_strings[do_endian_conversion
-                                                       (pc_event->event_id)];
-                       n_len = strlen(name);
-                       for (i = 0; i < 20; i++)
-                               d_len += sprintf(&data[2*i], "%02x",
-                                               pc_event->event_data[i]);
-                       break;
-               default:
-                       break;
-               }
-       default:
-               break;
-       }
-
-       return snprintf(dest, MAX_TEXT_EVENT, "[%.*s%.*s]",
-                       n_len, name, d_len, data);
-
-}
-
-static int tpm_binary_bios_measurements_show(struct seq_file *m, void *v)
-{
-       struct tcpa_event *event = v;
-       struct tcpa_event temp_event;
-       char *temp_ptr;
-       int i;
-
-       memcpy(&temp_event, event, sizeof(struct tcpa_event));
-
-       /* convert raw integers for endianness */
-       temp_event.pcr_index = do_endian_conversion(event->pcr_index);
-       temp_event.event_type = do_endian_conversion(event->event_type);
-       temp_event.event_size = do_endian_conversion(event->event_size);
-
-       temp_ptr = (char *) &temp_event;
-
-       for (i = 0; i < (sizeof(struct tcpa_event) - 1) ; i++)
-               seq_putc(m, temp_ptr[i]);
-
-       temp_ptr = (char *) v;
-
-       for (i = (sizeof(struct tcpa_event) - 1);
-            i < (sizeof(struct tcpa_event) + temp_event.event_size); i++)
-               seq_putc(m, temp_ptr[i]);
-
-       return 0;
-
-}
-
-static int tpm_bios_measurements_release(struct inode *inode,
-                                        struct file *file)
-{
-       struct seq_file *seq = (struct seq_file *)file->private_data;
-       struct tpm_chip *chip = (struct tpm_chip *)seq->private;
-
-       put_device(&chip->dev);
-
-       return seq_release(inode, file);
-}
-
-static int tpm_ascii_bios_measurements_show(struct seq_file *m, void *v)
-{
-       int len = 0;
-       char *eventname;
-       struct tcpa_event *event = v;
-       unsigned char *event_entry =
-           (unsigned char *)(v + sizeof(struct tcpa_event));
-
-       eventname = kmalloc(MAX_TEXT_EVENT, GFP_KERNEL);
-       if (!eventname) {
-               printk(KERN_ERR "%s: ERROR - No Memory for event name\n ",
-                      __func__);
-               return -EFAULT;
-       }
-
-       /* 1st: PCR */
-       seq_printf(m, "%2d ", do_endian_conversion(event->pcr_index));
-
-       /* 2nd: SHA1 */
-       seq_printf(m, "%20phN", event->pcr_value);
-
-       /* 3rd: event type identifier */
-       seq_printf(m, " %02x", do_endian_conversion(event->event_type));
-
-       len += get_event_name(eventname, event, event_entry);
-
-       /* 4th: eventname <= max + \'0' delimiter */
-       seq_printf(m, " %s\n", eventname);
-
-       kfree(eventname);
-       return 0;
-}
-
-static const struct seq_operations tpm_ascii_b_measurements_seqops = {
-       .start = tpm_bios_measurements_start,
-       .next = tpm_bios_measurements_next,
-       .stop = tpm_bios_measurements_stop,
-       .show = tpm_ascii_bios_measurements_show,
-};
-
-static const struct seq_operations tpm_binary_b_measurements_seqops = {
-       .start = tpm_bios_measurements_start,
-       .next = tpm_bios_measurements_next,
-       .stop = tpm_bios_measurements_stop,
-       .show = tpm_binary_bios_measurements_show,
-};
-
-static int tpm_bios_measurements_open(struct inode *inode,
-                                           struct file *file)
-{
-       int err;
-       struct seq_file *seq;
-       struct tpm_chip_seqops *chip_seqops;
-       const struct seq_operations *seqops;
-       struct tpm_chip *chip;
-
-       inode_lock(inode);
-       if (!inode->i_private) {
-               inode_unlock(inode);
-               return -ENODEV;
-       }
-       chip_seqops = (struct tpm_chip_seqops *)inode->i_private;
-       seqops = chip_seqops->seqops;
-       chip = chip_seqops->chip;
-       get_device(&chip->dev);
-       inode_unlock(inode);
-
-       /* now register seq file */
-       err = seq_open(file, seqops);
-       if (!err) {
-               seq = file->private_data;
-               seq->private = chip;
-       }
-
-       return err;
-}
-
-static const struct file_operations tpm_bios_measurements_ops = {
-       .owner = THIS_MODULE,
-       .open = tpm_bios_measurements_open,
-       .read = seq_read,
-       .llseek = seq_lseek,
-       .release = tpm_bios_measurements_release,
-};
-
-static int tpm_read_log(struct tpm_chip *chip)
-{
-       int rc;
-
-       if (chip->log.bios_event_log != NULL) {
-               dev_dbg(&chip->dev,
-                       "%s: ERROR - event log already initialized\n",
-                       __func__);
-               return -EFAULT;
-       }
-
-       rc = tpm_read_log_acpi(chip);
-       if (rc != -ENODEV)
-               return rc;
-
-       rc = tpm_read_log_efi(chip);
-       if (rc != -ENODEV)
-               return rc;
-
-       return tpm_read_log_of(chip);
-}
-
-/*
- * tpm_bios_log_setup() - Read the event log from the firmware
- * @chip: TPM chip to use.
- *
- * If an event log is found then the securityfs files are setup to
- * export it to userspace, otherwise nothing is done.
- *
- * Returns -ENODEV if the firmware has no event log or securityfs is not
- * supported.
- */
-int tpm_bios_log_setup(struct tpm_chip *chip)
-{
-       const char *name = dev_name(&chip->dev);
-       unsigned int cnt;
-       int log_version;
-       int rc = 0;
-
-       rc = tpm_read_log(chip);
-       if (rc < 0)
-               return rc;
-       log_version = rc;
-
-       cnt = 0;
-       chip->bios_dir[cnt] = securityfs_create_dir(name, NULL);
-       /* NOTE: securityfs_create_dir can return ENODEV if securityfs is
-        * compiled out. The caller should ignore the ENODEV return code.
-        */
-       if (IS_ERR(chip->bios_dir[cnt]))
-               goto err;
-       cnt++;
-
-       chip->bin_log_seqops.chip = chip;
-       if (log_version == EFI_TCG2_EVENT_LOG_FORMAT_TCG_2)
-               chip->bin_log_seqops.seqops =
-                       &tpm2_binary_b_measurements_seqops;
-       else
-               chip->bin_log_seqops.seqops =
-                       &tpm_binary_b_measurements_seqops;
-
-
-       chip->bios_dir[cnt] =
-           securityfs_create_file("binary_bios_measurements",
-                                  0440, chip->bios_dir[0],
-                                  (void *)&chip->bin_log_seqops,
-                                  &tpm_bios_measurements_ops);
-       if (IS_ERR(chip->bios_dir[cnt]))
-               goto err;
-       cnt++;
-
-       if (!(chip->flags & TPM_CHIP_FLAG_TPM2)) {
-
-               chip->ascii_log_seqops.chip = chip;
-               chip->ascii_log_seqops.seqops =
-                       &tpm_ascii_b_measurements_seqops;
-
-               chip->bios_dir[cnt] =
-                       securityfs_create_file("ascii_bios_measurements",
-                                              0440, chip->bios_dir[0],
-                                              (void *)&chip->ascii_log_seqops,
-                                              &tpm_bios_measurements_ops);
-               if (IS_ERR(chip->bios_dir[cnt]))
-                       goto err;
-               cnt++;
-       }
-
-       return 0;
-
-err:
-       rc = PTR_ERR(chip->bios_dir[cnt]);
-       chip->bios_dir[cnt] = NULL;
-       tpm_bios_log_teardown(chip);
-       return rc;
-}
-
-void tpm_bios_log_teardown(struct tpm_chip *chip)
-{
-       int i;
-       struct inode *inode;
-
-       /* securityfs_remove currently doesn't take care of handling sync
-        * between removal and opening of pseudo files. To handle this, a
-        * workaround is added by making i_private = NULL here during removal
-        * and to check it during open(), both within inode_lock()/unlock().
-        * This design ensures that open() either safely gets kref or fails.
-        */
-       for (i = (TPM_NUM_EVENT_LOG_FILES - 1); i >= 0; i--) {
-               if (chip->bios_dir[i]) {
-                       inode = d_inode(chip->bios_dir[i]);
-                       inode_lock(inode);
-                       inode->i_private = NULL;
-                       inode_unlock(inode);
-                       securityfs_remove(chip->bios_dir[i]);
-               }
-       }
-}
diff --git a/drivers/char/tpm/tpm2_eventlog.c b/drivers/char/tpm/tpm2_eventlog.c
deleted file mode 100644 (file)
index 1ce4411..0000000
+++ /dev/null
@@ -1,209 +0,0 @@
-/*
- * Copyright (C) 2016 IBM Corporation
- *
- * Authors:
- *      Nayna Jain <nayna@linux.vnet.ibm.com>
- *
- * Access to TPM 2.0 event log as written by Firmware.
- * It assumes that writer of event log has followed TCG Specification
- * for Family "2.0" and written the event data in little endian.
- * With that, it doesn't need any endian conversion for structure
- * content.
- *
- * 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/seq_file.h>
-#include <linux/fs.h>
-#include <linux/security.h>
-#include <linux/module.h>
-#include <linux/slab.h>
-#include <linux/tpm_eventlog.h>
-
-#include "tpm.h"
-
-/*
- * calc_tpm2_event_size() - calculate the event size, where event
- * is an entry in the TPM 2.0 event log. The event is of type Crypto
- * Agile Log Entry Format as defined in TCG EFI Protocol Specification
- * Family "2.0".
-
- * @event: event whose size is to be calculated.
- * @event_header: the first event in the event log.
- *
- * Returns size of the event. If it is an invalid event, returns 0.
- */
-static int calc_tpm2_event_size(struct tcg_pcr_event2 *event,
-                               struct tcg_pcr_event *event_header)
-{
-       struct tcg_efi_specid_event *efispecid;
-       struct tcg_event_field *event_field;
-       void *marker;
-       void *marker_start;
-       u32 halg_size;
-       size_t size;
-       u16 halg;
-       int i;
-       int j;
-
-       marker = event;
-       marker_start = marker;
-       marker = marker + sizeof(event->pcr_idx) + sizeof(event->event_type)
-               + sizeof(event->count);
-
-       efispecid = (struct tcg_efi_specid_event *)event_header->event;
-
-       /* Check if event is malformed. */
-       if (event->count > efispecid->num_algs)
-               return 0;
-
-       for (i = 0; i < event->count; i++) {
-               halg_size = sizeof(event->digests[i].alg_id);
-               memcpy(&halg, marker, halg_size);
-               marker = marker + halg_size;
-               for (j = 0; j < efispecid->num_algs; j++) {
-                       if (halg == efispecid->digest_sizes[j].alg_id) {
-                               marker +=
-                                       efispecid->digest_sizes[j].digest_size;
-                               break;
-                       }
-               }
-               /* Algorithm without known length. Such event is unparseable. */
-               if (j == efispecid->num_algs)
-                       return 0;
-       }
-
-       event_field = (struct tcg_event_field *)marker;
-       marker = marker + sizeof(event_field->event_size)
-               + event_field->event_size;
-       size = marker - marker_start;
-
-       if ((event->event_type == 0) && (event_field->event_size == 0))
-               return 0;
-
-       return size;
-}
-
-static void *tpm2_bios_measurements_start(struct seq_file *m, loff_t *pos)
-{
-       struct tpm_chip *chip = m->private;
-       struct tpm_bios_log *log = &chip->log;
-       void *addr = log->bios_event_log;
-       void *limit = log->bios_event_log_end;
-       struct tcg_pcr_event *event_header;
-       struct tcg_pcr_event2 *event;
-       size_t size;
-       int i;
-
-       event_header = addr;
-       size = sizeof(struct tcg_pcr_event) - sizeof(event_header->event)
-               + event_header->event_size;
-
-       if (*pos == 0) {
-               if (addr + size < limit) {
-                       if ((event_header->event_type == 0) &&
-                           (event_header->event_size == 0))
-                               return NULL;
-                       return SEQ_START_TOKEN;
-               }
-       }
-
-       if (*pos > 0) {
-               addr += size;
-               event = addr;
-               size = calc_tpm2_event_size(event, event_header);
-               if ((addr + size >=  limit) || (size == 0))
-                       return NULL;
-       }
-
-       for (i = 0; i < (*pos - 1); i++) {
-               event = addr;
-               size = calc_tpm2_event_size(event, event_header);
-
-               if ((addr + size >= limit) || (size == 0))
-                       return NULL;
-               addr += size;
-       }
-
-       return addr;
-}
-
-static void *tpm2_bios_measurements_next(struct seq_file *m, void *v,
-                                        loff_t *pos)
-{
-       struct tcg_pcr_event *event_header;
-       struct tcg_pcr_event2 *event;
-       struct tpm_chip *chip = m->private;
-       struct tpm_bios_log *log = &chip->log;
-       void *limit = log->bios_event_log_end;
-       size_t event_size;
-       void *marker;
-
-       event_header = log->bios_event_log;
-
-       if (v == SEQ_START_TOKEN) {
-               event_size = sizeof(struct tcg_pcr_event) -
-                       sizeof(event_header->event) + event_header->event_size;
-               marker = event_header;
-       } else {
-               event = v;
-               event_size = calc_tpm2_event_size(event, event_header);
-               if (event_size == 0)
-                       return NULL;
-               marker = event;
-       }
-
-       marker = marker + event_size;
-       if (marker >= limit)
-               return NULL;
-       v = marker;
-       event = v;
-
-       event_size = calc_tpm2_event_size(event, event_header);
-       if (((v + event_size) >= limit) || (event_size == 0))
-               return NULL;
-
-       (*pos)++;
-       return v;
-}
-
-static void tpm2_bios_measurements_stop(struct seq_file *m, void *v)
-{
-}
-
-static int tpm2_binary_bios_measurements_show(struct seq_file *m, void *v)
-{
-       struct tpm_chip *chip = m->private;
-       struct tpm_bios_log *log = &chip->log;
-       struct tcg_pcr_event *event_header = log->bios_event_log;
-       struct tcg_pcr_event2 *event = v;
-       void *temp_ptr;
-       size_t size;
-
-       if (v == SEQ_START_TOKEN) {
-               size = sizeof(struct tcg_pcr_event) -
-                       sizeof(event_header->event) + event_header->event_size;
-
-               temp_ptr = event_header;
-
-               if (size > 0)
-                       seq_write(m, temp_ptr, size);
-       } else {
-               size = calc_tpm2_event_size(event, event_header);
-               temp_ptr = event;
-               if (size > 0)
-                       seq_write(m, temp_ptr, size);
-       }
-
-       return 0;
-}
-
-const struct seq_operations tpm2_binary_b_measurements_seqops = {
-       .start = tpm2_bios_measurements_start,
-       .next = tpm2_bios_measurements_next,
-       .stop = tpm2_bios_measurements_stop,
-       .show = tpm2_binary_bios_measurements_show,
-};
diff --git a/drivers/char/tpm/tpm_eventlog_acpi.c b/drivers/char/tpm/tpm_eventlog_acpi.c
deleted file mode 100644 (file)
index 66f19e9..0000000
+++ /dev/null
@@ -1,112 +0,0 @@
-/*
- * 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>
- *     Nayna Jain <nayna@linux.vnet.ibm.com>
- *
- * Maintained by: <tpmdd-devel@lists.sourceforge.net>
- *
- * Access to the event log extended by the TCG BIOS of PC platform
- *
- * 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/seq_file.h>
-#include <linux/fs.h>
-#include <linux/security.h>
-#include <linux/module.h>
-#include <linux/slab.h>
-#include <linux/acpi.h>
-#include <linux/tpm_eventlog.h>
-
-#include "tpm.h"
-
-struct acpi_tcpa {
-       struct acpi_table_header hdr;
-       u16 platform_class;
-       union {
-               struct client_hdr {
-                       u32 log_max_len __packed;
-                       u64 log_start_addr __packed;
-               } client;
-               struct server_hdr {
-                       u16 reserved;
-                       u64 log_max_len __packed;
-                       u64 log_start_addr __packed;
-               } server;
-       };
-};
-
-/* read binary bios log */
-int tpm_read_log_acpi(struct tpm_chip *chip)
-{
-       struct acpi_tcpa *buff;
-       acpi_status status;
-       void __iomem *virt;
-       u64 len, start;
-       struct tpm_bios_log *log;
-
-       if (chip->flags & TPM_CHIP_FLAG_TPM2)
-               return -ENODEV;
-
-       log = &chip->log;
-
-       /* 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;
-
-       /* 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;
-       }
-       if (!len) {
-               dev_warn(&chip->dev, "%s: TCPA log area empty\n", __func__);
-               return -EIO;
-       }
-
-       /* malloc EventLog space */
-       log->bios_event_log = kmalloc(len, GFP_KERNEL);
-       if (!log->bios_event_log)
-               return -ENOMEM;
-
-       log->bios_event_log_end = log->bios_event_log + len;
-
-       virt = acpi_os_map_iomem(start, len);
-       if (!virt)
-               goto err;
-
-       memcpy_fromio(log->bios_event_log, virt, len);
-
-       acpi_os_unmap_iomem(virt, len);
-       return EFI_TCG2_EVENT_LOG_FORMAT_TCG_1_2;
-
-err:
-       kfree(log->bios_event_log);
-       log->bios_event_log = NULL;
-       return -EIO;
-
-}
diff --git a/drivers/char/tpm/tpm_eventlog_efi.c b/drivers/char/tpm/tpm_eventlog_efi.c
deleted file mode 100644 (file)
index e3f9ffd..0000000
+++ /dev/null
@@ -1,66 +0,0 @@
-/*
- * Copyright (C) 2017 Google
- *
- * Authors:
- *      Thiebaud Weksteen <tweek@google.com>
- *
- * 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/efi.h>
-#include <linux/tpm_eventlog.h>
-
-#include "tpm.h"
-
-/* read binary bios log from EFI configuration table */
-int tpm_read_log_efi(struct tpm_chip *chip)
-{
-
-       struct linux_efi_tpm_eventlog *log_tbl;
-       struct tpm_bios_log *log;
-       u32 log_size;
-       u8 tpm_log_version;
-
-       if (!(chip->flags & TPM_CHIP_FLAG_TPM2))
-               return -ENODEV;
-
-       if (efi.tpm_log == EFI_INVALID_TABLE_ADDR)
-               return -ENODEV;
-
-       log = &chip->log;
-
-       log_tbl = memremap(efi.tpm_log, sizeof(*log_tbl), MEMREMAP_WB);
-       if (!log_tbl) {
-               pr_err("Could not map UEFI TPM log table !\n");
-               return -ENOMEM;
-       }
-
-       log_size = log_tbl->size;
-       memunmap(log_tbl);
-
-       log_tbl = memremap(efi.tpm_log, sizeof(*log_tbl) + log_size,
-                          MEMREMAP_WB);
-       if (!log_tbl) {
-               pr_err("Could not map UEFI TPM log table payload!\n");
-               return -ENOMEM;
-       }
-
-       /* malloc EventLog space */
-       log->bios_event_log = kmalloc(log_size, GFP_KERNEL);
-       if (!log->bios_event_log)
-               goto err_memunmap;
-       memcpy(log->bios_event_log, log_tbl->log, log_size);
-       log->bios_event_log_end = log->bios_event_log + log_size;
-
-       tpm_log_version = log_tbl->version;
-       memunmap(log_tbl);
-       return tpm_log_version;
-
-err_memunmap:
-       memunmap(log_tbl);
-       return -ENOMEM;
-}
diff --git a/drivers/char/tpm/tpm_eventlog_of.c b/drivers/char/tpm/tpm_eventlog_of.c
deleted file mode 100644 (file)
index ea0f16f..0000000
+++ /dev/null
@@ -1,82 +0,0 @@
-/*
- * Copyright 2012 IBM Corporation
- *
- * Author: Ashley Lai <ashleydlai@gmail.com>
- *         Nayna Jain <nayna@linux.vnet.ibm.com>
- *
- * 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>
-#include <linux/tpm_eventlog.h>
-
-#include "tpm.h"
-
-int tpm_read_log_of(struct tpm_chip *chip)
-{
-       struct device_node *np;
-       const u32 *sizep;
-       const u64 *basep;
-       struct tpm_bios_log *log;
-       u32 size;
-       u64 base;
-
-       log = &chip->log;
-       if (chip->dev.parent && chip->dev.parent->of_node)
-               np = chip->dev.parent->of_node;
-       else
-               return -ENODEV;
-
-       if (of_property_read_bool(np, "powered-while-suspended"))
-               chip->flags |= TPM_CHIP_FLAG_ALWAYS_POWERED;
-
-       sizep = of_get_property(np, "linux,sml-size", NULL);
-       basep = of_get_property(np, "linux,sml-base", NULL);
-       if (sizep == NULL && basep == NULL)
-               return -ENODEV;
-       if (sizep == NULL || basep == NULL)
-               return -EIO;
-
-       /*
-        * 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((__force __be32 *)sizep);
-               base = be64_to_cpup((__force __be64 *)basep);
-       } else {
-               size = *sizep;
-               base = *basep;
-       }
-
-       if (size == 0) {
-               dev_warn(&chip->dev, "%s: Event log area empty\n", __func__);
-               return -EIO;
-       }
-
-       log->bios_event_log = kmalloc(size, GFP_KERNEL);
-       if (!log->bios_event_log)
-               return -ENOMEM;
-
-       log->bios_event_log_end = log->bios_event_log + size;
-
-       memcpy(log->bios_event_log, __va(base), size);
-
-       if (chip->flags & TPM_CHIP_FLAG_TPM2)
-               return EFI_TCG2_EVENT_LOG_FORMAT_TCG_2;
-       return EFI_TCG2_EVENT_LOG_FORMAT_TCG_1_2;
-}