summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/char/tpm/eventlog/efi.c11
-rw-r--r--drivers/firmware/efi/libstub/tpm.c30
-rw-r--r--include/linux/efi.h1
3 files changed, 41 insertions, 1 deletions
diff --git a/drivers/char/tpm/eventlog/efi.c b/drivers/char/tpm/eventlog/efi.c
index 73b981026627..6bb023de17f1 100644
--- a/drivers/char/tpm/eventlog/efi.c
+++ b/drivers/char/tpm/eventlog/efi.c
@@ -75,6 +75,8 @@ int tpm_read_log_efi(struct tpm_chip *chip)
goto out;
}
+ efi_tpm_final_log_size -= log_tbl->final_events_preboot_size;
+
tmp = krealloc(log->bios_event_log,
log_size + efi_tpm_final_log_size,
GFP_KERNEL);
@@ -85,8 +87,15 @@ int tpm_read_log_efi(struct tpm_chip *chip)
}
log->bios_event_log = tmp;
+
+ /*
+ * Copy any of the final events log that didn't also end up in the
+ * main log. Events can be logged in both if events are generated
+ * between GetEventLog() and ExitBootServices().
+ */
memcpy((void *)log->bios_event_log + log_size,
- final_tbl->events, efi_tpm_final_log_size);
+ final_tbl->events + log_tbl->final_events_preboot_size,
+ efi_tpm_final_log_size);
log->bios_event_log_end = log->bios_event_log +
log_size + efi_tpm_final_log_size;
diff --git a/drivers/firmware/efi/libstub/tpm.c b/drivers/firmware/efi/libstub/tpm.c
index 6b3b507a54eb..eb9af83e4d59 100644
--- a/drivers/firmware/efi/libstub/tpm.c
+++ b/drivers/firmware/efi/libstub/tpm.c
@@ -64,11 +64,13 @@ void efi_retrieve_tpm2_eventlog(efi_system_table_t *sys_table_arg)
efi_status_t status;
efi_physical_addr_t log_location = 0, log_last_entry = 0;
struct linux_efi_tpm_eventlog *log_tbl = NULL;
+ struct efi_tcg2_final_events_table *final_events_table;
unsigned long first_entry_addr, last_entry_addr;
size_t log_size, last_entry_size;
efi_bool_t truncated;
int version = EFI_TCG2_EVENT_LOG_FORMAT_TCG_2;
void *tcg2_protocol = NULL;
+ int final_events_size = 0;
status = efi_call_early(locate_protocol, &tcg2_guid, NULL,
&tcg2_protocol);
@@ -134,8 +136,36 @@ void efi_retrieve_tpm2_eventlog(efi_system_table_t *sys_table_arg)
return;
}
+ /*
+ * Figure out whether any events have already been logged to the
+ * final events structure, and if so how much space they take up
+ */
+ final_events_table = get_efi_config_table(sys_table_arg,
+ LINUX_EFI_TPM_FINAL_LOG_GUID);
+ if (final_events_table && final_events_table->nr_events) {
+ struct tcg_pcr_event2_head *header;
+ int offset;
+ void *data;
+ int event_size;
+ int i = final_events_table->nr_events;
+
+ data = (void *)final_events_table;
+ offset = sizeof(final_events_table->version) +
+ sizeof(final_events_table->nr_events);
+
+ while (i > 0) {
+ header = data + offset + final_events_size;
+ event_size = __calc_tpm2_event_size(header,
+ (void *)(long)log_location,
+ false);
+ final_events_size += event_size;
+ i--;
+ }
+ }
+
memset(log_tbl, 0, sizeof(*log_tbl) + log_size);
log_tbl->size = log_size;
+ log_tbl->final_events_preboot_size = final_events_size;
log_tbl->version = version;
memcpy(log_tbl->log, (void *) first_entry_addr, log_size);
diff --git a/include/linux/efi.h b/include/linux/efi.h
index b391263d8ec6..f87fabea4a85 100644
--- a/include/linux/efi.h
+++ b/include/linux/efi.h
@@ -1708,6 +1708,7 @@ struct linux_efi_random_seed {
struct linux_efi_tpm_eventlog {
u32 size;
+ u32 final_events_preboot_size;
u8 version;
u8 log[];
};