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

#include <acpi/acpi.h>
#include <bootstate.h>
#include <console/console.h>
#include <intelblocks/cse.h>
#include <intelblocks/pmc_ipc.h>
#include <security/vboot/vboot_common.h>
#include <soc/intel/common/reset.h>
#include <soc/pci_devs.h>
#include <timestamp.h>
#include <types.h>

enum cse_eop_result {
	CSE_EOP_RESULT_GLOBAL_RESET_REQUESTED,
	CSE_EOP_RESULT_SUCCESS,
	CSE_EOP_RESULT_ERROR,
	CSE_EOP_RESULT_DISABLED,
};

static bool cse_disable_mei_bus(void)
{
	struct bus_disable_message {
		uint8_t command;
		uint8_t reserved[3];
	} __packed msg = {
		.command = MEI_BUS_DISABLE_COMMAND,
	};
	struct bus_disable_resp {
		uint8_t command;
		uint8_t status;
		uint8_t reserved[2];
	} __packed reply = {};

	size_t reply_sz = sizeof(reply);

	if (!heci_send_receive(&msg, sizeof(msg), &reply, &reply_sz, HECI_MEI_ADDR)) {
		printk(BIOS_ERR, "HECI: Failed to Disable MEI bus\n");
		return false;
	}

	if (reply.status) {
		printk(BIOS_ERR, "HECI: MEI_Bus_Disable Failed (status: %d)\n", reply.status);
		return false;
	}

	return true;
}

static enum cse_eop_result cse_send_eop(void)
{
	enum {
		EOP_REQUESTED_ACTION_CONTINUE = 0,
		EOP_REQUESTED_ACTION_GLOBAL_RESET = 1,
	};
	struct end_of_post_msg {
		struct mkhi_hdr hdr;
	} __packed msg = {
		.hdr = {
			.group_id = MKHI_GROUP_ID_GEN,
			.command = MKHI_END_OF_POST,
		},
	};
	struct end_of_post_resp {
		struct mkhi_hdr hdr;
		uint32_t requested_actions;
	} __packed resp = {};
	size_t resp_size = sizeof(resp);

	/* For a CSE-Lite SKU, if the CSE is running RO FW and the board is
	   running vboot in recovery mode, the CSE is expected to be in SOFT
	   TEMP DISABLE state. */
	if (CONFIG(SOC_INTEL_CSE_LITE_SKU) && vboot_recovery_mode_enabled() &&
	    cse_is_hfs1_com_soft_temp_disable()) {
		printk(BIOS_INFO, "HECI: coreboot in recovery mode; found CSE in expected SOFT "
		       "TEMP DISABLE state, skipping EOP\n");
		return CSE_EOP_RESULT_SUCCESS;
	}

	/*
	 * Prerequisites:
	 * 1) HFSTS1 CWS is Normal
	 * 2) HFSTS1 COM is Normal
	 * 3) Only sent after DID (accomplished by compiling this into ramstage)
	 */

	if (cse_is_hfs1_com_soft_temp_disable()) {
		printk(BIOS_ERR, "HECI: Prerequisites not met for sending EOP\n");
		if (CONFIG(SOC_INTEL_CSE_LITE_SKU))
			return CSE_EOP_RESULT_ERROR;
		return CSE_EOP_RESULT_DISABLED;
	}

	if (!cse_is_hfs1_cws_normal() || !cse_is_hfs1_com_normal()) {
		printk(BIOS_ERR, "HECI: Prerequisites not met for sending EOP\n");
		return CSE_EOP_RESULT_ERROR;
	}

	printk(BIOS_INFO, "HECI: Sending End-of-Post\n");

	if (!heci_send_receive(&msg, sizeof(msg), &resp, &resp_size, HECI_MKHI_ADDR)) {
		printk(BIOS_ERR, "HECI: EOP send/receive fail\n");
		return CSE_EOP_RESULT_ERROR;
	}

	if (resp.hdr.result) {
		printk(BIOS_ERR, "HECI: EOP Resp Failed: %u\n", resp.hdr.result);
		return CSE_EOP_RESULT_ERROR;
	}

	printk(BIOS_INFO, "CSE: EOP requested action: ");

	switch (resp.requested_actions) {
	case EOP_REQUESTED_ACTION_GLOBAL_RESET:
		printk(BIOS_INFO, "global reset\n");
		return CSE_EOP_RESULT_GLOBAL_RESET_REQUESTED;
	case EOP_REQUESTED_ACTION_CONTINUE:
		printk(BIOS_INFO, "continue boot\n");
		return CSE_EOP_RESULT_SUCCESS;
	default:
		printk(BIOS_INFO, "unknown %u\n", resp.requested_actions);
		return CSE_EOP_RESULT_ERROR;
	}
}

/*
 * On EOP error, the BIOS is required to send an MEI bus disable message to the
 * CSE, followed by disabling all MEI devices. After successfully completing
 * this, it is safe to boot.
 */
static void cse_handle_eop_error(void)
{
	if (!cse_disable_mei_bus())
		die("Failed to disable MEI bus while recovering from EOP error\n"
		    "Preventing system from booting into an insecure state.\n");

	if (!cse_disable_mei_devices())
		die("Error disabling MEI devices while recovering from EOP error\n"
		    "Preventing system from booting into an insecure state.\n");
}

static void handle_cse_eop_result(enum cse_eop_result result)
{
	switch (result) {
	case CSE_EOP_RESULT_GLOBAL_RESET_REQUESTED:
		printk(BIOS_INFO, "CSE requested global reset in EOP response, resetting...\n");
		do_global_reset();
		break;
	case CSE_EOP_RESULT_SUCCESS:
		printk(BIOS_INFO, "CSE EOP successful, continuing boot\n");
		break;
	case CSE_EOP_RESULT_DISABLED:
		printk(BIOS_INFO, "CSE is disabled, continuing boot\n");
		break;
	case CSE_EOP_RESULT_ERROR: /* fallthrough */
	default:
		printk(BIOS_ERR, "Failed to send EOP to CSE, %d\n", result);
		/* For vboot, trigger recovery mode if applicable, as there is
		   likely something very broken in this case. */
		if (CONFIG(VBOOT) && !vboot_recovery_mode_enabled())
			cse_trigger_vboot_recovery(CSE_EOP_FAIL);

		/* In non-vboot builds or recovery mode, follow the BWG in order
		   to continue to boot securely. */
		cse_handle_eop_error();
		break;
	}
}

static void do_send_end_of_post(void)
{
	static bool eop_sent = false;

	if (eop_sent) {
		printk(BIOS_ERR, "EOP already sent\n");
		return;
	}

	if (acpi_get_sleep_type() == ACPI_S3) {
		printk(BIOS_INFO, "Skip sending EOP during S3 resume\n");
		return;
	}

	/*
	 * If CSE is already hidden then accessing CSE registers would be wrong and will
	 * receive junk, hence, return as CSE is already disabled.
	 */
	if (!is_cse_enabled()) {
		printk(BIOS_DEBUG, "CSE is disabled, cannot send End-of-Post (EOP) message\n");
		return;
	}

	set_cse_device_state(PCH_DEVFN_CSE, DEV_ACTIVE);

	timestamp_add_now(TS_ME_BEFORE_END_OF_POST);
	handle_cse_eop_result(cse_send_eop());
	timestamp_add_now(TS_ME_AFTER_END_OF_POST);

	set_cse_device_state(PCH_DEVFN_CSE, DEV_IDLE);

	eop_sent = true;
}

void cse_send_end_of_post(void)
{
	return do_send_end_of_post();
}

static void set_cse_end_of_post(void *unused)
{
	return do_send_end_of_post();
}

/*
 * Ideally, to give coreboot maximum flexibility, sending EOP would be done as
 * late possible. If HECI_DISABLE_USING_SMM is selected, then sending EOP must
 * be performed before the HECI bus is disabled, so these boards use
 * BS_PAYLOAD_LOAD, which happens before the HECI_DISABLE_USING_SMM Kconfig takes
 * effect (EOP is sent using the HECI bus).
 * Otherwise, EOP can be pushed a little later, and can be performed in
 * BS_PAYLOAD_BOOT instead.
 */
#if !CONFIG(HECI_DISABLE_USING_SMM)
BOOT_STATE_INIT_ENTRY(BS_PAYLOAD_BOOT, BS_ON_ENTRY, set_cse_end_of_post, NULL);
#else
BOOT_STATE_INIT_ENTRY(BS_PAYLOAD_LOAD, BS_ON_ENTRY, set_cse_end_of_post, NULL);
#endif
