1 /*
2 * Copyright (c) 2025-2026, Arm Limited. All rights reserved.
3 *
4 * SPDX-License-Identifier: BSD-3-Clause
5 */
6
7 #include <assert.h>
8 #include <stdarg.h>
9 #include <stdint.h>
10
11 #include <plat/common/common_def.h>
12 #include <plat/common/platform.h>
13 #include <platform_def.h>
14
15 #include <drivers/auth/crypto_mod.h>
16 #include <drivers/delay_timer.h>
17 #include <drivers/gpio_spi.h>
18 #include <drivers/measured_boot/metadata.h>
19 #include <drivers/tpm/tpm2_slb9670/slb9670_gpio.h>
20 #include <event_measure.h>
21 #include <event_print.h>
22 #include <tpm2.h>
23 #include <tpm2_chip.h>
24 #if TRANSFER_LIST
25 #include <tpm_event_log.h>
26 #include <transfer_list.h>
27 extern struct transfer_list_header *bl2_tl;
28 #endif
29 #include <tools_share/tbbr_oid.h>
30
31 #include "./include/rpi3_measured_boot.h"
32
33 /* RPI3 table with platform specific image IDs, names and PCRs */
34 const event_log_metadata_t rpi3_event_log_metadata[] = {
35 { BL31_IMAGE_ID, MBOOT_BL31_IMAGE_STRING, PCR_0 },
36 { BL33_IMAGE_ID, MBOOT_BL33_IMAGE_STRING, PCR_0 },
37 { NT_FW_CONFIG_ID, MBOOT_NT_FW_CONFIG_STRING, PCR_0 },
38
39 { EVLOG_INVALID_ID, NULL, (unsigned int)(-1) } /* Terminator */
40 };
41
42 #if DISCRETE_TPM
43 extern struct tpm_chip_data tpm_chip_data;
44
rpi3_bl2_tpm_early_interface_setup(void)45 static void rpi3_bl2_tpm_early_interface_setup(void)
46 {
47 #if TPM_INTERFACE_FIFO_SPI
48 struct tpm_spi_plat *spidev;
49 const struct tpm_timeout_ops timeout_ops = {
50 .timeout_init_us = timeout_init_us,
51 .timeout_elapsed = timeout_elapsed
52 };
53
54 const struct gpio_spi_config *tpm_rpi3_gpio_data =
55 tpm2_slb9670_get_config();
56 int rc;
57
58 tpm2_slb9670_gpio_init(tpm_rpi3_gpio_data);
59
60 spidev = gpio_spi_init(tpm_rpi3_gpio_data);
61
62 rc = tpm_interface_init(spidev, &timeout_ops, &tpm_chip_data, 0);
63 if (rc != 0) {
64 ERROR("BL2: TPM interface init failed\n");
65 panic();
66 }
67
68 #endif
69 }
70 #endif
71
72 static uint8_t *event_log_start;
73 static size_t event_log_size;
74 static uint8_t *event_log_base;
75 static uint8_t *event_log_finish;
76
bl2_plat_mboot_init(void)77 void bl2_plat_mboot_init(void)
78 {
79 struct transfer_list_entry *te __unused;
80 int rc;
81 #if DISCRETE_TPM
82 rpi3_bl2_tpm_early_interface_setup();
83 #endif
84
85 #if TRANSFER_LIST
86 if (bl2_tl != NULL &&
87 transfer_list_check_header(bl2_tl) != TL_OPS_NON) {
88 event_log_start = transfer_list_event_log_extend(
89 bl2_tl, PLAT_ARM_EVENT_LOG_MAX_SIZE);
90 flush_dcache_range((uintptr_t)bl2_tl, bl2_tl->size);
91 /*
92 * Retrieve the extend event log entry from the transfer list, the API above
93 * returns a cursor position rather than the base address - we need both to
94 * init the library.
95 */
96 te = transfer_list_find(bl2_tl, TL_TAG_TPM_EVLOG);
97
98 event_log_base =
99 transfer_list_entry_data(te) + EVENT_LOG_RESERVED_BYTES;
100 event_log_finish = transfer_list_entry_data(te) + te->data_size;
101
102 event_log_size = event_log_start - event_log_base;
103 } else {
104 ERROR("BL2: Valid transfer list not found");
105 panic();
106 }
107 #else
108 rpi3_mboot_fetch_eventlog_info(&event_log_start, &event_log_size);
109 event_log_base = event_log_start;
110 event_log_finish = event_log_start + PLAT_ARM_EVENT_LOG_MAX_SIZE;
111 #endif
112 rc = event_log_init_and_reg(event_log_base, event_log_finish,
113 event_log_size, crypto_mod_tcg_hash);
114 if (rc < 0) {
115 ERROR("Failed to initialize event log (%d).\n", rc);
116 panic();
117 }
118 }
119
bl2_plat_mboot_finish(void)120 void bl2_plat_mboot_finish(void)
121 {
122 int rc;
123 size_t event_log_cur_size;
124 #if TRANSFER_LIST
125 struct transfer_list_header *ns_tl = NULL;
126 uint8_t *cursor;
127 uint8_t *base_after_finish;
128
129 event_log_cur_size = event_log_get_cur_size(event_log_start);
130 cursor = event_log_start + event_log_cur_size;
131 base_after_finish =
132 transfer_list_event_log_finish(bl2_tl, (uintptr_t)cursor);
133 if (base_after_finish == NULL) {
134 WARN("BL2: Failed to finalize TL Event Log\n");
135 } else {
136 flush_dcache_range((uintptr_t)bl2_tl, bl2_tl->size);
137 transfer_list_update_checksum(bl2_tl);
138 event_log_start = base_after_finish;
139 event_log_cur_size = event_log_get_cur_size(event_log_start);
140 #ifdef FW_NS_HANDOFF_BASE
141 /* Update contents in NS Transfer List at FW_NS_HANDOFF_BASE */
142 ns_tl = transfer_list_relocate(
143 bl2_tl, (void *)(uintptr_t)FW_NS_HANDOFF_BASE,
144 bl2_tl->max_size);
145 if (!ns_tl) {
146 ERROR("Relocate TL to 0x%lx failed\n",
147 (unsigned long)FW_NS_HANDOFF_BASE);
148 panic();
149 }
150 #endif
151 }
152 #else
153
154 /* Event Log address in Non-Secure memory */
155 uintptr_t ns_log_addr;
156
157 event_log_cur_size = event_log_get_cur_size((uint8_t *)event_log_start);
158
159 /* write the eventlog addr and size to NT_FW_CONFIG TPM entry */
160 rc = rpi3_set_nt_fw_info(event_log_cur_size, &ns_log_addr);
161 if (rc != 0) {
162 ERROR("%s(): Unable to update %s_FW_CONFIG\n", __func__, "NT");
163 /*
164 * fatal error due to Bl33 maintaining the assumption
165 * that the eventlog is successfully passed via
166 * NT_FW_CONFIG.
167 */
168 panic();
169 }
170
171 /* Copy Event Log to Non-secure memory */
172 (void)memcpy((void *)ns_log_addr, (const void *)event_log_start,
173 event_log_cur_size);
174
175 /* Ensure that the Event Log is visible in Non-secure memory */
176 flush_dcache_range(ns_log_addr, event_log_cur_size);
177 #endif /* TRANSFER_LIST */
178 /* Dump Event Log for user view */
179 event_log_dump((uint8_t *)event_log_start, event_log_cur_size);
180
181 #if DISCRETE_TPM
182 /* relinquish control of TPM locality 0 and close interface */
183 rc = tpm_interface_close(&tpm_chip_data, 0);
184 if (rc != 0) {
185 ERROR("BL2: TPM interface close failed\n");
186 panic();
187 }
188 #endif
189 }
190