This patch introduces fsp print helper macros to print `efi_return_status_t' with the appropriate format. These macros are now used for fsp debug prints with return status efi_return_status_t is defined as UINT64 or UNIT32 based on the selected architecture BUG=b:329034258 TEST=Verified on Meteor Lake board (Rex) Change-Id: If6342c4d40c76b702351070e424797c21138a4a9 Signed-off-by: Appukuttan V K <appukuttan.vk@intel.com> Reviewed-on: https://review.coreboot.org/c/coreboot/+/81630 Reviewed-by: Subrata Banik <subratabanik@google.com> Tested-by: build bot (Jenkins) <no-reply@coreboot.org>
210 lines
5.7 KiB
C
210 lines
5.7 KiB
C
/* SPDX-License-Identifier: GPL-2.0-or-later */
|
|
|
|
#include <boot/coreboot_tables.h>
|
|
#include <device/mmio.h>
|
|
#include <cbfs.h>
|
|
#include <cf9_reset.h>
|
|
#include <commonlib/bsd/compression.h>
|
|
#include <commonlib/fsp.h>
|
|
#include <console/console.h>
|
|
#include <fsp/util.h>
|
|
#include <string.h>
|
|
#include <types.h>
|
|
#include <assert.h>
|
|
|
|
static uint32_t fsp_hdr_get_expected_min_length(void)
|
|
{
|
|
if (CONFIG(PLATFORM_USES_FSP2_3))
|
|
return 80;
|
|
else if (CONFIG(PLATFORM_USES_FSP2_2))
|
|
return 76;
|
|
else if (CONFIG(PLATFORM_USES_FSP2_1))
|
|
return 72;
|
|
else if (CONFIG(PLATFORM_USES_FSP2_0))
|
|
return 72;
|
|
else
|
|
return dead_code_t(uint32_t);
|
|
}
|
|
|
|
static bool looks_like_fsp_header(struct fsp_header *hdr)
|
|
{
|
|
if (memcmp(&hdr->signature, FSP_HDR_SIGNATURE, 4)) {
|
|
printk(BIOS_ALERT, "Did not find a valid FSP signature\n");
|
|
return false;
|
|
}
|
|
|
|
/* It is possible to build FSP with any version of edk2 which could have introduced new
|
|
fields in FSP_INFO_HEADER. The new fields will be ignored based on the reported FSP
|
|
version. This check ensures that the reported header length is at least what the
|
|
reported FSP version requires so that we do not access any out-of-bound bytes. */
|
|
if (hdr->header_length < fsp_hdr_get_expected_min_length()) {
|
|
printk(BIOS_ALERT, "FSP header has invalid length: %d\n", hdr->header_length);
|
|
return false;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
enum cb_err fsp_identify(struct fsp_header *hdr, const void *fsp_blob)
|
|
{
|
|
memcpy(hdr, fsp_blob, sizeof(struct fsp_header));
|
|
if (!looks_like_fsp_header(hdr))
|
|
return CB_ERR;
|
|
|
|
return CB_SUCCESS;
|
|
}
|
|
|
|
enum cb_err fsp_validate_component(struct fsp_header *hdr, void *fsp_file, size_t file_size)
|
|
{
|
|
void *raw_hdr = fsp_file + FSP_HDR_OFFSET;
|
|
|
|
if (file_size < FSP_HDR_OFFSET + fsp_hdr_get_expected_min_length()) {
|
|
printk(BIOS_CRIT, "FSP blob too small.\n");
|
|
return CB_ERR;
|
|
}
|
|
|
|
if (fsp_identify(hdr, raw_hdr) != CB_SUCCESS) {
|
|
printk(BIOS_CRIT, "No valid FSP header\n");
|
|
return CB_ERR;
|
|
}
|
|
|
|
if (CONFIG(DISPLAY_FSP_HEADER))
|
|
fsp_print_header_info(hdr);
|
|
|
|
/* Check if size specified in the header matches the cbfs file size */
|
|
if (file_size < hdr->image_size) {
|
|
printk(BIOS_CRIT, "Component size bigger than cbfs file.\n");
|
|
return CB_ERR;
|
|
}
|
|
|
|
if (ENV_RAMINIT)
|
|
soc_validate_fspm_header(hdr);
|
|
|
|
return CB_SUCCESS;
|
|
}
|
|
|
|
static bool fsp_reset_requested(efi_return_status_t status)
|
|
{
|
|
return (status >= FSP_STATUS_RESET_REQUIRED_COLD &&
|
|
status <= FSP_STATUS_RESET_REQUIRED_8);
|
|
}
|
|
|
|
void fsp_handle_reset(efi_return_status_t status)
|
|
{
|
|
if (!fsp_reset_requested(status))
|
|
return;
|
|
|
|
fsp_printk(status, BIOS_SPEW, "FSP: handling reset type");
|
|
|
|
switch (status) {
|
|
case FSP_STATUS_RESET_REQUIRED_COLD:
|
|
full_reset();
|
|
break;
|
|
case FSP_STATUS_RESET_REQUIRED_WARM:
|
|
system_reset();
|
|
break;
|
|
case FSP_STATUS_RESET_REQUIRED_3:
|
|
case FSP_STATUS_RESET_REQUIRED_4:
|
|
case FSP_STATUS_RESET_REQUIRED_5:
|
|
case FSP_STATUS_RESET_REQUIRED_6:
|
|
case FSP_STATUS_RESET_REQUIRED_7:
|
|
case FSP_STATUS_RESET_REQUIRED_8:
|
|
chipset_handle_reset(status);
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
|
|
static inline bool fspm_env(void)
|
|
{
|
|
if (ENV_RAMINIT)
|
|
return true;
|
|
return false;
|
|
}
|
|
|
|
static inline bool fspm_xip(void)
|
|
{
|
|
/* FSP-M is assumed to be loaded in romstage. */
|
|
if (fspm_env() && CONFIG(FSP_M_XIP))
|
|
return true;
|
|
return false;
|
|
}
|
|
|
|
/* Load the FSP component described by fsp_load_descriptor from cbfs. The FSP
|
|
* header object will be validated and filled in on successful load. */
|
|
enum cb_err fsp_load_component(struct fsp_load_descriptor *fspld, struct fsp_header *hdr)
|
|
{
|
|
size_t output_size;
|
|
void *dest;
|
|
struct prog *fsp_prog = &fspld->fsp_prog;
|
|
|
|
dest = cbfs_alloc(prog_name(fsp_prog), fspld->alloc, fspld, &output_size);
|
|
if (!dest)
|
|
return CB_ERR;
|
|
|
|
/* Don't allow FSP-M relocation when XIP. */
|
|
if (!fspm_xip() && fsp_component_relocate((uintptr_t)dest, dest, output_size) < 0) {
|
|
printk(BIOS_ERR, "Unable to relocate FSP component!\n");
|
|
return CB_ERR;
|
|
}
|
|
|
|
prog_set_area(fsp_prog, dest, output_size);
|
|
|
|
if (fsp_validate_component(hdr, dest, output_size) != CB_SUCCESS) {
|
|
printk(BIOS_ERR, "Invalid FSP header after load!\n");
|
|
return CB_ERR;
|
|
}
|
|
|
|
/* Signal that FSP component has been loaded. */
|
|
prog_segment_loaded(hdr->image_base, hdr->image_size, SEG_FINAL);
|
|
|
|
return CB_SUCCESS;
|
|
}
|
|
|
|
/* Only call this function when FSP header has been read and validated */
|
|
void fsp_get_version(char *buf)
|
|
{
|
|
struct fsp_header *hdr = &fsps_hdr;
|
|
union fsp_revision revision;
|
|
|
|
revision.val = hdr->image_revision;
|
|
snprintf(buf, FSP_VER_LEN, "%u.%u-%u.%u.%u.%u", (hdr->spec_version >> 4),
|
|
hdr->spec_version & 0xf, revision.rev.major,
|
|
revision.rev.minor, revision.rev.revision, revision.rev.bld_num);
|
|
}
|
|
|
|
/* Check if the signature in the UPD header matches the expected one. If it doesn't match, the
|
|
FSP binaries in CBFS are for a different platform than the platform code trying to use it
|
|
in which case the function calls die(). */
|
|
void fsp_verify_upd_header_signature(uint64_t upd_signature, uint64_t expected_signature)
|
|
{
|
|
if (upd_signature != expected_signature) {
|
|
/* The UPD signatures are non-zero-terminated ASCII stored as a little endian
|
|
uint64_t, so this needs some casts. */
|
|
die_with_post_code(POSTCODE_INVALID_VENDOR_BINARY,
|
|
"Invalid UPD signature! FSP provided \"%.8s\", expected was \"%.8s\".\n",
|
|
(char *)&upd_signature,
|
|
(char *)&expected_signature);
|
|
}
|
|
}
|
|
|
|
/* Add FSP version to coreboot table LB_TAG_PLATFORM_BLOB_VERSION */
|
|
void lb_string_platform_blob_version(struct lb_header *header)
|
|
{
|
|
struct lb_string *rec;
|
|
size_t len;
|
|
char fsp_version[FSP_VER_LEN] = {0};
|
|
|
|
fsp_get_version(fsp_version);
|
|
rec = (struct lb_string *)lb_new_record(header);
|
|
rec->tag = LB_TAG_PLATFORM_BLOB_VERSION;
|
|
len = strlen(fsp_version);
|
|
rec->size = ALIGN_UP(sizeof(*rec) + len + 1, 8);
|
|
memcpy(rec->string, fsp_version, len+1);
|
|
}
|
|
|
|
__weak void soc_validate_fspm_header(const struct fsp_header *hdr)
|
|
{
|
|
}
|