// SPDX-License-Identifier: GPL-2.0-only

#include <linux/efi.h>
#include <asm/efi.h>
#include "efistub.h"

struct efi_unaccepted_memory *unaccepted_table;

efi_status_t allocate_unaccepted_bitmap(__u32 nr_desc,
					struct efi_boot_memmap *map)
{
	efi_guid_t unaccepted_table_guid = LINUX_EFI_UNACCEPTED_MEM_TABLE_GUID;
	u64 unaccepted_start = ULLONG_MAX, unaccepted_end = 0, bitmap_size;
	efi_status_t status;
	int i;

	/* Check if the table is already installed */
	unaccepted_table = get_efi_config_table(unaccepted_table_guid);
	if (unaccepted_table) {
		if (unaccepted_table->version != 1) {
			efi_err("Unknown version of unaccepted memory table\n");
			return EFI_UNSUPPORTED;
		}
		return EFI_SUCCESS;
	}

	/* Check if there's any unaccepted memory and find the max address */
	for (i = 0; i < nr_desc; i++) {
		efi_memory_desc_t *d;
		unsigned long m = (unsigned long)map->map;

		d = efi_memdesc_ptr(m, map->desc_size, i);
		if (d->type != EFI_UNACCEPTED_MEMORY)
			continue;

		unaccepted_start = min(unaccepted_start, d->phys_addr);
		unaccepted_end = max(unaccepted_end,
				     d->phys_addr + d->num_pages * PAGE_SIZE);
	}

	if (unaccepted_start == ULLONG_MAX)
		return EFI_SUCCESS;

	unaccepted_start = round_down(unaccepted_start,
				      EFI_UNACCEPTED_UNIT_SIZE);
	unaccepted_end = round_up(unaccepted_end, EFI_UNACCEPTED_UNIT_SIZE);

	/*
	 * If unaccepted memory is present, allocate a bitmap to track what
	 * memory has to be accepted before access.
	 *
	 * One bit in the bitmap represents 2MiB in the address space:
	 * A 4k bitmap can track 64GiB of physical address space.
	 *
	 * In the worst case scenario -- a huge hole in the middle of the
	 * address space -- It needs 256MiB to handle 4PiB of the address
	 * space.
	 *
	 * The bitmap will be populated in setup_e820() according to the memory
	 * map after efi_exit_boot_services().
	 */
	bitmap_size = DIV_ROUND_UP(unaccepted_end - unaccepted_start,
				   EFI_UNACCEPTED_UNIT_SIZE * BITS_PER_BYTE);

	status = efi_bs_call(allocate_pool, EFI_ACPI_RECLAIM_MEMORY,
			     sizeof(*unaccepted_table) + bitmap_size,
			     (void **)&unaccepted_table);
	if (status != EFI_SUCCESS) {
		efi_err("Failed to allocate unaccepted memory config table\n");
		return status;
	}

	unaccepted_table->version = 1;
	unaccepted_table->unit_size = EFI_UNACCEPTED_UNIT_SIZE;
	unaccepted_table->phys_base = unaccepted_start;
	unaccepted_table->size = bitmap_size;
	memset(unaccepted_table->bitmap, 0, bitmap_size);

	status = efi_bs_call(install_configuration_table,
			     &unaccepted_table_guid, unaccepted_table);
	if (status != EFI_SUCCESS) {
		efi_bs_call(free_pool, unaccepted_table);
		efi_err("Failed to install unaccepted memory config table!\n");
	}

	return status;
}

/*
 * The accepted memory bitmap only works at unit_size granularity.  Take
 * unaligned start/end addresses and either:
 *  1. Accepts the memory immediately and in its entirety
 *  2. Accepts unaligned parts, and marks *some* aligned part unaccepted
 *
 * The function will never reach the bitmap_set() with zero bits to set.
 */
void process_unaccepted_memory(u64 start, u64 end)
{
	u64 unit_size = unaccepted_table->unit_size;
	u64 unit_mask = unaccepted_table->unit_size - 1;
	u64 bitmap_size = unaccepted_table->size;

	/*
	 * Ensure that at least one bit will be set in the bitmap by
	 * immediately accepting all regions under 2*unit_size.  This is
	 * imprecise and may immediately accept some areas that could
	 * have been represented in the bitmap.  But, results in simpler
	 * code below
	 *
	 * Consider case like this (assuming unit_size == 2MB):
	 *
	 * | 4k | 2044k |    2048k   |
	 * ^ 0x0        ^ 2MB        ^ 4MB
	 *
	 * Only the first 4k has been accepted. The 0MB->2MB region can not be
	 * represented in the bitmap. The 2MB->4MB region can be represented in
	 * the bitmap. But, the 0MB->4MB region is <2*unit_size and will be
	 * immediately accepted in its entirety.
	 */
	if (end - start < 2 * unit_size) {
		arch_accept_memory(start, end);
		return;
	}

	/*
	 * No matter how the start and end are aligned, at least one unaccepted
	 * unit_size area will remain to be marked in the bitmap.
	 */

	/* Immediately accept a <unit_size piece at the start: */
	if (start & unit_mask) {
		arch_accept_memory(start, round_up(start, unit_size));
		start = round_up(start, unit_size);
	}

	/* Immediately accept a <unit_size piece at the end: */
	if (end & unit_mask) {
		arch_accept_memory(round_down(end, unit_size), end);
		end = round_down(end, unit_size);
	}

	/*
	 * Accept part of the range that before phys_base and cannot be recorded
	 * into the bitmap.
	 */
	if (start < unaccepted_table->phys_base) {
		arch_accept_memory(start,
				   min(unaccepted_table->phys_base, end));
		start = unaccepted_table->phys_base;
	}

	/* Nothing to record */
	if (end < unaccepted_table->phys_base)
		return;

	/* Translate to offsets from the beginning of the bitmap */
	start -= unaccepted_table->phys_base;
	end -= unaccepted_table->phys_base;

	/* Accept memory that doesn't fit into bitmap */
	if (end > bitmap_size * unit_size * BITS_PER_BYTE) {
		unsigned long phys_start, phys_end;

		phys_start = bitmap_size * unit_size * BITS_PER_BYTE +
			     unaccepted_table->phys_base;
		phys_end = end + unaccepted_table->phys_base;

		arch_accept_memory(phys_start, phys_end);
		end = bitmap_size * unit_size * BITS_PER_BYTE;
	}

	/*
	 * 'start' and 'end' are now both unit_size-aligned.
	 * Record the range as being unaccepted:
	 */
	bitmap_set(unaccepted_table->bitmap,
		   start / unit_size, (end - start) / unit_size);
}

void accept_memory(phys_addr_t start, unsigned long size)
{
	unsigned long range_start, range_end;
	phys_addr_t end = start + size;
	unsigned long bitmap_size;
	u64 unit_size;

	if (!unaccepted_table)
		return;

	unit_size = unaccepted_table->unit_size;

	/*
	 * Only care for the part of the range that is represented
	 * in the bitmap.
	 */
	if (start < unaccepted_table->phys_base)
		start = unaccepted_table->phys_base;
	if (end < unaccepted_table->phys_base)
		return;

	/* Translate to offsets from the beginning of the bitmap */
	start -= unaccepted_table->phys_base;
	end -= unaccepted_table->phys_base;

	/* Make sure not to overrun the bitmap */
	if (end > unaccepted_table->size * unit_size * BITS_PER_BYTE)
		end = unaccepted_table->size * unit_size * BITS_PER_BYTE;

	range_start = start / unit_size;
	bitmap_size = DIV_ROUND_UP(end, unit_size);

	for_each_set_bitrange_from(range_start, range_end,
				   unaccepted_table->bitmap, bitmap_size) {
		unsigned long phys_start, phys_end;

		phys_start = range_start * unit_size + unaccepted_table->phys_base;
		phys_end = range_end * unit_size + unaccepted_table->phys_base;

		arch_accept_memory(phys_start, phys_end);
		bitmap_clear(unaccepted_table->bitmap,
			     range_start, range_end - range_start);
	}
}
