From 57d4bc63f03664240ed4d9585c288ac8e455ca4b Mon Sep 17 00:00:00 2001 From: Julius Werner Date: Mon, 15 Nov 2021 10:13:37 -0800 Subject: [PATCH] cbfs: Add helper functions to look up size and type of a file This patch adds cbfs_get_size() and cbfs_get_type() helper functions (and _ro_ variations) to look up the size or type of a CBFS file without loading it. Generally, use of these should be discouraged because that tends to mean that the file needs to be looked up more than once, and cbfs_alloc() or cbfs_type_load() are usually the more efficient alternative... but sometimes they're unavoidable, so we might as well offer them. Also remove the header which had already become sort of unnecessary with previous changes. cbfs_boot_lookup() is now exported in for use in inlines, but should not be used directly by other files (and is prefixed with an underscore to highlight that). Signed-off-by: Julius Werner Change-Id: I8092d8f6e04bdfb4df6c626dc7d42b402fe0a8ba Reviewed-on: https://review.coreboot.org/c/coreboot/+/59312 Tested-by: build bot (Jenkins) Reviewed-by: Werner Zeh Reviewed-by: Jakub Czapiga Reviewed-by: Lean Sheng Tan --- src/include/cbfs.h | 72 ++++++++++++++++++++++++++++++++++++++ src/include/cbfs_private.h | 23 ------------ src/lib/cbfs.c | 16 ++++----- 3 files changed, 80 insertions(+), 31 deletions(-) delete mode 100644 src/include/cbfs_private.h diff --git a/src/include/cbfs.h b/src/include/cbfs.h index f6309a3e30..43d8123454 100644 --- a/src/include/cbfs.h +++ b/src/include/cbfs.h @@ -7,6 +7,7 @@ #include #include #include +#include #include #include #include @@ -119,6 +120,20 @@ void cbfs_unmap(void *mapping); /* Load stage into memory filling in prog. Return 0 on success. < 0 on error. */ int cbfs_prog_stage_load(struct prog *prog); +/* Returns the size of a CBFS file, or 0 on error. Avoid using this function to allocate space, + and instead use cbfs_alloc() so the file only needs to be looked up once. */ +static inline size_t cbfs_get_size(const char *name); +static inline size_t cbfs_ro_get_size(const char *name); + +/* Returns the type of a CBFS file, or CBFS_TYPE_NULL on error. Use cbfs_type_load() instead of + this where possible to avoid looking up the file more than once. */ +static inline enum cbfs_type cbfs_get_type(const char *name); +static inline enum cbfs_type cbfs_ro_get_type(const char *name); + +/* Check whether a CBFS file exists. */ +static inline bool cbfs_file_exists(const char *name); +static inline bool cbfs_ro_file_exists(const char *name); + /********************************************************************************************** * BOOT DEVICE HELPER APIs * @@ -173,6 +188,9 @@ int cbfs_locate_file_in_region(struct cbfsf *fh, const char *region_name, /********************************************************************************************** * INTERNAL HELPERS FOR INLINES, DO NOT USE. * **********************************************************************************************/ +cb_err_t _cbfs_boot_lookup(const char *name, bool force_ro, + union cbfs_mdata *mdata, struct region_device *rdev); + void *_cbfs_alloc(const char *name, cbfs_allocator_t allocator, void *arg, size_t *size_out, bool force_ro, enum cbfs_type *type); @@ -287,4 +305,58 @@ static inline void *cbfs_ro_type_cbmem_alloc(const char *name, uint32_t cbmem_id size_out, type); } +static inline size_t cbfs_get_size(const char *name) +{ + union cbfs_mdata mdata; + struct region_device rdev; + if (_cbfs_boot_lookup(name, false, &mdata, &rdev) != CB_SUCCESS) + return 0; + return be32toh(mdata.h.len); +} + +static inline size_t cbfs_ro_get_size(const char *name) +{ + union cbfs_mdata mdata; + struct region_device rdev; + if (_cbfs_boot_lookup(name, true, &mdata, &rdev) != CB_SUCCESS) + return 0; + return be32toh(mdata.h.len); +} + +static inline enum cbfs_type cbfs_get_type(const char *name) +{ + union cbfs_mdata mdata; + struct region_device rdev; + if (_cbfs_boot_lookup(name, false, &mdata, &rdev) != CB_SUCCESS) + return CBFS_TYPE_NULL; + return be32toh(mdata.h.type); +} + +static inline enum cbfs_type cbfs_ro_get_type(const char *name) +{ + union cbfs_mdata mdata; + struct region_device rdev; + if (_cbfs_boot_lookup(name, true, &mdata, &rdev) != CB_SUCCESS) + return CBFS_TYPE_NULL; + return be32toh(mdata.h.type); +} + +static inline bool cbfs_file_exists(const char *name) +{ + union cbfs_mdata mdata; + struct region_device rdev; + if (_cbfs_boot_lookup(name, false, &mdata, &rdev) != CB_SUCCESS) + return false; + return true; +} + +static inline bool cbfs_ro_file_exists(const char *name) +{ + union cbfs_mdata mdata; + struct region_device rdev; + if (_cbfs_boot_lookup(name, true, &mdata, &rdev) != CB_SUCCESS) + return false; + return true; +} + #endif diff --git a/src/include/cbfs_private.h b/src/include/cbfs_private.h deleted file mode 100644 index 8e9803616f..0000000000 --- a/src/include/cbfs_private.h +++ /dev/null @@ -1,23 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-only */ - -#ifndef _CBFS_PRIVATE_H_ -#define _CBFS_PRIVATE_H_ - -#include -#include -#include - -/* - * 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 . 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 diff --git a/src/lib/cbfs.c b/src/lib/cbfs.c index dbb3b1a913..1ffc69508a 100644 --- a/src/lib/cbfs.c +++ b/src/lib/cbfs.c @@ -3,8 +3,8 @@ #include #include #include -#include #include +#include #include #include #include @@ -35,8 +35,8 @@ static void switch_to_postram_cache(int unused) } ROMSTAGE_CBMEM_INIT_HOOK(switch_to_postram_cache); -cb_err_t cbfs_boot_lookup(const char *name, bool force_ro, - union cbfs_mdata *mdata, struct region_device *rdev) +cb_err_t _cbfs_boot_lookup(const char *name, bool force_ro, + union cbfs_mdata *mdata, struct region_device *rdev) { const struct cbfs_boot_device *cbd = cbfs_get_boot_device(force_ro); if (!cbd) @@ -65,7 +65,7 @@ cb_err_t cbfs_boot_lookup(const char *name, bool force_ro, 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); + return _cbfs_boot_lookup(name, true, mdata, rdev); } if (err) { if (err == CB_CBFS_NOT_FOUND) @@ -90,7 +90,7 @@ cb_err_t cbfs_boot_lookup(const char *name, bool force_ro, int cbfs_boot_locate(struct cbfsf *fh, const char *name, uint32_t *type) { - if (cbfs_boot_lookup(name, false, &fh->mdata, &fh->data)) + if (_cbfs_boot_lookup(name, false, &fh->mdata, &fh->data)) return -1; size_t msize = be32toh(fh->mdata.h.offset); @@ -330,7 +330,7 @@ void cbfs_preload(const char *name) DEBUG("%s(name='%s')\n", __func__, name); - if (cbfs_boot_lookup(name, force_ro, &mdata, &rdev)) + if (_cbfs_boot_lookup(name, force_ro, &mdata, &rdev)) return; size = region_device_sz(&rdev); @@ -422,7 +422,7 @@ void *_cbfs_alloc(const char *name, cbfs_allocator_t allocator, void *arg, DEBUG("%s(name='%s', alloc=%p(%p), force_ro=%s, type=%d)\n", __func__, name, allocator, arg, force_ro ? "true" : "false", type ? *type : -1); - if (cbfs_boot_lookup(name, force_ro, &mdata, &rdev)) + if (_cbfs_boot_lookup(name, force_ro, &mdata, &rdev)) return NULL; if (type) { @@ -525,7 +525,7 @@ cb_err_t cbfs_prog_stage_load(struct prog *pstage) prog_locate_hook(pstage); - if ((err = cbfs_boot_lookup(prog_name(pstage), false, &mdata, &rdev))) + if ((err = _cbfs_boot_lookup(prog_name(pstage), false, &mdata, &rdev))) return err; assert(be32toh(mdata.h.type) == CBFS_TYPE_STAGE);