/* SPDX-License-Identifier: GPL-2.0-or-later */

#include <arch/null_breakpoint.h>
#include <arch/symbols.h>
#include <assert.h>
#include <cbfs.h>
#include <cbmem.h>
#include <cf9_reset.h>
#include <console/console.h>
#include <elog.h>
#include <fsp/api.h>
#include <fsp/util.h>
#include <memrange.h>
#include <mode_switch.h>
#include <mrc_cache.h>
#include <program_loading.h>
#include <romstage_handoff.h>
#include <security/tpm/tspi.h>
#include <security/vboot/antirollback.h>
#include <security/vboot/vboot_common.h>
#include <string.h>
#include <symbols.h>
#include <timestamp.h>
#include <types.h>
#include <vb2_api.h>

#if CONFIG(SOC_INTEL_COMMON_BASECODE_RAMTOP)
#include <intelbasecode/ramtop.h>
#endif

static uint8_t temp_ram[CONFIG_FSP_TEMP_RAM_SIZE] __aligned(sizeof(uint64_t));

/*
 * Helper function to store the MRC cache version into CBMEM
 *
 * ramstage uses either the MRC version or FSP-M version (depending on the config)
 * when updating the MRC cache
 */
static void do_cbmem_version_entry(uint32_t cbmem_id, uint32_t version)
{
	uint32_t *cbmem_version_entry = cbmem_add(cbmem_id, sizeof(version));
	if (!cbmem_version_entry) {
		printk(BIOS_ERR, "Failed to add %s version to cbmem.\n",
				CONFIG(MRC_CACHE_USING_MRC_VERSION) ? "MRC" : "FSP-M");
		return;
	}
	*cbmem_version_entry = version;
}

static void do_fsp_post_memory_init(bool s3wake, uint32_t version)
{
	struct range_entry fsp_mem;
	uint32_t cbmem_id = CONFIG(MRC_CACHE_USING_MRC_VERSION) ? CBMEM_ID_MRC_VERSION :
					 CBMEM_ID_FSPM_VERSION;

	fsp_find_reserved_memory(&fsp_mem);

	/* initialize cbmem by adding FSP reserved memory first thing */
	if (!s3wake) {
		cbmem_initialize_empty_id_size(CBMEM_ID_FSP_RESERVED_MEMORY,
			range_entry_size(&fsp_mem));
	} else if (cbmem_initialize_id_size(CBMEM_ID_FSP_RESERVED_MEMORY,
				range_entry_size(&fsp_mem))) {
		if (CONFIG(HAVE_ACPI_RESUME)) {
			printk(BIOS_ERR, "Failed to recover CBMEM in S3 resume.\n");
			/* Failed S3 resume, reset to come up cleanly */
			/* FIXME: A "system" reset is likely enough: */
			full_reset();
		}
	}

	/* make sure FSP memory is reserved in cbmem */
	if (range_entry_base(&fsp_mem) !=
		(uintptr_t)cbmem_find(CBMEM_ID_FSP_RESERVED_MEMORY))
		die("Failed to accommodate FSP reserved memory request!\n");

	if (CONFIG(CACHE_MRC_SETTINGS) && !s3wake)
		do_cbmem_version_entry(cbmem_id, version);

	/* Create romstage handof information */
	romstage_handoff_init(s3wake);
}

static void fsp_fill_mrc_cache(FSPM_ARCH_UPD *arch_upd, uint32_t version)
{
	void *data;
	size_t mrc_size;

	arch_upd->NvsBufferPtr = 0;

	if (!CONFIG(CACHE_MRC_SETTINGS))
		return;

	/* Assume boot device is memory mapped. */
	assert(CONFIG(BOOT_DEVICE_MEMORY_MAPPED));

	data = mrc_cache_current_mmap_leak(MRC_TRAINING_DATA, version,
					   &mrc_size);
	if (data == NULL)
		return;

	/* MRC cache found */
	arch_upd->NvsBufferPtr = (uintptr_t)data;

	printk(BIOS_SPEW, "MRC cache found, size %zu bytes\n", mrc_size);
}

static enum cb_err check_region_overlap(const struct memranges *ranges,
					const char *description,
					uintptr_t begin, uintptr_t end)
{
	const struct range_entry *r;

	memranges_each_entry(r, ranges) {
		if (end <= range_entry_base(r))
			continue;
		if (begin >= range_entry_end(r))
			continue;
		printk(BIOS_CRIT, "'%s' overlaps currently running program: "
			"[%p, %p)\n", description, (void *)begin, (void *)end);
		return CB_ERR;
	}

	return CB_SUCCESS;
}

static enum cb_err setup_fsp_stack_frame(FSPM_ARCH_UPD *arch_upd,
		const struct memranges *memmap)
{
	uintptr_t stack_begin;
	uintptr_t stack_end;

	/*
	 * FSPM_UPD passed here is populated with default values
	 * provided by the blob itself. We let FSPM use top of CAR
	 * region of the size it requests.
	 */
	stack_end = (uintptr_t)_car_region_end;
	stack_begin = stack_end - arch_upd->StackSize;
	if (check_region_overlap(memmap, "FSPM stack", stack_begin,
				stack_end) != CB_SUCCESS)
		return CB_ERR;

	arch_upd->StackBase = stack_begin;
	return CB_SUCCESS;
}

static enum cb_err fsp_fill_common_arch_params(FSPM_ARCH_UPD *arch_upd,
					bool s3wake, uint32_t version,
					const struct memranges *memmap)
{
	/*
	 * FSP 2.1 version would use same stack as coreboot instead of
	 * setting up separate stack frame. FSP 2.1 would not relocate stack
	 * top and does not reinitialize stack pointer. The parameters passed
	 * as StackBase and StackSize are actually for temporary RAM and HOBs
	 * and are not related to FSP stack at all.
	 * Non-CAR FSP 2.0 platforms pass a DRAM location for the FSP stack.
	 */
	if (CONFIG(FSP_USES_CB_STACK) || !ENV_CACHE_AS_RAM) {
		arch_upd->StackBase = (uintptr_t)temp_ram;
		arch_upd->StackSize = sizeof(temp_ram);
	} else if (setup_fsp_stack_frame(arch_upd, memmap)) {
		return CB_ERR;
	}

	fsp_fill_mrc_cache(arch_upd, version);

	/* Configure bootmode */
	if (s3wake) {
		arch_upd->BootMode = FSP_BOOT_ON_S3_RESUME;
	} else {
		if (arch_upd->NvsBufferPtr)
			arch_upd->BootMode =
				FSP_BOOT_ASSUMING_NO_CONFIGURATION_CHANGES;
		else
			arch_upd->BootMode = FSP_BOOT_WITH_FULL_CONFIGURATION;
	}

	printk(BIOS_SPEW, "bootmode is set to: %d\n", arch_upd->BootMode);

	return CB_SUCCESS;
}

__weak
uint8_t fsp_memory_mainboard_version(void)
{
	return 0;
}

__weak
uint8_t fsp_memory_soc_version(void)
{
	return 0;
}

/*
 * Allow SoC and/or mainboard to bump the revision of the FSP setting
 * number. The FSP spec uses the low 8 bits as the build number. Take over
 * bits 3:0 for the SoC setting and bits 7:4 for the mainboard. That way
 * a tweak in the settings will bump the version used to track the cached
 * setting which triggers retraining when the FSP version hasn't changed, but
 * the SoC or mainboard settings have.
 */
static uint32_t fsp_memory_settings_version(const struct fsp_header *hdr)
{
	/* Use the full FSP version by default. */
	uint32_t ver = hdr->image_revision;

	if (!CONFIG(FSP_PLATFORM_MEMORY_SETTINGS_VERSIONS))
		return ver;

	ver &= ~0xff;
	ver |= (0xf & fsp_memory_mainboard_version()) << 4;
	ver |= (0xf & fsp_memory_soc_version()) << 0;

	return ver;
}

struct fspm_context {
	struct fsp_header header;
	struct memranges memmap;
};

/*
 * Helper function to read MRC version
 *
 * There are multiple ways to read the MRC version using
 * Intel FSP. Currently the only supported method to get the
 * MRC version is by reading the FSP_PRODUCDER_DATA_TABLES
 * from the FSP-M binary (by parsing the FSP header).
 */
static uint32_t fsp_mrc_version(void)
{
	uint32_t ver = 0;
#if CONFIG(MRC_CACHE_USING_MRC_VERSION)
	size_t fspm_blob_size;
	void *fspm_blob_file = cbfs_map(CONFIG_FSP_M_CBFS, &fspm_blob_size);
	if (!fspm_blob_file)
		return 0;

	FSP_PRODUCER_DATA_TABLES *ft = fspm_blob_file + FSP_HDR_OFFSET;
	FSP_PRODUCER_DATA_TYPE2 *table2 = &ft->FspProduceDataType2;
	size_t mrc_version_size = sizeof(table2->MrcVersion);
	for (size_t i = 0; i < mrc_version_size; i++) {
		ver |= (table2->MrcVersion[i] << ((mrc_version_size - 1) - i) * 8);
	}
	cbfs_unmap(fspm_blob_file);
#endif
	return ver;
}

static void do_fsp_memory_init(const struct fspm_context *context, bool s3wake)
{
	uint32_t status;
	fsp_memory_init_fn fsp_raminit;
	FSPM_UPD fspm_upd, *upd;
	FSPM_ARCH_UPD *arch_upd;
	uint32_t version;
	const struct fsp_header *hdr = &context->header;
	const struct memranges *memmap = &context->memmap;

	post_code(POSTCODE_MEM_PREINIT_PREP_START);

	if (CONFIG(MRC_CACHE_USING_MRC_VERSION))
		version = fsp_mrc_version();
	else
		version = fsp_memory_settings_version(hdr);

	upd = (FSPM_UPD *)(uintptr_t)(hdr->cfg_region_offset + hdr->image_base);

	/*
	 * Verify UPD region size. We don't have malloc before ramstage, so we
	 * use a static buffer for the FSP-M UPDs which is sizeof(FSPM_UPD)
	 * bytes long, since that is the value known at compile time. If
	 * hdr->cfg_region_size is bigger than that, not all UPD defaults will
	 * be copied, so it'll contain random data at the end, so we just call
	 * die() in that case. If hdr->cfg_region_size is smaller than that,
	 * there's a mismatch between the FSP and the header, but since it will
	 * copy the full UPD defaults to the buffer, we try to continue and
	 * hope that there was no incompatible change in the UPDs.
	 */
	if (hdr->cfg_region_size > sizeof(FSPM_UPD))
		die("FSP-M UPD size is larger than FSPM_UPD struct size.\n");
	if (hdr->cfg_region_size < sizeof(FSPM_UPD))
		printk(BIOS_ERR, "FSP-M UPD size is smaller than FSPM_UPD struct size. "
				"Check if the FSP binary matches the FSP headers.\n");

	fsp_verify_upd_header_signature(upd->FspUpdHeader.Signature, FSPM_UPD_SIGNATURE);

	/* Copy the default values from the UPD area */
	memcpy(&fspm_upd, upd, sizeof(fspm_upd));

	arch_upd = &fspm_upd.FspmArchUpd;

	/* Reserve enough memory under TOLUD to save CBMEM header */
	arch_upd->BootLoaderTolumSize = cbmem_overhead_size();

	/* Fill common settings on behalf of chipset. */
	if (fsp_fill_common_arch_params(arch_upd, s3wake, version,
					memmap) != CB_SUCCESS)
		die_with_post_code(POSTCODE_INVALID_VENDOR_BINARY,
			"FSPM_ARCH_UPD not found!\n");

	/* Early caching of RAMTOP region if valid mrc cache data is found */
#if (CONFIG(SOC_INTEL_COMMON_BASECODE_RAMTOP))
	if (arch_upd->NvsBufferPtr)
		early_ramtop_enable_cache_range();
#endif

	/* Give SoC and mainboard a chance to update the UPD */
	platform_fsp_memory_init_params_cb(&fspm_upd, version);

	/*
	 * For S3 resume case, if valid mrc cache data is not found or
	 * RECOVERY_MRC_CACHE hash verification fails, the S3 data
	 * pointer would be null and S3 resume fails with fsp-m
	 * returning error. Invoking a reset here saves time.
	 */
	if (s3wake && !arch_upd->NvsBufferPtr)
		/* FIXME: A "system" reset is likely enough: */
		full_reset();

	if (CONFIG(MMA))
		setup_mma(&fspm_upd.FspmConfig);

	post_code(POSTCODE_MEM_PREINIT_PREP_END);

	/* Call FspMemoryInit */
	fsp_raminit = (void *)(uintptr_t)(hdr->image_base + hdr->fsp_memory_init_entry_offset);
	fsp_debug_before_memory_init(fsp_raminit, upd, &fspm_upd);

	/* FSP disables the interrupt handler so remove debug exceptions temporarily  */
	null_breakpoint_disable();
	post_code(POSTCODE_FSP_MEMORY_INIT);
	timestamp_add_now(TS_FSP_MEMORY_INIT_START);
	if (ENV_X86_64 && CONFIG(PLATFORM_USES_FSP2_X86_32))
		status = protected_mode_call_2arg(fsp_raminit,
						  (uintptr_t)&fspm_upd,
						  (uintptr_t)fsp_get_hob_list_ptr());
	else
		status = fsp_raminit(&fspm_upd, fsp_get_hob_list_ptr());
	null_breakpoint_init();

	post_code(POSTCODE_FSP_MEMORY_EXIT);
	timestamp_add_now(TS_FSP_MEMORY_INIT_END);

	/* Handle any errors returned by FspMemoryInit */
	fsp_handle_reset(status);
	if (status != FSP_SUCCESS) {
		die_with_post_code(POSTCODE_RAM_FAILURE,
			"FspMemoryInit returned with error 0x%08x!\n", status);
	}

	do_fsp_post_memory_init(s3wake, version);

	/*
	 * fsp_debug_after_memory_init() checks whether the end of the tolum
	 * region is the same as the top of cbmem, so must be called here
	 * after cbmem has been initialised in do_fsp_post_memory_init().
	 */
	fsp_debug_after_memory_init(status);
}

static void *fspm_allocator(void *arg, size_t size, const union cbfs_mdata *unused)
{
	const struct fsp_load_descriptor *fspld = arg;
	struct fspm_context *context = fspld->arg;
	struct memranges *memmap = &context->memmap;

	/* Non XIP FSP-M uses FSP-M address */
	uintptr_t fspm_begin = (uintptr_t)CONFIG_FSP_M_ADDR;
	uintptr_t fspm_end = fspm_begin + size;

	if (check_region_overlap(memmap, "FSPM", fspm_begin, fspm_end) != CB_SUCCESS)
		return NULL;

	return (void *)fspm_begin;
}

void preload_fspm(void)
{
	if (!CONFIG(CBFS_PRELOAD))
		return;

	printk(BIOS_DEBUG, "Preloading %s\n", CONFIG_FSP_M_CBFS);
	cbfs_preload(CONFIG_FSP_M_CBFS);
}

void fsp_memory_init(bool s3wake)
{
	struct range_entry prog_ranges[2];
	struct fspm_context context;
	struct fsp_load_descriptor fspld = {
		.fsp_prog = PROG_INIT(PROG_REFCODE, CONFIG_FSP_M_CBFS),
		.arg = &context,
	};
	struct fsp_header *hdr = &context.header;
	struct memranges *memmap = &context.memmap;

	/* For FSP-M XIP we leave alloc NULL to get a direct mapping to flash. */
	if (!CONFIG(FSP_M_XIP))
		fspld.alloc = fspm_allocator;

	elog_boot_notify(s3wake);

	/* Build up memory map of romstage address space including CAR. */
	memranges_init_empty(memmap, &prog_ranges[0], ARRAY_SIZE(prog_ranges));
	if (ENV_CACHE_AS_RAM)
		memranges_insert(memmap, (uintptr_t)_car_region_start,
			_car_unallocated_start - _car_region_start, 0);
	memranges_insert(memmap, (uintptr_t)_program, REGION_SIZE(program), 0);

	timestamp_add_now(TS_FSP_MEMORY_INIT_LOAD);
	if (fsp_load_component(&fspld, hdr) != CB_SUCCESS)
		die("FSPM not available or failed to load!\n");

	if (CONFIG(FSP_M_XIP) && (uintptr_t)prog_start(&fspld.fsp_prog) != hdr->image_base)
		die("FSPM XIP base does not match: %p vs %p\n",
		    (void *)(uintptr_t)hdr->image_base, prog_start(&fspld.fsp_prog));

	timestamp_add_now(TS_INITRAM_START);

	do_fsp_memory_init(&context, s3wake);

	timestamp_add_now(TS_INITRAM_END);
}
