diff options
Diffstat (limited to 'drivers/firmware/efi')
| -rw-r--r-- | drivers/firmware/efi/Makefile | 2 | ||||
| -rw-r--r-- | drivers/firmware/efi/efi.c | 4 | ||||
| -rw-r--r-- | drivers/firmware/efi/libstub/Makefile | 3 | ||||
| -rw-r--r-- | drivers/firmware/efi/libstub/tpm.c | 81 | ||||
| -rw-r--r-- | drivers/firmware/efi/tpm.c | 40 |
5 files changed, 127 insertions, 3 deletions
diff --git a/drivers/firmware/efi/Makefile b/drivers/firmware/efi/Makefile index a3e73d6e8a43..cb805374f4bc 100644 --- a/drivers/firmware/efi/Makefile +++ b/drivers/firmware/efi/Makefile | |||
| @@ -11,7 +11,7 @@ | |||
| 11 | KASAN_SANITIZE_runtime-wrappers.o := n | 11 | KASAN_SANITIZE_runtime-wrappers.o := n |
| 12 | 12 | ||
| 13 | obj-$(CONFIG_ACPI_BGRT) += efi-bgrt.o | 13 | obj-$(CONFIG_ACPI_BGRT) += efi-bgrt.o |
| 14 | obj-$(CONFIG_EFI) += efi.o vars.o reboot.o memattr.o | 14 | obj-$(CONFIG_EFI) += efi.o vars.o reboot.o memattr.o tpm.o |
| 15 | obj-$(CONFIG_EFI) += capsule.o memmap.o | 15 | obj-$(CONFIG_EFI) += capsule.o memmap.o |
| 16 | obj-$(CONFIG_EFI_VARS) += efivars.o | 16 | obj-$(CONFIG_EFI_VARS) += efivars.o |
| 17 | obj-$(CONFIG_EFI_ESRT) += esrt.o | 17 | obj-$(CONFIG_EFI_ESRT) += esrt.o |
diff --git a/drivers/firmware/efi/efi.c b/drivers/firmware/efi/efi.c index 8ce70c2e73d5..cd42f66a7c85 100644 --- a/drivers/firmware/efi/efi.c +++ b/drivers/firmware/efi/efi.c | |||
| @@ -52,6 +52,7 @@ struct efi __read_mostly efi = { | |||
| 52 | .properties_table = EFI_INVALID_TABLE_ADDR, | 52 | .properties_table = EFI_INVALID_TABLE_ADDR, |
| 53 | .mem_attr_table = EFI_INVALID_TABLE_ADDR, | 53 | .mem_attr_table = EFI_INVALID_TABLE_ADDR, |
| 54 | .rng_seed = EFI_INVALID_TABLE_ADDR, | 54 | .rng_seed = EFI_INVALID_TABLE_ADDR, |
| 55 | .tpm_log = EFI_INVALID_TABLE_ADDR | ||
| 55 | }; | 56 | }; |
| 56 | EXPORT_SYMBOL(efi); | 57 | EXPORT_SYMBOL(efi); |
| 57 | 58 | ||
| @@ -464,6 +465,7 @@ static __initdata efi_config_table_type_t common_tables[] = { | |||
| 464 | {EFI_PROPERTIES_TABLE_GUID, "PROP", &efi.properties_table}, | 465 | {EFI_PROPERTIES_TABLE_GUID, "PROP", &efi.properties_table}, |
| 465 | {EFI_MEMORY_ATTRIBUTES_TABLE_GUID, "MEMATTR", &efi.mem_attr_table}, | 466 | {EFI_MEMORY_ATTRIBUTES_TABLE_GUID, "MEMATTR", &efi.mem_attr_table}, |
| 466 | {LINUX_EFI_RANDOM_SEED_TABLE_GUID, "RNG", &efi.rng_seed}, | 467 | {LINUX_EFI_RANDOM_SEED_TABLE_GUID, "RNG", &efi.rng_seed}, |
| 468 | {LINUX_EFI_TPM_EVENT_LOG_GUID, "TPMEventLog", &efi.tpm_log}, | ||
| 467 | {NULL_GUID, NULL, NULL}, | 469 | {NULL_GUID, NULL, NULL}, |
| 468 | }; | 470 | }; |
| 469 | 471 | ||
| @@ -552,6 +554,8 @@ int __init efi_config_parse_tables(void *config_tables, int count, int sz, | |||
| 552 | if (efi_enabled(EFI_MEMMAP)) | 554 | if (efi_enabled(EFI_MEMMAP)) |
| 553 | efi_memattr_init(); | 555 | efi_memattr_init(); |
| 554 | 556 | ||
| 557 | efi_tpm_eventlog_init(); | ||
| 558 | |||
| 555 | /* Parse the EFI Properties table if it exists */ | 559 | /* Parse the EFI Properties table if it exists */ |
| 556 | if (efi.properties_table != EFI_INVALID_TABLE_ADDR) { | 560 | if (efi.properties_table != EFI_INVALID_TABLE_ADDR) { |
| 557 | efi_properties_table_t *tbl; | 561 | efi_properties_table_t *tbl; |
diff --git a/drivers/firmware/efi/libstub/Makefile b/drivers/firmware/efi/libstub/Makefile index adaa4a964f0c..7b3ba40f0745 100644 --- a/drivers/firmware/efi/libstub/Makefile +++ b/drivers/firmware/efi/libstub/Makefile | |||
| @@ -30,8 +30,7 @@ OBJECT_FILES_NON_STANDARD := y | |||
| 30 | # Prevents link failures: __sanitizer_cov_trace_pc() is not linked in. | 30 | # Prevents link failures: __sanitizer_cov_trace_pc() is not linked in. |
| 31 | KCOV_INSTRUMENT := n | 31 | KCOV_INSTRUMENT := n |
| 32 | 32 | ||
| 33 | lib-y := efi-stub-helper.o gop.o secureboot.o | 33 | lib-y := efi-stub-helper.o gop.o secureboot.o tpm.o |
| 34 | lib-$(CONFIG_RESET_ATTACK_MITIGATION) += tpm.o | ||
| 35 | 34 | ||
| 36 | # include the stub's generic dependencies from lib/ when building for ARM/arm64 | 35 | # include the stub's generic dependencies from lib/ when building for ARM/arm64 |
| 37 | arm-deps-y := fdt_rw.c fdt_ro.c fdt_wip.c fdt.c fdt_empty_tree.c fdt_sw.c | 36 | arm-deps-y := fdt_rw.c fdt_ro.c fdt_wip.c fdt.c fdt_empty_tree.c fdt_sw.c |
diff --git a/drivers/firmware/efi/libstub/tpm.c b/drivers/firmware/efi/libstub/tpm.c index 6224cdbc9669..da661bf8cb96 100644 --- a/drivers/firmware/efi/libstub/tpm.c +++ b/drivers/firmware/efi/libstub/tpm.c | |||
| @@ -4,15 +4,18 @@ | |||
| 4 | * Copyright (C) 2016 CoreOS, Inc | 4 | * Copyright (C) 2016 CoreOS, Inc |
| 5 | * Copyright (C) 2017 Google, Inc. | 5 | * Copyright (C) 2017 Google, Inc. |
| 6 | * Matthew Garrett <mjg59@google.com> | 6 | * Matthew Garrett <mjg59@google.com> |
| 7 | * Thiebaud Weksteen <tweek@google.com> | ||
| 7 | * | 8 | * |
| 8 | * This file is part of the Linux kernel, and is made available under the | 9 | * This file is part of the Linux kernel, and is made available under the |
| 9 | * terms of the GNU General Public License version 2. | 10 | * terms of the GNU General Public License version 2. |
| 10 | */ | 11 | */ |
| 11 | #include <linux/efi.h> | 12 | #include <linux/efi.h> |
| 13 | #include <linux/tpm_eventlog.h> | ||
| 12 | #include <asm/efi.h> | 14 | #include <asm/efi.h> |
| 13 | 15 | ||
| 14 | #include "efistub.h" | 16 | #include "efistub.h" |
| 15 | 17 | ||
| 18 | #ifdef CONFIG_RESET_ATTACK_MITIGATION | ||
| 16 | static const efi_char16_t efi_MemoryOverWriteRequest_name[] = { | 19 | static const efi_char16_t efi_MemoryOverWriteRequest_name[] = { |
| 17 | 'M', 'e', 'm', 'o', 'r', 'y', 'O', 'v', 'e', 'r', 'w', 'r', 'i', 't', | 20 | 'M', 'e', 'm', 'o', 'r', 'y', 'O', 'v', 'e', 'r', 'w', 'r', 'i', 't', |
| 18 | 'e', 'R', 'e', 'q', 'u', 'e', 's', 't', 'C', 'o', 'n', 't', 'r', 'o', | 21 | 'e', 'R', 'e', 'q', 'u', 'e', 's', 't', 'C', 'o', 'n', 't', 'r', 'o', |
| @@ -56,3 +59,81 @@ void efi_enable_reset_attack_mitigation(efi_system_table_t *sys_table_arg) | |||
| 56 | EFI_VARIABLE_BOOTSERVICE_ACCESS | | 59 | EFI_VARIABLE_BOOTSERVICE_ACCESS | |
| 57 | EFI_VARIABLE_RUNTIME_ACCESS, sizeof(val), &val); | 60 | EFI_VARIABLE_RUNTIME_ACCESS, sizeof(val), &val); |
| 58 | } | 61 | } |
| 62 | |||
| 63 | #endif | ||
| 64 | |||
| 65 | void efi_retrieve_tpm2_eventlog_1_2(efi_system_table_t *sys_table_arg) | ||
| 66 | { | ||
| 67 | efi_guid_t tcg2_guid = EFI_TCG2_PROTOCOL_GUID; | ||
| 68 | efi_guid_t linux_eventlog_guid = LINUX_EFI_TPM_EVENT_LOG_GUID; | ||
| 69 | efi_status_t status; | ||
| 70 | efi_physical_addr_t log_location, log_last_entry; | ||
| 71 | struct linux_efi_tpm_eventlog *log_tbl; | ||
| 72 | unsigned long first_entry_addr, last_entry_addr; | ||
| 73 | size_t log_size, last_entry_size; | ||
| 74 | efi_bool_t truncated; | ||
| 75 | void *tcg2_protocol; | ||
| 76 | |||
| 77 | status = efi_call_early(locate_protocol, &tcg2_guid, NULL, | ||
| 78 | &tcg2_protocol); | ||
| 79 | if (status != EFI_SUCCESS) | ||
| 80 | return; | ||
| 81 | |||
| 82 | status = efi_call_proto(efi_tcg2_protocol, get_event_log, tcg2_protocol, | ||
| 83 | EFI_TCG2_EVENT_LOG_FORMAT_TCG_1_2, | ||
| 84 | &log_location, &log_last_entry, &truncated); | ||
| 85 | if (status != EFI_SUCCESS) | ||
| 86 | return; | ||
| 87 | |||
| 88 | if (!log_location) | ||
| 89 | return; | ||
| 90 | first_entry_addr = (unsigned long) log_location; | ||
| 91 | |||
| 92 | /* | ||
| 93 | * We populate the EFI table even if the logs are empty. | ||
| 94 | */ | ||
| 95 | if (!log_last_entry) { | ||
| 96 | log_size = 0; | ||
| 97 | } else { | ||
| 98 | last_entry_addr = (unsigned long) log_last_entry; | ||
| 99 | /* | ||
| 100 | * get_event_log only returns the address of the last entry. | ||
| 101 | * We need to calculate its size to deduce the full size of | ||
| 102 | * the logs. | ||
| 103 | */ | ||
| 104 | last_entry_size = sizeof(struct tcpa_event) + | ||
| 105 | ((struct tcpa_event *) last_entry_addr)->event_size; | ||
| 106 | log_size = log_last_entry - log_location + last_entry_size; | ||
| 107 | } | ||
| 108 | |||
| 109 | /* Allocate space for the logs and copy them. */ | ||
| 110 | status = efi_call_early(allocate_pool, EFI_LOADER_DATA, | ||
| 111 | sizeof(*log_tbl) + log_size, | ||
| 112 | (void **) &log_tbl); | ||
| 113 | |||
| 114 | if (status != EFI_SUCCESS) { | ||
| 115 | efi_printk(sys_table_arg, | ||
| 116 | "Unable to allocate memory for event log\n"); | ||
| 117 | return; | ||
| 118 | } | ||
| 119 | |||
| 120 | memset(log_tbl, 0, sizeof(*log_tbl) + log_size); | ||
| 121 | log_tbl->size = log_size; | ||
| 122 | log_tbl->version = EFI_TCG2_EVENT_LOG_FORMAT_TCG_1_2; | ||
| 123 | memcpy(log_tbl->log, (void *) first_entry_addr, log_size); | ||
| 124 | |||
| 125 | status = efi_call_early(install_configuration_table, | ||
| 126 | &linux_eventlog_guid, log_tbl); | ||
| 127 | if (status != EFI_SUCCESS) | ||
| 128 | goto err_free; | ||
| 129 | return; | ||
| 130 | |||
| 131 | err_free: | ||
| 132 | efi_call_early(free_pool, log_tbl); | ||
| 133 | } | ||
| 134 | |||
| 135 | void efi_retrieve_tpm2_eventlog(efi_system_table_t *sys_table_arg) | ||
| 136 | { | ||
| 137 | /* Only try to retrieve the logs in 1.2 format. */ | ||
| 138 | efi_retrieve_tpm2_eventlog_1_2(sys_table_arg); | ||
| 139 | } | ||
diff --git a/drivers/firmware/efi/tpm.c b/drivers/firmware/efi/tpm.c new file mode 100644 index 000000000000..0cbeb3d46b18 --- /dev/null +++ b/drivers/firmware/efi/tpm.c | |||
| @@ -0,0 +1,40 @@ | |||
| 1 | /* | ||
| 2 | * Copyright (C) 2017 Google, Inc. | ||
| 3 | * Thiebaud Weksteen <tweek@google.com> | ||
| 4 | * | ||
| 5 | * This program is free software; you can redistribute it and/or modify | ||
| 6 | * it under the terms of the GNU General Public License version 2 as | ||
| 7 | * published by the Free Software Foundation. | ||
| 8 | */ | ||
| 9 | |||
| 10 | #include <linux/efi.h> | ||
| 11 | #include <linux/init.h> | ||
| 12 | #include <linux/memblock.h> | ||
| 13 | |||
| 14 | #include <asm/early_ioremap.h> | ||
| 15 | |||
| 16 | /* | ||
| 17 | * Reserve the memory associated with the TPM Event Log configuration table. | ||
| 18 | */ | ||
| 19 | int __init efi_tpm_eventlog_init(void) | ||
| 20 | { | ||
| 21 | struct linux_efi_tpm_eventlog *log_tbl; | ||
| 22 | unsigned int tbl_size; | ||
| 23 | |||
| 24 | if (efi.tpm_log == EFI_INVALID_TABLE_ADDR) | ||
| 25 | return 0; | ||
| 26 | |||
| 27 | log_tbl = early_memremap(efi.tpm_log, sizeof(*log_tbl)); | ||
| 28 | if (!log_tbl) { | ||
| 29 | pr_err("Failed to map TPM Event Log table @ 0x%lx\n", | ||
| 30 | efi.tpm_log); | ||
| 31 | efi.tpm_log = EFI_INVALID_TABLE_ADDR; | ||
| 32 | return -ENOMEM; | ||
| 33 | } | ||
| 34 | |||
| 35 | tbl_size = sizeof(*log_tbl) + log_tbl->size; | ||
| 36 | memblock_reserve(efi.tpm_log, tbl_size); | ||
| 37 | early_memunmap(log_tbl, sizeof(*log_tbl)); | ||
| 38 | return 0; | ||
| 39 | } | ||
| 40 | |||
