xref: /linux/drivers/char/tpm/eventlog/tpm1.c (revision 0bfb23746052168620c5b52f49d8a47c3bb022fa)
1*0bfb2374SThiebaud Weksteen /*
2*0bfb2374SThiebaud Weksteen  * Copyright (C) 2005, 2012 IBM Corporation
3*0bfb2374SThiebaud Weksteen  *
4*0bfb2374SThiebaud Weksteen  * Authors:
5*0bfb2374SThiebaud Weksteen  *	Kent Yoder <key@linux.vnet.ibm.com>
6*0bfb2374SThiebaud Weksteen  *	Seiji Munetoh <munetoh@jp.ibm.com>
7*0bfb2374SThiebaud Weksteen  *	Stefan Berger <stefanb@us.ibm.com>
8*0bfb2374SThiebaud Weksteen  *	Reiner Sailer <sailer@watson.ibm.com>
9*0bfb2374SThiebaud Weksteen  *	Kylene Hall <kjhall@us.ibm.com>
10*0bfb2374SThiebaud Weksteen  *	Nayna Jain <nayna@linux.vnet.ibm.com>
11*0bfb2374SThiebaud Weksteen  *
12*0bfb2374SThiebaud Weksteen  * Maintained by: <tpmdd-devel@lists.sourceforge.net>
13*0bfb2374SThiebaud Weksteen  *
14*0bfb2374SThiebaud Weksteen  * Access to the event log created by a system's firmware / BIOS
15*0bfb2374SThiebaud Weksteen  *
16*0bfb2374SThiebaud Weksteen  * This program is free software; you can redistribute it and/or
17*0bfb2374SThiebaud Weksteen  * modify it under the terms of the GNU General Public License
18*0bfb2374SThiebaud Weksteen  * as published by the Free Software Foundation; either version
19*0bfb2374SThiebaud Weksteen  * 2 of the License, or (at your option) any later version.
20*0bfb2374SThiebaud Weksteen  *
21*0bfb2374SThiebaud Weksteen  */
22*0bfb2374SThiebaud Weksteen 
23*0bfb2374SThiebaud Weksteen #include <linux/seq_file.h>
24*0bfb2374SThiebaud Weksteen #include <linux/efi.h>
25*0bfb2374SThiebaud Weksteen #include <linux/fs.h>
26*0bfb2374SThiebaud Weksteen #include <linux/security.h>
27*0bfb2374SThiebaud Weksteen #include <linux/module.h>
28*0bfb2374SThiebaud Weksteen #include <linux/slab.h>
29*0bfb2374SThiebaud Weksteen #include <linux/tpm_eventlog.h>
30*0bfb2374SThiebaud Weksteen 
31*0bfb2374SThiebaud Weksteen #include "../tpm.h"
32*0bfb2374SThiebaud Weksteen 
33*0bfb2374SThiebaud Weksteen 
34*0bfb2374SThiebaud Weksteen static const char* tcpa_event_type_strings[] = {
35*0bfb2374SThiebaud Weksteen 	"PREBOOT",
36*0bfb2374SThiebaud Weksteen 	"POST CODE",
37*0bfb2374SThiebaud Weksteen 	"",
38*0bfb2374SThiebaud Weksteen 	"NO ACTION",
39*0bfb2374SThiebaud Weksteen 	"SEPARATOR",
40*0bfb2374SThiebaud Weksteen 	"ACTION",
41*0bfb2374SThiebaud Weksteen 	"EVENT TAG",
42*0bfb2374SThiebaud Weksteen 	"S-CRTM Contents",
43*0bfb2374SThiebaud Weksteen 	"S-CRTM Version",
44*0bfb2374SThiebaud Weksteen 	"CPU Microcode",
45*0bfb2374SThiebaud Weksteen 	"Platform Config Flags",
46*0bfb2374SThiebaud Weksteen 	"Table of Devices",
47*0bfb2374SThiebaud Weksteen 	"Compact Hash",
48*0bfb2374SThiebaud Weksteen 	"IPL",
49*0bfb2374SThiebaud Weksteen 	"IPL Partition Data",
50*0bfb2374SThiebaud Weksteen 	"Non-Host Code",
51*0bfb2374SThiebaud Weksteen 	"Non-Host Config",
52*0bfb2374SThiebaud Weksteen 	"Non-Host Info"
53*0bfb2374SThiebaud Weksteen };
54*0bfb2374SThiebaud Weksteen 
55*0bfb2374SThiebaud Weksteen static const char* tcpa_pc_event_id_strings[] = {
56*0bfb2374SThiebaud Weksteen 	"",
57*0bfb2374SThiebaud Weksteen 	"SMBIOS",
58*0bfb2374SThiebaud Weksteen 	"BIS Certificate",
59*0bfb2374SThiebaud Weksteen 	"POST BIOS ",
60*0bfb2374SThiebaud Weksteen 	"ESCD ",
61*0bfb2374SThiebaud Weksteen 	"CMOS",
62*0bfb2374SThiebaud Weksteen 	"NVRAM",
63*0bfb2374SThiebaud Weksteen 	"Option ROM",
64*0bfb2374SThiebaud Weksteen 	"Option ROM config",
65*0bfb2374SThiebaud Weksteen 	"",
66*0bfb2374SThiebaud Weksteen 	"Option ROM microcode ",
67*0bfb2374SThiebaud Weksteen 	"S-CRTM Version",
68*0bfb2374SThiebaud Weksteen 	"S-CRTM Contents ",
69*0bfb2374SThiebaud Weksteen 	"POST Contents ",
70*0bfb2374SThiebaud Weksteen 	"Table of Devices",
71*0bfb2374SThiebaud Weksteen };
72*0bfb2374SThiebaud Weksteen 
73*0bfb2374SThiebaud Weksteen /* returns pointer to start of pos. entry of tcg log */
74*0bfb2374SThiebaud Weksteen static void *tpm_bios_measurements_start(struct seq_file *m, loff_t *pos)
75*0bfb2374SThiebaud Weksteen {
76*0bfb2374SThiebaud Weksteen 	loff_t i;
77*0bfb2374SThiebaud Weksteen 	struct tpm_chip *chip = m->private;
78*0bfb2374SThiebaud Weksteen 	struct tpm_bios_log *log = &chip->log;
79*0bfb2374SThiebaud Weksteen 	void *addr = log->bios_event_log;
80*0bfb2374SThiebaud Weksteen 	void *limit = log->bios_event_log_end;
81*0bfb2374SThiebaud Weksteen 	struct tcpa_event *event;
82*0bfb2374SThiebaud Weksteen 	u32 converted_event_size;
83*0bfb2374SThiebaud Weksteen 	u32 converted_event_type;
84*0bfb2374SThiebaud Weksteen 
85*0bfb2374SThiebaud Weksteen 
86*0bfb2374SThiebaud Weksteen 	/* read over *pos measurements */
87*0bfb2374SThiebaud Weksteen 	for (i = 0; i < *pos; i++) {
88*0bfb2374SThiebaud Weksteen 		event = addr;
89*0bfb2374SThiebaud Weksteen 
90*0bfb2374SThiebaud Weksteen 		converted_event_size =
91*0bfb2374SThiebaud Weksteen 		    do_endian_conversion(event->event_size);
92*0bfb2374SThiebaud Weksteen 		converted_event_type =
93*0bfb2374SThiebaud Weksteen 		    do_endian_conversion(event->event_type);
94*0bfb2374SThiebaud Weksteen 
95*0bfb2374SThiebaud Weksteen 		if ((addr + sizeof(struct tcpa_event)) < limit) {
96*0bfb2374SThiebaud Weksteen 			if ((converted_event_type == 0) &&
97*0bfb2374SThiebaud Weksteen 			    (converted_event_size == 0))
98*0bfb2374SThiebaud Weksteen 				return NULL;
99*0bfb2374SThiebaud Weksteen 			addr += (sizeof(struct tcpa_event) +
100*0bfb2374SThiebaud Weksteen 				 converted_event_size);
101*0bfb2374SThiebaud Weksteen 		}
102*0bfb2374SThiebaud Weksteen 	}
103*0bfb2374SThiebaud Weksteen 
104*0bfb2374SThiebaud Weksteen 	/* now check if current entry is valid */
105*0bfb2374SThiebaud Weksteen 	if ((addr + sizeof(struct tcpa_event)) >= limit)
106*0bfb2374SThiebaud Weksteen 		return NULL;
107*0bfb2374SThiebaud Weksteen 
108*0bfb2374SThiebaud Weksteen 	event = addr;
109*0bfb2374SThiebaud Weksteen 
110*0bfb2374SThiebaud Weksteen 	converted_event_size = do_endian_conversion(event->event_size);
111*0bfb2374SThiebaud Weksteen 	converted_event_type = do_endian_conversion(event->event_type);
112*0bfb2374SThiebaud Weksteen 
113*0bfb2374SThiebaud Weksteen 	if (((converted_event_type == 0) && (converted_event_size == 0))
114*0bfb2374SThiebaud Weksteen 	    || ((addr + sizeof(struct tcpa_event) + converted_event_size)
115*0bfb2374SThiebaud Weksteen 		>= limit))
116*0bfb2374SThiebaud Weksteen 		return NULL;
117*0bfb2374SThiebaud Weksteen 
118*0bfb2374SThiebaud Weksteen 	return addr;
119*0bfb2374SThiebaud Weksteen }
120*0bfb2374SThiebaud Weksteen 
121*0bfb2374SThiebaud Weksteen static void *tpm_bios_measurements_next(struct seq_file *m, void *v,
122*0bfb2374SThiebaud Weksteen 					loff_t *pos)
123*0bfb2374SThiebaud Weksteen {
124*0bfb2374SThiebaud Weksteen 	struct tcpa_event *event = v;
125*0bfb2374SThiebaud Weksteen 	struct tpm_chip *chip = m->private;
126*0bfb2374SThiebaud Weksteen 	struct tpm_bios_log *log = &chip->log;
127*0bfb2374SThiebaud Weksteen 	void *limit = log->bios_event_log_end;
128*0bfb2374SThiebaud Weksteen 	u32 converted_event_size;
129*0bfb2374SThiebaud Weksteen 	u32 converted_event_type;
130*0bfb2374SThiebaud Weksteen 
131*0bfb2374SThiebaud Weksteen 	converted_event_size = do_endian_conversion(event->event_size);
132*0bfb2374SThiebaud Weksteen 
133*0bfb2374SThiebaud Weksteen 	v += sizeof(struct tcpa_event) + converted_event_size;
134*0bfb2374SThiebaud Weksteen 
135*0bfb2374SThiebaud Weksteen 	/* now check if current entry is valid */
136*0bfb2374SThiebaud Weksteen 	if ((v + sizeof(struct tcpa_event)) >= limit)
137*0bfb2374SThiebaud Weksteen 		return NULL;
138*0bfb2374SThiebaud Weksteen 
139*0bfb2374SThiebaud Weksteen 	event = v;
140*0bfb2374SThiebaud Weksteen 
141*0bfb2374SThiebaud Weksteen 	converted_event_size = do_endian_conversion(event->event_size);
142*0bfb2374SThiebaud Weksteen 	converted_event_type = do_endian_conversion(event->event_type);
143*0bfb2374SThiebaud Weksteen 
144*0bfb2374SThiebaud Weksteen 	if (((converted_event_type == 0) && (converted_event_size == 0)) ||
145*0bfb2374SThiebaud Weksteen 	    ((v + sizeof(struct tcpa_event) + converted_event_size) >= limit))
146*0bfb2374SThiebaud Weksteen 		return NULL;
147*0bfb2374SThiebaud Weksteen 
148*0bfb2374SThiebaud Weksteen 	(*pos)++;
149*0bfb2374SThiebaud Weksteen 	return v;
150*0bfb2374SThiebaud Weksteen }
151*0bfb2374SThiebaud Weksteen 
152*0bfb2374SThiebaud Weksteen static void tpm_bios_measurements_stop(struct seq_file *m, void *v)
153*0bfb2374SThiebaud Weksteen {
154*0bfb2374SThiebaud Weksteen }
155*0bfb2374SThiebaud Weksteen 
156*0bfb2374SThiebaud Weksteen static int get_event_name(char *dest, struct tcpa_event *event,
157*0bfb2374SThiebaud Weksteen 			unsigned char * event_entry)
158*0bfb2374SThiebaud Weksteen {
159*0bfb2374SThiebaud Weksteen 	const char *name = "";
160*0bfb2374SThiebaud Weksteen 	/* 41 so there is room for 40 data and 1 nul */
161*0bfb2374SThiebaud Weksteen 	char data[41] = "";
162*0bfb2374SThiebaud Weksteen 	int i, n_len = 0, d_len = 0;
163*0bfb2374SThiebaud Weksteen 	struct tcpa_pc_event *pc_event;
164*0bfb2374SThiebaud Weksteen 
165*0bfb2374SThiebaud Weksteen 	switch (do_endian_conversion(event->event_type)) {
166*0bfb2374SThiebaud Weksteen 	case PREBOOT:
167*0bfb2374SThiebaud Weksteen 	case POST_CODE:
168*0bfb2374SThiebaud Weksteen 	case UNUSED:
169*0bfb2374SThiebaud Weksteen 	case NO_ACTION:
170*0bfb2374SThiebaud Weksteen 	case SCRTM_CONTENTS:
171*0bfb2374SThiebaud Weksteen 	case SCRTM_VERSION:
172*0bfb2374SThiebaud Weksteen 	case CPU_MICROCODE:
173*0bfb2374SThiebaud Weksteen 	case PLATFORM_CONFIG_FLAGS:
174*0bfb2374SThiebaud Weksteen 	case TABLE_OF_DEVICES:
175*0bfb2374SThiebaud Weksteen 	case COMPACT_HASH:
176*0bfb2374SThiebaud Weksteen 	case IPL:
177*0bfb2374SThiebaud Weksteen 	case IPL_PARTITION_DATA:
178*0bfb2374SThiebaud Weksteen 	case NONHOST_CODE:
179*0bfb2374SThiebaud Weksteen 	case NONHOST_CONFIG:
180*0bfb2374SThiebaud Weksteen 	case NONHOST_INFO:
181*0bfb2374SThiebaud Weksteen 		name = tcpa_event_type_strings[do_endian_conversion
182*0bfb2374SThiebaud Weksteen 						(event->event_type)];
183*0bfb2374SThiebaud Weksteen 		n_len = strlen(name);
184*0bfb2374SThiebaud Weksteen 		break;
185*0bfb2374SThiebaud Weksteen 	case SEPARATOR:
186*0bfb2374SThiebaud Weksteen 	case ACTION:
187*0bfb2374SThiebaud Weksteen 		if (MAX_TEXT_EVENT >
188*0bfb2374SThiebaud Weksteen 		    do_endian_conversion(event->event_size)) {
189*0bfb2374SThiebaud Weksteen 			name = event_entry;
190*0bfb2374SThiebaud Weksteen 			n_len = do_endian_conversion(event->event_size);
191*0bfb2374SThiebaud Weksteen 		}
192*0bfb2374SThiebaud Weksteen 		break;
193*0bfb2374SThiebaud Weksteen 	case EVENT_TAG:
194*0bfb2374SThiebaud Weksteen 		pc_event = (struct tcpa_pc_event *)event_entry;
195*0bfb2374SThiebaud Weksteen 
196*0bfb2374SThiebaud Weksteen 		/* ToDo Row data -> Base64 */
197*0bfb2374SThiebaud Weksteen 
198*0bfb2374SThiebaud Weksteen 		switch (do_endian_conversion(pc_event->event_id)) {
199*0bfb2374SThiebaud Weksteen 		case SMBIOS:
200*0bfb2374SThiebaud Weksteen 		case BIS_CERT:
201*0bfb2374SThiebaud Weksteen 		case CMOS:
202*0bfb2374SThiebaud Weksteen 		case NVRAM:
203*0bfb2374SThiebaud Weksteen 		case OPTION_ROM_EXEC:
204*0bfb2374SThiebaud Weksteen 		case OPTION_ROM_CONFIG:
205*0bfb2374SThiebaud Weksteen 		case S_CRTM_VERSION:
206*0bfb2374SThiebaud Weksteen 			name = tcpa_pc_event_id_strings[do_endian_conversion
207*0bfb2374SThiebaud Weksteen 							(pc_event->event_id)];
208*0bfb2374SThiebaud Weksteen 			n_len = strlen(name);
209*0bfb2374SThiebaud Weksteen 			break;
210*0bfb2374SThiebaud Weksteen 		/* hash data */
211*0bfb2374SThiebaud Weksteen 		case POST_BIOS_ROM:
212*0bfb2374SThiebaud Weksteen 		case ESCD:
213*0bfb2374SThiebaud Weksteen 		case OPTION_ROM_MICROCODE:
214*0bfb2374SThiebaud Weksteen 		case S_CRTM_CONTENTS:
215*0bfb2374SThiebaud Weksteen 		case POST_CONTENTS:
216*0bfb2374SThiebaud Weksteen 			name = tcpa_pc_event_id_strings[do_endian_conversion
217*0bfb2374SThiebaud Weksteen 							(pc_event->event_id)];
218*0bfb2374SThiebaud Weksteen 			n_len = strlen(name);
219*0bfb2374SThiebaud Weksteen 			for (i = 0; i < 20; i++)
220*0bfb2374SThiebaud Weksteen 				d_len += sprintf(&data[2*i], "%02x",
221*0bfb2374SThiebaud Weksteen 						pc_event->event_data[i]);
222*0bfb2374SThiebaud Weksteen 			break;
223*0bfb2374SThiebaud Weksteen 		default:
224*0bfb2374SThiebaud Weksteen 			break;
225*0bfb2374SThiebaud Weksteen 		}
226*0bfb2374SThiebaud Weksteen 	default:
227*0bfb2374SThiebaud Weksteen 		break;
228*0bfb2374SThiebaud Weksteen 	}
229*0bfb2374SThiebaud Weksteen 
230*0bfb2374SThiebaud Weksteen 	return snprintf(dest, MAX_TEXT_EVENT, "[%.*s%.*s]",
231*0bfb2374SThiebaud Weksteen 			n_len, name, d_len, data);
232*0bfb2374SThiebaud Weksteen 
233*0bfb2374SThiebaud Weksteen }
234*0bfb2374SThiebaud Weksteen 
235*0bfb2374SThiebaud Weksteen static int tpm_binary_bios_measurements_show(struct seq_file *m, void *v)
236*0bfb2374SThiebaud Weksteen {
237*0bfb2374SThiebaud Weksteen 	struct tcpa_event *event = v;
238*0bfb2374SThiebaud Weksteen 	struct tcpa_event temp_event;
239*0bfb2374SThiebaud Weksteen 	char *temp_ptr;
240*0bfb2374SThiebaud Weksteen 	int i;
241*0bfb2374SThiebaud Weksteen 
242*0bfb2374SThiebaud Weksteen 	memcpy(&temp_event, event, sizeof(struct tcpa_event));
243*0bfb2374SThiebaud Weksteen 
244*0bfb2374SThiebaud Weksteen 	/* convert raw integers for endianness */
245*0bfb2374SThiebaud Weksteen 	temp_event.pcr_index = do_endian_conversion(event->pcr_index);
246*0bfb2374SThiebaud Weksteen 	temp_event.event_type = do_endian_conversion(event->event_type);
247*0bfb2374SThiebaud Weksteen 	temp_event.event_size = do_endian_conversion(event->event_size);
248*0bfb2374SThiebaud Weksteen 
249*0bfb2374SThiebaud Weksteen 	temp_ptr = (char *) &temp_event;
250*0bfb2374SThiebaud Weksteen 
251*0bfb2374SThiebaud Weksteen 	for (i = 0; i < (sizeof(struct tcpa_event) - 1) ; i++)
252*0bfb2374SThiebaud Weksteen 		seq_putc(m, temp_ptr[i]);
253*0bfb2374SThiebaud Weksteen 
254*0bfb2374SThiebaud Weksteen 	temp_ptr = (char *) v;
255*0bfb2374SThiebaud Weksteen 
256*0bfb2374SThiebaud Weksteen 	for (i = (sizeof(struct tcpa_event) - 1);
257*0bfb2374SThiebaud Weksteen 	     i < (sizeof(struct tcpa_event) + temp_event.event_size); i++)
258*0bfb2374SThiebaud Weksteen 		seq_putc(m, temp_ptr[i]);
259*0bfb2374SThiebaud Weksteen 
260*0bfb2374SThiebaud Weksteen 	return 0;
261*0bfb2374SThiebaud Weksteen 
262*0bfb2374SThiebaud Weksteen }
263*0bfb2374SThiebaud Weksteen 
264*0bfb2374SThiebaud Weksteen static int tpm_bios_measurements_release(struct inode *inode,
265*0bfb2374SThiebaud Weksteen 					 struct file *file)
266*0bfb2374SThiebaud Weksteen {
267*0bfb2374SThiebaud Weksteen 	struct seq_file *seq = (struct seq_file *)file->private_data;
268*0bfb2374SThiebaud Weksteen 	struct tpm_chip *chip = (struct tpm_chip *)seq->private;
269*0bfb2374SThiebaud Weksteen 
270*0bfb2374SThiebaud Weksteen 	put_device(&chip->dev);
271*0bfb2374SThiebaud Weksteen 
272*0bfb2374SThiebaud Weksteen 	return seq_release(inode, file);
273*0bfb2374SThiebaud Weksteen }
274*0bfb2374SThiebaud Weksteen 
275*0bfb2374SThiebaud Weksteen static int tpm_ascii_bios_measurements_show(struct seq_file *m, void *v)
276*0bfb2374SThiebaud Weksteen {
277*0bfb2374SThiebaud Weksteen 	int len = 0;
278*0bfb2374SThiebaud Weksteen 	char *eventname;
279*0bfb2374SThiebaud Weksteen 	struct tcpa_event *event = v;
280*0bfb2374SThiebaud Weksteen 	unsigned char *event_entry =
281*0bfb2374SThiebaud Weksteen 	    (unsigned char *)(v + sizeof(struct tcpa_event));
282*0bfb2374SThiebaud Weksteen 
283*0bfb2374SThiebaud Weksteen 	eventname = kmalloc(MAX_TEXT_EVENT, GFP_KERNEL);
284*0bfb2374SThiebaud Weksteen 	if (!eventname) {
285*0bfb2374SThiebaud Weksteen 		printk(KERN_ERR "%s: ERROR - No Memory for event name\n ",
286*0bfb2374SThiebaud Weksteen 		       __func__);
287*0bfb2374SThiebaud Weksteen 		return -EFAULT;
288*0bfb2374SThiebaud Weksteen 	}
289*0bfb2374SThiebaud Weksteen 
290*0bfb2374SThiebaud Weksteen 	/* 1st: PCR */
291*0bfb2374SThiebaud Weksteen 	seq_printf(m, "%2d ", do_endian_conversion(event->pcr_index));
292*0bfb2374SThiebaud Weksteen 
293*0bfb2374SThiebaud Weksteen 	/* 2nd: SHA1 */
294*0bfb2374SThiebaud Weksteen 	seq_printf(m, "%20phN", event->pcr_value);
295*0bfb2374SThiebaud Weksteen 
296*0bfb2374SThiebaud Weksteen 	/* 3rd: event type identifier */
297*0bfb2374SThiebaud Weksteen 	seq_printf(m, " %02x", do_endian_conversion(event->event_type));
298*0bfb2374SThiebaud Weksteen 
299*0bfb2374SThiebaud Weksteen 	len += get_event_name(eventname, event, event_entry);
300*0bfb2374SThiebaud Weksteen 
301*0bfb2374SThiebaud Weksteen 	/* 4th: eventname <= max + \'0' delimiter */
302*0bfb2374SThiebaud Weksteen 	seq_printf(m, " %s\n", eventname);
303*0bfb2374SThiebaud Weksteen 
304*0bfb2374SThiebaud Weksteen 	kfree(eventname);
305*0bfb2374SThiebaud Weksteen 	return 0;
306*0bfb2374SThiebaud Weksteen }
307*0bfb2374SThiebaud Weksteen 
308*0bfb2374SThiebaud Weksteen static const struct seq_operations tpm_ascii_b_measurements_seqops = {
309*0bfb2374SThiebaud Weksteen 	.start = tpm_bios_measurements_start,
310*0bfb2374SThiebaud Weksteen 	.next = tpm_bios_measurements_next,
311*0bfb2374SThiebaud Weksteen 	.stop = tpm_bios_measurements_stop,
312*0bfb2374SThiebaud Weksteen 	.show = tpm_ascii_bios_measurements_show,
313*0bfb2374SThiebaud Weksteen };
314*0bfb2374SThiebaud Weksteen 
315*0bfb2374SThiebaud Weksteen static const struct seq_operations tpm_binary_b_measurements_seqops = {
316*0bfb2374SThiebaud Weksteen 	.start = tpm_bios_measurements_start,
317*0bfb2374SThiebaud Weksteen 	.next = tpm_bios_measurements_next,
318*0bfb2374SThiebaud Weksteen 	.stop = tpm_bios_measurements_stop,
319*0bfb2374SThiebaud Weksteen 	.show = tpm_binary_bios_measurements_show,
320*0bfb2374SThiebaud Weksteen };
321*0bfb2374SThiebaud Weksteen 
322*0bfb2374SThiebaud Weksteen static int tpm_bios_measurements_open(struct inode *inode,
323*0bfb2374SThiebaud Weksteen 					    struct file *file)
324*0bfb2374SThiebaud Weksteen {
325*0bfb2374SThiebaud Weksteen 	int err;
326*0bfb2374SThiebaud Weksteen 	struct seq_file *seq;
327*0bfb2374SThiebaud Weksteen 	struct tpm_chip_seqops *chip_seqops;
328*0bfb2374SThiebaud Weksteen 	const struct seq_operations *seqops;
329*0bfb2374SThiebaud Weksteen 	struct tpm_chip *chip;
330*0bfb2374SThiebaud Weksteen 
331*0bfb2374SThiebaud Weksteen 	inode_lock(inode);
332*0bfb2374SThiebaud Weksteen 	if (!inode->i_private) {
333*0bfb2374SThiebaud Weksteen 		inode_unlock(inode);
334*0bfb2374SThiebaud Weksteen 		return -ENODEV;
335*0bfb2374SThiebaud Weksteen 	}
336*0bfb2374SThiebaud Weksteen 	chip_seqops = (struct tpm_chip_seqops *)inode->i_private;
337*0bfb2374SThiebaud Weksteen 	seqops = chip_seqops->seqops;
338*0bfb2374SThiebaud Weksteen 	chip = chip_seqops->chip;
339*0bfb2374SThiebaud Weksteen 	get_device(&chip->dev);
340*0bfb2374SThiebaud Weksteen 	inode_unlock(inode);
341*0bfb2374SThiebaud Weksteen 
342*0bfb2374SThiebaud Weksteen 	/* now register seq file */
343*0bfb2374SThiebaud Weksteen 	err = seq_open(file, seqops);
344*0bfb2374SThiebaud Weksteen 	if (!err) {
345*0bfb2374SThiebaud Weksteen 		seq = file->private_data;
346*0bfb2374SThiebaud Weksteen 		seq->private = chip;
347*0bfb2374SThiebaud Weksteen 	}
348*0bfb2374SThiebaud Weksteen 
349*0bfb2374SThiebaud Weksteen 	return err;
350*0bfb2374SThiebaud Weksteen }
351*0bfb2374SThiebaud Weksteen 
352*0bfb2374SThiebaud Weksteen static const struct file_operations tpm_bios_measurements_ops = {
353*0bfb2374SThiebaud Weksteen 	.owner = THIS_MODULE,
354*0bfb2374SThiebaud Weksteen 	.open = tpm_bios_measurements_open,
355*0bfb2374SThiebaud Weksteen 	.read = seq_read,
356*0bfb2374SThiebaud Weksteen 	.llseek = seq_lseek,
357*0bfb2374SThiebaud Weksteen 	.release = tpm_bios_measurements_release,
358*0bfb2374SThiebaud Weksteen };
359*0bfb2374SThiebaud Weksteen 
360*0bfb2374SThiebaud Weksteen static int tpm_read_log(struct tpm_chip *chip)
361*0bfb2374SThiebaud Weksteen {
362*0bfb2374SThiebaud Weksteen 	int rc;
363*0bfb2374SThiebaud Weksteen 
364*0bfb2374SThiebaud Weksteen 	if (chip->log.bios_event_log != NULL) {
365*0bfb2374SThiebaud Weksteen 		dev_dbg(&chip->dev,
366*0bfb2374SThiebaud Weksteen 			"%s: ERROR - event log already initialized\n",
367*0bfb2374SThiebaud Weksteen 			__func__);
368*0bfb2374SThiebaud Weksteen 		return -EFAULT;
369*0bfb2374SThiebaud Weksteen 	}
370*0bfb2374SThiebaud Weksteen 
371*0bfb2374SThiebaud Weksteen 	rc = tpm_read_log_acpi(chip);
372*0bfb2374SThiebaud Weksteen 	if (rc != -ENODEV)
373*0bfb2374SThiebaud Weksteen 		return rc;
374*0bfb2374SThiebaud Weksteen 
375*0bfb2374SThiebaud Weksteen 	rc = tpm_read_log_efi(chip);
376*0bfb2374SThiebaud Weksteen 	if (rc != -ENODEV)
377*0bfb2374SThiebaud Weksteen 		return rc;
378*0bfb2374SThiebaud Weksteen 
379*0bfb2374SThiebaud Weksteen 	return tpm_read_log_of(chip);
380*0bfb2374SThiebaud Weksteen }
381*0bfb2374SThiebaud Weksteen 
382*0bfb2374SThiebaud Weksteen /*
383*0bfb2374SThiebaud Weksteen  * tpm_bios_log_setup() - Read the event log from the firmware
384*0bfb2374SThiebaud Weksteen  * @chip: TPM chip to use.
385*0bfb2374SThiebaud Weksteen  *
386*0bfb2374SThiebaud Weksteen  * If an event log is found then the securityfs files are setup to
387*0bfb2374SThiebaud Weksteen  * export it to userspace, otherwise nothing is done.
388*0bfb2374SThiebaud Weksteen  *
389*0bfb2374SThiebaud Weksteen  * Returns -ENODEV if the firmware has no event log or securityfs is not
390*0bfb2374SThiebaud Weksteen  * supported.
391*0bfb2374SThiebaud Weksteen  */
392*0bfb2374SThiebaud Weksteen int tpm_bios_log_setup(struct tpm_chip *chip)
393*0bfb2374SThiebaud Weksteen {
394*0bfb2374SThiebaud Weksteen 	const char *name = dev_name(&chip->dev);
395*0bfb2374SThiebaud Weksteen 	unsigned int cnt;
396*0bfb2374SThiebaud Weksteen 	int log_version;
397*0bfb2374SThiebaud Weksteen 	int rc = 0;
398*0bfb2374SThiebaud Weksteen 
399*0bfb2374SThiebaud Weksteen 	rc = tpm_read_log(chip);
400*0bfb2374SThiebaud Weksteen 	if (rc < 0)
401*0bfb2374SThiebaud Weksteen 		return rc;
402*0bfb2374SThiebaud Weksteen 	log_version = rc;
403*0bfb2374SThiebaud Weksteen 
404*0bfb2374SThiebaud Weksteen 	cnt = 0;
405*0bfb2374SThiebaud Weksteen 	chip->bios_dir[cnt] = securityfs_create_dir(name, NULL);
406*0bfb2374SThiebaud Weksteen 	/* NOTE: securityfs_create_dir can return ENODEV if securityfs is
407*0bfb2374SThiebaud Weksteen 	 * compiled out. The caller should ignore the ENODEV return code.
408*0bfb2374SThiebaud Weksteen 	 */
409*0bfb2374SThiebaud Weksteen 	if (IS_ERR(chip->bios_dir[cnt]))
410*0bfb2374SThiebaud Weksteen 		goto err;
411*0bfb2374SThiebaud Weksteen 	cnt++;
412*0bfb2374SThiebaud Weksteen 
413*0bfb2374SThiebaud Weksteen 	chip->bin_log_seqops.chip = chip;
414*0bfb2374SThiebaud Weksteen 	if (log_version == EFI_TCG2_EVENT_LOG_FORMAT_TCG_2)
415*0bfb2374SThiebaud Weksteen 		chip->bin_log_seqops.seqops =
416*0bfb2374SThiebaud Weksteen 			&tpm2_binary_b_measurements_seqops;
417*0bfb2374SThiebaud Weksteen 	else
418*0bfb2374SThiebaud Weksteen 		chip->bin_log_seqops.seqops =
419*0bfb2374SThiebaud Weksteen 			&tpm_binary_b_measurements_seqops;
420*0bfb2374SThiebaud Weksteen 
421*0bfb2374SThiebaud Weksteen 
422*0bfb2374SThiebaud Weksteen 	chip->bios_dir[cnt] =
423*0bfb2374SThiebaud Weksteen 	    securityfs_create_file("binary_bios_measurements",
424*0bfb2374SThiebaud Weksteen 				   0440, chip->bios_dir[0],
425*0bfb2374SThiebaud Weksteen 				   (void *)&chip->bin_log_seqops,
426*0bfb2374SThiebaud Weksteen 				   &tpm_bios_measurements_ops);
427*0bfb2374SThiebaud Weksteen 	if (IS_ERR(chip->bios_dir[cnt]))
428*0bfb2374SThiebaud Weksteen 		goto err;
429*0bfb2374SThiebaud Weksteen 	cnt++;
430*0bfb2374SThiebaud Weksteen 
431*0bfb2374SThiebaud Weksteen 	if (!(chip->flags & TPM_CHIP_FLAG_TPM2)) {
432*0bfb2374SThiebaud Weksteen 
433*0bfb2374SThiebaud Weksteen 		chip->ascii_log_seqops.chip = chip;
434*0bfb2374SThiebaud Weksteen 		chip->ascii_log_seqops.seqops =
435*0bfb2374SThiebaud Weksteen 			&tpm_ascii_b_measurements_seqops;
436*0bfb2374SThiebaud Weksteen 
437*0bfb2374SThiebaud Weksteen 		chip->bios_dir[cnt] =
438*0bfb2374SThiebaud Weksteen 			securityfs_create_file("ascii_bios_measurements",
439*0bfb2374SThiebaud Weksteen 					       0440, chip->bios_dir[0],
440*0bfb2374SThiebaud Weksteen 					       (void *)&chip->ascii_log_seqops,
441*0bfb2374SThiebaud Weksteen 					       &tpm_bios_measurements_ops);
442*0bfb2374SThiebaud Weksteen 		if (IS_ERR(chip->bios_dir[cnt]))
443*0bfb2374SThiebaud Weksteen 			goto err;
444*0bfb2374SThiebaud Weksteen 		cnt++;
445*0bfb2374SThiebaud Weksteen 	}
446*0bfb2374SThiebaud Weksteen 
447*0bfb2374SThiebaud Weksteen 	return 0;
448*0bfb2374SThiebaud Weksteen 
449*0bfb2374SThiebaud Weksteen err:
450*0bfb2374SThiebaud Weksteen 	rc = PTR_ERR(chip->bios_dir[cnt]);
451*0bfb2374SThiebaud Weksteen 	chip->bios_dir[cnt] = NULL;
452*0bfb2374SThiebaud Weksteen 	tpm_bios_log_teardown(chip);
453*0bfb2374SThiebaud Weksteen 	return rc;
454*0bfb2374SThiebaud Weksteen }
455*0bfb2374SThiebaud Weksteen 
456*0bfb2374SThiebaud Weksteen void tpm_bios_log_teardown(struct tpm_chip *chip)
457*0bfb2374SThiebaud Weksteen {
458*0bfb2374SThiebaud Weksteen 	int i;
459*0bfb2374SThiebaud Weksteen 	struct inode *inode;
460*0bfb2374SThiebaud Weksteen 
461*0bfb2374SThiebaud Weksteen 	/* securityfs_remove currently doesn't take care of handling sync
462*0bfb2374SThiebaud Weksteen 	 * between removal and opening of pseudo files. To handle this, a
463*0bfb2374SThiebaud Weksteen 	 * workaround is added by making i_private = NULL here during removal
464*0bfb2374SThiebaud Weksteen 	 * and to check it during open(), both within inode_lock()/unlock().
465*0bfb2374SThiebaud Weksteen 	 * This design ensures that open() either safely gets kref or fails.
466*0bfb2374SThiebaud Weksteen 	 */
467*0bfb2374SThiebaud Weksteen 	for (i = (TPM_NUM_EVENT_LOG_FILES - 1); i >= 0; i--) {
468*0bfb2374SThiebaud Weksteen 		if (chip->bios_dir[i]) {
469*0bfb2374SThiebaud Weksteen 			inode = d_inode(chip->bios_dir[i]);
470*0bfb2374SThiebaud Weksteen 			inode_lock(inode);
471*0bfb2374SThiebaud Weksteen 			inode->i_private = NULL;
472*0bfb2374SThiebaud Weksteen 			inode_unlock(inode);
473*0bfb2374SThiebaud Weksteen 			securityfs_remove(chip->bios_dir[i]);
474*0bfb2374SThiebaud Weksteen 		}
475*0bfb2374SThiebaud Weksteen 	}
476*0bfb2374SThiebaud Weksteen }
477