// SPDX-License-Identifier: GPL-2.0
/*
 * Copyright (C) 2016 Linaro Ltd. <ard.biesheuvel@linaro.org>
 */

#define pr_fmt(fmt)	"efi: memattr: " fmt

#include <linux/efi.h>
#include <linux/init.h>
#include <linux/io.h>
#include <linux/memblock.h>

#include <asm/early_ioremap.h>

static int __initdata tbl_size;
unsigned long __ro_after_init efi_mem_attr_table = EFI_INVALID_TABLE_ADDR;

/*
 * Reserve the memory associated with the Memory Attributes configuration
 * table, if it exists.
 */
int __init efi_memattr_init(void)
{
	efi_memory_attributes_table_t *tbl;

	if (efi_mem_attr_table == EFI_INVALID_TABLE_ADDR)
		return 0;

	tbl = early_memremap(efi_mem_attr_table, sizeof(*tbl));
	if (!tbl) {
		pr_err("Failed to map EFI Memory Attributes table @ 0x%lx\n",
		       efi_mem_attr_table);
		return -ENOMEM;
	}

	if (tbl->version > 1) {
		pr_warn("Unexpected EFI Memory Attributes table version %d\n",
			tbl->version);
		goto unmap;
	}

	tbl_size = sizeof(*tbl) + tbl->num_entries * tbl->desc_size;
	memblock_reserve(efi_mem_attr_table, tbl_size);
	set_bit(EFI_MEM_ATTR, &efi.flags);

unmap:
	early_memunmap(tbl, sizeof(*tbl));
	return 0;
}

/*
 * Returns a copy @out of the UEFI memory descriptor @in if it is covered
 * entirely by a UEFI memory map entry with matching attributes. The virtual
 * address of @out is set according to the matching entry that was found.
 */
static bool entry_is_valid(const efi_memory_desc_t *in, efi_memory_desc_t *out)
{
	u64 in_paddr = in->phys_addr;
	u64 in_size = in->num_pages << EFI_PAGE_SHIFT;
	efi_memory_desc_t *md;

	*out = *in;

	if (in->type != EFI_RUNTIME_SERVICES_CODE &&
	    in->type != EFI_RUNTIME_SERVICES_DATA) {
		pr_warn("Entry type should be RuntimeServiceCode/Data\n");
		return false;
	}

	if (PAGE_SIZE > EFI_PAGE_SIZE &&
	    (!PAGE_ALIGNED(in->phys_addr) ||
	     !PAGE_ALIGNED(in->num_pages << EFI_PAGE_SHIFT))) {
		/*
		 * Since arm64 may execute with page sizes of up to 64 KB, the
		 * UEFI spec mandates that RuntimeServices memory regions must
		 * be 64 KB aligned. We need to validate this here since we will
		 * not be able to tighten permissions on such regions without
		 * affecting adjacent regions.
		 */
		pr_warn("Entry address region misaligned\n");
		return false;
	}

	for_each_efi_memory_desc(md) {
		u64 md_paddr = md->phys_addr;
		u64 md_size = md->num_pages << EFI_PAGE_SHIFT;

		if (!(md->attribute & EFI_MEMORY_RUNTIME))
			continue;
		if (md->virt_addr == 0 && md->phys_addr != 0) {
			/* no virtual mapping has been installed by the stub */
			break;
		}

		if (md_paddr > in_paddr || (in_paddr - md_paddr) >= md_size)
			continue;

		/*
		 * This entry covers the start of @in, check whether
		 * it covers the end as well.
		 */
		if (md_paddr + md_size < in_paddr + in_size) {
			pr_warn("Entry covers multiple EFI memory map regions\n");
			return false;
		}

		if (md->type != in->type) {
			pr_warn("Entry type deviates from EFI memory map region type\n");
			return false;
		}

		out->virt_addr = in_paddr + (md->virt_addr - md_paddr);

		return true;
	}

	pr_warn("No matching entry found in the EFI memory map\n");
	return false;
}

/*
 * To be called after the EFI page tables have been populated. If a memory
 * attributes table is available, its contents will be used to update the
 * mappings with tightened permissions as described by the table.
 * This requires the UEFI memory map to have already been populated with
 * virtual addresses.
 */
int __init efi_memattr_apply_permissions(struct mm_struct *mm,
					 efi_memattr_perm_setter fn)
{
	efi_memory_attributes_table_t *tbl;
	int i, ret;

	if (tbl_size <= sizeof(*tbl))
		return 0;

	/*
	 * We need the EFI memory map to be setup so we can use it to
	 * lookup the virtual addresses of all entries in the  of EFI
	 * Memory Attributes table. If it isn't available, this
	 * function should not be called.
	 */
	if (WARN_ON(!efi_enabled(EFI_MEMMAP)))
		return 0;

	tbl = memremap(efi_mem_attr_table, tbl_size, MEMREMAP_WB);
	if (!tbl) {
		pr_err("Failed to map EFI Memory Attributes table @ 0x%lx\n",
		       efi_mem_attr_table);
		return -ENOMEM;
	}

	if (efi_enabled(EFI_DBG))
		pr_info("Processing EFI Memory Attributes table:\n");

	for (i = ret = 0; ret == 0 && i < tbl->num_entries; i++) {
		efi_memory_desc_t md;
		unsigned long size;
		bool valid;
		char buf[64];

		valid = entry_is_valid((void *)tbl->entry + i * tbl->desc_size,
				       &md);
		size = md.num_pages << EFI_PAGE_SHIFT;
		if (efi_enabled(EFI_DBG) || !valid)
			pr_info("%s 0x%012llx-0x%012llx %s\n",
				valid ? "" : "!", md.phys_addr,
				md.phys_addr + size - 1,
				efi_md_typeattr_format(buf, sizeof(buf), &md));

		if (valid) {
			ret = fn(mm, &md);
			if (ret)
				pr_err("Error updating mappings, skipping subsequent md's\n");
		}
	}
	memunmap(tbl);
	return ret;
}
