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

#include <bootsplash.h>
#include <cbfs.h>
#include <cbmem.h>
#include <commonlib/fsp.h>
#include <commonlib/stdlib.h>
#include <console/console.h>
#include <fsp/api.h>
#include <fsp/util.h>
#include <program_loading.h>
#include <soc/intel/common/vbt.h>
#include <stage_cache.h>
#include <string.h>
#include <timestamp.h>
#include <types.h>
#include <mode_switch.h>

struct fsp_header fsps_hdr;

struct fsp_multi_phase_get_number_of_phases_params {
	uint32_t number_of_phases;
	uint32_t phases_executed;
};

/* Callbacks for SoC/Mainboard specific overrides */
void __weak platform_fsp_multi_phase_init_cb(uint32_t phase_index)
{
	/* Leave for the SoC/Mainboard to implement if necessary. */
}

/* FSP Specification < 2.2 has only 1 stage like FspSiliconInit. FSP specification >= 2.2
 * has multiple stages as below.
 */
enum fsp_silicon_init_phases {
	FSP_SILICON_INIT_API,
	FSP_MULTI_PHASE_SI_INIT_GET_NUMBER_OF_PHASES_API,
	FSP_MULTI_PHASE_SI_INIT_EXECUTE_PHASE_API
};

static void fsps_return_value_handler(enum fsp_silicon_init_phases phases, uint32_t status)
{
	uint8_t postcode;

	/* Handle any reset request returned by FSP-S APIs */
	fsp_handle_reset(status);

	if (status == FSP_SUCCESS)
		return;
	/* Handle all other errors returned by FSP-S APIs */
	/* Assume video failure if attempted to initialize graphics */
	if (CONFIG(RUN_FSP_GOP) && vbt_get())
		postcode = POST_VIDEO_FAILURE;
	else
		postcode = POST_HW_INIT_FAILURE; /* else generic */

	switch (phases) {
	case FSP_SILICON_INIT_API:
		die_with_post_code(postcode, "FspSiliconInit returned with error 0x%08x\n",
				status);
		break;
	case FSP_MULTI_PHASE_SI_INIT_GET_NUMBER_OF_PHASES_API:
		printk(BIOS_SPEW, "FspMultiPhaseSiInit NumberOfPhases returned 0x%08x\n",
				status);
		break;
	case FSP_MULTI_PHASE_SI_INIT_EXECUTE_PHASE_API:
		printk(BIOS_SPEW, "FspMultiPhaseSiInit ExecutePhase returned 0x%08x\n",
				status);
		break;
	default:
		break;
	}
}

bool fsp_is_multi_phase_init_enabled(void)
{
	return CONFIG(FSPS_USE_MULTI_PHASE_INIT) &&
			 (fsps_hdr.multi_phase_si_init_entry_offset != 0);
}

static void fsp_fill_common_arch_params(FSPS_UPD *supd)
{
#if CONFIG(FSPS_HAS_ARCH_UPD)
	FSPS_ARCH_UPD *s_arch_cfg = &supd->FspsArchUpd;
	s_arch_cfg->EnableMultiPhaseSiliconInit = fsp_is_multi_phase_init_enabled();
#endif
}

static void do_silicon_init(struct fsp_header *hdr)
{
	FSPS_UPD *upd, *supd;
	fsp_silicon_init_fn silicon_init;
	uint32_t status;
	fsp_multi_phase_si_init_fn multi_phase_si_init;
	struct fsp_multi_phase_params multi_phase_params;
	struct fsp_multi_phase_get_number_of_phases_params multi_phase_get_number;

	supd = (FSPS_UPD *) (uintptr_t)(hdr->cfg_region_offset + hdr->image_base);

	fsp_verify_upd_header_signature(supd->FspUpdHeader.Signature, FSPS_UPD_SIGNATURE);

	/* FSPS UPD and coreboot structure sizes should match. However, enforcing the exact
	 * match mandates simultaneous updates to coreboot and FSP repos. Allow coreboot
	 * to proceed if its UPD structure is smaller than FSP one to enable staggered UPD
	 * update process on both sides. The mismatch indicates a temporary build problem,
	 * don't leave it like this as FSP default settings can be bad choices for coreboot.
	 */
	if (!hdr->cfg_region_size || hdr->cfg_region_size < sizeof(FSPS_UPD))
		die_with_post_code(POST_INVALID_VENDOR_BINARY,
			"Invalid FSPS UPD region\n");
	else if (hdr->cfg_region_size > sizeof(FSPS_UPD))
		printk(BIOS_ERR, "FSP and coreboot are out of sync! FSPS UPD size > coreboot\n");

	upd = xmalloc(hdr->cfg_region_size);

	memcpy(upd, supd, hdr->cfg_region_size);

	/* Fill common settings on behalf of chipset. */
	if (CONFIG(FSPS_HAS_ARCH_UPD))
		fsp_fill_common_arch_params(upd);
	/* Give SoC/mainboard a chance to populate entries */
	platform_fsp_silicon_init_params_cb(upd);

	/* Populate logo related entries */
	if (CONFIG(BMP_LOGO))
		soc_load_logo(upd);

	/* Call SiliconInit */
	silicon_init = (void *) (uintptr_t)(hdr->image_base +
				 hdr->silicon_init_entry_offset);
	fsp_debug_before_silicon_init(silicon_init, supd, upd);

	timestamp_add_now(TS_FSP_SILICON_INIT_START);
	post_code(POST_FSP_SILICON_INIT);

	if (ENV_X86_64 && CONFIG(PLATFORM_USES_FSP2_X86_32))
		status = protected_mode_call_1arg(silicon_init, (uintptr_t)upd);
	else
		status = silicon_init(upd);

	printk(BIOS_INFO, "FSPS returned %x\n", status);

	timestamp_add_now(TS_FSP_SILICON_INIT_END);
	post_code(POST_FSP_SILICON_EXIT);

	if (CONFIG(BMP_LOGO))
		bmp_release_logo();

	fsp_debug_after_silicon_init(status);
	fsps_return_value_handler(FSP_SILICON_INIT_API, status);

	/* Reinitialize CPUs if FSP-S has done MP Init */
	if (CONFIG(USE_INTEL_FSP_MP_INIT))
		do_mpinit_after_fsp();

	if (!CONFIG(PLATFORM_USES_FSP2_2))
		return;

	/* Check if SoC user would like to call Multi Phase Init */
	if (!fsp_is_multi_phase_init_enabled())
		return;

	/* Call MultiPhaseSiInit */
	multi_phase_si_init = (void *) (uintptr_t)(hdr->image_base +
			 hdr->multi_phase_si_init_entry_offset);

	/* Implementing multi_phase_si_init() is optional as per FSP 2.2 spec */
	if (multi_phase_si_init == NULL)
		return;

	post_code(POST_FSP_MULTI_PHASE_SI_INIT_ENTRY);
	timestamp_add_now(TS_FSP_MULTI_PHASE_SI_INIT_START);
	/* Get NumberOfPhases Value */
	multi_phase_params.multi_phase_action = GET_NUMBER_OF_PHASES;
	multi_phase_params.phase_index = 0;
	multi_phase_params.multi_phase_param_ptr = &multi_phase_get_number;
	status = multi_phase_si_init(&multi_phase_params);
	fsps_return_value_handler(FSP_MULTI_PHASE_SI_INIT_GET_NUMBER_OF_PHASES_API, status);

	/* Execute Multi Phase Execution */
	for (uint32_t i = 1; i <= multi_phase_get_number.number_of_phases; i++) {
		printk(BIOS_SPEW, "Executing Phase %u of FspMultiPhaseSiInit\n", i);
		/*
		 * Give SoC/mainboard a chance to perform any operation before
		 * Multi Phase Execution
		 */
		platform_fsp_multi_phase_init_cb(i);

		multi_phase_params.multi_phase_action = EXECUTE_PHASE;
		multi_phase_params.phase_index = i;
		multi_phase_params.multi_phase_param_ptr = NULL;
		status = multi_phase_si_init(&multi_phase_params);
		fsps_return_value_handler(FSP_MULTI_PHASE_SI_INIT_EXECUTE_PHASE_API, status);
	}
	timestamp_add_now(TS_FSP_MULTI_PHASE_SI_INIT_END);
	post_code(POST_FSP_MULTI_PHASE_SI_INIT_EXIT);
}

static void *fsps_allocator(void *arg_unused, size_t size, const union cbfs_mdata *mdata_unused)
{
	return cbmem_add(CBMEM_ID_REFCODE, size);
}

void fsps_load(void)
{
	struct fsp_load_descriptor fspld = {
		.fsp_prog = PROG_INIT(PROG_REFCODE, CONFIG_FSP_S_CBFS),
		.alloc = fsps_allocator,
	};
	struct prog *fsps = &fspld.fsp_prog;
	static int load_done;

	if (load_done)
		return;

	if (resume_from_stage_cache()) {
		printk(BIOS_DEBUG, "Loading FSPS from stage_cache\n");
		stage_cache_load_stage(STAGE_REFCODE, fsps);
		if (fsp_validate_component(&fsps_hdr, prog_start(fsps), prog_size(fsps)))
			die("On resume fsps header is invalid\n");
		load_done = 1;
		return;
	}

	if (fsp_load_component(&fspld, &fsps_hdr) != CB_SUCCESS)
		die("FSP-S failed to load\n");

	stage_cache_add(STAGE_REFCODE, fsps);

	load_done = 1;
}

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

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

void fsp_silicon_init(void)
{
	timestamp_add_now(TS_FSP_SILICON_INIT_LOAD);
	fsps_load();
	do_silicon_init(&fsps_hdr);
}

__weak void soc_load_logo(FSPS_UPD *supd) { }
