2 * Copyright (C) 2005 IBM Corporation
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>
10 * Maintained by: <tpmdd-devel@lists.sourceforge.net>
12 * Access to the eventlog extended by the TCG BIOS of PC platform
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.
21 #include <linux/seq_file.h>
23 #include <linux/security.h>
24 #include <linux/module.h>
25 #include <linux/slab.h>
26 #include <acpi/acpi.h>
29 #define TCG_EVENT_NAME_LEN_MAX 255
30 #define MAX_TEXT_EVENT 1000 /* Max event string length */
31 #define ACPI_TCPA_SIG "TCPA" /* 0x41504354 /'TCPA' */
33 enum bios_platform_class
{
40 void *bios_event_log_end
;
44 struct acpi_table_header hdr
;
48 u32 log_max_len
__attribute__ ((packed
));
49 u64 log_start_addr
__attribute__ ((packed
));
53 u64 log_max_len
__attribute__ ((packed
));
54 u64 log_start_addr
__attribute__ ((packed
));
62 u8 pcr_value
[20]; /* SHA1 */
67 enum tcpa_event_types
{
78 PLATFORM_CONFIG_FLAGS
,
88 static const char* tcpa_event_type_strings
[] = {
99 "Platform Config Flags",
103 "IPL Partition Data",
109 struct tcpa_pc_event
{
115 enum tcpa_pc_event_ids
{
124 OPTION_ROM_MICROCODE
= 10,
128 HOST_TABLE_OF_DEVICES
,
131 static const char* tcpa_pc_event_id_strings
[] = {
142 "Option ROM microcode ",
149 /* returns pointer to start of pos. entry of tcg log */
150 static void *tpm_bios_measurements_start(struct seq_file
*m
, loff_t
*pos
)
153 struct tpm_bios_log
*log
= m
->private;
154 void *addr
= log
->bios_event_log
;
155 void *limit
= log
->bios_event_log_end
;
156 struct tcpa_event
*event
;
158 /* read over *pos measurements */
159 for (i
= 0; i
< *pos
; i
++) {
162 if ((addr
+ sizeof(struct tcpa_event
)) < limit
) {
163 if (event
->event_type
== 0 && event
->event_size
== 0)
165 addr
+= sizeof(struct tcpa_event
) + event
->event_size
;
169 /* now check if current entry is valid */
170 if ((addr
+ sizeof(struct tcpa_event
)) >= limit
)
175 if ((event
->event_type
== 0 && event
->event_size
== 0) ||
176 ((addr
+ sizeof(struct tcpa_event
) + event
->event_size
) >= limit
))
182 static void *tpm_bios_measurements_next(struct seq_file
*m
, void *v
,
185 struct tcpa_event
*event
= v
;
186 struct tpm_bios_log
*log
= m
->private;
187 void *limit
= log
->bios_event_log_end
;
189 v
+= sizeof(struct tcpa_event
) + event
->event_size
;
191 /* now check if current entry is valid */
192 if ((v
+ sizeof(struct tcpa_event
)) >= limit
)
197 if (event
->event_type
== 0 && event
->event_size
== 0)
200 if ((event
->event_type
== 0 && event
->event_size
== 0) ||
201 ((v
+ sizeof(struct tcpa_event
) + event
->event_size
) >= limit
))
208 static void tpm_bios_measurements_stop(struct seq_file
*m
, void *v
)
212 static int get_event_name(char *dest
, struct tcpa_event
*event
,
213 unsigned char * event_entry
)
215 const char *name
= "";
216 /* 41 so there is room for 40 data and 1 nul */
218 int i
, n_len
= 0, d_len
= 0;
219 struct tcpa_pc_event
*pc_event
;
221 switch(event
->event_type
) {
229 case PLATFORM_CONFIG_FLAGS
:
230 case TABLE_OF_DEVICES
:
233 case IPL_PARTITION_DATA
:
237 name
= tcpa_event_type_strings
[event
->event_type
];
238 n_len
= strlen(name
);
242 if (MAX_TEXT_EVENT
> event
->event_size
) {
244 n_len
= event
->event_size
;
248 pc_event
= (struct tcpa_pc_event
*)event_entry
;
250 /* ToDo Row data -> Base64 */
252 switch (pc_event
->event_id
) {
257 case OPTION_ROM_EXEC
:
258 case OPTION_ROM_CONFIG
:
260 name
= tcpa_pc_event_id_strings
[pc_event
->event_id
];
261 n_len
= strlen(name
);
266 case OPTION_ROM_MICROCODE
:
267 case S_CRTM_CONTENTS
:
269 name
= tcpa_pc_event_id_strings
[pc_event
->event_id
];
270 n_len
= strlen(name
);
271 for (i
= 0; i
< 20; i
++)
272 d_len
+= sprintf(&data
[2*i
], "%02x",
273 pc_event
->event_data
[i
]);
282 return snprintf(dest
, MAX_TEXT_EVENT
, "[%.*s%.*s]",
283 n_len
, name
, d_len
, data
);
287 static int tpm_binary_bios_measurements_show(struct seq_file
*m
, void *v
)
289 struct tcpa_event
*event
= v
;
293 for (i
= 0; i
< sizeof(struct tcpa_event
) + event
->event_size
; i
++)
294 seq_putc(m
, data
[i
]);
299 static int tpm_bios_measurements_release(struct inode
*inode
,
302 struct seq_file
*seq
= file
->private_data
;
303 struct tpm_bios_log
*log
= seq
->private;
306 kfree(log
->bios_event_log
);
310 return seq_release(inode
, file
);
313 static int tpm_ascii_bios_measurements_show(struct seq_file
*m
, void *v
)
318 struct tcpa_event
*event
= v
;
319 unsigned char *event_entry
=
320 (unsigned char *) (v
+ sizeof(struct tcpa_event
));
322 eventname
= kmalloc(MAX_TEXT_EVENT
, GFP_KERNEL
);
324 printk(KERN_ERR
"%s: ERROR - No Memory for event name\n ",
329 seq_printf(m
, "%2d ", event
->pcr_index
);
332 for (i
= 0; i
< 20; i
++)
333 seq_printf(m
, "%02x", event
->pcr_value
[i
]);
335 /* 3rd: event type identifier */
336 seq_printf(m
, " %02x", event
->event_type
);
338 len
+= get_event_name(eventname
, event
, event_entry
);
340 /* 4th: eventname <= max + \'0' delimiter */
341 seq_printf(m
, " %s\n", eventname
);
347 static const struct seq_operations tpm_ascii_b_measurments_seqops
= {
348 .start
= tpm_bios_measurements_start
,
349 .next
= tpm_bios_measurements_next
,
350 .stop
= tpm_bios_measurements_stop
,
351 .show
= tpm_ascii_bios_measurements_show
,
354 static const struct seq_operations tpm_binary_b_measurments_seqops
= {
355 .start
= tpm_bios_measurements_start
,
356 .next
= tpm_bios_measurements_next
,
357 .stop
= tpm_bios_measurements_stop
,
358 .show
= tpm_binary_bios_measurements_show
,
361 /* read binary bios log */
362 static int read_log(struct tpm_bios_log
*log
)
364 struct acpi_tcpa
*buff
;
366 struct acpi_table_header
*virt
;
369 if (log
->bios_event_log
!= NULL
) {
371 "%s: ERROR - Eventlog already initialized\n",
376 /* Find TCPA entry in RSDT (ACPI_LOGICAL_ADDRESSING) */
377 status
= acpi_get_table(ACPI_SIG_TCPA
, 1,
378 (struct acpi_table_header
**)&buff
);
380 if (ACPI_FAILURE(status
)) {
381 printk(KERN_ERR
"%s: ERROR - Could not get TCPA table\n",
386 switch(buff
->platform_class
) {
388 len
= buff
->server
.log_max_len
;
389 start
= buff
->server
.log_start_addr
;
393 len
= buff
->client
.log_max_len
;
394 start
= buff
->client
.log_start_addr
;
398 printk(KERN_ERR
"%s: ERROR - TCPA log area empty\n", __func__
);
402 /* malloc EventLog space */
403 log
->bios_event_log
= kmalloc(len
, GFP_KERNEL
);
404 if (!log
->bios_event_log
) {
405 printk("%s: ERROR - Not enough Memory for BIOS measurements\n",
410 log
->bios_event_log_end
= log
->bios_event_log
+ len
;
412 virt
= acpi_os_map_memory(start
, len
);
414 memcpy(log
->bios_event_log
, virt
, len
);
416 acpi_os_unmap_memory(virt
, len
);
420 static int tpm_ascii_bios_measurements_open(struct inode
*inode
,
424 struct tpm_bios_log
*log
;
425 struct seq_file
*seq
;
427 log
= kzalloc(sizeof(struct tpm_bios_log
), GFP_KERNEL
);
431 if ((err
= read_log(log
)))
434 /* now register seq file */
435 err
= seq_open(file
, &tpm_ascii_b_measurments_seqops
);
437 seq
= file
->private_data
;
446 kfree(log
->bios_event_log
);
451 static const struct file_operations tpm_ascii_bios_measurements_ops
= {
452 .open
= tpm_ascii_bios_measurements_open
,
455 .release
= tpm_bios_measurements_release
,
458 static int tpm_binary_bios_measurements_open(struct inode
*inode
,
462 struct tpm_bios_log
*log
;
463 struct seq_file
*seq
;
465 log
= kzalloc(sizeof(struct tpm_bios_log
), GFP_KERNEL
);
469 if ((err
= read_log(log
)))
472 /* now register seq file */
473 err
= seq_open(file
, &tpm_binary_b_measurments_seqops
);
475 seq
= file
->private_data
;
484 kfree(log
->bios_event_log
);
489 static const struct file_operations tpm_binary_bios_measurements_ops
= {
490 .open
= tpm_binary_bios_measurements_open
,
493 .release
= tpm_bios_measurements_release
,
496 static int is_bad(void *p
)
500 if (IS_ERR(p
) && (PTR_ERR(p
) != -ENODEV
))
505 struct dentry
**tpm_bios_log_setup(char *name
)
507 struct dentry
**ret
= NULL
, *tpm_dir
, *bin_file
, *ascii_file
;
509 tpm_dir
= securityfs_create_dir(name
, NULL
);
514 securityfs_create_file("binary_bios_measurements",
515 S_IRUSR
| S_IRGRP
, tpm_dir
, NULL
,
516 &tpm_binary_bios_measurements_ops
);
517 if (is_bad(bin_file
))
521 securityfs_create_file("ascii_bios_measurements",
522 S_IRUSR
| S_IRGRP
, tpm_dir
, NULL
,
523 &tpm_ascii_bios_measurements_ops
);
524 if (is_bad(ascii_file
))
527 ret
= kmalloc(3 * sizeof(struct dentry
*), GFP_KERNEL
);
538 securityfs_remove(ascii_file
);
540 securityfs_remove(bin_file
);
542 securityfs_remove(tpm_dir
);
546 EXPORT_SYMBOL_GPL(tpm_bios_log_setup
);
548 void tpm_bios_log_teardown(struct dentry
**lst
)
552 for (i
= 0; i
< 3; i
++)
553 securityfs_remove(lst
[i
]);
555 EXPORT_SYMBOL_GPL(tpm_bios_log_teardown
);
556 MODULE_LICENSE("GPL");