/* SPDX-License-Identifier: GPL-2.0-only */

#include <bootstate.h>
#include <cbmem.h>
#include <commonlib/helpers.h>
#include <console/console.h>
#include <console/streams.h>
#include <fsp/util.h>
#include <timestamp.h>

/* Locate the FSP binary in the coreboot filesystem */
FSP_INFO_HEADER *find_fsp(uintptr_t fsp_base_address)
{
	union {
		EFI_FFS_FILE_HEADER *ffh;
		FSP_INFO_HEADER *fih;
		EFI_FIRMWARE_VOLUME_EXT_HEADER *fveh;
		EFI_FIRMWARE_VOLUME_HEADER *fvh;
		EFI_RAW_SECTION *rs;
		u32 u32;
	} fsp_ptr;

	u64 *image_id;

	/* Get the FSP binary base address in CBFS */
	fsp_ptr.u32 = fsp_base_address;

	/* Check the FV signature, _FVH */
	if (fsp_ptr.fvh->Signature != 0x4856465F)
		return (FSP_INFO_HEADER *)ERROR_NO_FV_SIG;

	/* Locate the file header which follows the FV header. */
	fsp_ptr.u32 += fsp_ptr.fvh->ExtHeaderOffset;
	fsp_ptr.u32 += fsp_ptr.fveh->ExtHeaderSize;
	fsp_ptr.u32 = ALIGN_UP(fsp_ptr.u32, 8);

	/* Check the FFS GUID */
	if ((((u32 *)&fsp_ptr.ffh->Name)[0] != 0x912740BE)
		|| (((u32 *)&fsp_ptr.ffh->Name)[1] != 0x47342284)
		|| (((u32 *)&fsp_ptr.ffh->Name)[2] != 0xB08471B9)
		|| (((u32 *)&fsp_ptr.ffh->Name)[3] != 0x0C3F3527)) {
		return (FSP_INFO_HEADER *)ERROR_NO_FFS_GUID;
	}

	/* Locate the Raw Section Header */
	fsp_ptr.u32 += sizeof(EFI_FFS_FILE_HEADER);

	if (fsp_ptr.rs->Type != EFI_SECTION_RAW)
		return (FSP_INFO_HEADER *)ERROR_NO_INFO_HEADER;

	/* Locate the FSP INFO Header which follows the Raw Header. */
	fsp_ptr.u32 += sizeof(EFI_RAW_SECTION);

	/* Verify that the FSP base address.*/
	if (fsp_ptr.fih->ImageBase != fsp_base_address)
		return (FSP_INFO_HEADER *)ERROR_IMAGEBASE_MISMATCH;

	/* Verify the FSP Signature */
	if (fsp_ptr.fih->Signature != FSP_SIG)
		return (FSP_INFO_HEADER *)ERROR_INFO_HEAD_SIG_MISMATCH;

	/* Verify the FSP ID */
	image_id = (u64 *)&fsp_ptr.fih->ImageId[0];
	if (*image_id != FSP_IMAGE_ID)
		return (FSP_INFO_HEADER *)ERROR_FSP_SIG_MISMATCH;

	/* Verify the FSP Revision */
	if (fsp_ptr.fih->ImageRevision > FSP_IMAGE_REV)
		return (FSP_INFO_HEADER *)ERROR_FSP_REV_MISMATCH;

	return fsp_ptr.fih;
}

void print_fsp_info(FSP_INFO_HEADER *fsp_header)
{
	u8 *fsp_base;

	fsp_base = (u8 *)fsp_header->ImageBase;
	printk(BIOS_SPEW, "FSP_INFO_HEADER: %p\n", fsp_header);
	printk(BIOS_INFO, "FSP Signature: %c%c%c%c%c%c%c%c\n",
			fsp_header->ImageId[0], fsp_header->ImageId[1],
			fsp_header->ImageId[2], fsp_header->ImageId[3],
			fsp_header->ImageId[4], fsp_header->ImageId[5],
			fsp_header->ImageId[6], fsp_header->ImageId[7]);
	printk(BIOS_INFO, "FSP Header Version: %d\n",
			fsp_header->HeaderRevision);
	printk(BIOS_INFO, "FSP Revision: %d.%d.%d.%d\n",
			(u8)((fsp_header->ImageRevision >> 24) & 0xff),
			(u8)((fsp_header->ImageRevision >> 16) & 0xff),
			(u8)((fsp_header->ImageRevision >> 8) & 0xff),
			(u8)(fsp_header->ImageRevision  & 0xff));
	if (CONFIG(DISPLAY_FSP_ENTRY_POINTS)) {
		printk(BIOS_SPEW, "FSP Entry Points:\n");
		printk(BIOS_SPEW, "    %p: Image Base\n", fsp_base);
		printk(BIOS_SPEW, "    %p: TempRamInit\n",
		       &fsp_base[fsp_header->TempRamInitEntryOffset]);
		printk(BIOS_SPEW, "    %p: FspInit\n",
		       &fsp_base[fsp_header->FspInitEntryOffset]);
		if (fsp_header->HeaderRevision >= FSP_HEADER_REVISION_2) {
			printk(BIOS_SPEW, "    %p: MemoryInit\n",
			       &fsp_base[fsp_header->FspMemoryInitEntryOffset]);
			printk(BIOS_SPEW, "    %p: TempRamExit\n",
			       &fsp_base[fsp_header->TempRamExitEntryOffset]);
			printk(BIOS_SPEW, "    %p: SiliconInit\n",
			       &fsp_base[fsp_header->FspSiliconInitEntryOffset]);
		}
		printk(BIOS_SPEW, "    %p: NotifyPhase\n",
		       &fsp_base[fsp_header->NotifyPhaseEntryOffset]);
		printk(BIOS_SPEW, "    %p: Image End\n",
		       &fsp_base[fsp_header->ImageSize]);
	}
}

void fsp_notify(u32 phase)
{
	FSP_NOTIFY_PHASE notify_phase_proc;
	NOTIFY_PHASE_PARAMS notify_phase_params;
	EFI_STATUS status;
	FSP_INFO_HEADER *fsp_header_ptr;

	fsp_header_ptr = fsp_get_fih();
	if (fsp_header_ptr == NULL) {
		fsp_header_ptr = (void *)find_fsp(CONFIG_FSP_LOC);
		if ((u32)fsp_header_ptr < 0xff) {
			/* output something in case there is no serial */
			post_code(0x4F);
			die("Can't find the FSP!\n");
		}
	}

	/* call FSP PEI to Notify PostPciEnumeration */
	notify_phase_proc = (FSP_NOTIFY_PHASE)(fsp_header_ptr->ImageBase +
		fsp_header_ptr->NotifyPhaseEntryOffset);
	notify_phase_params.Phase = phase;

	if (phase == EnumInitPhaseReadyToBoot) {
		timestamp_add_now(TS_FSP_FINALIZE_START);
		post_code(POST_FSP_NOTIFY_BEFORE_FINALIZE);
	} else {
		timestamp_add_now(TS_FSP_ENUMERATE_START);
		post_code(POST_FSP_NOTIFY_BEFORE_ENUMERATE);
	}

	status = notify_phase_proc(&notify_phase_params);

	timestamp_add_now(phase == EnumInitPhaseReadyToBoot ?
		TS_FSP_FINALIZE_END : TS_FSP_ENUMERATE_END);

	if (status != 0)
		printk(BIOS_ERR, "FSP API NotifyPhase failed for phase 0x%x with status: 0x%x\n",
			phase, status);
}

static void fsp_notify_boot_state_callback(void *arg)
{
	u32 phase = (u32)arg;

	printk(BIOS_SPEW, "Calling FspNotify(0x%08x)\n", phase);
	fsp_notify(phase);
}

BOOT_STATE_INIT_ENTRY(BS_DEV_RESOURCES, BS_ON_EXIT,
	fsp_notify_boot_state_callback,
	(void *)EnumInitPhaseAfterPciEnumeration);
BOOT_STATE_INIT_ENTRY(BS_PAYLOAD_LOAD, BS_ON_EXIT,
	fsp_notify_boot_state_callback,
	(void *)EnumInitPhaseReadyToBoot);
BOOT_STATE_INIT_ENTRY(BS_OS_RESUME, BS_ON_ENTRY,
	fsp_notify_boot_state_callback,
	(void *)EnumInitPhaseReadyToBoot);

struct fsp_runtime {
	uint32_t fih;
	uint32_t hob_list;
} __packed;

void fsp_set_runtime(FSP_INFO_HEADER *fih, void *hob_list)
{
	struct fsp_runtime *fspr;

	fspr = cbmem_add(CBMEM_ID_FSP_RUNTIME, sizeof(*fspr));

	if (fspr == NULL)
		die("Can't save FSP runtime information.\n");

	fspr->fih = (uintptr_t)fih;
	fspr->hob_list = (uintptr_t)hob_list;
}

FSP_INFO_HEADER *fsp_get_fih(void)
{
	struct fsp_runtime *fspr;

	fspr = cbmem_find(CBMEM_ID_FSP_RUNTIME);

	if (fspr == NULL)
		return NULL;

	return (void *)(uintptr_t)fspr->fih;
}

void *fsp_get_hob_list(void)
{
	struct fsp_runtime *fspr;

	fspr = cbmem_find(CBMEM_ID_FSP_RUNTIME);

	if (fspr == NULL)
		return NULL;

	return (void *)(uintptr_t)fspr->hob_list;
}

void fsp_update_fih(FSP_INFO_HEADER *fih)
{
	struct fsp_runtime *fspr;

	fspr = cbmem_find(CBMEM_ID_FSP_RUNTIME);

	if (fspr == NULL)
		die("Can't update FSP runtime information.\n");

	fspr->fih = (uintptr_t)fih;
}

void fsp_display_upd_value(const char *name, uint32_t size, uint64_t old,
	uint64_t new)
{
	if (old == new) {
		switch (size) {
		case 1:
			printk(BIOS_SPEW, "  0x%02llx: %s\n", new, name);
			break;

		case 2:
			printk(BIOS_SPEW, "  0x%04llx: %s\n", new, name);
			break;

		case 4:
			printk(BIOS_SPEW, "  0x%08llx: %s\n", new, name);
			break;

		case 8:
			printk(BIOS_SPEW, "  0x%016llx: %s\n", new, name);
			break;
		}
	} else {
		switch (size) {
		case 1:
			printk(BIOS_SPEW, "  0x%02llx --> 0x%02llx: %s\n", old,
				new, name);
			break;

		case 2:
			printk(BIOS_SPEW, "  0x%04llx --> 0x%04llx: %s\n", old,
				new, name);
			break;

		case 4:
			printk(BIOS_SPEW, "  0x%08llx --> 0x%08llx: %s\n", old,
				new, name);
			break;

		case 8:
			printk(BIOS_SPEW, "  0x%016llx --> 0x%016llx: %s\n",
				old, new, name);
			break;
		}
	}
}
