]>
Commit | Line | Data |
---|---|---|
4febfb8d | 1 | // SPDX-License-Identifier: GPL-2.0 |
33b6d034 TW |
2 | /* |
3 | * Copyright (C) 2017 Google, Inc. | |
4 | * Thiebaud Weksteen <tweek@google.com> | |
33b6d034 TW |
5 | */ |
6 | ||
c46f3405 MG |
7 | #define TPM_MEMREMAP(start, size) early_memremap(start, size) |
8 | #define TPM_MEMUNMAP(start, size) early_memunmap(start, size) | |
9 | ||
10 | #include <asm/early_ioremap.h> | |
33b6d034 TW |
11 | #include <linux/efi.h> |
12 | #include <linux/init.h> | |
13 | #include <linux/memblock.h> | |
c46f3405 | 14 | #include <linux/tpm_eventlog.h> |
33b6d034 | 15 | |
c46f3405 MG |
16 | int efi_tpm_final_log_size; |
17 | EXPORT_SYMBOL(efi_tpm_final_log_size); | |
18 | ||
e99332e7 | 19 | static int __init tpm2_calc_event_log_size(void *data, int count, void *size_info) |
c46f3405 MG |
20 | { |
21 | struct tcg_pcr_event2_head *header; | |
22 | int event_size, size = 0; | |
23 | ||
24 | while (count > 0) { | |
25 | header = data + size; | |
26 | event_size = __calc_tpm2_event_size(header, size_info, true); | |
27 | if (event_size == 0) | |
28 | return -1; | |
29 | size += event_size; | |
30 | count--; | |
31 | } | |
32 | ||
33 | return size; | |
34 | } | |
33b6d034 TW |
35 | |
36 | /* | |
37 | * Reserve the memory associated with the TPM Event Log configuration table. | |
38 | */ | |
39 | int __init efi_tpm_eventlog_init(void) | |
40 | { | |
41 | struct linux_efi_tpm_eventlog *log_tbl; | |
c46f3405 | 42 | struct efi_tcg2_final_events_table *final_tbl; |
be59d57f | 43 | int tbl_size; |
c46f3405 | 44 | int ret = 0; |
33b6d034 | 45 | |
c46f3405 MG |
46 | if (efi.tpm_log == EFI_INVALID_TABLE_ADDR) { |
47 | /* | |
48 | * We can't calculate the size of the final events without the | |
49 | * first entry in the TPM log, so bail here. | |
50 | */ | |
33b6d034 | 51 | return 0; |
c46f3405 | 52 | } |
33b6d034 TW |
53 | |
54 | log_tbl = early_memremap(efi.tpm_log, sizeof(*log_tbl)); | |
55 | if (!log_tbl) { | |
56 | pr_err("Failed to map TPM Event Log table @ 0x%lx\n", | |
c46f3405 | 57 | efi.tpm_log); |
33b6d034 TW |
58 | efi.tpm_log = EFI_INVALID_TABLE_ADDR; |
59 | return -ENOMEM; | |
60 | } | |
61 | ||
62 | tbl_size = sizeof(*log_tbl) + log_tbl->size; | |
63 | memblock_reserve(efi.tpm_log, tbl_size); | |
c46f3405 MG |
64 | |
65 | if (efi.tpm_final_log == EFI_INVALID_TABLE_ADDR) | |
66 | goto out; | |
67 | ||
68 | final_tbl = early_memremap(efi.tpm_final_log, sizeof(*final_tbl)); | |
69 | ||
70 | if (!final_tbl) { | |
71 | pr_err("Failed to map TPM Final Event Log table @ 0x%lx\n", | |
72 | efi.tpm_final_log); | |
73 | efi.tpm_final_log = EFI_INVALID_TABLE_ADDR; | |
74 | ret = -ENOMEM; | |
75 | goto out; | |
76 | } | |
77 | ||
05c8c1ff PJ |
78 | tbl_size = 0; |
79 | if (final_tbl->nr_events != 0) { | |
80 | void *events = (void *)efi.tpm_final_log | |
81 | + sizeof(final_tbl->version) | |
82 | + sizeof(final_tbl->nr_events); | |
83 | ||
84 | tbl_size = tpm2_calc_event_log_size(events, | |
85 | final_tbl->nr_events, | |
86 | log_tbl->log); | |
87 | } | |
e658c82b JS |
88 | |
89 | if (tbl_size < 0) { | |
90 | pr_err(FW_BUG "Failed to parse event in TPM Final Events Log\n"); | |
2bb6a816 | 91 | ret = -EINVAL; |
e658c82b JS |
92 | goto out_calc; |
93 | } | |
94 | ||
c46f3405 MG |
95 | memblock_reserve((unsigned long)final_tbl, |
96 | tbl_size + sizeof(*final_tbl)); | |
c46f3405 MG |
97 | efi_tpm_final_log_size = tbl_size; |
98 | ||
e658c82b JS |
99 | out_calc: |
100 | early_memunmap(final_tbl, sizeof(*final_tbl)); | |
c46f3405 | 101 | out: |
33b6d034 | 102 | early_memunmap(log_tbl, sizeof(*log_tbl)); |
c46f3405 | 103 | return ret; |
33b6d034 TW |
104 | } |
105 |