/*
 * Copyright (c) 2014 Oracle Co., Daniel Kiper
 *
 * 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, see <http://www.gnu.org/licenses/>.
 */

#include <linux/bitops.h>
#include <linux/efi.h>
#include <linux/init.h>
#include <linux/string.h>

#include <xen/xen.h>
#include <xen/xen-ops.h>
#include <xen/interface/platform.h>

#include <asm/page.h>
#include <asm/setup.h>
#include <asm/xen/hypercall.h>

static efi_char16_t vendor[100] __initdata;

static efi_system_table_t efi_systab_xen __initdata = {
	.hdr = {
		.signature	= EFI_SYSTEM_TABLE_SIGNATURE,
		.revision	= 0, /* Initialized later. */
		.headersize	= 0, /* Ignored by Linux Kernel. */
		.crc32		= 0, /* Ignored by Linux Kernel. */
		.reserved	= 0
	},
	.fw_vendor	= EFI_INVALID_TABLE_ADDR, /* Initialized later. */
	.fw_revision	= 0,			  /* Initialized later. */
	.con_in_handle	= EFI_INVALID_TABLE_ADDR, /* Not used under Xen. */
	.con_in		= EFI_INVALID_TABLE_ADDR, /* Not used under Xen. */
	.con_out_handle	= EFI_INVALID_TABLE_ADDR, /* Not used under Xen. */
	.con_out	= EFI_INVALID_TABLE_ADDR, /* Not used under Xen. */
	.stderr_handle	= EFI_INVALID_TABLE_ADDR, /* Not used under Xen. */
	.stderr		= EFI_INVALID_TABLE_ADDR, /* Not used under Xen. */
	.runtime	= (efi_runtime_services_t *)EFI_INVALID_TABLE_ADDR,
						  /* Not used under Xen. */
	.boottime	= (efi_boot_services_t *)EFI_INVALID_TABLE_ADDR,
						  /* Not used under Xen. */
	.nr_tables	= 0,			  /* Initialized later. */
	.tables		= EFI_INVALID_TABLE_ADDR  /* Initialized later. */
};

static efi_system_table_t __init *xen_efi_probe(void)
{
	struct xen_platform_op op = {
		.cmd = XENPF_firmware_info,
		.u.firmware_info = {
			.type = XEN_FW_EFI_INFO,
			.index = XEN_FW_EFI_CONFIG_TABLE
		}
	};
	union xenpf_efi_info *info = &op.u.firmware_info.u.efi_info;

	if (!xen_initial_domain() || HYPERVISOR_platform_op(&op) < 0)
		return NULL;

	/* Here we know that Xen runs on EFI platform. */

	efi.get_time                 = xen_efi_get_time;
	efi.set_time                 = xen_efi_set_time;
	efi.get_wakeup_time          = xen_efi_get_wakeup_time;
	efi.set_wakeup_time          = xen_efi_set_wakeup_time;
	efi.get_variable             = xen_efi_get_variable;
	efi.get_next_variable        = xen_efi_get_next_variable;
	efi.set_variable             = xen_efi_set_variable;
	efi.set_variable_nonblocking = xen_efi_set_variable;
	efi.query_variable_info      = xen_efi_query_variable_info;
	efi.query_variable_info_nonblocking = xen_efi_query_variable_info;
	efi.update_capsule           = xen_efi_update_capsule;
	efi.query_capsule_caps       = xen_efi_query_capsule_caps;
	efi.get_next_high_mono_count = xen_efi_get_next_high_mono_count;
	efi.reset_system             = xen_efi_reset_system;

	efi_systab_xen.tables = info->cfg.addr;
	efi_systab_xen.nr_tables = info->cfg.nent;

	op.cmd = XENPF_firmware_info;
	op.u.firmware_info.type = XEN_FW_EFI_INFO;
	op.u.firmware_info.index = XEN_FW_EFI_VENDOR;
	info->vendor.bufsz = sizeof(vendor);
	set_xen_guest_handle(info->vendor.name, vendor);

	if (HYPERVISOR_platform_op(&op) == 0) {
		efi_systab_xen.fw_vendor = __pa_symbol(vendor);
		efi_systab_xen.fw_revision = info->vendor.revision;
	} else
		efi_systab_xen.fw_vendor = __pa_symbol(L"UNKNOWN");

	op.cmd = XENPF_firmware_info;
	op.u.firmware_info.type = XEN_FW_EFI_INFO;
	op.u.firmware_info.index = XEN_FW_EFI_VERSION;

	if (HYPERVISOR_platform_op(&op) == 0)
		efi_systab_xen.hdr.revision = info->version;

	op.cmd = XENPF_firmware_info;
	op.u.firmware_info.type = XEN_FW_EFI_INFO;
	op.u.firmware_info.index = XEN_FW_EFI_RT_VERSION;

	if (HYPERVISOR_platform_op(&op) == 0)
		efi.runtime_version = info->version;

	return &efi_systab_xen;
}

/*
 * Determine whether we're in secure boot mode.
 *
 * Please keep the logic in sync with
 * drivers/firmware/efi/libstub/secureboot.c:efi_get_secureboot().
 */
static enum efi_secureboot_mode xen_efi_get_secureboot(void)
{
	static efi_guid_t efi_variable_guid = EFI_GLOBAL_VARIABLE_GUID;
	static efi_guid_t shim_guid = EFI_SHIM_LOCK_GUID;
	efi_status_t status;
	u8 moksbstate, secboot, setupmode;
	unsigned long size;

	size = sizeof(secboot);
	status = efi.get_variable(L"SecureBoot", &efi_variable_guid,
				  NULL, &size, &secboot);

	if (status == EFI_NOT_FOUND)
		return efi_secureboot_mode_disabled;

	if (status != EFI_SUCCESS)
		goto out_efi_err;

	size = sizeof(setupmode);
	status = efi.get_variable(L"SetupMode", &efi_variable_guid,
				  NULL, &size, &setupmode);

	if (status != EFI_SUCCESS)
		goto out_efi_err;

	if (secboot == 0 || setupmode == 1)
		return efi_secureboot_mode_disabled;

	/* See if a user has put the shim into insecure mode. */
	size = sizeof(moksbstate);
	status = efi.get_variable(L"MokSBStateRT", &shim_guid,
				  NULL, &size, &moksbstate);

	/* If it fails, we don't care why. Default to secure. */
	if (status != EFI_SUCCESS)
		goto secure_boot_enabled;

	if (moksbstate == 1)
		return efi_secureboot_mode_disabled;

 secure_boot_enabled:
	pr_info("UEFI Secure Boot is enabled.\n");
	return efi_secureboot_mode_enabled;

 out_efi_err:
	pr_err("Could not determine UEFI Secure Boot status.\n");
	return efi_secureboot_mode_unknown;
}

void __init xen_efi_init(void)
{
	efi_system_table_t *efi_systab_xen;

	efi_systab_xen = xen_efi_probe();

	if (efi_systab_xen == NULL)
		return;

	strncpy((char *)&boot_params.efi_info.efi_loader_signature, "Xen",
			sizeof(boot_params.efi_info.efi_loader_signature));
	boot_params.efi_info.efi_systab = (__u32)__pa(efi_systab_xen);
	boot_params.efi_info.efi_systab_hi = (__u32)(__pa(efi_systab_xen) >> 32);

	boot_params.secure_boot = xen_efi_get_secureboot();

	set_bit(EFI_BOOT, &efi.flags);
	set_bit(EFI_PARAVIRT, &efi.flags);
	set_bit(EFI_64BIT, &efi.flags);
}
