David Brazdil | 0f672f6 | 2019-12-10 10:32:29 +0000 | [diff] [blame^] | 1 | // SPDX-License-Identifier: GPL-2.0-or-later |
Andrew Scull | b4b6d4a | 2019-01-02 15:54:55 +0000 | [diff] [blame] | 2 | /* |
| 3 | * Copyright (C) 2017 Google |
| 4 | * |
| 5 | * Authors: |
| 6 | * Thiebaud Weksteen <tweek@google.com> |
Andrew Scull | b4b6d4a | 2019-01-02 15:54:55 +0000 | [diff] [blame] | 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 | |
David Brazdil | 0f672f6 | 2019-12-10 10:32:29 +0000 | [diff] [blame^] | 19 | struct efi_tcg2_final_events_table *final_tbl = NULL; |
Andrew Scull | b4b6d4a | 2019-01-02 15:54:55 +0000 | [diff] [blame] | 20 | struct linux_efi_tpm_eventlog *log_tbl; |
| 21 | struct tpm_bios_log *log; |
| 22 | u32 log_size; |
| 23 | u8 tpm_log_version; |
David Brazdil | 0f672f6 | 2019-12-10 10:32:29 +0000 | [diff] [blame^] | 24 | void *tmp; |
| 25 | int ret; |
Andrew Scull | b4b6d4a | 2019-01-02 15:54:55 +0000 | [diff] [blame] | 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 | log_tbl = memremap(efi.tpm_log, sizeof(*log_tbl) + log_size, |
| 45 | MEMREMAP_WB); |
| 46 | if (!log_tbl) { |
| 47 | pr_err("Could not map UEFI TPM log table payload!\n"); |
| 48 | return -ENOMEM; |
| 49 | } |
| 50 | |
| 51 | /* malloc EventLog space */ |
| 52 | log->bios_event_log = kmemdup(log_tbl->log, log_size, GFP_KERNEL); |
David Brazdil | 0f672f6 | 2019-12-10 10:32:29 +0000 | [diff] [blame^] | 53 | if (!log->bios_event_log) { |
| 54 | ret = -ENOMEM; |
| 55 | goto out; |
| 56 | } |
| 57 | |
Andrew Scull | b4b6d4a | 2019-01-02 15:54:55 +0000 | [diff] [blame] | 58 | log->bios_event_log_end = log->bios_event_log + log_size; |
Andrew Scull | b4b6d4a | 2019-01-02 15:54:55 +0000 | [diff] [blame] | 59 | tpm_log_version = log_tbl->version; |
Andrew Scull | b4b6d4a | 2019-01-02 15:54:55 +0000 | [diff] [blame] | 60 | |
David Brazdil | 0f672f6 | 2019-12-10 10:32:29 +0000 | [diff] [blame^] | 61 | ret = tpm_log_version; |
| 62 | |
| 63 | if (efi.tpm_final_log == EFI_INVALID_TABLE_ADDR || |
| 64 | efi_tpm_final_log_size == 0 || |
| 65 | tpm_log_version != EFI_TCG2_EVENT_LOG_FORMAT_TCG_2) |
| 66 | goto out; |
| 67 | |
| 68 | final_tbl = memremap(efi.tpm_final_log, |
| 69 | sizeof(*final_tbl) + efi_tpm_final_log_size, |
| 70 | MEMREMAP_WB); |
| 71 | if (!final_tbl) { |
| 72 | pr_err("Could not map UEFI TPM final log\n"); |
| 73 | kfree(log->bios_event_log); |
| 74 | ret = -ENOMEM; |
| 75 | goto out; |
| 76 | } |
| 77 | |
| 78 | efi_tpm_final_log_size -= log_tbl->final_events_preboot_size; |
| 79 | |
| 80 | tmp = krealloc(log->bios_event_log, |
| 81 | log_size + efi_tpm_final_log_size, |
| 82 | GFP_KERNEL); |
| 83 | if (!tmp) { |
| 84 | kfree(log->bios_event_log); |
| 85 | ret = -ENOMEM; |
| 86 | goto out; |
| 87 | } |
| 88 | |
| 89 | log->bios_event_log = tmp; |
| 90 | |
| 91 | /* |
| 92 | * Copy any of the final events log that didn't also end up in the |
| 93 | * main log. Events can be logged in both if events are generated |
| 94 | * between GetEventLog() and ExitBootServices(). |
| 95 | */ |
| 96 | memcpy((void *)log->bios_event_log + log_size, |
| 97 | final_tbl->events + log_tbl->final_events_preboot_size, |
| 98 | efi_tpm_final_log_size); |
| 99 | log->bios_event_log_end = log->bios_event_log + |
| 100 | log_size + efi_tpm_final_log_size; |
| 101 | |
| 102 | out: |
| 103 | memunmap(final_tbl); |
Andrew Scull | b4b6d4a | 2019-01-02 15:54:55 +0000 | [diff] [blame] | 104 | memunmap(log_tbl); |
David Brazdil | 0f672f6 | 2019-12-10 10:32:29 +0000 | [diff] [blame^] | 105 | return ret; |
Andrew Scull | b4b6d4a | 2019-01-02 15:54:55 +0000 | [diff] [blame] | 106 | } |