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>
 
  26 #include <acpi/actypes.h>
 
  27 #include <acpi/actbl.h>
 
  30 #define TCG_EVENT_NAME_LEN_MAX  255
 
  31 #define MAX_TEXT_EVENT          1000    /* Max event string length */
 
  32 #define ACPI_TCPA_SIG           "TCPA"  /* 0x41504354 /'TCPA' */
 
  34 enum bios_platform_class {
 
  41         void *bios_event_log_end;
 
  45         struct acpi_table_header hdr;
 
  49                         u32 log_max_len __attribute__ ((packed));
 
  50                         u64 log_start_addr __attribute__ ((packed));
 
  54                         u64 log_max_len __attribute__ ((packed));
 
  55                         u64 log_start_addr __attribute__ ((packed));
 
  63         u8 pcr_value[20];       /* SHA1 */
 
  68 enum tcpa_event_types {
 
  79         PLATFORM_CONFIG_FLAGS,
 
  89 static const char* tcpa_event_type_strings[] = {
 
 100         "Platform Config Flags",
 
 104         "IPL Partition Data",
 
 110 struct tcpa_pc_event {
 
 116 enum tcpa_pc_event_ids {
 
 125         OPTION_ROM_MICROCODE = 10,
 
 129         HOST_TABLE_OF_DEVICES,
 
 132 static const char* tcpa_pc_event_id_strings[] = {
 
 143         "Option ROM microcode ",
 
 150 /* returns pointer to start of pos. entry of tcg log */
 
 151 static void *tpm_bios_measurements_start(struct seq_file *m, loff_t *pos)
 
 154         struct tpm_bios_log *log = m->private;
 
 155         void *addr = log->bios_event_log;
 
 156         void *limit = log->bios_event_log_end;
 
 157         struct tcpa_event *event;
 
 159         /* read over *pos measurements */
 
 160         for (i = 0; i < *pos; i++) {
 
 163                 if ((addr + sizeof(struct tcpa_event)) < limit) {
 
 164                         if (event->event_type == 0 && event->event_size == 0)
 
 166                         addr += sizeof(struct tcpa_event) + event->event_size;
 
 170         /* now check if current entry is valid */
 
 171         if ((addr + sizeof(struct tcpa_event)) >= limit)
 
 176         if ((event->event_type == 0 && event->event_size == 0) ||
 
 177             ((addr + sizeof(struct tcpa_event) + event->event_size) >= limit))
 
 183 static void *tpm_bios_measurements_next(struct seq_file *m, void *v,
 
 186         struct tcpa_event *event = v;
 
 187         struct tpm_bios_log *log = m->private;
 
 188         void *limit = log->bios_event_log_end;
 
 190         v += sizeof(struct tcpa_event) + event->event_size;
 
 192         /* now check if current entry is valid */
 
 193         if ((v + sizeof(struct tcpa_event)) >= limit)
 
 198         if (event->event_type == 0 && event->event_size == 0)
 
 201         if ((event->event_type == 0 && event->event_size == 0) ||
 
 202             ((v + sizeof(struct tcpa_event) + event->event_size) >= limit))
 
 209 static void tpm_bios_measurements_stop(struct seq_file *m, void *v)
 
 213 static int get_event_name(char *dest, struct tcpa_event *event,
 
 214                         unsigned char * event_entry)
 
 216         const char *name = "";
 
 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 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 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");