1 // SPDX-License-Identifier: GPL-2.0-or-later 2 /* 3 * Copyright (C) 2017 Google 4 * 5 * Authors: 6 * Thiebaud Weksteen <tweek@google.com> 7 */ 8 9 #include <linux/efi.h> 10 #include <linux/tpm_eventlog.h> 11 12 #include "../tpm.h" 13 #include "common.h" 14 15 /* read binary bios log from EFI configuration table */ 16 int tpm_read_log_efi(struct tpm_chip *chip) 17 { 18 19 struct efi_tcg2_final_events_table *final_tbl = NULL; 20 struct linux_efi_tpm_eventlog *log_tbl; 21 struct tpm_bios_log *log; 22 u32 log_size; 23 u8 tpm_log_version; 24 void *tmp; 25 int ret; 26 27 if (!(chip->flags & TPM_CHIP_FLAG_TPM2)) 28 return -ENODEV; 29 30 if (efi.tpm_log == EFI_INVALID_TABLE_ADDR) 31 return -ENODEV; 32 33 log = &chip->log; 34 35 log_tbl = memremap(efi.tpm_log, sizeof(*log_tbl), MEMREMAP_WB); 36 if (!log_tbl) { 37 pr_err("Could not map UEFI TPM log table !\n"); 38 return -ENOMEM; 39 } 40 41 log_size = log_tbl->size; 42 memunmap(log_tbl); 43 44 if (!log_size) { 45 pr_warn("UEFI TPM log area empty\n"); 46 return -EIO; 47 } 48 49 log_tbl = memremap(efi.tpm_log, sizeof(*log_tbl) + log_size, 50 MEMREMAP_WB); 51 if (!log_tbl) { 52 pr_err("Could not map UEFI TPM log table payload!\n"); 53 return -ENOMEM; 54 } 55 56 /* malloc EventLog space */ 57 log->bios_event_log = kmemdup(log_tbl->log, log_size, GFP_KERNEL); 58 if (!log->bios_event_log) { 59 ret = -ENOMEM; 60 goto out; 61 } 62 63 log->bios_event_log_end = log->bios_event_log + log_size; 64 tpm_log_version = log_tbl->version; 65 66 ret = tpm_log_version; 67 68 if (efi.tpm_final_log == EFI_INVALID_TABLE_ADDR || 69 efi_tpm_final_log_size == 0 || 70 tpm_log_version != EFI_TCG2_EVENT_LOG_FORMAT_TCG_2) 71 goto out; 72 73 final_tbl = memremap(efi.tpm_final_log, 74 sizeof(*final_tbl) + efi_tpm_final_log_size, 75 MEMREMAP_WB); 76 if (!final_tbl) { 77 pr_err("Could not map UEFI TPM final log\n"); 78 kfree(log->bios_event_log); 79 ret = -ENOMEM; 80 goto out; 81 } 82 83 efi_tpm_final_log_size -= log_tbl->final_events_preboot_size; 84 85 tmp = krealloc(log->bios_event_log, 86 log_size + efi_tpm_final_log_size, 87 GFP_KERNEL); 88 if (!tmp) { 89 kfree(log->bios_event_log); 90 ret = -ENOMEM; 91 goto out; 92 } 93 94 log->bios_event_log = tmp; 95 96 /* 97 * Copy any of the final events log that didn't also end up in the 98 * main log. Events can be logged in both if events are generated 99 * between GetEventLog() and ExitBootServices(). 100 */ 101 memcpy((void *)log->bios_event_log + log_size, 102 final_tbl->events + log_tbl->final_events_preboot_size, 103 efi_tpm_final_log_size); 104 log->bios_event_log_end = log->bios_event_log + 105 log_size + efi_tpm_final_log_size; 106 107 out: 108 memunmap(final_tbl); 109 memunmap(log_tbl); 110 return ret; 111 } 112