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