/*
 * This file is part of the coreboot project.
 *
 * Copyright (C) 2015-2016 Intel Corp.
 * (Written by Andrey Petrov <andrey.petrov@intel.com> for Intel Corp.)
 * (Written by Alexandru Gagniuc <alexandrux.gagniuc@intel.com> for Intel Corp.)
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 */

#include <antirollback.h>
#include <arch/io.h>
#include <arch/cpu.h>
#include <arch/symbols.h>
#include <assert.h>
#include <cbfs.h>
#include <cbmem.h>
#include <console/console.h>
#include <elog.h>
#include <fsp/api.h>
#include <fsp/util.h>
#include <memrange.h>
#include <program_loading.h>
#include <reset.h>
#include <romstage_handoff.h>
#include <soc/intel/common/mrc_cache.h>
#include <string.h>
#include <symbols.h>
#include <timestamp.h>
#include <tpm_lite/tlcl.h>
#include <vboot/vboot_common.h>
#include <vb2_api.h>

static void mrc_cache_update_tpm_hash(const uint8_t *data, size_t size)
{
	uint8_t data_hash[VB2_SHA256_DIGEST_SIZE];
	static const uint8_t dead_hash[VB2_SHA256_DIGEST_SIZE] = {
		0xba, 0xad, 0xda, 0x1a, /* BAADDA1A */
		0xde, 0xad, 0xde, 0xad, /* DEADDEAD */
		0xde, 0xad, 0xda, 0x1a, /* DEADDA1A */
		0xba, 0xad, 0xba, 0xad, /* BAADBAAD */
		0xba, 0xad, 0xda, 0x1a, /* BAADDA1A */
		0xde, 0xad, 0xde, 0xad, /* DEADDEAD */
		0xde, 0xad, 0xda, 0x1a, /* DEADDA1A */
		0xba, 0xad, 0xba, 0xad, /* BAADBAAD */
	};
	const uint8_t *hash_ptr = data_hash;

	/* We do not store normal mode data hash in TPM. */
	if (!vboot_recovery_mode_enabled())
		return;

	/* Bail out early if no mrc hash space is supported in TPM. */
	if (!IS_ENABLED(CONFIG_FSP2_0_USES_TPM_MRC_HASH))
		return;

	/* Initialize TPM driver. */
	if (tlcl_lib_init() != VB2_SUCCESS) {
		printk(BIOS_ERR, "MRC: TPM driver initialization failed.\n");
		return;
	}

	/* Calculate hash of data generated by MRC. */
	if (vb2_digest_buffer(data, size, VB2_HASH_SHA256, data_hash,
			      sizeof(data_hash))) {
		printk(BIOS_ERR, "MRC: SHA-256 calculation failed for data. "
		       "Not updating TPM hash space.\n");
		/*
		 * Since data is being updated in recovery cache, the hash
		 * currently stored in TPM recovery hash space is no longer
		 * valid. If we are not able to calculate hash of the data being
		 * updated, reset all the bits in TPM recovery hash space to
		 * pre-defined hash pattern.
		 */
		hash_ptr = dead_hash;
	}

	/* Write hash of data to TPM space. */
	if (antirollback_write_space_rec_hash(hash_ptr, VB2_SHA256_DIGEST_SIZE)
	    != TPM_SUCCESS) {
		printk(BIOS_ERR, "MRC: Could not save hash to TPM.\n");
		return;
	}

	printk(BIOS_INFO, "MRC: TPM MRC hash updated successfully.\n");
}

static void save_memory_training_data(bool s3wake, uint32_t fsp_version)
{
	size_t  mrc_data_size;
	const void *mrc_data;

	if (!IS_ENABLED(CONFIG_CACHE_MRC_SETTINGS) || s3wake)
		return;

	mrc_data = fsp_find_nv_storage_data(&mrc_data_size);
	if (!mrc_data) {
		printk(BIOS_ERR, "Couldn't find memory training data HOB.\n");
		return;
	}

	/*
	 * Save MRC Data to CBMEM. By always saving the data this forces
	 * a retrain after a trip through Chrome OS recovery path. The
	 * code which saves the data to flash doesn't write if the latest
	 * training data matches this one.
	 */
	if (mrc_cache_stash_data(MRC_TRAINING_DATA, fsp_version, mrc_data,
				mrc_data_size) < 0)
		printk(BIOS_ERR, "Failed to stash MRC data\n");

	mrc_cache_update_tpm_hash(mrc_data, mrc_data_size);
}

static void do_fsp_post_memory_init(bool s3wake, uint32_t fsp_version)
{
	struct range_entry fsp_mem;

	if (fsp_find_reserved_memory(&fsp_mem))
		die("Failed to find FSP_RESERVED_MEMORY_RESOURCE_HOB!\n");

	/* 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 (IS_ENABLED(CONFIG_HAVE_ACPI_RESUME)) {
			printk(BIOS_ERR,
				"Failed to recover CBMEM in S3 resume.\n");
			/* Failed S3 resume, reset to come up cleanly */
			hard_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");

	save_memory_training_data(s3wake, fsp_version);

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

static int mrc_cache_verify_tpm_hash(const uint8_t *data, size_t size)
{
	uint8_t data_hash[VB2_SHA256_DIGEST_SIZE];
	uint8_t tpm_hash[VB2_SHA256_DIGEST_SIZE];

	/* We do not store normal mode data hash in TPM. */
	if (!vboot_recovery_mode_enabled())
		return 1;

	if (!IS_ENABLED(CONFIG_FSP2_0_USES_TPM_MRC_HASH))
		return 1;

	/* Calculate hash of data read from RECOVERY_MRC_CACHE. */
	if (vb2_digest_buffer(data, size, VB2_HASH_SHA256, data_hash,
			      sizeof(data_hash))) {
		printk(BIOS_ERR, "MRC: SHA-256 calculation failed for data.\n");
		return 0;
	}

	/* Initialize TPM driver. */
	if (tlcl_lib_init() != VB2_SUCCESS) {
		printk(BIOS_ERR, "MRC: TPM driver initialization failed.\n");
		return 0;
	}

	/* Read hash of MRC data saved in TPM. */
	if (antirollback_read_space_rec_hash(tpm_hash, sizeof(tpm_hash))
	    != TPM_SUCCESS) {
		printk(BIOS_ERR, "MRC: Could not read hash from TPM.\n");
		return 0;
	}

	if (memcmp(tpm_hash, data_hash, sizeof(tpm_hash))) {
		printk(BIOS_ERR, "MRC: Hash comparison failed.\n");
		return 0;
	}

	printk(BIOS_INFO, "MRC: Hash comparison successful. "
	       "Using data from RECOVERY_MRC_CACHE\n");
	return 1;
}

static void fsp_fill_mrc_cache(FSPM_ARCH_UPD *arch_upd, bool s3wake,
				uint32_t fsp_version)
{
	struct region_device rdev;
	void *data;

	arch_upd->NvsBufferPtr = NULL;

	if (!IS_ENABLED(CONFIG_CACHE_MRC_SETTINGS))
		return;

	/*
	 * In recovery mode, force retraining:
	 * 1. Recovery cache is not supported, or
	 * 2. Memory retrain switch is set.
	 */
	if (vboot_recovery_mode_enabled()) {
		if (!IS_ENABLED(CONFIG_HAS_RECOVERY_MRC_CACHE))
			return;
		if (vboot_recovery_mode_memory_retrain())
			return;
	}

	if (mrc_cache_get_current(MRC_TRAINING_DATA, fsp_version, &rdev) < 0)
		return;

	/* Assume boot device is memory mapped. */
	assert(IS_ENABLED(CONFIG_BOOT_DEVICE_MEMORY_MAPPED));
	data = rdev_mmap_full(&rdev);

	if (data == NULL)
		return;

	if (!mrc_cache_verify_tpm_hash(data, region_device_sz(&rdev)))
		return;

	/* MRC cache found */
	arch_upd->NvsBufferPtr = data;
	arch_upd->BootMode = s3wake ?
		FSP_BOOT_ON_S3_RESUME :
		FSP_BOOT_ASSUMING_NO_CONFIGURATION_CHANGES;
	printk(BIOS_SPEW, "MRC cache found, size %zx bootmode:%d\n",
				region_device_sz(&rdev), arch_upd->BootMode);
}

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 fsp_fill_common_arch_params(FSPM_ARCH_UPD *arch_upd,
					bool s3wake, uint32_t fsp_version,
					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 = (void *)stack_begin;

	arch_upd->BootMode = FSP_BOOT_WITH_FULL_CONFIGURATION;

	fsp_fill_mrc_cache(arch_upd, s3wake, fsp_version);

	return CB_SUCCESS;
}

static void do_fsp_memory_init(struct fsp_header *hdr, bool s3wake,
					const struct memranges *memmap)
{
	uint32_t status;
	fsp_memory_init_fn fsp_raminit;
	FSPM_UPD fspm_upd, *upd;
	FSPM_ARCH_UPD *arch_upd;

	post_code(0x34);

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

	if (upd->FspUpdHeader.Signature != FSPM_UPD_SIGNATURE) {
		die("Invalid FSPM signature!\n");
	}

	/* 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, hdr->fsp_revision,
					memmap) != CB_SUCCESS)
		die("FSPM_ARCH_UPD not found!\n");

	/* Give SoC and mainboard a chance to update the UPD */
	platform_fsp_memory_init_params_cb(&fspm_upd, hdr->fsp_revision);

	if (IS_ENABLED(CONFIG_MMA))
		setup_mma(&fspm_upd.FspmConfig);

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

	post_code(POST_FSP_MEMORY_INIT);
	timestamp_add_now(TS_FSP_MEMORY_INIT_START);
	status = fsp_raminit(&fspm_upd, fsp_get_hob_list_ptr());
	post_code(POST_FSP_MEMORY_INIT);
	timestamp_add_now(TS_FSP_MEMORY_INIT_END);

	fsp_debug_after_memory_init(status);

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

	do_fsp_post_memory_init(s3wake, hdr->fsp_revision);
}

/* Load the binary into the memory specified by the info header. */
static enum cb_err load_fspm_mem(struct fsp_header *hdr,
					const struct region_device *rdev,
					const struct memranges *memmap)
{
	uintptr_t fspm_begin;
	uintptr_t fspm_end;

	if (fsp_validate_component(hdr, rdev) != CB_SUCCESS)
		return CB_ERR;

	fspm_begin = hdr->image_base;
	fspm_end = fspm_begin + hdr->image_size;

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

	/* Load binary into memory at provided address. */
	if (rdev_readat(rdev, (void *)fspm_begin, 0, fspm_end - fspm_begin) < 0)
		return CB_ERR;

	return CB_SUCCESS;
}

/* Handle the case when FSPM is running XIP. */
static enum cb_err load_fspm_xip(struct fsp_header *hdr,
					const struct region_device *rdev)
{
	void *base;

	if (fsp_validate_component(hdr, rdev) != CB_SUCCESS)
		return CB_ERR;

	base = rdev_mmap_full(rdev);
	if ((uintptr_t)base != hdr->image_base) {
		printk(BIOS_CRIT, "FSPM XIP base does not match: %p vs %p\n",
			(void *)(uintptr_t)hdr->image_base, base);
		return CB_ERR;
	}

	/*
	 * Since the component is XIP it's already in the address space. Thus,
	 * there's no need to rdev_munmap().
	 */
	return CB_SUCCESS;
}

void fsp_memory_init(bool s3wake)
{
	struct fsp_header hdr;
	enum cb_err status;
	struct cbfsf file_desc;
	struct region_device file_data;
	const char *name = CONFIG_FSP_M_CBFS;
	struct memranges memmap;
	struct range_entry freeranges[2];

	if (IS_ENABLED(CONFIG_ELOG_BOOT_COUNT) && !s3wake)
		boot_count_increment();

	if (cbfs_boot_locate(&file_desc, name, NULL)) {
		printk(BIOS_CRIT, "Could not locate %s in CBFS\n", name);
		die("FSPM not available!\n");
	}

	cbfs_file_data(&file_data, &file_desc);

	/* Build up memory map of romstage address space including CAR. */
	memranges_init_empty(&memmap, &freeranges[0], ARRAY_SIZE(freeranges));
	memranges_insert(&memmap, (uintptr_t)_car_region_start,
		_car_relocatable_data_end - _car_region_start, 0);
	memranges_insert(&memmap, (uintptr_t)_program, _program_size, 0);

	if (!IS_ENABLED(CONFIG_FSP_M_XIP))
		status = load_fspm_mem(&hdr, &file_data, &memmap);
	else
		status = load_fspm_xip(&hdr, &file_data);

	if (status != CB_SUCCESS) {
		die("Loading FSPM failed!\n");
	}

	/* Signal that FSP component has been loaded. */
	prog_segment_loaded(hdr.image_base, hdr.image_size, SEG_FINAL);

	do_fsp_memory_init(&hdr, s3wake, &memmap);
}
