Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
torvalds
GitHub Repository: torvalds/linux
Path: blob/master/drivers/char/tpm/eventlog/efi.c
26292 views
1
// SPDX-License-Identifier: GPL-2.0-or-later
2
/*
3
* Copyright (C) 2017 Google
4
*
5
* Authors:
6
* Thiebaud Weksteen <[email protected]>
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
127