1 /* SPDX-License-Identifier: GPL-2.0-only */
3 #include <console/console.h>
12 static int tpm_log_initialized
;
13 static inline int tpm_log_available(void)
16 return tpm_log_initialized
;
22 * Initializes the Core Root of Trust for Measurements
23 * in coreboot. The initial code in a chain of trust must measure
27 * + Measures the FMAP FMAP partition.
28 * + Measures bootblock in CBFS or BOOTBLOCK FMAP partition.
29 * + If vboot starts in romstage, it measures the romstage
31 * + Measure the verstage if it is compiled as separate
34 * Takes the current vboot context as parameter for s3 checks.
35 * returns on success TPM_SUCCESS, else a TPM error.
37 static tpm_result_t
tspi_init_crtm(void)
39 tpm_result_t rc
= TPM_SUCCESS
;
40 /* Initialize TPM PRERAM log. */
41 if (!tpm_log_available()) {
42 tpm_preram_log_clear();
43 tpm_log_initialized
= 1;
45 printk(BIOS_WARNING
, "TSPI: CRTM already initialized!\n");
49 struct region_device fmap
;
50 if (fmap_locate_area_as_rdev("FMAP", &fmap
) == 0) {
51 rc
= tpm_measure_region(&fmap
, CONFIG_PCR_SRTM
, "FMAP: FMAP");
54 "TSPI: Couldn't measure FMAP into CRTM! rc %#x\n", rc
);
58 printk(BIOS_ERR
, "TSPI: Could not find FMAP!\n");
61 /* measure bootblock from RO */
62 if (!CONFIG(ARCH_X86
)) {
63 struct region_device bootblock_fmap
;
64 if (fmap_locate_area_as_rdev("BOOTBLOCK", &bootblock_fmap
) == 0) {
65 rc
= tpm_measure_region(&bootblock_fmap
,
71 } else if (CONFIG(BOOTBLOCK_IN_CBFS
)) {
72 /* Mapping measures the file. We know we can safely map here because
73 bootblock-as-a-file is only used on x86, where we don't need cache to map. */
74 enum cbfs_type type
= CBFS_TYPE_BOOTBLOCK
;
75 void *mapping
= cbfs_ro_type_map("bootblock", NULL
, &type
);
78 "TSPI: Couldn't measure bootblock into CRTM!\n");
83 /* Since none of the above conditions are met let the SOC code measure the
84 * bootblock. This accomplishes for cases where the bootblock is treated
85 * in a special way (e.g. part of IFWI or located in a different CBFS). */
86 if (tspi_soc_measure_bootblock(CONFIG_PCR_SRTM
)) {
88 "TSPI: Couldn't measure bootblock into CRTM on SoC level!\n");
96 static bool is_runtime_data(const char *name
)
98 const char *allowlist
= CONFIG_TPM_MEASURED_BOOT_RUNTIME_DATA
;
99 size_t allowlist_len
= sizeof(CONFIG_TPM_MEASURED_BOOT_RUNTIME_DATA
) - 1;
100 size_t name_len
= strlen(name
);
103 if (!allowlist_len
|| !name_len
)
106 while ((end
= strchr(allowlist
, ' '))) {
107 if (end
- allowlist
== name_len
&& !strncmp(allowlist
, name
, name_len
))
112 return !strcmp(allowlist
, name
);
115 tpm_result_t
tspi_cbfs_measurement(const char *name
, uint32_t type
, const struct vb2_hash
*hash
)
118 tpm_result_t rc
= TPM_SUCCESS
;
119 char tpm_log_metadata
[TPM_CB_LOG_PCR_HASH_NAME
];
121 if (!tpm_log_available()) {
122 rc
= tspi_init_crtm();
125 "Initializing CRTM failed!\n");
128 printk(BIOS_DEBUG
, "CRTM initialized.\n");
132 case CBFS_TYPE_MRC_CACHE
:
133 pcr_index
= CONFIG_PCR_RUNTIME_DATA
;
136 * mrc.bin is code executed on CPU, so it
137 * should not be considered runtime data
140 case CBFS_TYPE_STAGE
:
142 case CBFS_TYPE_FIT_PAYLOAD
:
143 pcr_index
= CONFIG_PCR_SRTM
;
146 if (is_runtime_data(name
))
147 pcr_index
= CONFIG_PCR_RUNTIME_DATA
;
149 pcr_index
= CONFIG_PCR_SRTM
;
153 snprintf(tpm_log_metadata
, TPM_CB_LOG_PCR_HASH_NAME
, "CBFS: %s", name
);
155 return tpm_extend_pcr(pcr_index
, hash
->algo
, hash
->raw
, vb2_digest_size(hash
->algo
),
159 void *tpm_log_init(void)
163 /* We are dealing here with pre CBMEM environment.
164 * If cbmem isn't available use CAR or SRAM */
165 if (!ENV_HAS_CBMEM
&& !CONFIG(VBOOT_RETURN_FROM_VERSTAGE
))
167 else if (ENV_CREATES_CBMEM
168 && !CONFIG(VBOOT_RETURN_FROM_VERSTAGE
)) {
169 tclt
= tpm_log_cbmem_init();
173 tclt
= tpm_log_cbmem_init();
179 tpm_result_t
tspi_measure_cache_to_pcr(void)
183 const char *event_name
;
184 const uint8_t *digest_data
;
185 enum vb2_hash_algorithm digest_algo
;
187 /* This means the table is empty. */
188 if (!tpm_log_available())
191 if (tpm_log_init() == NULL
) {
192 printk(BIOS_WARNING
, "TPM LOG: log non-existent!\n");
196 printk(BIOS_DEBUG
, "TPM: Write digests cached in TPM log to PCR\n");
198 while (!tpm_log_get(i
++, &pcr
, &digest_data
, &digest_algo
, &event_name
)) {
199 printk(BIOS_DEBUG
, "TPM: Write digest for %s into PCR %d\n", event_name
, pcr
);
200 tpm_result_t rc
= tlcl_extend(pcr
, digest_data
, digest_algo
);
201 if (rc
!= TPM_SUCCESS
) {
203 "TPM: Writing digest of %s into PCR failed with error %d\n",
212 #if !CONFIG(VBOOT_RETURN_FROM_VERSTAGE)
213 static void recover_tpm_log(int is_recovery
)
215 const void *preram_log
= _tpm_log
;
216 void *ram_log
= tpm_log_cbmem_init();
218 if (tpm_log_get_size(preram_log
) > MAX_PRERAM_TPM_LOG_ENTRIES
) {
219 printk(BIOS_WARNING
, "TPM LOG: pre-RAM log is too full, possible corruption\n");
223 if (ram_log
== NULL
) {
224 printk(BIOS_WARNING
, "TPM LOG: CBMEM not available, something went wrong\n");
228 tpm_log_copy_entries(_tpm_log
, ram_log
);
230 CBMEM_CREATION_HOOK(recover_tpm_log
);
233 BOOT_STATE_INIT_ENTRY(BS_PAYLOAD_BOOT
, BS_ON_ENTRY
, tpm_log_dump
, NULL
);