cbfs: Move more stuff into cbfs_boot_lookup()
cbfs_boot_locate() is supposed to be deprecated eventually, after slowly migrating all APIs to bypass it. That means common features (like RO-fallback or measurement) need to be moved to the new cbfs_boot_lookup(). Also export the function externally. Since it is a low-level API and most code should use the higher-level loading or mapping functions instead, put it into a new <cbfs_private.h> to raise the mental barrier for using this API (this will make more sense once cbfs_boot_locate() is removed from <cbfs.h>). Signed-off-by: Julius Werner <jwerner@chromium.org> Change-Id: I4bc9b7cbc42a4211d806a3e3389abab7f589a25a Reviewed-on: https://review.coreboot.org/c/coreboot/+/39327 Tested-by: build bot (Jenkins) <no-reply@coreboot.org> Reviewed-by: Aaron Durbin <adurbin@chromium.org>
This commit is contained in:
		
				
					committed by
					
						 Patrick Georgi
						Patrick Georgi
					
				
			
			
				
	
			
			
			
						parent
						
							baf27dbaeb
						
					
				
				
					commit
					0d9072b1a1
				
			| @@ -27,7 +27,8 @@ enum bootdev_prot_type { | |||||||
|  * most likely not to work so don't rely on such semantics. |  * most likely not to work so don't rely on such semantics. | ||||||
|  */ |  */ | ||||||
|  |  | ||||||
| /* Return the region_device for the read-only boot device. */ | /* Return the region_device for the read-only boot device. This is the root | ||||||
|  |    device for all CBFS boot devices. */ | ||||||
| const struct region_device *boot_device_ro(void); | const struct region_device *boot_device_ro(void); | ||||||
|  |  | ||||||
| /* Return the region_device for the read-write boot device. */ | /* Return the region_device for the read-write boot device. */ | ||||||
|   | |||||||
| @@ -42,6 +42,12 @@ size_t cbfs_load_and_decompress(const struct region_device *rdev, size_t offset, | |||||||
| /* Load stage into memory filling in prog. Return 0 on success. < 0 on error. */ | /* Load stage into memory filling in prog. Return 0 on success. < 0 on error. */ | ||||||
| int cbfs_prog_stage_load(struct prog *prog); | int cbfs_prog_stage_load(struct prog *prog); | ||||||
|  |  | ||||||
|  | /* | ||||||
|  |  * Data structure that represents "a" CBFS boot device, with optional metadata | ||||||
|  |  * cache. Generally we only have one of these, or two (RO and RW) when | ||||||
|  |  * CONFIG(VBOOT) is set. The region device stored here must always be a | ||||||
|  |  * subregion of boot_device_ro(). | ||||||
|  |  */ | ||||||
| struct cbfs_boot_device { | struct cbfs_boot_device { | ||||||
| 	struct region_device rdev; | 	struct region_device rdev; | ||||||
| 	void *mcache; | 	void *mcache; | ||||||
|   | |||||||
							
								
								
									
										23
									
								
								src/include/cbfs_private.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										23
									
								
								src/include/cbfs_private.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,23 @@ | |||||||
|  | /* SPDX-License-Identifier: GPL-2.0-only */ | ||||||
|  |  | ||||||
|  | #ifndef _CBFS_PRIVATE_H_ | ||||||
|  | #define _CBFS_PRIVATE_H_ | ||||||
|  |  | ||||||
|  | #include <commonlib/bsd/cbfs_private.h> | ||||||
|  | #include <commonlib/region.h> | ||||||
|  | #include <types.h> | ||||||
|  |  | ||||||
|  | /* | ||||||
|  |  * This header contains low-level CBFS APIs that should only be used by code | ||||||
|  |  * that really needs this level of access. Most code (particularly platform | ||||||
|  |  * code) should use the higher-level CBFS APIs in <cbfs.h>. Code using these | ||||||
|  |  * APIs needs to take special care to ensure CBFS file data is verified (in a | ||||||
|  |  * TOCTOU-safe manner) before access (TODO: add details on how to do this once | ||||||
|  |  * file verification code is in). | ||||||
|  |  */ | ||||||
|  |  | ||||||
|  | /* Find by name, load metadata into |mdata| and chain file data to |rdev|. */ | ||||||
|  | cb_err_t cbfs_boot_lookup(const char *name, bool force_ro, | ||||||
|  | 			  union cbfs_mdata *mdata, struct region_device *rdev); | ||||||
|  |  | ||||||
|  | #endif | ||||||
| @@ -3,8 +3,8 @@ | |||||||
| #include <assert.h> | #include <assert.h> | ||||||
| #include <boot_device.h> | #include <boot_device.h> | ||||||
| #include <cbfs.h> | #include <cbfs.h> | ||||||
|  | #include <cbfs_private.h> | ||||||
| #include <cbmem.h> | #include <cbmem.h> | ||||||
| #include <commonlib/bsd/cbfs_private.h> |  | ||||||
| #include <commonlib/bsd/compression.h> | #include <commonlib/bsd/compression.h> | ||||||
| #include <commonlib/endian.h> | #include <commonlib/endian.h> | ||||||
| #include <console/console.h> | #include <console/console.h> | ||||||
| @@ -17,43 +17,49 @@ | |||||||
| #include <symbols.h> | #include <symbols.h> | ||||||
| #include <timestamp.h> | #include <timestamp.h> | ||||||
|  |  | ||||||
| static cb_err_t cbfs_boot_lookup(const struct cbfs_boot_device *cbd, | cb_err_t cbfs_boot_lookup(const char *name, bool force_ro, | ||||||
| 		const char *name, union cbfs_mdata *mdata, size_t *data_offset) | 			  union cbfs_mdata *mdata, struct region_device *rdev) | ||||||
| { | { | ||||||
|  | 	const struct cbfs_boot_device *cbd = cbfs_get_boot_device(force_ro); | ||||||
|  | 	if (!cbd) | ||||||
|  | 		return CB_ERR; | ||||||
|  |  | ||||||
|  | 	size_t data_offset; | ||||||
| 	cb_err_t err = CB_CBFS_CACHE_FULL; | 	cb_err_t err = CB_CBFS_CACHE_FULL; | ||||||
| 	if (!CONFIG(NO_CBFS_MCACHE) && !ENV_SMM) | 	if (!CONFIG(NO_CBFS_MCACHE) && !ENV_SMM) | ||||||
| 		err = cbfs_mcache_lookup(cbd->mcache, cbd->mcache_size, | 		err = cbfs_mcache_lookup(cbd->mcache, cbd->mcache_size, | ||||||
| 					  name, mdata, data_offset); | 					  name, mdata, &data_offset); | ||||||
| 	if (err == CB_CBFS_CACHE_FULL) | 	if (err == CB_CBFS_CACHE_FULL) | ||||||
| 		err = cbfs_lookup(&cbd->rdev, name, mdata, data_offset, NULL); | 		err = cbfs_lookup(&cbd->rdev, name, mdata, &data_offset, NULL); | ||||||
| 	return err; |  | ||||||
|  | 	if (CONFIG(VBOOT_ENABLE_CBFS_FALLBACK) && !force_ro && | ||||||
|  | 	    err == CB_CBFS_NOT_FOUND) { | ||||||
|  | 		printk(BIOS_INFO, "CBFS: Fall back to RO region for %s\n", | ||||||
|  | 		       name); | ||||||
|  | 		return cbfs_boot_lookup(name, true, mdata, rdev); | ||||||
|  | 	} | ||||||
|  | 	if (err) | ||||||
|  | 		return err; | ||||||
|  |  | ||||||
|  | 	if (rdev_chain(rdev, &cbd->rdev, data_offset, be32toh(mdata->h.len))) | ||||||
|  | 		return CB_ERR; | ||||||
|  |  | ||||||
|  | 	if (tspi_measure_cbfs_hook(rdev, name, be32toh(mdata->h.type))) | ||||||
|  | 		return CB_ERR; | ||||||
|  |  | ||||||
|  | 	return CB_SUCCESS; | ||||||
| } | } | ||||||
|  |  | ||||||
| int cbfs_boot_locate(struct cbfsf *fh, const char *name, uint32_t *type) | int cbfs_boot_locate(struct cbfsf *fh, const char *name, uint32_t *type) | ||||||
| { | { | ||||||
| 	const struct cbfs_boot_device *cbd = cbfs_get_boot_device(false); | 	if (cbfs_boot_lookup(name, false, &fh->mdata, &fh->data)) | ||||||
| 	if (!cbd) |  | ||||||
| 		return -1; |  | ||||||
|  |  | ||||||
| 	size_t data_offset; |  | ||||||
| 	cb_err_t err = cbfs_boot_lookup(cbd, name, &fh->mdata, &data_offset); |  | ||||||
|  |  | ||||||
| 	if (CONFIG(VBOOT_ENABLE_CBFS_FALLBACK) && err == CB_CBFS_NOT_FOUND) { |  | ||||||
| 		printk(BIOS_INFO, "CBFS: Fall back to RO region for %s\n", |  | ||||||
| 		       name); |  | ||||||
| 		if (!(cbd = cbfs_get_boot_device(true))) |  | ||||||
| 			return -1; |  | ||||||
| 		err = cbfs_boot_lookup(cbd, name, &fh->mdata, &data_offset); |  | ||||||
| 	} |  | ||||||
| 	if (err) |  | ||||||
| 		return -1; | 		return -1; | ||||||
|  |  | ||||||
| 	size_t msize = be32toh(fh->mdata.h.offset); | 	size_t msize = be32toh(fh->mdata.h.offset); | ||||||
| 	if (rdev_chain(&fh->metadata, &addrspace_32bit.rdev, | 	if (rdev_chain(&fh->metadata, &addrspace_32bit.rdev, | ||||||
| 		       (uintptr_t)&fh->mdata, msize) || | 		       (uintptr_t)&fh->mdata, msize)) | ||||||
| 	    rdev_chain(&fh->data, &cbd->rdev, data_offset, |  | ||||||
| 		       be32toh(fh->mdata.h.len))) |  | ||||||
| 		return -1; | 		return -1; | ||||||
|  |  | ||||||
| 	if (type) { | 	if (type) { | ||||||
| 		if (!*type) | 		if (!*type) | ||||||
| 			*type = be32toh(fh->mdata.h.type); | 			*type = be32toh(fh->mdata.h.type); | ||||||
| @@ -61,9 +67,6 @@ int cbfs_boot_locate(struct cbfsf *fh, const char *name, uint32_t *type) | |||||||
| 			return -1; | 			return -1; | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	if (tspi_measure_cbfs_hook(fh, name)) |  | ||||||
| 		return -1; |  | ||||||
|  |  | ||||||
| 	return 0; | 	return 0; | ||||||
| } | } | ||||||
|  |  | ||||||
| @@ -94,9 +97,13 @@ int cbfs_locate_file_in_region(struct cbfsf *fh, const char *region_name, | |||||||
| 		return -1; | 		return -1; | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
|  | 	uint32_t dummy_type = 0; | ||||||
|  | 	if (!type) | ||||||
|  | 		type = &dummy_type; | ||||||
|  |  | ||||||
| 	ret = cbfs_locate(fh, &rdev, name, type); | 	ret = cbfs_locate(fh, &rdev, name, type); | ||||||
| 	if (!ret) | 	if (!ret) | ||||||
| 		if (tspi_measure_cbfs_hook(fh, name)) | 		if (tspi_measure_cbfs_hook(&rdev, name, *type)) | ||||||
| 			return -1; | 			return -1; | ||||||
| 	return ret; | 	return ret; | ||||||
| } | } | ||||||
|   | |||||||
| @@ -102,11 +102,10 @@ static bool is_runtime_data(const char *name) | |||||||
| 	return !strcmp(allowlist, name); | 	return !strcmp(allowlist, name); | ||||||
| } | } | ||||||
|  |  | ||||||
| uint32_t tspi_measure_cbfs_hook(struct cbfsf *fh, const char *name) | uint32_t tspi_measure_cbfs_hook(const struct region_device *rdev, const char *name, | ||||||
|  | 				uint32_t cbfs_type) | ||||||
| { | { | ||||||
| 	uint32_t pcr_index; | 	uint32_t pcr_index; | ||||||
| 	uint32_t cbfs_type; |  | ||||||
| 	struct region_device rdev; |  | ||||||
| 	char tcpa_metadata[TCPA_PCR_HASH_NAME]; | 	char tcpa_metadata[TCPA_PCR_HASH_NAME]; | ||||||
|  |  | ||||||
| 	if (!tcpa_log_available()) { | 	if (!tcpa_log_available()) { | ||||||
| @@ -118,9 +117,6 @@ uint32_t tspi_measure_cbfs_hook(struct cbfsf *fh, const char *name) | |||||||
| 		printk(BIOS_DEBUG, "CRTM initialized.\n"); | 		printk(BIOS_DEBUG, "CRTM initialized.\n"); | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	cbfsf_file_type(fh, &cbfs_type); |  | ||||||
| 	cbfs_file_data(&rdev, fh); |  | ||||||
|  |  | ||||||
| 	switch (cbfs_type) { | 	switch (cbfs_type) { | ||||||
| 	case CBFS_TYPE_MRC_CACHE: | 	case CBFS_TYPE_MRC_CACHE: | ||||||
| 		pcr_index = TPM_RUNTIME_DATA_PCR; | 		pcr_index = TPM_RUNTIME_DATA_PCR; | ||||||
| @@ -143,10 +139,10 @@ uint32_t tspi_measure_cbfs_hook(struct cbfsf *fh, const char *name) | |||||||
| 		break; | 		break; | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	if (create_tcpa_metadata(&rdev, name, tcpa_metadata) < 0) | 	if (create_tcpa_metadata(rdev, name, tcpa_metadata) < 0) | ||||||
| 		return VB2_ERROR_UNKNOWN; | 		return VB2_ERROR_UNKNOWN; | ||||||
|  |  | ||||||
| 	return tpm_measure_region(&rdev, pcr_index, tcpa_metadata); | 	return tpm_measure_region(rdev, pcr_index, tcpa_metadata); | ||||||
| } | } | ||||||
|  |  | ||||||
| int tspi_measure_cache_to_pcr(void) | int tspi_measure_cache_to_pcr(void) | ||||||
|   | |||||||
| @@ -41,13 +41,13 @@ int tspi_measure_cache_to_pcr(void); | |||||||
| #if !ENV_SMM && CONFIG(TPM_MEASURED_BOOT) | #if !ENV_SMM && CONFIG(TPM_MEASURED_BOOT) | ||||||
| /* | /* | ||||||
|  * Measures cbfs data via hook (cbfs) |  * Measures cbfs data via hook (cbfs) | ||||||
|  * fh is the cbfs file handle to measure |  * rdev covers the file data (not metadata) | ||||||
|  * return 0 if successful, else an error |  * return 0 if successful, else an error | ||||||
|  */ |  */ | ||||||
| uint32_t tspi_measure_cbfs_hook(struct cbfsf *fh, const char *name); | uint32_t tspi_measure_cbfs_hook(const struct region_device *rdev, | ||||||
|  | 				const char *name, uint32_t cbfs_type); | ||||||
| #else | #else | ||||||
| #define tspi_measure_cbfs_hook(fh, name) 0 | #define tspi_measure_cbfs_hook(rdev, name, cbfs_type) 0 | ||||||
| #endif | #endif | ||||||
|  |  | ||||||
| #endif /* __SECURITY_TSPI_CRTM_H__ */ | #endif /* __SECURITY_TSPI_CRTM_H__ */ | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user