cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

efi.c (2949B)


      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	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
    120out:
    121	memunmap(final_tbl);
    122	memunmap(log_tbl);
    123	return ret;
    124}