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