mirror of
https://github.com/AuxXxilium/linux_dsm_epyc7002.git
synced 2024-12-28 11:18:45 +07:00
166a2809d6
After the first call to GetEventLog() on UEFI systems using the TCG2 crypto agile log format, any further log events (other than those triggered by ExitBootServices()) will be logged in both the main log and also in the Final Events Log. While the kernel only calls GetEventLog() immediately before ExitBootServices(), we can't control whether earlier parts of the boot process have done so. This will result in log entries that exist in both logs, and so the current approach of simply appending the Final Event Log to the main log will result in events being duplicated. We can avoid this problem by looking at the size of the Final Event Log just before we call ExitBootServices() and exporting this to the main kernel. The kernel can then skip over all events that occured before ExitBootServices() and only append events that were not also logged to the main log. Signed-off-by: Matthew Garrett <mjg59@google.com> Reported-by: Joe Richey <joerichey@google.com> Suggested-by: Joe Richey <joerichey@google.com> Acked-by: Ard Biesheuvel <ard.biesheuvel@linaro.org> Reviewed-by: Jarkko Sakkinen <jarkko.sakkinen@linux.intel.com> Tested-by: Jarkko Sakkinen <jarkko.sakkinen@linux.intel.com> Signed-off-by: Jarkko Sakkinen <jarkko.sakkinen@linux.intel.com>
107 lines
2.4 KiB
C
107 lines
2.4 KiB
C
// SPDX-License-Identifier: GPL-2.0-or-later
|
|
/*
|
|
* Copyright (C) 2017 Google
|
|
*
|
|
* Authors:
|
|
* Thiebaud Weksteen <tweek@google.com>
|
|
*/
|
|
|
|
#include <linux/efi.h>
|
|
#include <linux/tpm_eventlog.h>
|
|
|
|
#include "../tpm.h"
|
|
#include "common.h"
|
|
|
|
/* read binary bios log from EFI configuration table */
|
|
int tpm_read_log_efi(struct tpm_chip *chip)
|
|
{
|
|
|
|
struct efi_tcg2_final_events_table *final_tbl = NULL;
|
|
struct linux_efi_tpm_eventlog *log_tbl;
|
|
struct tpm_bios_log *log;
|
|
u32 log_size;
|
|
u8 tpm_log_version;
|
|
void *tmp;
|
|
int ret;
|
|
|
|
if (!(chip->flags & TPM_CHIP_FLAG_TPM2))
|
|
return -ENODEV;
|
|
|
|
if (efi.tpm_log == EFI_INVALID_TABLE_ADDR)
|
|
return -ENODEV;
|
|
|
|
log = &chip->log;
|
|
|
|
log_tbl = memremap(efi.tpm_log, sizeof(*log_tbl), MEMREMAP_WB);
|
|
if (!log_tbl) {
|
|
pr_err("Could not map UEFI TPM log table !\n");
|
|
return -ENOMEM;
|
|
}
|
|
|
|
log_size = log_tbl->size;
|
|
memunmap(log_tbl);
|
|
|
|
log_tbl = memremap(efi.tpm_log, sizeof(*log_tbl) + log_size,
|
|
MEMREMAP_WB);
|
|
if (!log_tbl) {
|
|
pr_err("Could not map UEFI TPM log table payload!\n");
|
|
return -ENOMEM;
|
|
}
|
|
|
|
/* malloc EventLog space */
|
|
log->bios_event_log = kmemdup(log_tbl->log, log_size, GFP_KERNEL);
|
|
if (!log->bios_event_log) {
|
|
ret = -ENOMEM;
|
|
goto out;
|
|
}
|
|
|
|
log->bios_event_log_end = log->bios_event_log + log_size;
|
|
tpm_log_version = log_tbl->version;
|
|
|
|
ret = tpm_log_version;
|
|
|
|
if (efi.tpm_final_log == EFI_INVALID_TABLE_ADDR ||
|
|
efi_tpm_final_log_size == 0 ||
|
|
tpm_log_version != EFI_TCG2_EVENT_LOG_FORMAT_TCG_2)
|
|
goto out;
|
|
|
|
final_tbl = memremap(efi.tpm_final_log,
|
|
sizeof(*final_tbl) + efi_tpm_final_log_size,
|
|
MEMREMAP_WB);
|
|
if (!final_tbl) {
|
|
pr_err("Could not map UEFI TPM final log\n");
|
|
kfree(log->bios_event_log);
|
|
ret = -ENOMEM;
|
|
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);
|
|
if (!tmp) {
|
|
kfree(log->bios_event_log);
|
|
ret = -ENOMEM;
|
|
goto out;
|
|
}
|
|
|
|
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 + 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;
|
|
|
|
out:
|
|
memunmap(final_tbl);
|
|
memunmap(log_tbl);
|
|
return ret;
|
|
}
|