/*
 * Copyright 2012 Google Inc.
 *
 * See file CREDITS for list of people who contributed to this
 * project.
 *
 * 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.
 *
 * 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., 59 Temple Place, Suite 330, Boston,
 * MA 02111-1307 USA
 */

#include <assert.h>
#include <stdint.h>
#include <vboot_api.h>
#include <vboot_nvstorage.h>

#include "base/xalloc.h"
#include "base/memory.h"
#include "base/power.h"
#include "base/timestamp.h"
#include "boot/boot.h"
#include "boot/commandline.h"
#include "drivers/blockdev/blockdev.h"
#include "drivers/board/board.h"
#include "drivers/keyboard/keyboard.h"
#include "module/module.h"
#include "module/symbols.h"
#include "vboot/board.h"
#include "vboot/stages.h"
#include "vboot/crossystem/crossystem.h"
#include "vboot/util/commonparams.h"
#include "vboot/util/ec.h"
#include "vboot/vbnv.h"

enum {
	CmdLineSize = 4096,
	CrosParamSize = 4096,
};

int vboot_init(void)
{
	VbInitParams iparams = {
		.flags = 0
	};

	int dev_switch = board_flag_developer_mode();
	int rec_switch = board_flag_recovery();
	int wp_switch = board_flag_write_protect();
	int lid_switch = board_flag_lid_open();
	int oprom_loaded = 0;
	if (CONFIG_OPROM_MATTERS)
		oprom_loaded = board_flag_option_roms_loaded();

	printf("%s:%d dev %d, rec %d, wp %d, lid %d, oprom %d\n",
	       __func__, __LINE__, dev_switch, rec_switch,
	       wp_switch, lid_switch, oprom_loaded);

	if (dev_switch < 0 || rec_switch < 0 || lid_switch < 0 ||
	    wp_switch < 0 || oprom_loaded < 0) {
		// An error message should have already been printed.
		return 1;
	}

	// Decide what flags to pass into VbInit.
	iparams.flags |= VB_INIT_FLAG_RO_NORMAL_SUPPORT;
	/* Don't fail the boot process when lid switch is closed.
	 * The OS might not have enough time to log success before
	 * shutting down.
	 */
	if (!lid_switch)
		iparams.flags |= VB_INIT_FLAG_NOFAIL_BOOT;
	if (dev_switch)
		iparams.flags |= VB_INIT_FLAG_DEV_SWITCH_ON;
	if (rec_switch)
		iparams.flags |= VB_INIT_FLAG_REC_BUTTON_PRESSED;
	if (wp_switch)
		iparams.flags |= VB_INIT_FLAG_WP_ENABLED;
	if (oprom_loaded)
		iparams.flags |= VB_INIT_FLAG_OPROM_LOADED;
	if (CONFIG_OPROM_MATTERS)
		iparams.flags |= VB_INIT_FLAG_OPROM_MATTERS;
	if (CONFIG_VIRTUAL_DEV_SWITCH)
		iparams.flags |= VB_INIT_FLAG_VIRTUAL_DEV_SWITCH;
	if (CONFIG_EC_SOFTWARE_SYNC)
		iparams.flags |= VB_INIT_FLAG_EC_SOFTWARE_SYNC;
        if (!CONFIG_PHYSICAL_REC_SWITCH)
                iparams.flags |= VB_INIT_FLAG_VIRTUAL_REC_SWITCH;

	if (common_params_init())
		return 1;

	printf("Calling VbInit().\n");
	VbError_t res = VbInit(&cparams, &iparams);
	if (res != VBERROR_SUCCESS) {
		printf("VbInit returned %d, Doing a cold reboot.\n", res);
		if (cold_reboot())
			return 1;
	}

	return vboot_do_init_out_flags(iparams.out_flags);
};

int vboot_do_init_out_flags(uint32_t out_flags)
{
	if (out_flags & VB_INIT_OUT_CLEAR_RAM) {
		if (memory_wipe_unused())
			return 1;
	}
	/*
	 * If in developer mode or recovery mode, assume we're going to need
	 * input. We'll want it up and responsive by the time we present
	 * prompts to the user, so get it going ahead of time.
	 */
	if (out_flags & (VB_INIT_OUT_ENABLE_DEVELOPER |
			 VB_INIT_OUT_ENABLE_RECOVERY))
		keyboard_prepare();

	return 0;
}

int vboot_select_firmware(DcModuleOps *rwa, DcModuleOps *rwb)
{
	if (common_params_init())
		return 1;

	StorageOps *storage_a = board_storage_vblock_a();
	StorageOps *storage_b = board_storage_vblock_b();

	int size_a = storage_size(storage_a);
	int size_b = storage_size(storage_b);
	if (size_a < 0 || size_b < 0)
		return 1;

	void *vblock_a = xmalloc(size_a);
	void *vblock_b = xmalloc(size_b);

	if (storage_read(storage_a, vblock_a, 0, size_a) ||
	    storage_read(storage_b, vblock_b, 0, size_b)) {
		free(vblock_a);
		free(vblock_b);
		return 1;
	}

	VbSelectFirmwareParams fparams = {
		.verification_block_A = vblock_a,
		.verification_block_B = vblock_b,
		.verification_size_A = size_a,
		.verification_size_B = size_b
	};

	printf("Calling VbSelectFirmware().\n");
	VbError_t res = VbSelectFirmware(&cparams, &fparams);
	free(vblock_a);
	free(vblock_b);
	if (res != VBERROR_SUCCESS) {
		printf("VbSelectFirmware returned %d, "
		       "Doing a cold reboot.\n", res);
		if (cold_reboot())
			return 1;
	}

	enum VbSelectFirmware_t select = fparams.selected_firmware;

	// If an RW firmware was selected, start it.
	if (select == VB_SELECT_FIRMWARE_A)
		return dc_module_start(rwa);
	else if (select == VB_SELECT_FIRMWARE_B)
		return dc_module_start(rwb);

	return 0;
}

int vboot_select_and_load_kernel(void)
{
	static char cmd_line_buf[2 * CmdLineSize];

	VbSelectAndLoadKernelParams kparams;
	if (CONFIG_HOSTED) {
		// If we're hosted, stay in our own address space for now.
		static uint8_t hosted_kernel_buffer[CONFIG_KERNEL_SIZE];
		kparams.kernel_buffer = hosted_kernel_buffer;
		kparams.kernel_buffer_size = sizeof(hosted_kernel_buffer);
	} else {
		// If we're not hosted, set the kernel up in place.
		kparams.kernel_buffer = (void *)(uintptr_t)CONFIG_KERNEL_START;
		kparams.kernel_buffer_size = CONFIG_KERNEL_SIZE;
	};

	if (common_params_init())
		return 1;

	printf("Calling VbSelectAndLoadKernel().\n");
	VbError_t res = VbSelectAndLoadKernel(&cparams, &kparams);
	if (res == VBERROR_EC_REBOOT_TO_RO_REQUIRED) {
		printf("Rebooting the EC to RO.\n");
		reboot_ec_to_ro();
		if (power_off())
			return 1;
	} else if (res == VBERROR_SHUTDOWN_REQUESTED) {
		printf("Powering off.\n");
		if (power_off())
			return 1;
	}
	if (res != VBERROR_SUCCESS) {
		printf("VbSelectAndLoadKernel returned %d, "
		       "Doing a cold reboot.\n", res);
		if (cold_reboot())
			return 1;
	}

	timestamp_add_now(TS_CROSSYSTEM_DATA);

	// The scripts that packaged the kernel assumed it was going to end
	// up at 1MB which is frequently not right. The address of the 
	// "loader", which isn't actually used any more, is set based on that
	// assumption. We have to subtract the 1MB offset from it, and then add
	// the actual load address to figure ou thwere it actually is,
	// or would be if it existed.
	void *kernel = kparams.kernel_buffer;
	void *loader = (uint8_t *)kernel +
		(kparams.bootloader_address - 0x100000);
	void *params = (uint8_t *)loader - CrosParamSize;
	void *orig_cmd_line = (uint8_t *)params - CmdLineSize;

	BlockDev *bdev = (BlockDev *)kparams.disk_handle;

	if (commandline_subst(orig_cmd_line, cmd_line_buf,
			      sizeof(cmd_line_buf), 0,
			      kparams.partition_number + 1,
			      kparams.partition_guid, bdev->external_gpt))
		return 1;

	if (crossystem_setup())
		return 1;

	boot(kernel, cmd_line_buf, params, loader, NULL, 0);

	return 1;
}
