cbfs: Introduce cbfs_ro_map() and cbfs_ro_load()
This patch introduces two new CBFS API functions which are equivalent to cbfs_map() and cbfs_load(), respectively, with the difference that they always operate on the read-only CBFS region ("COREBOOT" FMAP section). Use it to replace some of the simple cases that needed to use cbfs_locate_file_in_region(). Change-Id: I9c55b022b6502a333a9805ab0e4891dd7b97ef7f Signed-off-by: Julius Werner <jwerner@chromium.org> Reviewed-on: https://review.coreboot.org/c/coreboot/+/39306 Reviewed-by: Furquan Shaikh <furquan@google.com> Reviewed-by: Patrick Georgi <pgeorgi@google.com> Tested-by: build bot (Jenkins) <no-reply@coreboot.org>
This commit is contained in:
parent
8c99c27df1
commit
9d0cc2aea9
|
@ -49,36 +49,28 @@ static enum cb_err get_cmos_value(unsigned long bit, unsigned long length,
|
||||||
return CB_SUCCESS;
|
return CB_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
static enum cb_err locate_cmos_layout(struct region_device *rdev)
|
static struct cmos_option_table *get_cmos_layout(void)
|
||||||
{
|
{
|
||||||
uint32_t cbfs_type = CBFS_COMPONENT_CMOS_LAYOUT;
|
static struct cmos_option_table *ct = NULL;
|
||||||
static struct cbfsf fh;
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* In case VBOOT is enabled and this function is called from SMM,
|
* In case VBOOT is enabled and this function is called from SMM,
|
||||||
* we have multiple CMOS layout files and to locate them we'd need to
|
* we have multiple CMOS layout files and to locate them we'd need to
|
||||||
* include VBOOT into SMM...
|
* include VBOOT into SMM...
|
||||||
*
|
*
|
||||||
* Support only one CMOS layout in the 'COREBOOT' region for now.
|
* Support only one CMOS layout in the RO CBFS for now.
|
||||||
*/
|
*/
|
||||||
if (!region_device_sz(&(fh.data))) {
|
if (!ct)
|
||||||
if (cbfs_locate_file_in_region(&fh, "COREBOOT", "cmos_layout.bin",
|
ct = cbfs_ro_map("cmos_layout.bin", NULL);
|
||||||
&cbfs_type)) {
|
if (!ct)
|
||||||
printk(BIOS_ERR, "RTC: cmos_layout.bin could not be found. "
|
printk(BIOS_ERR, "RTC: cmos_layout.bin could not be found. "
|
||||||
"Options are disabled\n");
|
"Options are disabled\n");
|
||||||
return CB_CMOS_LAYOUT_NOT_FOUND;
|
return ct;
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
cbfs_file_data(rdev, &fh);
|
|
||||||
|
|
||||||
return CB_SUCCESS;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
enum cb_err cmos_get_option(void *dest, const char *name)
|
enum cb_err cmos_get_option(void *dest, const char *name)
|
||||||
{
|
{
|
||||||
struct cmos_option_table *ct;
|
struct cmos_option_table *ct;
|
||||||
struct region_device rdev;
|
|
||||||
struct cmos_entries *ce;
|
struct cmos_entries *ce;
|
||||||
size_t namelen;
|
size_t namelen;
|
||||||
int found = 0;
|
int found = 0;
|
||||||
|
@ -86,16 +78,9 @@ enum cb_err cmos_get_option(void *dest, const char *name)
|
||||||
/* Figure out how long name is */
|
/* Figure out how long name is */
|
||||||
namelen = strnlen(name, CMOS_MAX_NAME_LENGTH);
|
namelen = strnlen(name, CMOS_MAX_NAME_LENGTH);
|
||||||
|
|
||||||
if (locate_cmos_layout(&rdev) != CB_SUCCESS) {
|
ct = get_cmos_layout();
|
||||||
|
if (!ct)
|
||||||
return CB_CMOS_LAYOUT_NOT_FOUND;
|
return CB_CMOS_LAYOUT_NOT_FOUND;
|
||||||
}
|
|
||||||
ct = rdev_mmap_full(&rdev);
|
|
||||||
if (!ct) {
|
|
||||||
printk(BIOS_ERR, "RTC: cmos_layout.bin could not be mapped. "
|
|
||||||
"Options are disabled\n");
|
|
||||||
|
|
||||||
return CB_CMOS_LAYOUT_NOT_FOUND;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* find the requested entry record */
|
/* find the requested entry record */
|
||||||
ce = (struct cmos_entries *)((unsigned char *)ct + ct->header_length);
|
ce = (struct cmos_entries *)((unsigned char *)ct + ct->header_length);
|
||||||
|
@ -108,19 +93,15 @@ enum cb_err cmos_get_option(void *dest, const char *name)
|
||||||
}
|
}
|
||||||
if (!found) {
|
if (!found) {
|
||||||
printk(BIOS_DEBUG, "No CMOS option '%s'.\n", name);
|
printk(BIOS_DEBUG, "No CMOS option '%s'.\n", name);
|
||||||
rdev_munmap(&rdev, ct);
|
|
||||||
return CB_CMOS_OPTION_NOT_FOUND;
|
return CB_CMOS_OPTION_NOT_FOUND;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!cmos_checksum_valid(LB_CKS_RANGE_START, LB_CKS_RANGE_END, LB_CKS_LOC)) {
|
if (!cmos_checksum_valid(LB_CKS_RANGE_START, LB_CKS_RANGE_END, LB_CKS_LOC))
|
||||||
rdev_munmap(&rdev, ct);
|
|
||||||
return CB_CMOS_CHECKSUM_INVALID;
|
return CB_CMOS_CHECKSUM_INVALID;
|
||||||
}
|
|
||||||
if (get_cmos_value(ce->bit, ce->length, dest) != CB_SUCCESS) {
|
if (get_cmos_value(ce->bit, ce->length, dest) != CB_SUCCESS)
|
||||||
rdev_munmap(&rdev, ct);
|
|
||||||
return CB_CMOS_ACCESS_ERROR;
|
return CB_CMOS_ACCESS_ERROR;
|
||||||
}
|
|
||||||
rdev_munmap(&rdev, ct);
|
|
||||||
return CB_SUCCESS;
|
return CB_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -168,7 +149,6 @@ static enum cb_err set_cmos_value(unsigned long bit, unsigned long length,
|
||||||
enum cb_err cmos_set_option(const char *name, void *value)
|
enum cb_err cmos_set_option(const char *name, void *value)
|
||||||
{
|
{
|
||||||
struct cmos_option_table *ct;
|
struct cmos_option_table *ct;
|
||||||
struct region_device rdev;
|
|
||||||
struct cmos_entries *ce;
|
struct cmos_entries *ce;
|
||||||
unsigned long length;
|
unsigned long length;
|
||||||
size_t namelen;
|
size_t namelen;
|
||||||
|
@ -177,16 +157,9 @@ enum cb_err cmos_set_option(const char *name, void *value)
|
||||||
/* Figure out how long name is */
|
/* Figure out how long name is */
|
||||||
namelen = strnlen(name, CMOS_MAX_NAME_LENGTH);
|
namelen = strnlen(name, CMOS_MAX_NAME_LENGTH);
|
||||||
|
|
||||||
if (locate_cmos_layout(&rdev) != CB_SUCCESS) {
|
ct = get_cmos_layout();
|
||||||
|
if (!ct)
|
||||||
return CB_CMOS_LAYOUT_NOT_FOUND;
|
return CB_CMOS_LAYOUT_NOT_FOUND;
|
||||||
}
|
|
||||||
ct = rdev_mmap_full(&rdev);
|
|
||||||
if (!ct) {
|
|
||||||
printk(BIOS_ERR, "RTC: cmos_layout.bin could not be mapped. "
|
|
||||||
"Options are disabled\n");
|
|
||||||
|
|
||||||
return CB_CMOS_LAYOUT_NOT_FOUND;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* find the requested entry record */
|
/* find the requested entry record */
|
||||||
ce = (struct cmos_entries *)((unsigned char *)ct + ct->header_length);
|
ce = (struct cmos_entries *)((unsigned char *)ct + ct->header_length);
|
||||||
|
@ -199,7 +172,6 @@ enum cb_err cmos_set_option(const char *name, void *value)
|
||||||
}
|
}
|
||||||
if (!found) {
|
if (!found) {
|
||||||
printk(BIOS_DEBUG, "WARNING: No CMOS option '%s'.\n", name);
|
printk(BIOS_DEBUG, "WARNING: No CMOS option '%s'.\n", name);
|
||||||
rdev_munmap(&rdev, ct);
|
|
||||||
return CB_CMOS_OPTION_NOT_FOUND;
|
return CB_CMOS_OPTION_NOT_FOUND;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -208,18 +180,13 @@ enum cb_err cmos_set_option(const char *name, void *value)
|
||||||
length = MAX(strlen((const char *)value) * 8, ce->length - 8);
|
length = MAX(strlen((const char *)value) * 8, ce->length - 8);
|
||||||
/* make sure the string is null terminated */
|
/* make sure the string is null terminated */
|
||||||
if (set_cmos_value(ce->bit + ce->length - 8, 8, &(u8[]){0})
|
if (set_cmos_value(ce->bit + ce->length - 8, 8, &(u8[]){0})
|
||||||
!= CB_SUCCESS) {
|
!= CB_SUCCESS)
|
||||||
rdev_munmap(&rdev, ct);
|
|
||||||
return CB_CMOS_ACCESS_ERROR;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (set_cmos_value(ce->bit, length, value) != CB_SUCCESS) {
|
|
||||||
rdev_munmap(&rdev, ct);
|
|
||||||
return CB_CMOS_ACCESS_ERROR;
|
return CB_CMOS_ACCESS_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
rdev_munmap(&rdev, ct);
|
if (set_cmos_value(ce->bit, length, value) != CB_SUCCESS)
|
||||||
|
return CB_CMOS_ACCESS_ERROR;
|
||||||
|
|
||||||
return CB_SUCCESS;
|
return CB_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -23,9 +23,12 @@ int cbfs_boot_locate(struct cbfsf *fh, const char *name, uint32_t *type);
|
||||||
NOTE: Since this may return a direct pointer to memory-mapped hardware,
|
NOTE: Since this may return a direct pointer to memory-mapped hardware,
|
||||||
compressed files are NOT transparently decompressed (unlike cbfs_load()). */
|
compressed files are NOT transparently decompressed (unlike cbfs_load()). */
|
||||||
void *cbfs_map(const char *name, size_t *size_out);
|
void *cbfs_map(const char *name, size_t *size_out);
|
||||||
/* Removes a mapping previously allocated with cbfs_map(). Should try to unmap
|
/* Like cbfs_map(), except that it will always read from the read-only CBFS
|
||||||
mappings in strict LIFO order where possible, since mapping backends often
|
("COREBOOT" FMAP region), even when CONFIG(VBOOT) is enabled. */
|
||||||
don't support more complicated cases. */
|
void *cbfs_ro_map(const char *name, size_t *size_out);
|
||||||
|
/* Removes a previously allocated CBFS mapping. Should try to unmap mappings in
|
||||||
|
strict LIFO order where possible, since mapping backends often don't support
|
||||||
|
more complicated cases. */
|
||||||
int cbfs_unmap(void *mapping);
|
int cbfs_unmap(void *mapping);
|
||||||
/* Locate file in a specific region of fmap. Return 0 on success. < 0 on error*/
|
/* Locate file in a specific region of fmap. Return 0 on success. < 0 on error*/
|
||||||
int cbfs_locate_file_in_region(struct cbfsf *fh, const char *region_name,
|
int cbfs_locate_file_in_region(struct cbfsf *fh, const char *region_name,
|
||||||
|
@ -34,6 +37,9 @@ int cbfs_locate_file_in_region(struct cbfsf *fh, const char *region_name,
|
||||||
success or 0 on error. File will get decompressed as necessary. Same
|
success or 0 on error. File will get decompressed as necessary. Same
|
||||||
decompression requirements as cbfs_load_and_decompress(). */
|
decompression requirements as cbfs_load_and_decompress(). */
|
||||||
size_t cbfs_load(const char *name, void *buf, size_t buf_size);
|
size_t cbfs_load(const char *name, void *buf, size_t buf_size);
|
||||||
|
/* Like cbfs_load(), except that it will always read from the read-only CBFS
|
||||||
|
("COREBOOT" FMAP region), even when CONFIG(VBOOT) is enabled. */
|
||||||
|
size_t cbfs_ro_load(const char *name, void *buf, size_t buf_size);
|
||||||
/* Load |in_size| bytes from |rdev| at |offset| to the |buffer_size| bytes
|
/* Load |in_size| bytes from |rdev| at |offset| to the |buffer_size| bytes
|
||||||
* large |buffer|, decompressing it according to |compression| in the process.
|
* large |buffer|, decompressing it according to |compression| in the process.
|
||||||
* Returns the decompressed file size, or 0 on error.
|
* Returns the decompressed file size, or 0 on error.
|
||||||
|
|
|
@ -70,12 +70,12 @@ int cbfs_boot_locate(struct cbfsf *fh, const char *name, uint32_t *type)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void *cbfs_map(const char *name, size_t *size_out)
|
static void *_cbfs_map(const char *name, size_t *size_out, bool force_ro)
|
||||||
{
|
{
|
||||||
struct region_device rdev;
|
struct region_device rdev;
|
||||||
union cbfs_mdata mdata;
|
union cbfs_mdata mdata;
|
||||||
|
|
||||||
if (cbfs_boot_lookup(name, false, &mdata, &rdev))
|
if (cbfs_boot_lookup(name, force_ro, &mdata, &rdev))
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
if (size_out != NULL)
|
if (size_out != NULL)
|
||||||
|
@ -84,6 +84,16 @@ void *cbfs_map(const char *name, size_t *size_out)
|
||||||
return rdev_mmap_full(&rdev);
|
return rdev_mmap_full(&rdev);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void *cbfs_map(const char *name, size_t *size_out)
|
||||||
|
{
|
||||||
|
return _cbfs_map(name, size_out, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
void *cbfs_ro_map(const char *name, size_t *size_out)
|
||||||
|
{
|
||||||
|
return _cbfs_map(name, size_out, true);
|
||||||
|
}
|
||||||
|
|
||||||
int cbfs_unmap(void *mapping)
|
int cbfs_unmap(void *mapping)
|
||||||
{
|
{
|
||||||
/* This works because munmap() only works on the root rdev and never
|
/* This works because munmap() only works on the root rdev and never
|
||||||
|
@ -281,12 +291,13 @@ void *cbfs_boot_map_optionrom_revision(uint16_t vendor, uint16_t device, uint8_t
|
||||||
return cbfs_map(name, NULL);
|
return cbfs_map(name, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t cbfs_load(const char *name, void *buf, size_t buf_size)
|
static size_t _cbfs_load(const char *name, void *buf, size_t buf_size,
|
||||||
|
bool force_ro)
|
||||||
{
|
{
|
||||||
struct region_device rdev;
|
struct region_device rdev;
|
||||||
union cbfs_mdata mdata;
|
union cbfs_mdata mdata;
|
||||||
|
|
||||||
if (cbfs_boot_lookup(name, false, &mdata, &rdev))
|
if (cbfs_boot_lookup(name, force_ro, &mdata, &rdev))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
uint32_t compression = CBFS_COMPRESS_NONE;
|
uint32_t compression = CBFS_COMPRESS_NONE;
|
||||||
|
@ -302,6 +313,16 @@ size_t cbfs_load(const char *name, void *buf, size_t buf_size)
|
||||||
buf, buf_size, compression);
|
buf, buf_size, compression);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
size_t cbfs_load(const char *name, void *buf, size_t buf_size)
|
||||||
|
{
|
||||||
|
return _cbfs_load(name, buf, buf_size, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t cbfs_ro_load(const char *name, void *buf, size_t buf_size)
|
||||||
|
{
|
||||||
|
return _cbfs_load(name, buf, buf_size, true);
|
||||||
|
}
|
||||||
|
|
||||||
int cbfs_prog_stage_load(struct prog *pstage)
|
int cbfs_prog_stage_load(struct prog *pstage)
|
||||||
{
|
{
|
||||||
struct cbfs_stage stage;
|
struct cbfs_stage stage;
|
||||||
|
|
|
@ -107,9 +107,6 @@ void sdram_initialize(struct pei_data *pei_data)
|
||||||
{
|
{
|
||||||
int (*entry)(struct pei_data *pei_data) __attribute__((regparm(1)));
|
int (*entry)(struct pei_data *pei_data) __attribute__((regparm(1)));
|
||||||
|
|
||||||
uint32_t type = CBFS_TYPE_MRC;
|
|
||||||
struct cbfsf f;
|
|
||||||
|
|
||||||
printk(BIOS_DEBUG, "Starting UEFI PEI System Agent\n");
|
printk(BIOS_DEBUG, "Starting UEFI PEI System Agent\n");
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -130,13 +127,10 @@ void sdram_initialize(struct pei_data *pei_data)
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Locate and call UEFI System Agent binary. The binary needs to be at a fixed offset
|
* Locate and call UEFI System Agent binary. The binary needs to be at a fixed offset
|
||||||
* in the flash and can therefore only reside in the COREBOOT fmap region.
|
* in the flash and can therefore only reside in the COREBOOT fmap region. We don't care
|
||||||
|
* about leaking the mapping.
|
||||||
*/
|
*/
|
||||||
if (cbfs_locate_file_in_region(&f, "COREBOOT", "mrc.bin", &type) < 0)
|
entry = cbfs_ro_map("mrc.bin", NULL);
|
||||||
die("mrc.bin not found!");
|
|
||||||
|
|
||||||
/* We don't care about leaking the mapping */
|
|
||||||
entry = rdev_mmap_full(&f.data);
|
|
||||||
if (entry) {
|
if (entry) {
|
||||||
int rv = entry(pei_data);
|
int rv = entry(pei_data);
|
||||||
|
|
||||||
|
|
|
@ -80,8 +80,6 @@ void raminit(struct pei_data *pei_data)
|
||||||
struct memory_info *mem_info;
|
struct memory_info *mem_info;
|
||||||
pei_wrapper_entry_t entry;
|
pei_wrapper_entry_t entry;
|
||||||
int ret;
|
int ret;
|
||||||
struct cbfsf f;
|
|
||||||
uint32_t type = CBFS_TYPE_MRC;
|
|
||||||
|
|
||||||
broadwell_fill_pei_data(pei_data);
|
broadwell_fill_pei_data(pei_data);
|
||||||
|
|
||||||
|
@ -114,15 +112,10 @@ void raminit(struct pei_data *pei_data)
|
||||||
pei_data->saved_data_size = 0;
|
pei_data->saved_data_size = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Determine if mrc.bin is in the cbfs. */
|
|
||||||
if (cbfs_locate_file_in_region(&f, "COREBOOT", "mrc.bin", &type) < 0)
|
|
||||||
die("mrc.bin not found!");
|
|
||||||
/* We don't care about leaking the mapping */
|
/* We don't care about leaking the mapping */
|
||||||
entry = (pei_wrapper_entry_t)rdev_mmap_full(&f.data);
|
entry = cbfs_ro_map("mrc.bin", NULL);
|
||||||
if (entry == NULL) {
|
if (entry == NULL)
|
||||||
printk(BIOS_DEBUG, "Couldn't find mrc.bin\n");
|
die("mrc.bin not found!");
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
printk(BIOS_DEBUG, "Starting Memory Reference Code\n");
|
printk(BIOS_DEBUG, "Starting Memory Reference Code\n");
|
||||||
|
|
||||||
|
|
|
@ -49,29 +49,16 @@ void disable_rom_shadow(void)
|
||||||
|
|
||||||
void *locate_rmu_file(size_t *rmu_file_len)
|
void *locate_rmu_file(size_t *rmu_file_len)
|
||||||
{
|
{
|
||||||
struct cbfsf fh;
|
|
||||||
size_t fsize;
|
size_t fsize;
|
||||||
void *rmu_data;
|
void *rmu_data;
|
||||||
uint32_t type;
|
|
||||||
|
|
||||||
/* Locate the rmu.bin file in the read-only region of the flash */
|
/* Locate the rmu.bin file in the read-only region of the flash */
|
||||||
type = CBFS_TYPE_RAW;
|
rmu_data = cbfs_ro_map("rmu.bin", &fsize);
|
||||||
if (cbfs_locate_file_in_region(&fh, "COREBOOT", "rmu.bin", &type))
|
if (!rmu_data)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
/* Get the file size */
|
|
||||||
fsize = region_device_sz(&fh.data);
|
|
||||||
if (rmu_file_len != NULL)
|
if (rmu_file_len != NULL)
|
||||||
*rmu_file_len = fsize;
|
*rmu_file_len = fsize;
|
||||||
|
|
||||||
/* Get the data address */
|
|
||||||
rmu_data = rdev_mmap(&fh.data, 0, fsize);
|
|
||||||
|
|
||||||
/* Since the SPI flash is directly mapped into memory, we do not need
|
|
||||||
* the mapping provided by the rdev service. Unmap the file to prevent
|
|
||||||
* a memory leak. Return/leak the SPI flash address for the rmu.bin
|
|
||||||
* file data which will be directly accessed by FSP MemoryInit.
|
|
||||||
*/
|
|
||||||
rdev_munmap(&fh.data, rmu_data);
|
|
||||||
return rmu_data;
|
return rmu_data;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue