/*
 * This file is part of the coreboot project.
 *
 * Copyright (C) 2013 Google, Inc.
 *
 * 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; version 2 of the License.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA
 */

#include <stdint.h>
#include <stddef.h>
#include <cbfs.h>
#include <cbmem.h>
#include <console/console.h>
#include <console/vtxprintf.h>
#include <pc80/tpm.h>
#include <reset.h>
#include <romstage_handoff.h>
#include <rmodule.h>
#include <string.h>
#include <stdlib.h>
#include <timestamp.h>
#include <arch/stages.h>
#include "chromeos.h"
#include "fmap.h"
#include "vboot_context.h"
#include "vboot_handoff.h"

static void vboot_run_stub(struct vboot_context *context)
{
	const struct cbmem_entry *vboot_entry;
	struct rmodule vbootstub;
	struct cbfs_stage *stage;
	size_t region_size;
	int rmodule_offset;
	int load_offset;
	char *vboot_region;
	void (*entry)(struct vboot_context *context);

	stage = cbfs_get_file_content(CBFS_DEFAULT_MEDIA,
	                              CONFIG_CBFS_PREFIX "/vboot",
	                              CBFS_TYPE_STAGE);

	if (stage == NULL)
		return;

	rmodule_offset =
		rmodule_calc_region(DYN_CBMEM_ALIGN_SIZE,
	                            stage->memlen, &region_size, &load_offset);

	vboot_entry = cbmem_entry_add(0xffffffff, region_size);

	if (vboot_entry == NULL) {
		printk(BIOS_DEBUG, "Couldn't get region for vboot stub.\n");
		return;
	}

	vboot_region = cbmem_entry_start(vboot_entry);

	if (cbfs_decompress(stage->compression, &stage[1],
	                    &vboot_region[rmodule_offset], stage->len)) {
		printk(BIOS_DEBUG, "Couldn't decompress vboot stub.\n");
		goto out;
	}

	if (rmodule_parse(&vboot_region[rmodule_offset], &vbootstub)) {
		printk(BIOS_DEBUG, "Couldn't parse vboot stub rmodule.\n");
		goto out;
	}

	if (rmodule_load(&vboot_region[load_offset], &vbootstub)) {
		printk(BIOS_DEBUG, "Couldn't load vboot stub.\n");
		goto out;
	}

	entry = rmodule_entry(&vbootstub);

	/* Call stub. */
	entry(context);

out:
	/* Tear down the region no longer needed. */
	cbmem_entry_remove(vboot_entry);
}

/* Helper routines for the vboot stub. */
static void log_msg(const char *fmt, va_list args)
{
	vtxprintf(console_tx_byte, fmt, args);
	console_tx_flush();
}

static void fatal_error(void)
{
	printk(BIOS_ERR, "vboot encountered fatal error. Reseting.\n");
	hard_reset();
}

static void vboot_invoke_wrapper(struct vboot_handoff *vboot_handoff)
{
	VbCommonParams cparams;
	VbSelectFirmwareParams fparams;
	struct vboot_context context;
	uint32_t *iflags;

	vboot_handoff->selected_firmware = VB_SELECT_FIRMWARE_READONLY;

	memset(&cparams, 0, sizeof(cparams));
	memset(&fparams, 0, sizeof(fparams));
	memset(&context, 0, sizeof(context));

	iflags = &vboot_handoff->init_params.flags;
	if (get_developer_mode_switch())
		*iflags |= VB_INIT_FLAG_DEV_SWITCH_ON;
	if (get_recovery_mode_switch())
		*iflags |= VB_INIT_FLAG_REC_BUTTON_PRESSED;
	if (get_write_protect_state())
		*iflags |= VB_INIT_FLAG_WP_ENABLED;
	if (CONFIG_VIRTUAL_DEV_SWITCH)
		*iflags |= VB_INIT_FLAG_VIRTUAL_DEV_SWITCH;
	if (CONFIG_EC_SOFTWARE_SYNC)
		*iflags |= VB_INIT_FLAG_EC_SOFTWARE_SYNC;

	context.handoff = vboot_handoff;
	context.cparams = &cparams;
	context.fparams = &fparams;

	cparams.gbb_size = find_fmap_entry("GBB", &cparams.gbb_data);
	cparams.shared_data_blob = &vboot_handoff->shared_data[0];
	cparams.shared_data_size = VB_SHARED_DATA_MIN_SIZE;
	cparams.caller_context = &context;

	fparams.verification_size_A =
		find_fmap_entry("VBLOCK_A", &fparams.verification_block_A);
	fparams.verification_size_B =
		find_fmap_entry("VBLOCK_B", &fparams.verification_block_B);

	context.fw_a_size =
		find_fmap_entry("FW_MAIN_A", (void **)&context.fw_a);
	context.fw_b_size =
		find_fmap_entry("FW_MAIN_B", (void **)&context.fw_b);

	/* Check all fmap entries. */
	if (context.fw_a == NULL || context.fw_b == NULL ||
	    fparams.verification_block_A == NULL ||
	    fparams.verification_block_B == NULL ||
	    cparams.gbb_data == NULL) {
		printk(BIOS_DEBUG, "Not all fmap entries found for vboot.\n");
		return;
	}

	/* Initialize callbacks. */
	context.read_vbnv = &read_vbnv;
	context.save_vbnv = &save_vbnv;
	context.tis_init = &tis_init;
	context.tis_open = &tis_open;
	context.tis_close = &tis_close;
	context.tis_sendrecv = &tis_sendrecv;
	context.log_msg = &log_msg;
	context.fatal_error = &fatal_error;

	vboot_run_stub(&context);
}

static void vboot_load_ramstage(struct vboot_handoff *vboot_handoff,
                                struct romstage_handoff *handoff)
{
	struct cbfs_stage *stage;
	struct rmodule ramstage;
	void *entry_point;
	size_t region_size;
	char *ramstage_region;
	int rmodule_offset;
	int load_offset;
	const struct cbmem_entry *ramstage_entry;
	const struct firmware_component *fwc;

	if (CONFIG_VBOOT_RAMSTAGE_INDEX >= MAX_PARSED_FW_COMPONENTS) {
		printk(BIOS_ERR, "Invalid ramstage index: %d\n",
		       CONFIG_VBOOT_RAMSTAGE_INDEX);
		return;
	}

	/* Check for invalid address. */
	fwc = &vboot_handoff->components[CONFIG_VBOOT_RAMSTAGE_INDEX];
	if (fwc->address == 0) {
		printk(BIOS_DEBUG, "RW ramstage image address invalid.\n");
		return;
	}

	printk(BIOS_DEBUG, "RW ramstage image at 0x%08x, 0x%08x bytes.\n",
	       fwc->address, fwc->size);

	stage = (void *)fwc->address;

	rmodule_offset =
		rmodule_calc_region(DYN_CBMEM_ALIGN_SIZE,
	                            stage->memlen, &region_size, &load_offset);

	ramstage_entry = cbmem_entry_add(CBMEM_ID_RAMSTAGE, region_size);

	if (ramstage_entry == NULL) {
		vboot_handoff->selected_firmware = VB_SELECT_FIRMWARE_READONLY;
		printk(BIOS_DEBUG, "Could not add ramstage region.\n");
		return;
	}

	timestamp_add_now(TS_START_COPYRAM);

	ramstage_region = cbmem_entry_start(ramstage_entry);

	printk(BIOS_DEBUG, "Decompressing ramstage @ 0x%p (%d bytes)\n",
	       &ramstage_region[rmodule_offset], stage->memlen);

	if (cbfs_decompress(stage->compression, &stage[1],
	                    &ramstage_region[rmodule_offset], stage->len))
		return;

	if (rmodule_parse(&ramstage_region[rmodule_offset], &ramstage))
		return;

	if (rmodule_load(&ramstage_region[load_offset], &ramstage))
		return;

	entry_point = rmodule_entry(&ramstage);

	cache_loaded_ramstage(handoff, ramstage_entry, entry_point);

	timestamp_add_now(TS_END_COPYRAM);

#if CONFIG_ARCH_X86
	__asm__ volatile (
		"movl $0, %%ebp\n"
		"jmp  *%%edi\n"
		:: "D"(entry_point)
	);
#elif CONFIG_ARCH_ARMV7
	stage_exit(entry_point);
#endif
}

void vboot_verify_firmware(struct romstage_handoff *handoff)
{
	struct vboot_handoff *vboot_handoff;

	/* Don't go down verified boot path on S3 resume. */
	if (handoff != NULL && handoff->s3_resume)
		return;

	timestamp_add_now(TS_START_VBOOT);

	vboot_handoff = cbmem_add(CBMEM_ID_VBOOT_HANDOFF,
	                          sizeof(*vboot_handoff));

	if (vboot_handoff == NULL) {
		printk(BIOS_DEBUG, "Could not add vboot_handoff structure.\n");
		return;
	}

	memset(vboot_handoff, 0, sizeof(*vboot_handoff));

	vboot_invoke_wrapper(vboot_handoff);

	timestamp_add_now(TS_END_VBOOT);

	/* Take RO firmware path since no RW area was selected. */
	if (vboot_handoff->selected_firmware != VB_SELECT_FIRMWARE_A &&
	    vboot_handoff->selected_firmware != VB_SELECT_FIRMWARE_B) {
		printk(BIOS_DEBUG, "No RW firmware selected: 0x%08x\n",
		       vboot_handoff->selected_firmware);
		return;
	}

	/* Load ramstage from the vboot_handoff structure. */
	vboot_load_ramstage(vboot_handoff, handoff);
}
