/* 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 - user interface for RW firmware
 */

#include "2common.h"
#include "2misc.h"
#include "2nvstorage.h"
#include "2rsa.h"
#include "2secdata.h"
#include "2sysincludes.h"
#include "load_kernel_fw.h"
#include "tlcl.h"
#include "vb2_common.h"
#include "vboot_api.h"
#include "vboot_audio.h"
#include "vboot_kernel.h"
#include "vboot_struct.h"
#include "vboot_test.h"
#include "vboot_ui_legacy.h"
#include "vboot_ui_legacy_wilco.h"

static uint32_t disp_current_screen = VB_SCREEN_BLANK;

test_mockable
vb2_error_t VbDisplayScreen(struct vb2_context *ctx, uint32_t screen, int force,
			    const VbScreenData *data)
{
	uint32_t locale;

	/* If requested screen is the same as the current one, we're done. */
	if (disp_current_screen == screen && !force)
		return VB2_SUCCESS;

	/* Keep track of the currently displayed screen */
	disp_current_screen = screen;

	/* Read the locale last saved */
	locale = vb2_nv_get(ctx, VB2_NV_LOCALIZATION_INDEX);

	return VbExDisplayScreen(screen, locale, data);
}

static vb2_error_t VbTryUsb(struct vb2_context *ctx)
{
	int retval = VbTryLoadKernel(ctx, VB_DISK_FLAG_REMOVABLE);
	if (VB2_SUCCESS == retval) {
		VB2_DEBUG("developer UI - booting USB\n");
	} else {
		vb2_error_notify("Could not boot from USB\n",
				 "developer UI - no kernel found on USB\n",
				 VB_BEEP_FAILED);
	}
	return retval;
}

int VbUserConfirms(struct vb2_context *ctx, uint32_t confirm_flags)
{
	uint32_t key;
	uint32_t key_flags;
	uint32_t btn;
	int button_pressed = 0;
	int shutdown_requested = 0;

	VB2_DEBUG("Entering(%x)\n", confirm_flags);

	/* Await further instructions */
	do {
		key = VbExKeyboardReadWithFlags(&key_flags);
		shutdown_requested = vb2_want_shutdown(ctx, key);
		switch (key) {
		case VB_KEY_ENTER:
			/* If we are using a trusted keyboard or a trusted
			 * keyboard is not required then return yes, otherwise
			 * keep waiting (for instance if the user is using a
			 * USB keyboard).
			 */
			if (!(confirm_flags & VB_CONFIRM_MUST_TRUST_KEYBOARD) ||
			     (key_flags & VB_KEY_FLAG_TRUSTED_KEYBOARD)) {
				VB2_DEBUG("Yes (1)\n");
				return 1;
			}

			/*
			 * If physical presence is confirmed using the keyboard,
			 * beep and notify the user when the ENTER key comes
			 * from an untrusted keyboard.
			 *
			 * If physical presence is confirmed using a physical
			 * button, the existing message on the screen will
			 * instruct the user which button to push.  Silently
			 * ignore any ENTER presses.
			 */
			if (PHYSICAL_PRESENCE_KEYBOARD)
				vb2_error_notify("Please use internal keyboard "
					"to confirm\n",
					"VbUserConfirms() - "
					"Trusted keyboard is required\n",
					VB_BEEP_NOT_ALLOWED);

			break;
		case ' ':
			VB2_DEBUG("Space (%d)\n",
				  confirm_flags & VB_CONFIRM_SPACE_MEANS_NO);
			if (confirm_flags & VB_CONFIRM_SPACE_MEANS_NO)
				return 0;
			break;
		case VB_KEY_ESC:
			VB2_DEBUG("No (0)\n");
			return 0;
		default:
			/*
			 * If the physical presence button is separate from the
			 * keyboard, and is pressed, this is also a YES, but
			 * must wait for release.
			 */
			if (!PHYSICAL_PRESENCE_KEYBOARD) {
				btn = vb2ex_physical_presence_pressed();
				if (btn) {
					VB2_DEBUG("Presence button pressed, "
						  "awaiting release\n");
					button_pressed = 1;
				} else if (button_pressed) {
					VB2_DEBUG("Presence button released "
						  "(1)\n");
					return 1;
				}
			}
			VbCheckDisplayKey(ctx, key, disp_current_screen, NULL);
		}
		vb2ex_msleep(KEY_DELAY_MS);
	} while (!shutdown_requested);

	return -1;
}

/*
 * User interface for selecting alternative firmware
 *
 * This shows the user a list of bootloaders and allows selection of one of
 * them. We loop forever until something is chosen or Escape is pressed.
 */
static vb2_error_t vb2_altfw_ui(struct vb2_context *ctx)
{
	int active = 1;

	VbDisplayScreen(ctx, VB_SCREEN_ALT_FW_PICK, 0, NULL);

	/* We'll loop until the user decides what to do */
	do {
		uint32_t key = VbExKeyboardRead();

		if (vb2_want_shutdown(ctx, key)) {
			VB2_DEBUG("developer UI - shutdown requested!\n");
			return VB2_REQUEST_SHUTDOWN;
		}
		switch (key) {
		case 0:
			/* nothing pressed */
			break;
		case VB_KEY_ESC:
			/* Escape pressed - return to developer screen */
			VB2_DEBUG("developer UI - user pressed Esc; "
				  "exit to Developer screen\n");
			active = 0;
			break;
		/* We allow selection of the default '0' bootloader here */
		case '0'...'9':
			VB2_DEBUG("developer UI - user pressed key '%c';"
				  "Boot alternative firmware\n", key);
			/*
			 * This will not return if successful. Drop out to
			 * developer mode on failure.
			 */
			vb2_try_altfw(ctx, 1, key - '0');
			active = 0;
			break;
		default:
			VB2_DEBUG("developer UI - pressed key %#x\n", key);
			VbCheckDisplayKey(ctx, key, disp_current_screen, NULL);
			break;
		}
		vb2ex_msleep(KEY_DELAY_MS);
	} while (active);

	/* Back to developer screen */
	VbDisplayScreen(ctx, VB_SCREEN_DEVELOPER_WARNING, 0, NULL);

	return 0;
}

static vb2_error_t vb2_developer_ui(struct vb2_context *ctx)
{
	struct vb2_shared_data *sd = vb2_get_sd(ctx);
	struct vb2_gbb_header *gbb = vb2_get_gbb(ctx);

	uint32_t disable_dev_boot = 0;
	uint32_t use_usb = 0;
	uint32_t use_legacy = 0;
	uint32_t ctrl_d_pressed = 0;

	VB2_DEBUG("Entering\n");

	/* Check if USB booting is allowed */
	uint32_t allow_usb = vb2_nv_get(ctx, VB2_NV_DEV_BOOT_USB);
	uint32_t allow_legacy = vb2_nv_get(ctx, VB2_NV_DEV_BOOT_LEGACY);

	/* Check if the default is to boot using disk, usb, or legacy */
	uint32_t default_boot = vb2_nv_get(ctx, VB2_NV_DEV_DEFAULT_BOOT);

	if (default_boot == VB2_DEV_DEFAULT_BOOT_TARGET_USB)
		use_usb = 1;
	if (default_boot == VB2_DEV_DEFAULT_BOOT_TARGET_LEGACY)
		use_legacy = 1;

	/* Handle GBB flag override */
	if (gbb->flags & VB2_GBB_FLAG_FORCE_DEV_BOOT_USB)
		allow_usb = 1;
	if (gbb->flags & VB2_GBB_FLAG_FORCE_DEV_BOOT_LEGACY)
		allow_legacy = 1;
	if (gbb->flags & VB2_GBB_FLAG_DEFAULT_DEV_BOOT_LEGACY) {
		use_legacy = 1;
		use_usb = 0;
	}

	/* Handle FWMP override */
	if (vb2_secdata_fwmp_get_flag(ctx, VB2_SECDATA_FWMP_DEV_ENABLE_USB))
		allow_usb = 1;
	if (vb2_secdata_fwmp_get_flag(ctx, VB2_SECDATA_FWMP_DEV_ENABLE_LEGACY))
		allow_legacy = 1;
	if (vb2_secdata_fwmp_get_flag(ctx, VB2_SECDATA_FWMP_DEV_DISABLE_BOOT)) {
		if (gbb->flags & VB2_GBB_FLAG_FORCE_DEV_SWITCH_ON) {
			VB2_DEBUG("FWMP_DEV_DISABLE_BOOT rejected by "
				  "FORCE_DEV_SWITCH_ON\n");
		} else {
			disable_dev_boot = 1;
		}
	}

	/* If dev mode is disabled, only allow TONORM */
	while (disable_dev_boot) {
		VB2_DEBUG("dev_disable_boot is set\n");
		VbDisplayScreen(ctx,
				VB_SCREEN_DEVELOPER_TO_NORM, 0, NULL);
		VbExDisplayDebugInfo(dev_disable_msg, 0);

		/* Ignore space in VbUserConfirms()... */
		switch (VbUserConfirms(ctx, 0)) {
		case 1:
			VB2_DEBUG("leaving dev-mode\n");
			vb2_nv_set(ctx, VB2_NV_DISABLE_DEV_REQUEST, 1);
			VbDisplayScreen(ctx,
				VB_SCREEN_TO_NORM_CONFIRMED, 0, NULL);
			vb2ex_msleep(5 * VB2_MSEC_PER_SEC);
			return VB2_REQUEST_REBOOT;
		case -1:
			VB2_DEBUG("shutdown requested\n");
			return VB2_REQUEST_SHUTDOWN;
		default:
			/* Ignore user attempt to cancel */
			VB2_DEBUG("ignore cancel TONORM\n");
		}
	}

	if ((ctx->flags & VB2_CONTEXT_VENDOR_DATA_SETTABLE) &&
		VENDOR_DATA_LENGTH > 0) {
		vb2_error_t ret;
		VB2_DEBUG("developer UI - Vendor data not set\n");
		ret = vb2_vendor_data_ui(ctx);
		if (ret)
			return ret;
        }

        /* Show the dev mode warning screen */
        VbDisplayScreen(ctx, VB_SCREEN_DEVELOPER_WARNING, 0, NULL);

	/* Initialize audio/delay context */
	vb2_audio_start(ctx);

	/* We'll loop until we finish the delay or are interrupted */
	do {
		uint32_t key = VbExKeyboardRead();
		if (vb2_want_shutdown(ctx, key)) {
			VB2_DEBUG("developer UI - shutdown requested!\n");
			return VB2_REQUEST_SHUTDOWN;
		}

		switch (key) {
		case 0:
			/* nothing pressed */
			break;
		case VB_KEY_ENTER:
			/* Only disable virtual dev switch if allowed by GBB */
			if (!(gbb->flags & VB2_GBB_FLAG_ENTER_TRIGGERS_TONORM))
				break;
			__attribute__ ((fallthrough));
		case ' ':
			/* See if we should disable virtual dev-mode switch. */
			VB2_DEBUG("sd->flags=%#x\n", sd->flags);

			/* Sanity check, should never fail. */
			VB2_ASSERT(sd->flags & VB2_SD_FLAG_DEV_MODE_ENABLED);

			/* Stop the countdown while we go ask... */
			if (gbb->flags & VB2_GBB_FLAG_FORCE_DEV_SWITCH_ON) {
				/*
				 * TONORM won't work (only for
				 * non-shipping devices).
				 */
				vb2_error_notify(
					"WARNING: TONORM prohibited by "
					"GBB FORCE_DEV_SWITCH_ON.\n",
					NULL, VB_BEEP_NOT_ALLOWED);
				break;
			}
			VbDisplayScreen(ctx, VB_SCREEN_DEVELOPER_TO_NORM,
					0, NULL);
			/* Ignore space in VbUserConfirms()... */
			switch (VbUserConfirms(ctx, 0)) {
			case 1:
				VB2_DEBUG("leaving dev-mode\n");
				vb2_nv_set(ctx, VB2_NV_DISABLE_DEV_REQUEST, 1);
				VbDisplayScreen(ctx,
					VB_SCREEN_TO_NORM_CONFIRMED, 0, NULL);
				vb2ex_msleep(5 * VB2_MSEC_PER_SEC);
				return VB2_REQUEST_REBOOT;
			case -1:
				VB2_DEBUG("shutdown requested\n");
				return VB2_REQUEST_SHUTDOWN;
			default:
				/* Stay in dev-mode */
				VB2_DEBUG("stay in dev-mode\n");
				VbDisplayScreen(ctx,
					VB_SCREEN_DEVELOPER_WARNING, 0, NULL);
				/* Start new countdown */
				vb2_audio_start(ctx);
			}
			break;
		case VB_KEY_CTRL('D'):
			/* Ctrl+D = dismiss warning; advance to timeout */
			VB2_DEBUG("developer UI - user pressed Ctrl+D; "
				  "skip delay\n");
			ctrl_d_pressed = 1;
			goto fallout;
		case VB_KEY_CTRL('L'):
			VB2_DEBUG("developer UI - user pressed Ctrl+L; "
				  "Try alt firmware\n");
			if (allow_legacy) {
				vb2_error_t ret;

				ret = vb2_altfw_ui(ctx);
				if (ret)
					return ret;
			} else {
				vb2_error_no_altfw();
			}
			break;
		case VB_KEY_CTRL_ENTER:
			/*
			 * The Ctrl-Enter is special for Lumpy test purpose;
			 * fall through to Ctrl+U handler.
			 */
		case VB_KEY_CTRL('U'):
			/* Ctrl+U = try USB boot, or beep if failure */
			VB2_DEBUG("developer UI - user pressed Ctrl+U; "
				  "try USB\n");
			if (!allow_usb) {
				vb2_error_notify(
					"WARNING: Booting from external media "
					"(USB/SD) has not been enabled. Refer "
					"to the developer-mode documentation "
					"for details.\n",
					"developer UI - "
					"USB booting is disabled\n",
					VB_BEEP_NOT_ALLOWED);
			} else {
				/*
				 * Clear the screen to show we get the Ctrl+U
				 * key press.
				 */
				VbDisplayScreen(ctx, VB_SCREEN_BLANK, 0, NULL);
				if (VB2_SUCCESS == VbTryUsb(ctx)) {
					return VB2_SUCCESS;
				} else {
					/* Show dev mode warning screen again */
					VbDisplayScreen(ctx,
						VB_SCREEN_DEVELOPER_WARNING,
						0, NULL);
				}
			}
			break;
		/* We allow selection of the default '0' bootloader here */
		case '0'...'9':
			VB2_DEBUG("developer UI - user pressed key '%c'; "
				  "Boot alternative firmware\n", key);
			vb2_try_altfw(ctx, allow_legacy, key - '0');
			break;
		default:
			VB2_DEBUG("developer UI - pressed key %#x\n", key);
			VbCheckDisplayKey(ctx, key, disp_current_screen, NULL);
			break;
		}

		vb2ex_msleep(KEY_DELAY_MS);
	} while(vb2_audio_looping());

 fallout:

	/* If defaulting to legacy boot, try that unless Ctrl+D was pressed */
	if (use_legacy && !ctrl_d_pressed) {
		VB2_DEBUG("developer UI - defaulting to legacy\n");
		vb2_try_altfw(ctx, allow_legacy, 0);
	}

	if ((use_usb && !ctrl_d_pressed) && allow_usb) {
		if (VB2_SUCCESS == VbTryUsb(ctx)) {
			return VB2_SUCCESS;
		}
	}

	/* Timeout or Ctrl+D; attempt loading from fixed disk */
	VB2_DEBUG("developer UI - trying fixed disk\n");
	return VbTryLoadKernel(ctx, VB_DISK_FLAG_FIXED);
}

vb2_error_t VbBootDeveloperLegacyClamshell(struct vb2_context *ctx)
{
	vb2_reset_power_button();
	vb2_error_t retval = vb2_developer_ui(ctx);
	VbDisplayScreen(ctx, VB_SCREEN_BLANK, 0, NULL);
	return retval;
}

vb2_error_t VbBootDiagnosticLegacyClamshell(struct vb2_context *ctx)
{
	vb2_reset_power_button();
	vb2_error_t retval = vb2_diagnostics_ui(ctx);
	VbDisplayScreen(ctx, VB_SCREEN_BLANK, 0, NULL);
	return retval;
}

static vb2_error_t recovery_ui(struct vb2_context *ctx)
{
	struct vb2_shared_data *sd = vb2_get_sd(ctx);
	uint32_t retval;
	uint32_t key;
	const char release_button_msg[] =
		"Release the recovery button and try again\n";
	const char recovery_pressed_msg[] =
		"^D but recovery switch is pressed\n";

	VB2_DEBUG("recovery UI - start\n");

	if (!vb2_allow_recovery(ctx)) {
		VbDisplayScreen(ctx, VB_SCREEN_OS_BROKEN, 0, NULL);
		VB2_DEBUG("recovery UI - waiting for manual recovery\n");
		while (1) {
			key = VbExKeyboardRead();
			VbCheckDisplayKey(ctx, key, disp_current_screen, NULL);
			if (vb2_want_shutdown(ctx, key))
				return VB2_REQUEST_SHUTDOWN;
			else if ((retval =
				  vb2_check_diagnostic_key(ctx, key)) !=
				  VB2_SUCCESS)
				return retval;
			vb2ex_msleep(KEY_DELAY_MS);
		}
	}

	/* Loop and wait for a recovery image */
	VB2_DEBUG("recovery UI - waiting for a recovery image\n");
	while (1) {
		retval = VbTryLoadKernel(ctx, VB_DISK_FLAG_REMOVABLE);

		if (VB2_SUCCESS == retval)
			break; /* Found a recovery kernel */

		enum VbScreenType_t next_screen =
			retval == VB2_ERROR_LK_NO_DISK_FOUND ?
			VB_SCREEN_RECOVERY_INSERT : VB_SCREEN_RECOVERY_NO_GOOD;
		VbDisplayScreen(ctx, next_screen, 0, NULL);

		key = VbExKeyboardRead();
		/*
		 * We might want to enter dev-mode from the Insert
		 * screen if all of the following are true:
		 *   - user pressed Ctrl-D
		 *   - we can honor the virtual dev switch
		 *   - not already in dev mode
		 *   - user forced recovery mode
		 */
		if (key == VB_KEY_CTRL('D') &&
		    !(sd->flags & VB2_SD_FLAG_DEV_MODE_ENABLED) &&
		    (sd->flags & VB2_SD_FLAG_MANUAL_RECOVERY)) {
			if (!PHYSICAL_PRESENCE_KEYBOARD &&
			    vb2ex_physical_presence_pressed()) {
				/*
				 * Is the presence button stuck?  In any case
				 * we don't like this.  Beep and ignore.
				 */
				vb2_error_notify(release_button_msg,
						 recovery_pressed_msg,
						 VB_BEEP_NOT_ALLOWED);
				continue;
			}

			/* Ask the user to confirm entering dev-mode */
			VbDisplayScreen(ctx, VB_SCREEN_RECOVERY_TO_DEV,
					0, NULL);
			/* SPACE means no... */
			uint32_t vbc_flags = VB_CONFIRM_SPACE_MEANS_NO |
					     VB_CONFIRM_MUST_TRUST_KEYBOARD;
			switch (VbUserConfirms(ctx, vbc_flags)) {
			case 1:
				vb2_enable_developer_mode(ctx);
				return VB2_REQUEST_REBOOT_EC_TO_RO;
			case -1:
				VB2_DEBUG("Shutdown requested\n");
				return VB2_REQUEST_SHUTDOWN;
			default: /* zero, actually */
				VB2_DEBUG("Not enabling dev-mode\n");
				break;
			}
		} else if ((retval = vb2_check_diagnostic_key(ctx, key)) !=
			   VB2_SUCCESS) {
			return retval;
		} else {
			VbCheckDisplayKey(ctx, key, disp_current_screen, NULL);
		}
		if (vb2_want_shutdown(ctx, key))
			return VB2_REQUEST_SHUTDOWN;
		vb2ex_msleep(KEY_DELAY_MS);
	}

	return VB2_SUCCESS;
}

vb2_error_t VbBootRecoveryLegacyClamshell(struct vb2_context *ctx)
{
	vb2_error_t retval = recovery_ui(ctx);
	VbDisplayScreen(ctx, VB_SCREEN_BLANK, 0, NULL);
	return retval;
}
