// SPDX-License-Identifier: GPL-2.0
/*
 * Helpers for early access to EFI configuration table.
 *
 * Originally derived from arch/x86/boot/compressed/acpi.c
 */

#include "misc.h"

#include <asm/bootparam.h>

/**
 * efi_get_type - Given a pointer to boot_params, determine the type of EFI environment.
 *
 * @bp:         pointer to boot_params
 *
 * Return: EFI_TYPE_{32,64} for valid EFI environments, EFI_TYPE_NONE otherwise.
 */
enum efi_type efi_get_type(struct boot_params *bp)
{
	struct efi_info *ei;
	enum efi_type et;
	const char *sig;

	ei = &bp->efi_info;
	sig = (char *)&ei->efi_loader_signature;

	if (!strncmp(sig, EFI64_LOADER_SIGNATURE, 4)) {
		et = EFI_TYPE_64;
	} else if (!strncmp(sig, EFI32_LOADER_SIGNATURE, 4)) {
		et = EFI_TYPE_32;
	} else {
		debug_putstr("No EFI environment detected.\n");
		et = EFI_TYPE_NONE;
	}

#ifndef CONFIG_X86_64
	/*
	 * Existing callers like acpi.c treat this case as an indicator to
	 * fall-through to non-EFI, rather than an error, so maintain that
	 * functionality here as well.
	 */
	if (ei->efi_systab_hi || ei->efi_memmap_hi) {
		debug_putstr("EFI system table is located above 4GB and cannot be accessed.\n");
		et = EFI_TYPE_NONE;
	}
#endif

	return et;
}

/**
 * efi_get_system_table - Given a pointer to boot_params, retrieve the physical address
 *                        of the EFI system table.
 *
 * @bp:         pointer to boot_params
 *
 * Return: EFI system table address on success. On error, return 0.
 */
unsigned long efi_get_system_table(struct boot_params *bp)
{
	unsigned long sys_tbl_pa;
	struct efi_info *ei;
	enum efi_type et;

	/* Get systab from boot params. */
	ei = &bp->efi_info;
#ifdef CONFIG_X86_64
	sys_tbl_pa = ei->efi_systab | ((__u64)ei->efi_systab_hi << 32);
#else
	sys_tbl_pa = ei->efi_systab;
#endif
	if (!sys_tbl_pa) {
		debug_putstr("EFI system table not found.");
		return 0;
	}

	return sys_tbl_pa;
}

/*
 * EFI config table address changes to virtual address after boot, which may
 * not be accessible for the kexec'd kernel. To address this, kexec provides
 * the initial physical address via a struct setup_data entry, which is
 * checked for here, along with some sanity checks.
 */
static struct efi_setup_data *get_kexec_setup_data(struct boot_params *bp,
						   enum efi_type et)
{
#ifdef CONFIG_X86_64
	struct efi_setup_data *esd = NULL;
	struct setup_data *data;
	u64 pa_data;

	pa_data = bp->hdr.setup_data;
	while (pa_data) {
		data = (struct setup_data *)pa_data;
		if (data->type == SETUP_EFI) {
			esd = (struct efi_setup_data *)(pa_data + sizeof(struct setup_data));
			break;
		}

		pa_data = data->next;
	}

	/*
	 * Original ACPI code falls back to attempting normal EFI boot in these
	 * cases, so maintain existing behavior by indicating non-kexec
	 * environment to the caller, but print them for debugging.
	 */
	if (esd && !esd->tables) {
		debug_putstr("kexec EFI environment missing valid configuration table.\n");
		return NULL;
	}

	return esd;
#endif
	return NULL;
}

/**
 * efi_get_conf_table - Given a pointer to boot_params, locate and return the physical
 *                      address of EFI configuration table.
 *
 * @bp:                 pointer to boot_params
 * @cfg_tbl_pa:         location to store physical address of config table
 * @cfg_tbl_len:        location to store number of config table entries
 *
 * Return: 0 on success. On error, return params are left unchanged.
 */
int efi_get_conf_table(struct boot_params *bp, unsigned long *cfg_tbl_pa,
		       unsigned int *cfg_tbl_len)
{
	unsigned long sys_tbl_pa;
	enum efi_type et;
	int ret;

	if (!cfg_tbl_pa || !cfg_tbl_len)
		return -EINVAL;

	sys_tbl_pa = efi_get_system_table(bp);
	if (!sys_tbl_pa)
		return -EINVAL;

	/* Handle EFI bitness properly */
	et = efi_get_type(bp);
	if (et == EFI_TYPE_64) {
		efi_system_table_64_t *stbl = (efi_system_table_64_t *)sys_tbl_pa;
		struct efi_setup_data *esd;

		/* kexec provides an alternative EFI conf table, check for it. */
		esd = get_kexec_setup_data(bp, et);

		*cfg_tbl_pa = esd ? esd->tables : stbl->tables;
		*cfg_tbl_len = stbl->nr_tables;
	} else if (et == EFI_TYPE_32) {
		efi_system_table_32_t *stbl = (efi_system_table_32_t *)sys_tbl_pa;

		*cfg_tbl_pa = stbl->tables;
		*cfg_tbl_len = stbl->nr_tables;
	} else {
		return -EINVAL;
	}

	return 0;
}

/* Get vendor table address/guid from EFI config table at the given index */
static int get_vendor_table(void *cfg_tbl, unsigned int idx,
			    unsigned long *vendor_tbl_pa,
			    efi_guid_t *vendor_tbl_guid,
			    enum efi_type et)
{
	if (et == EFI_TYPE_64) {
		efi_config_table_64_t *tbl_entry = (efi_config_table_64_t *)cfg_tbl + idx;

		if (!IS_ENABLED(CONFIG_X86_64) && tbl_entry->table >> 32) {
			debug_putstr("Error: EFI config table entry located above 4GB.\n");
			return -EINVAL;
		}

		*vendor_tbl_pa = tbl_entry->table;
		*vendor_tbl_guid = tbl_entry->guid;

	} else if (et == EFI_TYPE_32) {
		efi_config_table_32_t *tbl_entry = (efi_config_table_32_t *)cfg_tbl + idx;

		*vendor_tbl_pa = tbl_entry->table;
		*vendor_tbl_guid = tbl_entry->guid;
	} else {
		return -EINVAL;
	}

	return 0;
}

/**
 * efi_find_vendor_table - Given EFI config table, search it for the physical
 *                         address of the vendor table associated with GUID.
 *
 * @bp:                pointer to boot_params
 * @cfg_tbl_pa:        pointer to EFI configuration table
 * @cfg_tbl_len:       number of entries in EFI configuration table
 * @guid:              GUID of vendor table
 *
 * Return: vendor table address on success. On error, return 0.
 */
unsigned long efi_find_vendor_table(struct boot_params *bp,
				    unsigned long cfg_tbl_pa,
				    unsigned int cfg_tbl_len,
				    efi_guid_t guid)
{
	enum efi_type et;
	unsigned int i;

	et = efi_get_type(bp);
	if (et == EFI_TYPE_NONE)
		return 0;

	for (i = 0; i < cfg_tbl_len; i++) {
		unsigned long vendor_tbl_pa;
		efi_guid_t vendor_tbl_guid;
		int ret;

		ret = get_vendor_table((void *)cfg_tbl_pa, i,
				       &vendor_tbl_pa,
				       &vendor_tbl_guid, et);
		if (ret)
			return 0;

		if (!efi_guidcmp(guid, vendor_tbl_guid))
			return vendor_tbl_pa;
	}

	return 0;
}
