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