/* Copyright (c) 2013 The Chromium OS Authors. All rights reserved.
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 *
 * High-level firmware wrapper API - entry points for kernel selection
 */

#include "2api.h"
#include "2common.h"
#include "2kernel.h"
#include "2misc.h"
#include "2nvstorage.h"
#include "2rsa.h"
#include "2secdata.h"
#include "2sysincludes.h"
#include "2ui.h"
#include "load_kernel_fw.h"
#include "vboot_api.h"
#include "vboot_kernel.h"
#include "vboot_struct.h"
#include "vboot_test.h"

/* Global variables */
static VbSelectAndLoadKernelParams lkp;

#ifdef CHROMEOS_ENVIRONMENT
/* Global variable accessor for unit tests */
struct VbSelectAndLoadKernelParams *VbApiKernelGetParams(void)
{
	return &lkp;
}
#endif

static vb2_error_t handle_battery_cutoff(struct vb2_context *ctx)
{
	/*
	 * Check if we need to cut-off battery. This should be done after EC
	 * FW and auxfw are updated, and before the kernel is started.  This
	 * is to make sure all firmware is up-to-date before shipping (which
	 * is the typical use-case for cutoff).
	 */
	if (vb2_nv_get(ctx, VB2_NV_BATTERY_CUTOFF_REQUEST)) {
		VB2_DEBUG("Request to cut-off battery\n");
		vb2_nv_set(ctx, VB2_NV_BATTERY_CUTOFF_REQUEST, 0);

		/* May lose power immediately, so commit our update now. */
		VB2_TRY(vb2ex_commit_data(ctx));

		vb2ex_ec_battery_cutoff();
		return VB2_REQUEST_SHUTDOWN;
	}

	return VB2_SUCCESS;
}

static int is_valid_disk(VbDiskInfo *info, uint32_t disk_flags)
{
	return info->bytes_per_lba >= 512 &&
		(info->bytes_per_lba & (info->bytes_per_lba - 1)) == 0 &&
		info->lba_count >= 16 &&
		(info->flags & disk_flags & VB_DISK_FLAG_SELECT_MASK) &&
		((info->flags & VB_DISK_FLAG_SELECT_MASK) &
		 ((info->flags & VB_DISK_FLAG_SELECT_MASK) - 1)) == 0;
}

test_mockable
vb2_error_t VbTryLoadKernel(struct vb2_context *ctx, uint32_t disk_flags)
{
	vb2_error_t rv = VB2_ERROR_LK_NO_DISK_FOUND;
	VbDiskInfo* disk_info = NULL;
	uint32_t disk_count = 0;
	uint32_t i;

	lkp.disk_handle = NULL;

	/* Find disks */
	if (VB2_SUCCESS != VbExDiskGetInfo(&disk_info, &disk_count, disk_flags))
		disk_count = 0;

	/* Loop over disks */
	for (i = 0; i < disk_count; i++) {
		VB2_DEBUG("trying disk %d\n", (int)i);

		if (!is_valid_disk(&disk_info[i], disk_flags)) {
			VB2_DEBUG("  skipping: bytes_per_lba=%" PRIu64
				  " lba_count=%" PRIu64 " flags=%#x\n",
				  disk_info[i].bytes_per_lba,
				  disk_info[i].lba_count,
				  disk_info[i].flags);
			continue;
		}

		lkp.disk_handle = disk_info[i].handle;
		vb2_error_t new_rv = LoadKernel(ctx, &lkp, &disk_info[i]);
		VB2_DEBUG("LoadKernel() = %#x\n", new_rv);

		/* Stop now if we found a kernel. */
		if (VB2_SUCCESS == new_rv) {
			VbExDiskFreeInfo(disk_info, disk_info[i].handle);
			return VB2_SUCCESS;
		}

		/* Don't update error if we already have a more specific one. */
		if (VB2_ERROR_LK_INVALID_KERNEL_FOUND != rv)
			rv = new_rv;
	}

	/* If we drop out of the loop, we didn't find any usable kernel. */
	if (disk_flags & VB_DISK_FLAG_FIXED) {
		switch (rv) {
		case VB2_ERROR_LK_INVALID_KERNEL_FOUND:
			vb2api_fail(ctx, VB2_RECOVERY_RW_INVALID_OS, rv);
			break;
		case VB2_ERROR_LK_NO_KERNEL_FOUND:
			vb2api_fail(ctx, VB2_RECOVERY_RW_NO_KERNEL, rv);
			break;
		case VB2_ERROR_LK_NO_DISK_FOUND:
			vb2api_fail(ctx, VB2_RECOVERY_RW_NO_DISK, rv);
			break;
		default:
			vb2api_fail(ctx, VB2_RECOVERY_LK_UNSPECIFIED, rv);
			break;
		}
	}

	/* If we didn't find any good kernels, don't return a disk handle. */
	VbExDiskFreeInfo(disk_info, NULL);

	return rv;
}

static vb2_error_t vb2_kernel_init_kparams(struct vb2_context *ctx,
					   VbSelectAndLoadKernelParams *kparams)
{
	/* Fill in params for calls to LoadKernel() */
	memset(&lkp, 0, sizeof(lkp));
	lkp.kernel_buffer = kparams->kernel_buffer;
	lkp.kernel_buffer_size = kparams->kernel_buffer_size;

	/* Clear output params in case we fail */
	kparams->disk_handle = NULL;
	kparams->partition_number = 0;
	kparams->bootloader_address = 0;
	kparams->bootloader_size = 0;
	kparams->flags = 0;
	memset(kparams->partition_guid, 0, sizeof(kparams->partition_guid));

	return VB2_SUCCESS;
}

static void vb2_kernel_fill_kparams(struct vb2_context *ctx,
				    VbSelectAndLoadKernelParams *kparams)
{
	/* Save disk parameters */
	kparams->disk_handle = lkp.disk_handle;
	kparams->partition_number = lkp.partition_number;
	kparams->bootloader_address = lkp.bootloader_address;
	kparams->bootloader_size = lkp.bootloader_size;
	kparams->flags = lkp.flags;
	kparams->kernel_buffer = lkp.kernel_buffer;
	kparams->kernel_buffer_size = lkp.kernel_buffer_size;
	memcpy(kparams->partition_guid, lkp.partition_guid,
	       sizeof(kparams->partition_guid));
}

vb2_error_t VbSelectAndLoadKernel(struct vb2_context *ctx,
				  VbSelectAndLoadKernelParams *kparams)
{
	struct vb2_shared_data *sd = vb2_get_sd(ctx);
	vb2_gbb_flags_t gbb_flags = vb2api_gbb_get_flags(ctx);

	/* Init nvstorage space. TODO(kitching): Remove once we add assertions
	   to vb2_nv_get and vb2_nv_set. */
	vb2_nv_init(ctx);

	VB2_TRY(vb2_kernel_init_kparams(ctx, kparams));

	VB2_TRY(vb2api_kernel_phase1(ctx));

	VB2_DEBUG("GBB flags are %#x\n", gbb_flags);

	/*
	 * Do EC and auxfw software sync unless we're in recovery mode. This
	 * has UI but it's just a single non-interactive WAIT screen.
	 */
	if (!(ctx->flags & VB2_CONTEXT_RECOVERY_MODE)) {
		VB2_TRY(vb2api_ec_sync(ctx));
		VB2_TRY(vb2api_auxfw_sync(ctx));
		VB2_TRY(handle_battery_cutoff(ctx));
	}

	/*
	 * If in non-manual recovery mode, save the recovery reason as subcode.
	 * Otherwise, clear any leftover recovery requests or subcodes.
	 */
	vb2_clear_recovery(ctx);

	/* Select boot path */
	if (ctx->flags & VB2_CONTEXT_RECOVERY_MODE) {
		/* If we're in recovery mode just to do memory retraining, all
		   we need to do is reboot. */
		if (sd->recovery_reason == VB2_RECOVERY_TRAIN_AND_REBOOT) {
			VB2_DEBUG("Reboot after retraining in recovery\n");
			return VB2_REQUEST_REBOOT;
		}

		/*
		 * Need to commit nvdata changes immediately, since we will be
		 * entering either manual recovery UI or BROKEN screen shortly.
		 */
		vb2ex_commit_data(ctx);

		/*
		 * In EFS2, recovery mode can be entered even when battery is
		 * drained or damaged. EC-RO sets NO_BOOT flag in such case and
		 * uses PD power to boot AP.
		 *
		 * TODO: Inform user why recovery failed to start.
		 */
		if (ctx->flags & VB2_CONTEXT_NO_BOOT)
			VB2_DEBUG("NO_BOOT in RECOVERY mode\n");

		/* Recovery boot.  This has UI. */
		if (vb2_allow_recovery(ctx))
			VB2_TRY(vb2_manual_recovery_menu(ctx));
		else
			VB2_TRY(vb2_broken_recovery_menu(ctx));
	} else if (DIAGNOSTIC_UI && vb2api_diagnostic_ui_enabled(ctx) &&
		   vb2_nv_get(ctx, VB2_NV_DIAG_REQUEST)) {
		/*
		 * Need to clear the request flag and commit nvdata changes
		 * immediately to avoid booting back into diagnostic tool when a
		 * forced system reset occurs.
		 */
		vb2_nv_set(ctx, VB2_NV_DIAG_REQUEST, 0);
		vb2ex_commit_data(ctx);

		/* Diagnostic boot.  This has UI. */
		VB2_TRY(vb2_diagnostic_menu(ctx));
		/*
		 * The diagnostic menu should either boot a rom, or
		 * return either of reboot or shutdown.
		 */
		return VB2_REQUEST_REBOOT;
	} else if (ctx->flags & VB2_CONTEXT_DEVELOPER_MODE) {
		/* Developer boot.  This has UI. */
		VB2_TRY(vb2_developer_menu(ctx));
	} else {
		/* Normal boot */
		VB2_TRY(vb2_normal_boot(ctx));
	}

	/*
	 * Stop all cases returning SUCCESS against NO_BOOT flag except when
	 * GBB flag disables software sync.
	 */
	if (!(gbb_flags & VB2_GBB_FLAG_DISABLE_EC_SOFTWARE_SYNC)
	    && (ctx->flags & VB2_CONTEXT_NO_BOOT)) {
		VB2_DEBUG("Blocking escape from NO_BOOT mode.\n");
		vb2api_fail(ctx, VB2_RECOVERY_ESCAPE_NO_BOOT, 0);
		return VB2_ERROR_ESCAPE_NO_BOOT;
	}

	vb2_kernel_fill_kparams(ctx, kparams);
	return VB2_SUCCESS;
}
