diff options
Diffstat (limited to 'drivers/char/tpm/tpm_bios.c')
-rw-r--r-- | drivers/char/tpm/tpm_bios.c | 49 |
1 files changed, 37 insertions, 12 deletions
diff --git a/drivers/char/tpm/tpm_bios.c b/drivers/char/tpm/tpm_bios.c index 5bcbaef53798..e45f0d3d12de 100644 --- a/drivers/char/tpm/tpm_bios.c +++ b/drivers/char/tpm/tpm_bios.c | |||
@@ -29,6 +29,11 @@ | |||
29 | #define MAX_TEXT_EVENT 1000 /* Max event string length */ | 29 | #define MAX_TEXT_EVENT 1000 /* Max event string length */ |
30 | #define ACPI_TCPA_SIG "TCPA" /* 0x41504354 /'TCPA' */ | 30 | #define ACPI_TCPA_SIG "TCPA" /* 0x41504354 /'TCPA' */ |
31 | 31 | ||
32 | enum bios_platform_class { | ||
33 | BIOS_CLIENT = 0x00, | ||
34 | BIOS_SERVER = 0x01, | ||
35 | }; | ||
36 | |||
32 | struct tpm_bios_log { | 37 | struct tpm_bios_log { |
33 | void *bios_event_log; | 38 | void *bios_event_log; |
34 | void *bios_event_log_end; | 39 | void *bios_event_log_end; |
@@ -36,9 +41,18 @@ struct tpm_bios_log { | |||
36 | 41 | ||
37 | struct acpi_tcpa { | 42 | struct acpi_tcpa { |
38 | struct acpi_table_header hdr; | 43 | struct acpi_table_header hdr; |
39 | u16 reserved; | 44 | u16 platform_class; |
40 | u32 log_max_len __attribute__ ((packed)); | 45 | union { |
41 | u32 log_start_addr __attribute__ ((packed)); | 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 | }; | ||
42 | }; | 56 | }; |
43 | 57 | ||
44 | struct tcpa_event { | 58 | struct tcpa_event { |
@@ -379,6 +393,7 @@ static int read_log(struct tpm_bios_log *log) | |||
379 | struct acpi_tcpa *buff; | 393 | struct acpi_tcpa *buff; |
380 | acpi_status status; | 394 | acpi_status status; |
381 | struct acpi_table_header *virt; | 395 | struct acpi_table_header *virt; |
396 | u64 len, start; | ||
382 | 397 | ||
383 | if (log->bios_event_log != NULL) { | 398 | if (log->bios_event_log != NULL) { |
384 | printk(KERN_ERR | 399 | printk(KERN_ERR |
@@ -399,27 +414,37 @@ static int read_log(struct tpm_bios_log *log) | |||
399 | return -EIO; | 414 | return -EIO; |
400 | } | 415 | } |
401 | 416 | ||
402 | if (buff->log_max_len == 0) { | 417 | switch(buff->platform_class) { |
418 | case BIOS_SERVER: | ||
419 | len = buff->server.log_max_len; | ||
420 | start = buff->server.log_start_addr; | ||
421 | break; | ||
422 | case BIOS_CLIENT: | ||
423 | default: | ||
424 | len = buff->client.log_max_len; | ||
425 | start = buff->client.log_start_addr; | ||
426 | break; | ||
427 | } | ||
428 | if (!len) { | ||
403 | printk(KERN_ERR "%s: ERROR - TCPA log area empty\n", __func__); | 429 | printk(KERN_ERR "%s: ERROR - TCPA log area empty\n", __func__); |
404 | return -EIO; | 430 | return -EIO; |
405 | } | 431 | } |
406 | 432 | ||
407 | /* malloc EventLog space */ | 433 | /* malloc EventLog space */ |
408 | log->bios_event_log = kmalloc(buff->log_max_len, GFP_KERNEL); | 434 | log->bios_event_log = kmalloc(len, GFP_KERNEL); |
409 | if (!log->bios_event_log) { | 435 | if (!log->bios_event_log) { |
410 | printk | 436 | printk("%s: ERROR - Not enough Memory for BIOS measurements\n", |
411 | ("%s: ERROR - Not enough Memory for BIOS measurements\n", | 437 | __func__); |
412 | __func__); | ||
413 | return -ENOMEM; | 438 | return -ENOMEM; |
414 | } | 439 | } |
415 | 440 | ||
416 | log->bios_event_log_end = log->bios_event_log + buff->log_max_len; | 441 | log->bios_event_log_end = log->bios_event_log + len; |
417 | 442 | ||
418 | acpi_os_map_memory(buff->log_start_addr, buff->log_max_len, (void *) &virt); | 443 | acpi_os_map_memory(start, len, (void *) &virt); |
419 | 444 | ||
420 | memcpy(log->bios_event_log, virt, buff->log_max_len); | 445 | memcpy(log->bios_event_log, virt, len); |
421 | 446 | ||
422 | acpi_os_unmap_memory(virt, buff->log_max_len); | 447 | acpi_os_unmap_memory(virt, len); |
423 | return 0; | 448 | return 0; |
424 | } | 449 | } |
425 | 450 | ||