126 lines · c
1// SPDX-License-Identifier: GPL-2.0-or-later2/*3 * Copyright (C) 2017 Google4 *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 */17int 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 the93 * '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 the108 * 'main log'. Events can be logged in both if events are generated109 * 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' plus116 * 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 121out:122 memunmap(final_tbl);123 memunmap(log_tbl);124 return ret;125}126