vboot: Fix linking error with USE_OPTION_TABLE enabled
Fix a linking problem with VBOOT and USE_OPTION_TABLE enabled. Make use of cbfs_locate_file_in_region() and always search the cmos_layout.bin in the 'COREBOOT' region. With this change applied there's no need to include the vboot_locator in SMM any more, we can't break NVRAM with different CMOS layouts, and we keep VBOOT and non VBOOT behaviour the same. Only include cmos_layout.bin and cmos.default in RO region. Add notes explaining the decisions. Tested on Intel Sandybridge, builds and boots with vboot enabled. Change-Id: I10ae94d7936581bbb5ea49384122062bd4934ea5 Signed-off-by: Patrick Rudolph <patrick.rudolph@9elements.com> Reviewed-on: https://review.coreboot.org/26863 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
parent
7837c203d6
commit
9554b26f9f
@ -240,9 +240,34 @@ 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)
|
||||||
|
{
|
||||||
|
uint32_t cbfs_type = CBFS_COMPONENT_CMOS_LAYOUT;
|
||||||
|
struct cbfsf fh;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 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
|
||||||
|
* include VBOOT into SMM...
|
||||||
|
*
|
||||||
|
* Support only one CMOS layout in the 'COREBOOT' region for now.
|
||||||
|
*/
|
||||||
|
if (cbfs_locate_file_in_region(&fh, "COREBOOT", "cmos_layout.bin",
|
||||||
|
&cbfs_type)) {
|
||||||
|
printk(BIOS_ERR, "RTC: cmos_layout.bin could not be found. "
|
||||||
|
"Options are disabled\n");
|
||||||
|
return CB_CMOS_LAYOUT_NOT_FOUND;
|
||||||
|
}
|
||||||
|
|
||||||
|
cbfs_file_data(rdev, &fh);
|
||||||
|
|
||||||
|
return CB_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
enum cb_err get_option(void *dest, const char *name)
|
enum cb_err 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;
|
||||||
@ -255,16 +280,20 @@ enum cb_err 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);
|
||||||
|
|
||||||
/* find the requested entry record */
|
if (locate_cmos_layout(&rdev) != CB_SUCCESS) {
|
||||||
ct = cbfs_boot_map_with_leak("cmos_layout.bin",
|
UNLOCK_NVRAM_CBFS_SPINLOCK();
|
||||||
CBFS_COMPONENT_CMOS_LAYOUT, NULL);
|
return CB_CMOS_LAYOUT_NOT_FOUND;
|
||||||
|
}
|
||||||
|
ct = rdev_mmap_full(&rdev);
|
||||||
if (!ct) {
|
if (!ct) {
|
||||||
printk(BIOS_ERR, "RTC: cmos_layout.bin could not be found. "
|
printk(BIOS_ERR, "RTC: cmos_layout.bin could not be mapped. "
|
||||||
"Options are disabled\n");
|
"Options are disabled\n");
|
||||||
|
|
||||||
UNLOCK_NVRAM_CBFS_SPINLOCK();
|
UNLOCK_NVRAM_CBFS_SPINLOCK();
|
||||||
return CB_CMOS_LAYOUT_NOT_FOUND;
|
return CB_CMOS_LAYOUT_NOT_FOUND;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* 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);
|
||||||
for (; ce->tag == LB_TAG_OPTION;
|
for (; ce->tag == LB_TAG_OPTION;
|
||||||
ce = (struct cmos_entries *)((unsigned char *)ce + ce->size)) {
|
ce = (struct cmos_entries *)((unsigned char *)ce + ce->size)) {
|
||||||
@ -275,18 +304,22 @@ enum cb_err get_option(void *dest, const char *name)
|
|||||||
}
|
}
|
||||||
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);
|
||||||
UNLOCK_NVRAM_CBFS_SPINLOCK();
|
UNLOCK_NVRAM_CBFS_SPINLOCK();
|
||||||
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);
|
||||||
UNLOCK_NVRAM_CBFS_SPINLOCK();
|
UNLOCK_NVRAM_CBFS_SPINLOCK();
|
||||||
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);
|
||||||
UNLOCK_NVRAM_CBFS_SPINLOCK();
|
UNLOCK_NVRAM_CBFS_SPINLOCK();
|
||||||
return CB_CMOS_ACCESS_ERROR;
|
return CB_CMOS_ACCESS_ERROR;
|
||||||
}
|
}
|
||||||
|
rdev_munmap(&rdev, ct);
|
||||||
UNLOCK_NVRAM_CBFS_SPINLOCK();
|
UNLOCK_NVRAM_CBFS_SPINLOCK();
|
||||||
return CB_SUCCESS;
|
return CB_SUCCESS;
|
||||||
}
|
}
|
||||||
@ -347,6 +380,7 @@ unsigned int read_option_lowlevel(unsigned int start, unsigned int size,
|
|||||||
enum cb_err set_option(const char *name, void *value)
|
enum cb_err 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;
|
||||||
@ -358,14 +392,20 @@ enum cb_err 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);
|
||||||
|
|
||||||
/* find the requested entry record */
|
if (locate_cmos_layout(&rdev) != CB_SUCCESS) {
|
||||||
ct = cbfs_boot_map_with_leak("cmos_layout.bin",
|
UNLOCK_NVRAM_CBFS_SPINLOCK();
|
||||||
CBFS_COMPONENT_CMOS_LAYOUT, NULL);
|
|
||||||
if (!ct) {
|
|
||||||
printk(BIOS_ERR, "cmos_layout.bin could not be found. "
|
|
||||||
"Options are disabled\n");
|
|
||||||
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");
|
||||||
|
|
||||||
|
UNLOCK_NVRAM_CBFS_SPINLOCK();
|
||||||
|
return CB_CMOS_LAYOUT_NOT_FOUND;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 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);
|
||||||
for (; ce->tag == LB_TAG_OPTION;
|
for (; ce->tag == LB_TAG_OPTION;
|
||||||
ce = (struct cmos_entries *)((unsigned char *)ce + ce->size)) {
|
ce = (struct cmos_entries *)((unsigned char *)ce + ce->size)) {
|
||||||
@ -376,6 +416,7 @@ enum cb_err 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;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -384,13 +425,18 @@ enum cb_err 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;
|
return CB_CMOS_ACCESS_ERROR;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (set_cmos_value(ce->bit, length, value) != CB_SUCCESS)
|
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);
|
||||||
return CB_SUCCESS;
|
return CB_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -321,6 +321,11 @@ extern const struct cbfs_locator vboot_locator;
|
|||||||
|
|
||||||
static const struct cbfs_locator *locators[] = {
|
static const struct cbfs_locator *locators[] = {
|
||||||
#if IS_ENABLED(CONFIG_VBOOT)
|
#if IS_ENABLED(CONFIG_VBOOT)
|
||||||
|
/*
|
||||||
|
* NOTE: Does not link in SMM, as the vboot_locator isn't compiled.
|
||||||
|
* ATM there's no need for VBOOT functionality in SMM and it's not
|
||||||
|
* a problem.
|
||||||
|
*/
|
||||||
&vboot_locator,
|
&vboot_locator,
|
||||||
#endif
|
#endif
|
||||||
&cbfs_master_header_locator,
|
&cbfs_master_header_locator,
|
||||||
|
@ -154,6 +154,8 @@ regions-for-file = $(subst $(spc),$(comma),$(sort \
|
|||||||
font.bin \
|
font.bin \
|
||||||
vbgfx.bin \
|
vbgfx.bin \
|
||||||
rmu.bin \
|
rmu.bin \
|
||||||
|
cmos_layout.bin \
|
||||||
|
cmos.default \
|
||||||
$(call strip_quotes,$(CONFIG_RO_REGION_ONLY)) \
|
$(call strip_quotes,$(CONFIG_RO_REGION_ONLY)) \
|
||||||
,$(1)),COREBOOT,COREBOOT FW_MAIN_A FW_MAIN_B)))
|
,$(1)),COREBOOT,COREBOOT FW_MAIN_A FW_MAIN_B)))
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user