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 * Access to the eventlog extended by the TCG BIOS of PC platform
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version
15 * 2 of the License, or (at your option) any later version.
19 #include <linux/seq_file.h>
21 #include <linux/security.h>
22 #include <linux/module.h>
23 #include <acpi/acpi.h>
24 #include <acpi/actypes.h>
25 #include <acpi/actbl.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' */
34 void *bios_event_log_end
;
38 struct acpi_table_header hdr
;
40 u32 log_max_len
__attribute__ ((packed
));
41 u32 log_start_addr
__attribute__ ((packed
));
47 u8 pcr_value
[20]; /* SHA1 */
52 enum tcpa_event_types
{
63 PLATFORM_CONFIG_FLAGS
,
73 static const char* tcpa_event_type_strings
[] = {
84 "Platform Config Flags",
94 enum tcpa_pc_event_ids
{
103 OPTION_ROM_MICROCODE
,
109 static const char* tcpa_pc_event_id_strings
[] = {
119 "Option ROM microcode",
122 "S-CRTM POST Contents",
125 /* returns pointer to start of pos. entry of tcg log */
126 static void *tpm_bios_measurements_start(struct seq_file
*m
, loff_t
*pos
)
129 struct tpm_bios_log
*log
= m
->private;
130 void *addr
= log
->bios_event_log
;
131 void *limit
= log
->bios_event_log_end
;
132 struct tcpa_event
*event
;
134 /* read over *pos measurements */
135 for (i
= 0; i
< *pos
; i
++) {
138 if ((addr
+ sizeof(struct tcpa_event
)) < limit
) {
139 if (event
->event_type
== 0 && event
->event_size
== 0)
141 addr
+= sizeof(struct tcpa_event
) + event
->event_size
;
145 /* now check if current entry is valid */
146 if ((addr
+ sizeof(struct tcpa_event
)) >= limit
)
151 if ((event
->event_type
== 0 && event
->event_size
== 0) ||
152 ((addr
+ sizeof(struct tcpa_event
) + event
->event_size
) >= limit
))
158 static void *tpm_bios_measurements_next(struct seq_file
*m
, void *v
,
161 struct tcpa_event
*event
= v
;
162 struct tpm_bios_log
*log
= m
->private;
163 void *limit
= log
->bios_event_log_end
;
165 v
+= sizeof(struct tcpa_event
) + event
->event_size
;
167 /* now check if current entry is valid */
168 if ((v
+ sizeof(struct tcpa_event
)) >= limit
)
173 if (event
->event_type
== 0 && event
->event_size
== 0)
176 if ((event
->event_type
== 0 && event
->event_size
== 0) ||
177 ((v
+ sizeof(struct tcpa_event
) + event
->event_size
) >= limit
))
184 static void tpm_bios_measurements_stop(struct seq_file
*m
, void *v
)
188 static int get_event_name(char *dest
, struct tcpa_event
*event
,
189 unsigned char * event_entry
)
191 const char *name
= "";
193 int i
, n_len
= 0, d_len
= 0;
194 u32 event_id
, event_data_size
;
196 switch(event
->event_type
) {
204 case PLATFORM_CONFIG_FLAGS
:
205 case TABLE_OF_DEVICES
:
208 case IPL_PARTITION_DATA
:
212 name
= tcpa_event_type_strings
[event
->event_type
];
213 n_len
= strlen(name
);
217 if (MAX_TEXT_EVENT
> event
->event_size
) {
219 n_len
= event
->event_size
;
223 event_id
= be32_to_cpu(event_entry
);
224 event_data_size
= be32_to_cpu(&event_entry
[4]);
226 /* ToDo Row data -> Base64 */
233 case OPTION_ROM_EXEC
:
234 case OPTION_ROM_CONFIG
:
235 case OPTION_ROM_MICROCODE
:
237 case S_CRTM_CONTENTS
:
239 name
= tcpa_pc_event_id_strings
[event_id
];
240 n_len
= strlen(name
);
244 name
= tcpa_pc_event_id_strings
[event_id
];
245 n_len
= strlen(name
);
246 for (i
= 0; i
< 20; i
++)
247 d_len
+= sprintf(data
, "%02x",
257 return snprintf(dest
, MAX_TEXT_EVENT
, "[%.*s%.*s]",
258 n_len
, name
, d_len
, data
);
262 static int tpm_binary_bios_measurements_show(struct seq_file
*m
, void *v
)
269 struct tcpa_event
*event
= (struct tcpa_event
*) v
;
270 unsigned char *event_entry
=
271 (unsigned char *) (v
+ sizeof(struct tcpa_event
));
273 eventname
= kmalloc(MAX_TEXT_EVENT
, GFP_KERNEL
);
275 printk(KERN_ERR
"%s: ERROR - No Memory for event name\n ",
280 /* 1st: PCR used is in little-endian format (4 bytes) */
281 help
= le32_to_cpu(event
->pcr_index
);
282 memcpy(data
, &help
, 4);
283 for (i
= 0; i
< 4; i
++)
284 seq_putc(m
, data
[i
]);
286 /* 2nd: SHA1 (20 bytes) */
287 for (i
= 0; i
< 20; i
++)
288 seq_putc(m
, event
->pcr_value
[i
]);
290 /* 3rd: event type identifier (4 bytes) */
291 help
= le32_to_cpu(event
->event_type
);
292 memcpy(data
, &help
, 4);
293 for (i
= 0; i
< 4; i
++)
294 seq_putc(m
, data
[i
]);
298 len
+= get_event_name(eventname
, event
, event_entry
);
300 /* 4th: filename <= 255 + \'0' delimiter */
301 if (len
> TCG_EVENT_NAME_LEN_MAX
)
302 len
= TCG_EVENT_NAME_LEN_MAX
;
304 for (i
= 0; i
< len
; i
++)
305 seq_putc(m
, eventname
[i
]);
313 static int tpm_bios_measurements_release(struct inode
*inode
,
316 struct seq_file
*seq
= file
->private_data
;
317 struct tpm_bios_log
*log
= seq
->private;
320 kfree(log
->bios_event_log
);
324 return seq_release(inode
, file
);
327 static int tpm_ascii_bios_measurements_show(struct seq_file
*m
, void *v
)
332 struct tcpa_event
*event
= v
;
333 unsigned char *event_entry
=
334 (unsigned char *) (v
+ sizeof(struct tcpa_event
));
336 eventname
= kmalloc(MAX_TEXT_EVENT
, GFP_KERNEL
);
338 printk(KERN_ERR
"%s: ERROR - No Memory for event name\n ",
343 seq_printf(m
, "%2d ", event
->pcr_index
);
346 for (i
= 0; i
< 20; i
++)
347 seq_printf(m
, "%02x", event
->pcr_value
[i
]);
349 /* 3rd: event type identifier */
350 seq_printf(m
, " %02x", event
->event_type
);
352 len
+= get_event_name(eventname
, event
, event_entry
);
354 /* 4th: eventname <= max + \'0' delimiter */
355 seq_printf(m
, " %s\n", eventname
);
360 static struct seq_operations tpm_ascii_b_measurments_seqops
= {
361 .start
= tpm_bios_measurements_start
,
362 .next
= tpm_bios_measurements_next
,
363 .stop
= tpm_bios_measurements_stop
,
364 .show
= tpm_ascii_bios_measurements_show
,
367 static struct seq_operations tpm_binary_b_measurments_seqops
= {
368 .start
= tpm_bios_measurements_start
,
369 .next
= tpm_bios_measurements_next
,
370 .stop
= tpm_bios_measurements_stop
,
371 .show
= tpm_binary_bios_measurements_show
,
374 /* read binary bios log */
375 static int read_log(struct tpm_bios_log
*log
)
377 struct acpi_tcpa
*buff
;
381 if (log
->bios_event_log
!= NULL
) {
383 "%s: ERROR - Eventlog already initialized\n",
388 /* Find TCPA entry in RSDT (ACPI_LOGICAL_ADDRESSING) */
389 status
= acpi_get_firmware_table(ACPI_TCPA_SIG
, 1,
390 ACPI_LOGICAL_ADDRESSING
,
391 (struct acpi_table_header
**)
394 if (ACPI_FAILURE(status
)) {
395 printk(KERN_ERR
"%s: ERROR - Could not get TCPA table\n",
400 if (buff
->log_max_len
== 0) {
401 printk(KERN_ERR
"%s: ERROR - TCPA log area empty\n", __func__
);
405 /* malloc EventLog space */
406 log
->bios_event_log
= kmalloc(buff
->log_max_len
, GFP_KERNEL
);
407 if (!log
->bios_event_log
) {
409 ("%s: ERROR - Not enough Memory for BIOS measurements\n",
414 log
->bios_event_log_end
= log
->bios_event_log
+ buff
->log_max_len
;
416 acpi_os_map_memory(buff
->log_start_addr
, buff
->log_max_len
, &virt
);
418 memcpy(log
->bios_event_log
, virt
, buff
->log_max_len
);
420 acpi_os_unmap_memory(virt
, buff
->log_max_len
);
424 static int tpm_ascii_bios_measurements_open(struct inode
*inode
,
428 struct tpm_bios_log
*log
;
429 struct seq_file
*seq
;
431 log
= kzalloc(sizeof(struct tpm_bios_log
), GFP_KERNEL
);
435 if ((err
= read_log(log
)))
438 /* now register seq file */
439 err
= seq_open(file
, &tpm_ascii_b_measurments_seqops
);
441 seq
= file
->private_data
;
444 kfree(log
->bios_event_log
);
450 struct file_operations tpm_ascii_bios_measurements_ops
= {
451 .open
= tpm_ascii_bios_measurements_open
,
454 .release
= tpm_bios_measurements_release
,
457 static int tpm_binary_bios_measurements_open(struct inode
*inode
,
461 struct tpm_bios_log
*log
;
462 struct seq_file
*seq
;
464 log
= kzalloc(sizeof(struct tpm_bios_log
), GFP_KERNEL
);
468 if ((err
= read_log(log
)))
471 /* now register seq file */
472 err
= seq_open(file
, &tpm_binary_b_measurments_seqops
);
474 seq
= file
->private_data
;
477 kfree(log
->bios_event_log
);
483 struct file_operations tpm_binary_bios_measurements_ops
= {
484 .open
= tpm_binary_bios_measurements_open
,
487 .release
= tpm_bios_measurements_release
,
490 static int is_bad(void *p
)
494 if (IS_ERR(p
) && (PTR_ERR(p
) != -ENODEV
))
499 struct dentry
**tpm_bios_log_setup(char *name
)
501 struct dentry
**ret
= NULL
, *tpm_dir
, *bin_file
, *ascii_file
;
503 tpm_dir
= securityfs_create_dir(name
, NULL
);
508 securityfs_create_file("binary_bios_measurements",
509 S_IRUSR
| S_IRGRP
, tpm_dir
, NULL
,
510 &tpm_binary_bios_measurements_ops
);
511 if (is_bad(bin_file
))
515 securityfs_create_file("ascii_bios_measurements",
516 S_IRUSR
| S_IRGRP
, tpm_dir
, NULL
,
517 &tpm_ascii_bios_measurements_ops
);
518 if (is_bad(ascii_file
))
521 ret
= kmalloc(3 * sizeof(struct dentry
*), GFP_KERNEL
);
532 securityfs_remove(ascii_file
);
534 securityfs_remove(bin_file
);
536 securityfs_remove(tpm_dir
);
540 EXPORT_SYMBOL_GPL(tpm_bios_log_setup
);
542 void tpm_bios_log_teardown(struct dentry
**lst
)
546 for (i
= 0; i
< 3; i
++)
547 securityfs_remove(lst
[i
]);
549 EXPORT_SYMBOL_GPL(tpm_bios_log_teardown
);