Commit | Line | Data |
---|---|---|
e5dcd87f KY |
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 | * | |
10 | * Maintained by: <tpmdd-devel@lists.sourceforge.net> | |
11 | * | |
12 | * Access to the eventlog extended by the TCG BIOS of PC platform | |
13 | * | |
14 | * This program is free software; you can redistribute it and/or | |
15 | * modify it under the terms of the GNU General Public License | |
16 | * as published by the Free Software Foundation; either version | |
17 | * 2 of the License, or (at your option) any later version. | |
18 | * | |
19 | */ | |
20 | ||
21 | #include <linux/seq_file.h> | |
22 | #include <linux/fs.h> | |
23 | #include <linux/security.h> | |
24 | #include <linux/module.h> | |
25 | #include <linux/slab.h> | |
26 | #include <acpi/acpi.h> | |
27 | ||
28 | #include "tpm.h" | |
29 | #include "tpm_eventlog.h" | |
30 | ||
31 | struct acpi_tcpa { | |
32 | struct acpi_table_header hdr; | |
33 | u16 platform_class; | |
34 | union { | |
35 | struct client_hdr { | |
348df8db JG |
36 | u32 log_max_len __packed; |
37 | u64 log_start_addr __packed; | |
e5dcd87f KY |
38 | } client; |
39 | struct server_hdr { | |
40 | u16 reserved; | |
348df8db JG |
41 | u64 log_max_len __packed; |
42 | u64 log_start_addr __packed; | |
e5dcd87f KY |
43 | } server; |
44 | }; | |
45 | }; | |
46 | ||
47 | /* read binary bios log */ | |
48 | int read_log(struct tpm_bios_log *log) | |
49 | { | |
50 | struct acpi_tcpa *buff; | |
51 | acpi_status status; | |
a40695ed | 52 | void __iomem *virt; |
e5dcd87f KY |
53 | u64 len, start; |
54 | ||
55 | if (log->bios_event_log != NULL) { | |
56 | printk(KERN_ERR | |
57 | "%s: ERROR - Eventlog already initialized\n", | |
58 | __func__); | |
59 | return -EFAULT; | |
60 | } | |
61 | ||
62 | /* Find TCPA entry in RSDT (ACPI_LOGICAL_ADDRESSING) */ | |
63 | status = acpi_get_table(ACPI_SIG_TCPA, 1, | |
64 | (struct acpi_table_header **)&buff); | |
65 | ||
66 | if (ACPI_FAILURE(status)) { | |
67 | printk(KERN_ERR "%s: ERROR - Could not get TCPA table\n", | |
68 | __func__); | |
69 | return -EIO; | |
70 | } | |
71 | ||
72 | switch(buff->platform_class) { | |
73 | case BIOS_SERVER: | |
74 | len = buff->server.log_max_len; | |
75 | start = buff->server.log_start_addr; | |
76 | break; | |
77 | case BIOS_CLIENT: | |
78 | default: | |
79 | len = buff->client.log_max_len; | |
80 | start = buff->client.log_start_addr; | |
81 | break; | |
82 | } | |
83 | if (!len) { | |
84 | printk(KERN_ERR "%s: ERROR - TCPA log area empty\n", __func__); | |
85 | return -EIO; | |
86 | } | |
87 | ||
88 | /* malloc EventLog space */ | |
89 | log->bios_event_log = kmalloc(len, GFP_KERNEL); | |
90 | if (!log->bios_event_log) { | |
91 | printk("%s: ERROR - Not enough Memory for BIOS measurements\n", | |
92 | __func__); | |
93 | return -ENOMEM; | |
94 | } | |
95 | ||
96 | log->bios_event_log_end = log->bios_event_log + len; | |
97 | ||
98 | virt = acpi_os_map_memory(start, len); | |
f334ac8d JJ |
99 | if (!virt) { |
100 | kfree(log->bios_event_log); | |
101 | printk("%s: ERROR - Unable to map memory\n", __func__); | |
102 | return -EIO; | |
103 | } | |
e5dcd87f | 104 | |
a40695ed | 105 | memcpy_fromio(log->bios_event_log, virt, len); |
e5dcd87f KY |
106 | |
107 | acpi_os_unmap_memory(virt, len); | |
108 | return 0; | |
109 | } |