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 int final_events_log_size = efi_tpm_final_log_size; 21 struct linux_efi_tpm_eventlog *log_tbl; 22 struct tpm_bios_log *log; 23 u32 log_size; 24 u8 tpm_log_version; 25 void *tmp; 26 int ret; 27 28 if (!(chip->flags & TPM_CHIP_FLAG_TPM2)) 29 return -ENODEV; 30 31 if (efi.tpm_log == EFI_INVALID_TABLE_ADDR) 32 return -ENODEV; 33 34 log = &chip->log; 35 36 log_tbl = memremap(efi.tpm_log, sizeof(*log_tbl), MEMREMAP_WB); 37 if (!log_tbl) { 38 pr_err("Could not map UEFI TPM log table !\n"); 39 return -ENOMEM; 40 } 41 42 log_size = log_tbl->size; 43 memunmap(log_tbl); 44 45 if (!log_size) { 46 pr_warn("UEFI TPM log area empty\n"); 47 return -EIO; 48 } 49 50 log_tbl = memremap(efi.tpm_log, sizeof(*log_tbl) + log_size, 51 MEMREMAP_WB); 52 if (!log_tbl) { 53 pr_err("Could not map UEFI TPM log table payload!\n"); 54 return -ENOMEM; 55 } 56 57 /* malloc EventLog space */ 58 log->bios_event_log = kmemdup(log_tbl->log, log_size, GFP_KERNEL); 59 if (!log->bios_event_log) { 60 ret = -ENOMEM; 61 goto out; 62 } 63 64 log->bios_event_log_end = log->bios_event_log + log_size; 65 tpm_log_version = log_tbl->version; 66 67 ret = tpm_log_version; 68 69 if (efi.tpm_final_log == EFI_INVALID_TABLE_ADDR || 70 final_events_log_size == 0 || 71 tpm_log_version != EFI_TCG2_EVENT_LOG_FORMAT_TCG_2) 72 goto out; 73 74 final_tbl = memremap(efi.tpm_final_log, 75 sizeof(*final_tbl) + final_events_log_size, 76 MEMREMAP_WB); 77 if (!final_tbl) { 78 pr_err("Could not map UEFI TPM final log\n"); 79 kfree(log->bios_event_log); 80 ret = -ENOMEM; 81 goto out; 82 } 83 84 /* 85 * The 'final events log' size excludes the 'final events preboot log' 86 * at its beginning. 87 */ 88 final_events_log_size -= log_tbl->final_events_preboot_size; 89 90 /* 91 * Allocate memory for the 'combined log' where we will append the 92 * 'final events log' to. 93 */ 94 tmp = krealloc(log->bios_event_log, 95 log_size + final_events_log_size, 96 GFP_KERNEL); 97 if (!tmp) { 98 kfree(log->bios_event_log); 99 ret = -ENOMEM; 100 goto out; 101 } 102 103 log->bios_event_log = tmp; 104 105 /* 106 * Append any of the 'final events log' that didn't also end up in the 107 * 'main log'. Events can be logged in both if events are generated 108 * between GetEventLog() and ExitBootServices(). 109 */ 110 memcpy((void *)log->bios_event_log + log_size, 111 final_tbl->events + log_tbl->final_events_preboot_size, 112 final_events_log_size); 113 /* 114 * The size of the 'combined log' is the size of the 'main log' plus 115 * the size of the 'final events log'. 116 */ 117 log->bios_event_log_end = log->bios_event_log + 118 log_size + final_events_log_size; 119 120 out: 121 memunmap(final_tbl); 122 memunmap(log_tbl); 123 return ret; 124 } 125