// SPDX-License-Identifier: GPL-2.0
#define BOOT_CTYPE_H
#include "misc.h"
#include "error.h"
#include "../string.h"
#include "efi.h"

#include <asm/bootparam.h>

#include <linux/numa.h>

/*
 * Longest parameter of 'acpi=' is 'copy_dsdt', plus an extra '\0'
 * for termination.
 */
#define MAX_ACPI_ARG_LENGTH 10

/*
 * Immovable memory regions representation. Max amount of memory regions is
 * MAX_NUMNODES*2.
 */
struct mem_vector immovable_mem[MAX_NUMNODES*2];

static acpi_physical_address
__efi_get_rsdp_addr(unsigned long cfg_tbl_pa, unsigned int cfg_tbl_len)
{
#ifdef CONFIG_EFI
	unsigned long rsdp_addr;
	int ret;

	/*
	 * Search EFI system tables for RSDP. Preferred is ACPI_20_TABLE_GUID to
	 * ACPI_TABLE_GUID because it has more features.
	 */
	rsdp_addr = efi_find_vendor_table(boot_params_ptr, cfg_tbl_pa, cfg_tbl_len,
					  ACPI_20_TABLE_GUID);
	if (rsdp_addr)
		return (acpi_physical_address)rsdp_addr;

	/* No ACPI_20_TABLE_GUID found, fallback to ACPI_TABLE_GUID. */
	rsdp_addr = efi_find_vendor_table(boot_params_ptr, cfg_tbl_pa, cfg_tbl_len,
					  ACPI_TABLE_GUID);
	if (rsdp_addr)
		return (acpi_physical_address)rsdp_addr;

	debug_putstr("Error getting RSDP address.\n");
#endif
	return 0;
}

static acpi_physical_address efi_get_rsdp_addr(void)
{
#ifdef CONFIG_EFI
	unsigned long cfg_tbl_pa = 0;
	unsigned int cfg_tbl_len;
	unsigned long systab_pa;
	unsigned int nr_tables;
	enum efi_type et;
	int ret;

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

	systab_pa = efi_get_system_table(boot_params_ptr);
	if (!systab_pa)
		error("EFI support advertised, but unable to locate system table.");

	ret = efi_get_conf_table(boot_params_ptr, &cfg_tbl_pa, &cfg_tbl_len);
	if (ret || !cfg_tbl_pa)
		error("EFI config table not found.");

	return __efi_get_rsdp_addr(cfg_tbl_pa, cfg_tbl_len);
#else
	return 0;
#endif
}

static u8 compute_checksum(u8 *buffer, u32 length)
{
	u8 *end = buffer + length;
	u8 sum = 0;

	while (buffer < end)
		sum += *(buffer++);

	return sum;
}

/* Search a block of memory for the RSDP signature. */
static u8 *scan_mem_for_rsdp(u8 *start, u32 length)
{
	struct acpi_table_rsdp *rsdp;
	u8 *address, *end;

	end = start + length;

	/* Search from given start address for the requested length */
	for (address = start; address < end; address += ACPI_RSDP_SCAN_STEP) {
		/*
		 * Both RSDP signature and checksum must be correct.
		 * Note: Sometimes there exists more than one RSDP in memory;
		 * the valid RSDP has a valid checksum, all others have an
		 * invalid checksum.
		 */
		rsdp = (struct acpi_table_rsdp *)address;

		/* BAD Signature */
		if (!ACPI_VALIDATE_RSDP_SIG(rsdp->signature))
			continue;

		/* Check the standard checksum */
		if (compute_checksum((u8 *)rsdp, ACPI_RSDP_CHECKSUM_LENGTH))
			continue;

		/* Check extended checksum if table version >= 2 */
		if ((rsdp->revision >= 2) &&
		    (compute_checksum((u8 *)rsdp, ACPI_RSDP_XCHECKSUM_LENGTH)))
			continue;

		/* Signature and checksum valid, we have found a real RSDP */
		return address;
	}
	return NULL;
}

/* Search RSDP address in EBDA. */
static acpi_physical_address bios_get_rsdp_addr(void)
{
	unsigned long address;
	u8 *rsdp;

	/* Get the location of the Extended BIOS Data Area (EBDA) */
	address = *(u16 *)ACPI_EBDA_PTR_LOCATION;
	address <<= 4;

	/*
	 * Search EBDA paragraphs (EBDA is required to be a minimum of
	 * 1K length)
	 */
	if (address > 0x400) {
		rsdp = scan_mem_for_rsdp((u8 *)address, ACPI_EBDA_WINDOW_SIZE);
		if (rsdp)
			return (acpi_physical_address)(unsigned long)rsdp;
	}

	/* Search upper memory: 16-byte boundaries in E0000h-FFFFFh */
	rsdp = scan_mem_for_rsdp((u8 *) ACPI_HI_RSDP_WINDOW_BASE,
					ACPI_HI_RSDP_WINDOW_SIZE);
	if (rsdp)
		return (acpi_physical_address)(unsigned long)rsdp;

	return 0;
}

/* Return RSDP address on success, otherwise 0. */
acpi_physical_address get_rsdp_addr(void)
{
	acpi_physical_address pa;

	pa = boot_params_ptr->acpi_rsdp_addr;

	if (!pa)
		pa = efi_get_rsdp_addr();

	if (!pa)
		pa = bios_get_rsdp_addr();

	return pa;
}

#if defined(CONFIG_RANDOMIZE_BASE) && defined(CONFIG_MEMORY_HOTREMOVE)
/*
 * Max length of 64-bit hex address string is 19, prefix "0x" + 16 hex
 * digits, and '\0' for termination.
 */
#define MAX_ADDR_LEN 19

static unsigned long get_cmdline_acpi_rsdp(void)
{
	unsigned long addr = 0;

#ifdef CONFIG_KEXEC_CORE
	char val[MAX_ADDR_LEN] = { };
	int ret;

	ret = cmdline_find_option("acpi_rsdp", val, MAX_ADDR_LEN);
	if (ret < 0)
		return 0;

	if (boot_kstrtoul(val, 16, &addr))
		return 0;
#endif
	return addr;
}

/* Compute SRAT address from RSDP. */
static unsigned long get_acpi_srat_table(void)
{
	unsigned long root_table, acpi_table;
	struct acpi_table_header *header;
	struct acpi_table_rsdp *rsdp;
	u32 num_entries, size, len;
	char arg[10];
	u8 *entry;

	/*
	 * Check whether we were given an RSDP on the command line. We don't
	 * stash this in boot params because the kernel itself may have
	 * different ideas about whether to trust a command-line parameter.
	 */
	rsdp = (struct acpi_table_rsdp *)get_cmdline_acpi_rsdp();
	if (!rsdp)
		rsdp = (struct acpi_table_rsdp *)(long)
			boot_params_ptr->acpi_rsdp_addr;

	if (!rsdp)
		return 0;

	/* Get ACPI root table from RSDP.*/
	if (!(cmdline_find_option("acpi", arg, sizeof(arg)) == 4 &&
	    !strncmp(arg, "rsdt", 4)) &&
	    rsdp->xsdt_physical_address &&
	    rsdp->revision > 1) {
		root_table = rsdp->xsdt_physical_address;
		size = ACPI_XSDT_ENTRY_SIZE;
	} else {
		root_table = rsdp->rsdt_physical_address;
		size = ACPI_RSDT_ENTRY_SIZE;
	}

	if (!root_table)
		return 0;

	header = (struct acpi_table_header *)root_table;
	len = header->length;
	if (len < sizeof(struct acpi_table_header) + size)
		return 0;

	num_entries = (len - sizeof(struct acpi_table_header)) / size;
	entry = (u8 *)(root_table + sizeof(struct acpi_table_header));

	while (num_entries--) {
		if (size == ACPI_RSDT_ENTRY_SIZE)
			acpi_table = *(u32 *)entry;
		else
			acpi_table = *(u64 *)entry;

		if (acpi_table) {
			header = (struct acpi_table_header *)acpi_table;

			if (ACPI_COMPARE_NAMESEG(header->signature, ACPI_SIG_SRAT))
				return acpi_table;
		}
		entry += size;
	}
	return 0;
}

/**
 * count_immovable_mem_regions - Parse SRAT and cache the immovable
 * memory regions into the immovable_mem array.
 *
 * Return the number of immovable memory regions on success, 0 on failure:
 *
 * - Too many immovable memory regions
 * - ACPI off or no SRAT found
 * - No immovable memory region found.
 */
int count_immovable_mem_regions(void)
{
	unsigned long table_addr, table_end, table;
	struct acpi_subtable_header *sub_table;
	struct acpi_table_header *table_header;
	char arg[MAX_ACPI_ARG_LENGTH];
	int num = 0;

	if (cmdline_find_option("acpi", arg, sizeof(arg)) == 3 &&
	    !strncmp(arg, "off", 3))
		return 0;

	table_addr = get_acpi_srat_table();
	if (!table_addr)
		return 0;

	table_header = (struct acpi_table_header *)table_addr;
	table_end = table_addr + table_header->length;
	table = table_addr + sizeof(struct acpi_table_srat);

	while (table + sizeof(struct acpi_subtable_header) < table_end) {

		sub_table = (struct acpi_subtable_header *)table;
		if (!sub_table->length) {
			debug_putstr("Invalid zero length SRAT subtable.\n");
			return 0;
		}

		if (sub_table->type == ACPI_SRAT_TYPE_MEMORY_AFFINITY) {
			struct acpi_srat_mem_affinity *ma;

			ma = (struct acpi_srat_mem_affinity *)sub_table;
			if (!(ma->flags & ACPI_SRAT_MEM_HOT_PLUGGABLE) && ma->length) {
				immovable_mem[num].start = ma->base_address;
				immovable_mem[num].size = ma->length;
				num++;
			}

			if (num >= MAX_NUMNODES*2) {
				debug_putstr("Too many immovable memory regions, aborting.\n");
				return 0;
			}
		}
		table += sub_table->length;
	}
	return num;
}
#endif /* CONFIG_RANDOMIZE_BASE && CONFIG_MEMORY_HOTREMOVE */
