linux/drivers/char/tpm/eventlog/efi.c
<<
>>
Prefs
   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 */
  16int 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        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);
  53        if (!log->bios_event_log) {
  54                ret = -ENOMEM;
  55                goto out;
  56        }
  57
  58        log->bios_event_log_end = log->bios_event_log + log_size;
  59        tpm_log_version = log_tbl->version;
  60
  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
 102out:
 103        memunmap(final_tbl);
 104        memunmap(log_tbl);
 105        return ret;
 106}
 107