iwlwifi: unify iwlagn and 3945 power save management
[linux-2.6] / drivers / char / tpm / tpm_bios.c
1 /*
2  * Copyright (C) 2005 IBM Corporation
3  *
4  * Authors:
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>
9  *
10  * Maintained by: <tpmdd-devel@lists.sourceforge.net>
11  *
12  * Access to the eventlog extended by the TCG BIOS of PC platform
13  *
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.
18  *
19  */
20
21 #include <linux/seq_file.h>
22 #include <linux/fs.h>
23 #include <linux/security.h>
24 #include <linux/module.h>
25 #include <acpi/acpi.h>
26 #include "tpm.h"
27
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' */
31
32 enum bios_platform_class {
33         BIOS_CLIENT = 0x00,
34         BIOS_SERVER = 0x01,
35 };
36
37 struct tpm_bios_log {
38         void *bios_event_log;
39         void *bios_event_log_end;
40 };
41
42 struct acpi_tcpa {
43         struct acpi_table_header hdr;
44         u16 platform_class;
45         union {
46                 struct client_hdr {
47                         u32 log_max_len __attribute__ ((packed));
48                         u64 log_start_addr __attribute__ ((packed));
49                 } client;
50                 struct server_hdr {
51                         u16 reserved;
52                         u64 log_max_len __attribute__ ((packed));
53                         u64 log_start_addr __attribute__ ((packed));
54                 } server;
55         };
56 };
57
58 struct tcpa_event {
59         u32 pcr_index;
60         u32 event_type;
61         u8 pcr_value[20];       /* SHA1 */
62         u32 event_size;
63         u8 event_data[0];
64 };
65
66 enum tcpa_event_types {
67         PREBOOT = 0,
68         POST_CODE,
69         UNUSED,
70         NO_ACTION,
71         SEPARATOR,
72         ACTION,
73         EVENT_TAG,
74         SCRTM_CONTENTS,
75         SCRTM_VERSION,
76         CPU_MICROCODE,
77         PLATFORM_CONFIG_FLAGS,
78         TABLE_OF_DEVICES,
79         COMPACT_HASH,
80         IPL,
81         IPL_PARTITION_DATA,
82         NONHOST_CODE,
83         NONHOST_CONFIG,
84         NONHOST_INFO,
85 };
86
87 static const char* tcpa_event_type_strings[] = {
88         "PREBOOT",
89         "POST CODE",
90         "",
91         "NO ACTION",
92         "SEPARATOR",
93         "ACTION",
94         "EVENT TAG",
95         "S-CRTM Contents",
96         "S-CRTM Version",
97         "CPU Microcode",
98         "Platform Config Flags",
99         "Table of Devices",
100         "Compact Hash",
101         "IPL",
102         "IPL Partition Data",
103         "Non-Host Code",
104         "Non-Host Config",
105         "Non-Host Info"
106 };
107
108 struct tcpa_pc_event {
109         u32 event_id;
110         u32 event_size;
111         u8 event_data[0];
112 };
113
114 enum tcpa_pc_event_ids {
115         SMBIOS = 1,
116         BIS_CERT,
117         POST_BIOS_ROM,
118         ESCD,
119         CMOS,
120         NVRAM,
121         OPTION_ROM_EXEC,
122         OPTION_ROM_CONFIG,
123         OPTION_ROM_MICROCODE = 10,
124         S_CRTM_VERSION,
125         S_CRTM_CONTENTS,
126         POST_CONTENTS,
127         HOST_TABLE_OF_DEVICES,
128 };
129
130 static const char* tcpa_pc_event_id_strings[] = {
131         "",
132         "SMBIOS",
133         "BIS Certificate",
134         "POST BIOS ",
135         "ESCD ",
136         "CMOS",
137         "NVRAM",
138         "Option ROM",
139         "Option ROM config",
140         "",
141         "Option ROM microcode ",
142         "S-CRTM Version",
143         "S-CRTM Contents ",
144         "POST Contents ",
145         "Table of Devices",
146 };
147
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)
150 {
151         loff_t i;
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;
156
157         /* read over *pos measurements */
158         for (i = 0; i < *pos; i++) {
159                 event = addr;
160
161                 if ((addr + sizeof(struct tcpa_event)) < limit) {
162                         if (event->event_type == 0 && event->event_size == 0)
163                                 return NULL;
164                         addr += sizeof(struct tcpa_event) + event->event_size;
165                 }
166         }
167
168         /* now check if current entry is valid */
169         if ((addr + sizeof(struct tcpa_event)) >= limit)
170                 return NULL;
171
172         event = addr;
173
174         if ((event->event_type == 0 && event->event_size == 0) ||
175             ((addr + sizeof(struct tcpa_event) + event->event_size) >= limit))
176                 return NULL;
177
178         return addr;
179 }
180
181 static void *tpm_bios_measurements_next(struct seq_file *m, void *v,
182                                         loff_t *pos)
183 {
184         struct tcpa_event *event = v;
185         struct tpm_bios_log *log = m->private;
186         void *limit = log->bios_event_log_end;
187
188         v += sizeof(struct tcpa_event) + event->event_size;
189
190         /* now check if current entry is valid */
191         if ((v + sizeof(struct tcpa_event)) >= limit)
192                 return NULL;
193
194         event = v;
195
196         if (event->event_type == 0 && event->event_size == 0)
197                 return NULL;
198
199         if ((event->event_type == 0 && event->event_size == 0) ||
200             ((v + sizeof(struct tcpa_event) + event->event_size) >= limit))
201                 return NULL;
202
203         (*pos)++;
204         return v;
205 }
206
207 static void tpm_bios_measurements_stop(struct seq_file *m, void *v)
208 {
209 }
210
211 static int get_event_name(char *dest, struct tcpa_event *event,
212                         unsigned char * event_entry)
213 {
214         const char *name = "";
215         char data[40] = "";
216         int i, n_len = 0, d_len = 0;
217         struct tcpa_pc_event *pc_event;
218
219         switch(event->event_type) {
220         case PREBOOT:
221         case POST_CODE:
222         case UNUSED:
223         case NO_ACTION:
224         case SCRTM_CONTENTS:
225         case SCRTM_VERSION:
226         case CPU_MICROCODE:
227         case PLATFORM_CONFIG_FLAGS:
228         case TABLE_OF_DEVICES:
229         case COMPACT_HASH:
230         case IPL:
231         case IPL_PARTITION_DATA:
232         case NONHOST_CODE:
233         case NONHOST_CONFIG:
234         case NONHOST_INFO:
235                 name = tcpa_event_type_strings[event->event_type];
236                 n_len = strlen(name);
237                 break;
238         case SEPARATOR:
239         case ACTION:
240                 if (MAX_TEXT_EVENT > event->event_size) {
241                         name = event_entry;
242                         n_len = event->event_size;
243                 }
244                 break;
245         case EVENT_TAG:
246                 pc_event = (struct tcpa_pc_event *)event_entry;
247
248                 /* ToDo Row data -> Base64 */
249
250                 switch (pc_event->event_id) {
251                 case SMBIOS:
252                 case BIS_CERT:
253                 case CMOS:
254                 case NVRAM:
255                 case OPTION_ROM_EXEC:
256                 case OPTION_ROM_CONFIG:
257                 case S_CRTM_VERSION:
258                         name = tcpa_pc_event_id_strings[pc_event->event_id];
259                         n_len = strlen(name);
260                         break;
261                 /* hash data */
262                 case POST_BIOS_ROM:
263                 case ESCD:
264                 case OPTION_ROM_MICROCODE:
265                 case S_CRTM_CONTENTS:
266                 case POST_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]);
272                         break;
273                 default:
274                         break;
275                 }
276         default:
277                 break;
278         }
279
280         return snprintf(dest, MAX_TEXT_EVENT, "[%.*s%.*s]",
281                         n_len, name, d_len, data);
282
283 }
284
285 static int tpm_binary_bios_measurements_show(struct seq_file *m, void *v)
286 {
287         struct tcpa_event *event = v;
288         char *data = v;
289         int i;
290
291         for (i = 0; i < sizeof(struct tcpa_event) + event->event_size; i++)
292                 seq_putc(m, data[i]);
293
294         return 0;
295 }
296
297 static int tpm_bios_measurements_release(struct inode *inode,
298                                          struct file *file)
299 {
300         struct seq_file *seq = file->private_data;
301         struct tpm_bios_log *log = seq->private;
302
303         if (log) {
304                 kfree(log->bios_event_log);
305                 kfree(log);
306         }
307
308         return seq_release(inode, file);
309 }
310
311 static int tpm_ascii_bios_measurements_show(struct seq_file *m, void *v)
312 {
313         int len = 0;
314         int i;
315         char *eventname;
316         struct tcpa_event *event = v;
317         unsigned char *event_entry =
318             (unsigned char *) (v + sizeof(struct tcpa_event));
319
320         eventname = kmalloc(MAX_TEXT_EVENT, GFP_KERNEL);
321         if (!eventname) {
322                 printk(KERN_ERR "%s: ERROR - No Memory for event name\n ",
323                        __func__);
324                 return -EFAULT;
325         }
326
327         seq_printf(m, "%2d ", event->pcr_index);
328
329         /* 2nd: SHA1 */
330         for (i = 0; i < 20; i++)
331                 seq_printf(m, "%02x", event->pcr_value[i]);
332
333         /* 3rd: event type identifier */
334         seq_printf(m, " %02x", event->event_type);
335
336         len += get_event_name(eventname, event, event_entry);
337
338         /* 4th: eventname <= max + \'0' delimiter */
339         seq_printf(m, " %s\n", eventname);
340
341         kfree(eventname);
342         return 0;
343 }
344
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,
350 };
351
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,
357 };
358
359 /* read binary bios log */
360 static int read_log(struct tpm_bios_log *log)
361 {
362         struct acpi_tcpa *buff;
363         acpi_status status;
364         struct acpi_table_header *virt;
365         u64 len, start;
366
367         if (log->bios_event_log != NULL) {
368                 printk(KERN_ERR
369                        "%s: ERROR - Eventlog already initialized\n",
370                        __func__);
371                 return -EFAULT;
372         }
373
374         /* Find TCPA entry in RSDT (ACPI_LOGICAL_ADDRESSING) */
375         status = acpi_get_table(ACPI_SIG_TCPA, 1,
376                                 (struct acpi_table_header **)&buff);
377
378         if (ACPI_FAILURE(status)) {
379                 printk(KERN_ERR "%s: ERROR - Could not get TCPA table\n",
380                        __func__);
381                 return -EIO;
382         }
383
384         switch(buff->platform_class) {
385         case BIOS_SERVER:
386                 len = buff->server.log_max_len;
387                 start = buff->server.log_start_addr;
388                 break;
389         case BIOS_CLIENT:
390         default:
391                 len = buff->client.log_max_len;
392                 start = buff->client.log_start_addr;
393                 break;
394         }
395         if (!len) {
396                 printk(KERN_ERR "%s: ERROR - TCPA log area empty\n", __func__);
397                 return -EIO;
398         }
399
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",
404                         __func__);
405                 return -ENOMEM;
406         }
407
408         log->bios_event_log_end = log->bios_event_log + len;
409
410         virt = acpi_os_map_memory(start, len);
411
412         memcpy(log->bios_event_log, virt, len);
413
414         acpi_os_unmap_memory(virt, len);
415         return 0;
416 }
417
418 static int tpm_ascii_bios_measurements_open(struct inode *inode,
419                                             struct file *file)
420 {
421         int err;
422         struct tpm_bios_log *log;
423         struct seq_file *seq;
424
425         log = kzalloc(sizeof(struct tpm_bios_log), GFP_KERNEL);
426         if (!log)
427                 return -ENOMEM;
428
429         if ((err = read_log(log)))
430                 goto out_free;
431
432         /* now register seq file */
433         err = seq_open(file, &tpm_ascii_b_measurments_seqops);
434         if (!err) {
435                 seq = file->private_data;
436                 seq->private = log;
437         } else {
438                 goto out_free;
439         }
440
441 out:
442         return err;
443 out_free:
444         kfree(log->bios_event_log);
445         kfree(log);
446         goto out;
447 }
448
449 static const struct file_operations tpm_ascii_bios_measurements_ops = {
450         .open = tpm_ascii_bios_measurements_open,
451         .read = seq_read,
452         .llseek = seq_lseek,
453         .release = tpm_bios_measurements_release,
454 };
455
456 static int tpm_binary_bios_measurements_open(struct inode *inode,
457                                              struct file *file)
458 {
459         int err;
460         struct tpm_bios_log *log;
461         struct seq_file *seq;
462
463         log = kzalloc(sizeof(struct tpm_bios_log), GFP_KERNEL);
464         if (!log)
465                 return -ENOMEM;
466
467         if ((err = read_log(log)))
468                 goto out_free;
469
470         /* now register seq file */
471         err = seq_open(file, &tpm_binary_b_measurments_seqops);
472         if (!err) {
473                 seq = file->private_data;
474                 seq->private = log;
475         } else {
476                 goto out_free;
477         }
478
479 out:
480         return err;
481 out_free:
482         kfree(log->bios_event_log);
483         kfree(log);
484         goto out;
485 }
486
487 static const struct file_operations tpm_binary_bios_measurements_ops = {
488         .open = tpm_binary_bios_measurements_open,
489         .read = seq_read,
490         .llseek = seq_lseek,
491         .release = tpm_bios_measurements_release,
492 };
493
494 static int is_bad(void *p)
495 {
496         if (!p)
497                 return 1;
498         if (IS_ERR(p) && (PTR_ERR(p) != -ENODEV))
499                 return 1;
500         return 0;
501 }
502
503 struct dentry **tpm_bios_log_setup(char *name)
504 {
505         struct dentry **ret = NULL, *tpm_dir, *bin_file, *ascii_file;
506
507         tpm_dir = securityfs_create_dir(name, NULL);
508         if (is_bad(tpm_dir))
509                 goto out;
510
511         bin_file =
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))
516                 goto out_tpm;
517
518         ascii_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))
523                 goto out_bin;
524
525         ret = kmalloc(3 * sizeof(struct dentry *), GFP_KERNEL);
526         if (!ret)
527                 goto out_ascii;
528
529         ret[0] = ascii_file;
530         ret[1] = bin_file;
531         ret[2] = tpm_dir;
532
533         return ret;
534
535 out_ascii:
536         securityfs_remove(ascii_file);
537 out_bin:
538         securityfs_remove(bin_file);
539 out_tpm:
540         securityfs_remove(tpm_dir);
541 out:
542         return NULL;
543 }
544 EXPORT_SYMBOL_GPL(tpm_bios_log_setup);
545
546 void tpm_bios_log_teardown(struct dentry **lst)
547 {
548         int i;
549
550         for (i = 0; i < 3; i++)
551                 securityfs_remove(lst[i]);
552 }
553 EXPORT_SYMBOL_GPL(tpm_bios_log_teardown);
554 MODULE_LICENSE("GPL");