xref: /openbmc/linux/drivers/char/tpm/eventlog/acpi.c (revision a5a7daa5)
1 // SPDX-License-Identifier: GPL-2.0-or-later
2 /*
3  * Copyright (C) 2005 IBM Corporation
4  *
5  * Authors:
6  *	Seiji Munetoh <munetoh@jp.ibm.com>
7  *	Stefan Berger <stefanb@us.ibm.com>
8  *	Reiner Sailer <sailer@watson.ibm.com>
9  *	Kylene Hall <kjhall@us.ibm.com>
10  *	Nayna Jain <nayna@linux.vnet.ibm.com>
11  *
12  * Maintained by: <tpmdd-devel@lists.sourceforge.net>
13  *
14  * Access to the event log extended by the TCG BIOS of PC platform
15  */
16 
17 #include <linux/seq_file.h>
18 #include <linux/fs.h>
19 #include <linux/security.h>
20 #include <linux/module.h>
21 #include <linux/slab.h>
22 #include <linux/acpi.h>
23 #include <linux/tpm_eventlog.h>
24 
25 #include "../tpm.h"
26 #include "common.h"
27 
28 struct acpi_tcpa {
29 	struct acpi_table_header hdr;
30 	u16 platform_class;
31 	union {
32 		struct client_hdr {
33 			u32 log_max_len __packed;
34 			u64 log_start_addr __packed;
35 		} client;
36 		struct server_hdr {
37 			u16 reserved;
38 			u64 log_max_len __packed;
39 			u64 log_start_addr __packed;
40 		} server;
41 	};
42 };
43 
44 /* read binary bios log */
45 int tpm_read_log_acpi(struct tpm_chip *chip)
46 {
47 	struct acpi_tcpa *buff;
48 	acpi_status status;
49 	void __iomem *virt;
50 	u64 len, start;
51 	struct tpm_bios_log *log;
52 
53 	if (chip->flags & TPM_CHIP_FLAG_TPM2)
54 		return -ENODEV;
55 
56 	log = &chip->log;
57 
58 	/* Unfortuntely ACPI does not associate the event log with a specific
59 	 * TPM, like PPI. Thus all ACPI TPMs will read the same log.
60 	 */
61 	if (!chip->acpi_dev_handle)
62 		return -ENODEV;
63 
64 	/* Find TCPA entry in RSDT (ACPI_LOGICAL_ADDRESSING) */
65 	status = acpi_get_table(ACPI_SIG_TCPA, 1,
66 				(struct acpi_table_header **)&buff);
67 
68 	if (ACPI_FAILURE(status))
69 		return -ENODEV;
70 
71 	switch(buff->platform_class) {
72 	case BIOS_SERVER:
73 		len = buff->server.log_max_len;
74 		start = buff->server.log_start_addr;
75 		break;
76 	case BIOS_CLIENT:
77 	default:
78 		len = buff->client.log_max_len;
79 		start = buff->client.log_start_addr;
80 		break;
81 	}
82 	if (!len) {
83 		dev_warn(&chip->dev, "%s: TCPA log area empty\n", __func__);
84 		return -EIO;
85 	}
86 
87 	/* malloc EventLog space */
88 	log->bios_event_log = kmalloc(len, GFP_KERNEL);
89 	if (!log->bios_event_log)
90 		return -ENOMEM;
91 
92 	log->bios_event_log_end = log->bios_event_log + len;
93 
94 	virt = acpi_os_map_iomem(start, len);
95 	if (!virt)
96 		goto err;
97 
98 	memcpy_fromio(log->bios_event_log, virt, len);
99 
100 	acpi_os_unmap_iomem(virt, len);
101 	return EFI_TCG2_EVENT_LOG_FORMAT_TCG_1_2;
102 
103 err:
104 	kfree(log->bios_event_log);
105 	log->bios_event_log = NULL;
106 	return -EIO;
107 
108 }
109