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 <acpi/acpi.h>
28 #define TCG_EVENT_NAME_LEN_MAX 255
29 #define MAX_TEXT_EVENT 1000 /* Max event string length */
30 #define ACPI_TCPA_SIG "TCPA" /* 0x41504354 /'TCPA' */
32 enum bios_platform_class
{
39 void *bios_event_log_end
;
43 struct acpi_table_header hdr
;
47 u32 log_max_len
__attribute__ ((packed
));
48 u64 log_start_addr
__attribute__ ((packed
));
52 u64 log_max_len
__attribute__ ((packed
));
53 u64 log_start_addr
__attribute__ ((packed
));
61 u8 pcr_value
[20]; /* SHA1 */
66 enum tcpa_event_types
{
77 PLATFORM_CONFIG_FLAGS
,
87 static const char* tcpa_event_type_strings
[] = {
98 "Platform Config Flags",
102 "IPL Partition Data",
108 struct tcpa_pc_event
{
114 enum tcpa_pc_event_ids
{
123 OPTION_ROM_MICROCODE
= 10,
127 HOST_TABLE_OF_DEVICES
,
130 static const char* tcpa_pc_event_id_strings
[] = {
141 "Option ROM microcode ",
148 /* returns pointer to start of pos. entry of tcg log */
149 static void *tpm_bios_measurements_start(struct seq_file
*m
, loff_t
*pos
)
152 struct tpm_bios_log
*log
= m
->private;
153 void *addr
= log
->bios_event_log
;
154 void *limit
= log
->bios_event_log_end
;
155 struct tcpa_event
*event
;
157 /* read over *pos measurements */
158 for (i
= 0; i
< *pos
; i
++) {
161 if ((addr
+ sizeof(struct tcpa_event
)) < limit
) {
162 if (event
->event_type
== 0 && event
->event_size
== 0)
164 addr
+= sizeof(struct tcpa_event
) + event
->event_size
;
168 /* now check if current entry is valid */
169 if ((addr
+ sizeof(struct tcpa_event
)) >= limit
)
174 if ((event
->event_type
== 0 && event
->event_size
== 0) ||
175 ((addr
+ sizeof(struct tcpa_event
) + event
->event_size
) >= limit
))
181 static void *tpm_bios_measurements_next(struct seq_file
*m
, void *v
,
184 struct tcpa_event
*event
= v
;
185 struct tpm_bios_log
*log
= m
->private;
186 void *limit
= log
->bios_event_log_end
;
188 v
+= sizeof(struct tcpa_event
) + event
->event_size
;
190 /* now check if current entry is valid */
191 if ((v
+ sizeof(struct tcpa_event
)) >= limit
)
196 if (event
->event_type
== 0 && event
->event_size
== 0)
199 if ((event
->event_type
== 0 && event
->event_size
== 0) ||
200 ((v
+ sizeof(struct tcpa_event
) + event
->event_size
) >= limit
))
207 static void tpm_bios_measurements_stop(struct seq_file
*m
, void *v
)
211 static int get_event_name(char *dest
, struct tcpa_event
*event
,
212 unsigned char * event_entry
)
214 const char *name
= "";
216 int i
, n_len
= 0, d_len
= 0;
217 struct tcpa_pc_event
*pc_event
;
219 switch(event
->event_type
) {
227 case PLATFORM_CONFIG_FLAGS
:
228 case TABLE_OF_DEVICES
:
231 case IPL_PARTITION_DATA
:
235 name
= tcpa_event_type_strings
[event
->event_type
];
236 n_len
= strlen(name
);
240 if (MAX_TEXT_EVENT
> event
->event_size
) {
242 n_len
= event
->event_size
;
246 pc_event
= (struct tcpa_pc_event
*)event_entry
;
248 /* ToDo Row data -> Base64 */
250 switch (pc_event
->event_id
) {
255 case OPTION_ROM_EXEC
:
256 case OPTION_ROM_CONFIG
:
258 name
= tcpa_pc_event_id_strings
[pc_event
->event_id
];
259 n_len
= strlen(name
);
264 case OPTION_ROM_MICROCODE
:
265 case S_CRTM_CONTENTS
:
267 name
= tcpa_pc_event_id_strings
[pc_event
->event_id
];
268 n_len
= strlen(name
);
269 for (i
= 0; i
< 20; i
++)
270 d_len
+= sprintf(&data
[2*i
], "%02x",
271 pc_event
->event_data
[i
]);
280 return snprintf(dest
, MAX_TEXT_EVENT
, "[%.*s%.*s]",
281 n_len
, name
, d_len
, data
);
285 static int tpm_binary_bios_measurements_show(struct seq_file
*m
, void *v
)
287 struct tcpa_event
*event
= v
;
291 for (i
= 0; i
< sizeof(struct tcpa_event
) + event
->event_size
; i
++)
292 seq_putc(m
, data
[i
]);
297 static int tpm_bios_measurements_release(struct inode
*inode
,
300 struct seq_file
*seq
= file
->private_data
;
301 struct tpm_bios_log
*log
= seq
->private;
304 kfree(log
->bios_event_log
);
308 return seq_release(inode
, file
);
311 static int tpm_ascii_bios_measurements_show(struct seq_file
*m
, void *v
)
316 struct tcpa_event
*event
= v
;
317 unsigned char *event_entry
=
318 (unsigned char *) (v
+ sizeof(struct tcpa_event
));
320 eventname
= kmalloc(MAX_TEXT_EVENT
, GFP_KERNEL
);
322 printk(KERN_ERR
"%s: ERROR - No Memory for event name\n ",
327 seq_printf(m
, "%2d ", event
->pcr_index
);
330 for (i
= 0; i
< 20; i
++)
331 seq_printf(m
, "%02x", event
->pcr_value
[i
]);
333 /* 3rd: event type identifier */
334 seq_printf(m
, " %02x", event
->event_type
);
336 len
+= get_event_name(eventname
, event
, event_entry
);
338 /* 4th: eventname <= max + \'0' delimiter */
339 seq_printf(m
, " %s\n", eventname
);
345 static struct seq_operations tpm_ascii_b_measurments_seqops
= {
346 .start
= tpm_bios_measurements_start
,
347 .next
= tpm_bios_measurements_next
,
348 .stop
= tpm_bios_measurements_stop
,
349 .show
= tpm_ascii_bios_measurements_show
,
352 static struct seq_operations tpm_binary_b_measurments_seqops
= {
353 .start
= tpm_bios_measurements_start
,
354 .next
= tpm_bios_measurements_next
,
355 .stop
= tpm_bios_measurements_stop
,
356 .show
= tpm_binary_bios_measurements_show
,
359 /* read binary bios log */
360 static int read_log(struct tpm_bios_log
*log
)
362 struct acpi_tcpa
*buff
;
364 struct acpi_table_header
*virt
;
367 if (log
->bios_event_log
!= NULL
) {
369 "%s: ERROR - Eventlog already initialized\n",
374 /* Find TCPA entry in RSDT (ACPI_LOGICAL_ADDRESSING) */
375 status
= acpi_get_table(ACPI_SIG_TCPA
, 1,
376 (struct acpi_table_header
**)&buff
);
378 if (ACPI_FAILURE(status
)) {
379 printk(KERN_ERR
"%s: ERROR - Could not get TCPA table\n",
384 switch(buff
->platform_class
) {
386 len
= buff
->server
.log_max_len
;
387 start
= buff
->server
.log_start_addr
;
391 len
= buff
->client
.log_max_len
;
392 start
= buff
->client
.log_start_addr
;
396 printk(KERN_ERR
"%s: ERROR - TCPA log area empty\n", __func__
);
400 /* malloc EventLog space */
401 log
->bios_event_log
= kmalloc(len
, GFP_KERNEL
);
402 if (!log
->bios_event_log
) {
403 printk("%s: ERROR - Not enough Memory for BIOS measurements\n",
408 log
->bios_event_log_end
= log
->bios_event_log
+ len
;
410 virt
= acpi_os_map_memory(start
, len
);
412 memcpy(log
->bios_event_log
, virt
, len
);
414 acpi_os_unmap_memory(virt
, len
);
418 static int tpm_ascii_bios_measurements_open(struct inode
*inode
,
422 struct tpm_bios_log
*log
;
423 struct seq_file
*seq
;
425 log
= kzalloc(sizeof(struct tpm_bios_log
), GFP_KERNEL
);
429 if ((err
= read_log(log
)))
432 /* now register seq file */
433 err
= seq_open(file
, &tpm_ascii_b_measurments_seqops
);
435 seq
= file
->private_data
;
444 kfree(log
->bios_event_log
);
449 static const struct file_operations tpm_ascii_bios_measurements_ops
= {
450 .open
= tpm_ascii_bios_measurements_open
,
453 .release
= tpm_bios_measurements_release
,
456 static int tpm_binary_bios_measurements_open(struct inode
*inode
,
460 struct tpm_bios_log
*log
;
461 struct seq_file
*seq
;
463 log
= kzalloc(sizeof(struct tpm_bios_log
), GFP_KERNEL
);
467 if ((err
= read_log(log
)))
470 /* now register seq file */
471 err
= seq_open(file
, &tpm_binary_b_measurments_seqops
);
473 seq
= file
->private_data
;
482 kfree(log
->bios_event_log
);
487 static const struct file_operations tpm_binary_bios_measurements_ops
= {
488 .open
= tpm_binary_bios_measurements_open
,
491 .release
= tpm_bios_measurements_release
,
494 static int is_bad(void *p
)
498 if (IS_ERR(p
) && (PTR_ERR(p
) != -ENODEV
))
503 struct dentry
**tpm_bios_log_setup(char *name
)
505 struct dentry
**ret
= NULL
, *tpm_dir
, *bin_file
, *ascii_file
;
507 tpm_dir
= securityfs_create_dir(name
, NULL
);
512 securityfs_create_file("binary_bios_measurements",
513 S_IRUSR
| S_IRGRP
, tpm_dir
, NULL
,
514 &tpm_binary_bios_measurements_ops
);
515 if (is_bad(bin_file
))
519 securityfs_create_file("ascii_bios_measurements",
520 S_IRUSR
| S_IRGRP
, tpm_dir
, NULL
,
521 &tpm_ascii_bios_measurements_ops
);
522 if (is_bad(ascii_file
))
525 ret
= kmalloc(3 * sizeof(struct dentry
*), GFP_KERNEL
);
536 securityfs_remove(ascii_file
);
538 securityfs_remove(bin_file
);
540 securityfs_remove(tpm_dir
);
544 EXPORT_SYMBOL_GPL(tpm_bios_log_setup
);
546 void tpm_bios_log_teardown(struct dentry
**lst
)
550 for (i
= 0; i
< 3; i
++)
551 securityfs_remove(lst
[i
]);
553 EXPORT_SYMBOL_GPL(tpm_bios_log_teardown
);
554 MODULE_LICENSE("GPL");