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 <cbfs_private.h> header which had already become sort of
unnecessary with previous changes. cbfs_boot_lookup() is now exported in
<cbfs.h> 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 <jwerner@chromium.org>
Change-Id: I8092d8f6e04bdfb4df6c626dc7d42b402fe0a8ba
Reviewed-on: https://review.coreboot.org/c/coreboot/+/59312
Tested-by: build bot (Jenkins) <no-reply@coreboot.org>
Reviewed-by: Werner Zeh <werner.zeh@siemens.com>
Reviewed-by: Jakub Czapiga <jacz@semihalf.com>
Reviewed-by: Lean Sheng Tan <lean.sheng.tan@intel.com>
This commit is contained in:
Julius Werner 2021-11-15 10:13:37 -08:00 committed by Werner Zeh
commit 57d4bc63f0
3 changed files with 80 additions and 31 deletions

View file

@ -7,6 +7,7 @@
#include <commonlib/bsd/cbfs_mdata.h>
#include <commonlib/cbfs.h>
#include <commonlib/mem_pool.h>
#include <commonlib/region.h>
#include <program_loading.h>
#include <types.h>
#include <vb2_sha.h>
@ -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

View file

@ -1,23 +0,0 @@
/* 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