/*
 * Copyright (c) 2023 Intel Corporation.
 *
 * SPDX-License-Identifier: Apache-2.0
 */

#include "acpi.h"
#include "accommon.h"
#include "acapps.h"
#include <aecommon.h>

#include <zephyr/drivers/pcie/pcie.h>
#include <zephyr/acpi/acpi.h>
#include <zephyr/logging/log.h>
LOG_MODULE_REGISTER(ACPI, CONFIG_ACPI_LOG_LEVEL);

static struct {
	struct acpi_dev child_dev[CONFIG_ACPI_DEV_MAX];
	int num_dev;
#ifdef CONFIG_PCIE_PRT
	ACPI_PCI_ROUTING_TABLE pci_prt_table[CONFIG_ACPI_MAX_PRT_ENTRY];
#endif
	bool early_init;
	ACPI_STATUS status;
} acpi = {
	.status = AE_NOT_CONFIGURED,
};

static int acpi_init(void);

static int check_init_status(void)
{
	if (acpi.status == AE_NOT_CONFIGURED) {
		acpi.status = acpi_init();
	}

	if (ACPI_FAILURE(acpi.status)) {
		LOG_ERR("ACPI init was not success");
		return -EIO;
	}

	return 0;
}

static void notify_handler(ACPI_HANDLE device, UINT32 value, void *ctx)
{
	ACPI_INFO(("Received a notify 0x%X", value));
}

static ACPI_STATUS install_handlers(void)
{
	ACPI_STATUS status;

	/* Install global notify handler */
	status = AcpiInstallNotifyHandler(ACPI_ROOT_OBJECT, ACPI_SYSTEM_NOTIFY, notify_handler,
					  NULL);
	if (ACPI_FAILURE(status)) {
		ACPI_EXCEPTION((AE_INFO, status, "While installing Notify handler"));
		goto exit;
	}

exit:
	return status;
}

static ACPI_STATUS initialize_acpica(void)
{
	ACPI_STATUS status;

	/* Initialize the ACPI subsystem */
	status = AcpiInitializeSubsystem();
	if (ACPI_FAILURE(status)) {
		ACPI_EXCEPTION((AE_INFO, status, "While initializing ACPI"));
		goto exit;
	}

	/* Initialize the ACPI Table Manager and get all ACPI tables */
	if (!acpi.early_init) {
		status = AcpiInitializeTables(NULL, 16, FALSE);
		if (ACPI_FAILURE(status)) {
			ACPI_EXCEPTION((AE_INFO, status, "While initializing Table Manager"));
			goto exit;
		}
	}

	/* Create the ACPI namespace from ACPI tables */
	status = AcpiLoadTables();
	if (ACPI_FAILURE(status)) {
		ACPI_EXCEPTION((AE_INFO, status, "While loading ACPI tables"));
		goto exit;
	}

	/* Install local handlers */
	status = install_handlers();
	if (ACPI_FAILURE(status)) {
		ACPI_EXCEPTION((AE_INFO, status, "While installing handlers"));
		goto exit;
	}

	/* Initialize the ACPI hardware */
	status = AcpiEnableSubsystem(ACPI_FULL_INITIALIZATION);
	if (ACPI_FAILURE(status)) {
		ACPI_EXCEPTION((AE_INFO, status, "While enabling ACPI"));
		goto exit;
	}

	/* Complete the ACPI namespace object initialization */
	status = AcpiInitializeObjects(ACPI_FULL_INITIALIZATION);
	if (ACPI_FAILURE(status)) {
		ACPI_EXCEPTION((AE_INFO, status, "While initializing ACPI objects"));
	}
exit:

	return status;
}

static ACPI_NAMESPACE_NODE *acpi_name_lookup(char *name)
{
	char *path;
	ACPI_STATUS status;
	ACPI_NAMESPACE_NODE *node;

	LOG_DBG("");

	status = AcpiNsInternalizeName(name, &path);
	if (ACPI_FAILURE(status)) {
		LOG_ERR("Invalid namestring: %s", name);
		return NULL;
	}

	status = AcpiNsLookup(NULL, path, ACPI_TYPE_ANY, ACPI_IMODE_EXECUTE,
			      ACPI_NS_NO_UPSEARCH | ACPI_NS_DONT_OPEN_SCOPE, NULL, &node);
	if (ACPI_FAILURE(status)) {
		LOG_ERR("Could not locate name: %s, %d", name, status);
		node = NULL;
	}

	ACPI_FREE(path);
	return node;
}

static ACPI_NAMESPACE_NODE *acpi_evaluate_method(char *bus_name, char *method)
{
	ACPI_NAMESPACE_NODE *node;
	ACPI_NAMESPACE_NODE *handle;
	ACPI_NAMESPACE_NODE *prt_node = NULL;

	LOG_DBG("%s", bus_name);

	handle = acpi_name_lookup(bus_name);
	if (!handle) {
		LOG_ERR("No ACPI node with given name: %s", bus_name);
		goto exit;
	}

	if (handle->Type != ACPI_TYPE_DEVICE) {
		LOG_ERR("No ACPI node foud with given name: %s", bus_name);
		goto exit;
	}

	node = ACPI_CAST_PTR(ACPI_NAMESPACE_NODE, handle);

	(void)AcpiGetHandle(node, method, ACPI_CAST_PTR(ACPI_HANDLE, &prt_node));

	if (!prt_node) {
		LOG_ERR("No entry for the ACPI node with given name: %s", bus_name);
		goto exit;
	}
	return node;
exit:
	return NULL;
}

static ACPI_STATUS acpi_enable_pic_mode(void)
{
	ACPI_STATUS status;
	ACPI_OBJECT_LIST arg_list;
	ACPI_OBJECT arg[1];

	arg_list.Count = 1;
	arg_list.Pointer = arg;

	arg[0].Type = ACPI_TYPE_INTEGER;
	arg[0].Integer.Value = 1;

	status = AcpiEvaluateObject(NULL, "\\_PIC", &arg_list, NULL);
	if (ACPI_FAILURE(status)) {
		LOG_WRN("error While executing \\_pic method: %d", status);
	}

	return status;
}

static ACPI_STATUS dev_resource_enum_callback(ACPI_HANDLE obj_handle, UINT32 level, void *ctx,
					      void **ret_value)
{
	ACPI_NAMESPACE_NODE *node;
	ACPI_BUFFER rt_buffer;
	struct acpi_dev *child_dev;

	node = ACPI_CAST_PTR(ACPI_NAMESPACE_NODE, obj_handle);
	char *path_name;
	ACPI_STATUS status;
	ACPI_DEVICE_INFO *dev_info;

	LOG_DBG("%s %p", __func__, node);

	/* get device info such as HID, Class ID etc. */
	status = AcpiGetObjectInfo(obj_handle, &dev_info);
	if (ACPI_FAILURE(status)) {
		LOG_ERR("AcpiGetObjectInfo failed: %s", AcpiFormatException(status));
		goto exit;
	}

	if (acpi.num_dev >= CONFIG_ACPI_DEV_MAX) {
		return AE_NO_MEMORY;
	}

	if (!(dev_info->Valid & ACPI_VALID_HID)) {
		goto exit;
	}

	child_dev = (struct acpi_dev *)&acpi.child_dev[acpi.num_dev++];
	child_dev->handle = obj_handle;
	child_dev->dev_info = dev_info;

	path_name = AcpiNsGetNormalizedPathname(node, TRUE);
	if (!path_name) {
		LOG_ERR("No memory for path_name");
		goto exit;
	} else {
		LOG_DBG("Device path: %s", path_name);
		child_dev->path = path_name;
	}

	rt_buffer.Pointer = NULL;
	rt_buffer.Length = ACPI_ALLOCATE_LOCAL_BUFFER;

	status = AcpiGetCurrentResources(node, &rt_buffer);
	if (ACPI_FAILURE(status)) {
		LOG_DBG("AcpiGetCurrentResources failed: %s", AcpiFormatException(status));
	} else {
		child_dev->res_lst = rt_buffer.Pointer;
	}

exit:

	return AE_OK;
}

static int acpi_enum_devices(void)
{
	LOG_DBG("");

	AcpiWalkNamespace(ACPI_TYPE_DEVICE, ACPI_ROOT_OBJECT, ACPI_UINT32_MAX,
			  dev_resource_enum_callback, NULL, NULL, NULL);

	return 0;
}

static int acpi_early_init(void)
{
	ACPI_STATUS status;

	LOG_DBG("");

	if (acpi.early_init) {
		LOG_DBG("acpi early init already done");
		return 0;
	}

	status = AcpiInitializeTables(NULL, 16, FALSE);
	if (ACPI_FAILURE(status)) {
		LOG_ERR("Error in acpi table init:%d", status);
		return -EIO;
	}

	acpi.early_init = true;

	return 0;
}

int acpi_current_resource_get(char *dev_name, ACPI_RESOURCE **res)
{
	ACPI_BUFFER rt_buffer;
	ACPI_NAMESPACE_NODE *node;
	ACPI_STATUS status;

	LOG_DBG("%s", dev_name);

	status = check_init_status();
	if (status) {
		return -EAGAIN;
	}

	node = acpi_evaluate_method(dev_name, METHOD_NAME__CRS);
	if (!node) {
		LOG_ERR("Evaluation failed for given device: %s", dev_name);
		return -ENOTSUP;
	}

	rt_buffer.Pointer = NULL;
	rt_buffer.Length = ACPI_ALLOCATE_LOCAL_BUFFER;

	status = AcpiGetCurrentResources(node, &rt_buffer);
	if (ACPI_FAILURE(status)) {
		LOG_ERR("AcpiGetCurrentResources failed: %s", AcpiFormatException(status));
		return -ENOTSUP;
	}

	*res = rt_buffer.Pointer;

	return 0;
}

int acpi_possible_resource_get(char *dev_name, ACPI_RESOURCE **res)
{
	ACPI_BUFFER rt_buffer;
	ACPI_NAMESPACE_NODE *node;
	ACPI_STATUS status;

	LOG_DBG("%s", dev_name);

	status = check_init_status();
	if (status) {
		return -EAGAIN;
	}

	node = acpi_evaluate_method(dev_name, METHOD_NAME__PRS);
	if (!node) {
		LOG_ERR("Evaluation failed for given device: %s", dev_name);
		return -ENOTSUP;
	}

	rt_buffer.Pointer = NULL;
	rt_buffer.Length = ACPI_ALLOCATE_LOCAL_BUFFER;

	AcpiGetPossibleResources(node, &rt_buffer);
	*res = rt_buffer.Pointer;

	return 0;
}

int acpi_current_resource_free(ACPI_RESOURCE *res)
{
	ACPI_FREE(res);

	return 0;
}

#ifdef CONFIG_PCIE_PRT
uint32_t acpi_legacy_irq_get(pcie_bdf_t bdf)
{
	uint32_t slot = PCIE_BDF_TO_DEV(bdf), pin;

	LOG_DBG("");

	if (check_init_status()) {
		return UINT_MAX;
	}

	pin = (pcie_conf_read(bdf, PCIE_CONF_INTR) >> 8) & 0x3;

	LOG_DBG("Device irq info: slot:%d pin:%d", slot, pin);

	for (int i = 0; i < CONFIG_ACPI_MAX_PRT_ENTRY; i++) {
		if (((acpi.pci_prt_table[i].Address >> 16) & 0xffff) == slot &&
		    acpi.pci_prt_table[i].Pin + 1 == pin) {
			LOG_DBG("[%d]Device irq info: slot:%d pin:%d irq:%d", i, slot, pin,
				acpi.pci_prt_table[i].SourceIndex);
			return acpi.pci_prt_table[i].SourceIndex;
		}
	}

	return UINT_MAX;
}

int acpi_legacy_irq_init(const char *hid, const char *uid)
{
	struct acpi_dev *child_dev = acpi_device_get(hid, uid);
	ACPI_PCI_ROUTING_TABLE *rt_table = acpi.pci_prt_table;
	ACPI_BUFFER rt_buffer;
	ACPI_NAMESPACE_NODE *node;
	ACPI_STATUS status;

	if (!child_dev) {
		LOG_ERR("no such PCI bus device %s %s", hid, uid);
		return -ENODEV;
	}

	node = acpi_evaluate_method(child_dev->path, METHOD_NAME__PRT);
	if (!node) {
		LOG_ERR("Evaluation failed for given device: %s", child_dev->path);
		return -ENODEV;
	}

	rt_buffer.Pointer = rt_table;
	rt_buffer.Length = ARRAY_SIZE(acpi.pci_prt_table) * sizeof(ACPI_PCI_ROUTING_TABLE);

	status = AcpiGetIrqRoutingTable(node, &rt_buffer);
	if (ACPI_FAILURE(status)) {
		LOG_ERR("unable to retrieve IRQ Routing Table: %s", child_dev->path);
		return -EIO;
	}

	if (rt_table->Source[0]) {
		/*
		 * If Name path exist then PCI interrupts are configurable and are not hardwired to
		 * any specific interrupt inputs on the interrupt controller. OSPM can uses
		 * _PRS/_CRS/_SRS to configure interrupts. But currently leave existing PCI bus
		 * driver with arch_irq_allocate() method for allocate and configure interrupts
		 * without conflicting.
		 */
		return -ENOENT;
	}

	for (size_t i = 0; i < ARRAY_SIZE(acpi.pci_prt_table); i++) {
		if (!acpi.pci_prt_table[i].SourceIndex) {
			break;
		}
		if (IS_ENABLED(CONFIG_X86_64)) {
			/* mark the PRT irq numbers as reserved. */
			arch_irq_set_used(acpi.pci_prt_table[i].SourceIndex);
		}
	}

	return 0;
}
#endif /* CONFIG_PCIE_PRT */

ACPI_RESOURCE *acpi_resource_parse(ACPI_RESOURCE *res, int res_type)
{
	do {
		if (!res->Length) {
			LOG_DBG("zero length found!");
			break;
		} else if (res->Type == res_type) {
			break;
		}
		res = ACPI_NEXT_RESOURCE(res);
	} while (res->Type != ACPI_RESOURCE_TYPE_END_TAG);

	if (res->Type == ACPI_RESOURCE_TYPE_END_TAG) {
		return NULL;
	}

	return res;
}

int acpi_device_irq_get(struct acpi_dev *child_dev, struct acpi_irq_resource *irq_res)
{
	ACPI_RESOURCE *res = acpi_resource_parse(child_dev->res_lst, ACPI_RESOURCE_TYPE_IRQ);

	if (!res) {
		res = acpi_resource_parse(child_dev->res_lst, ACPI_RESOURCE_TYPE_EXTENDED_IRQ);
		if (!res) {
			return -ENODEV;
		}

		if (res->Data.ExtendedIrq.InterruptCount > irq_res->irq_vector_max) {
			return -ENOMEM;
		}

		irq_res->irq_vector_max = res->Data.ExtendedIrq.InterruptCount;
		for (int i = 0; i < irq_res->irq_vector_max; i++) {
			irq_res->irqs[i] = (uint16_t)res->Data.ExtendedIrq.Interrupts[i];
		}

		irq_res->flags = arch_acpi_encode_irq_flags(res->Data.ExtendedIrq.Polarity,
							    res->Data.ExtendedIrq.Triggering);
	} else {
		if (res->Data.Irq.InterruptCount > irq_res->irq_vector_max) {
			return -ENOMEM;
		}

		irq_res->irq_vector_max = res->Data.Irq.InterruptCount;
		for (int i = 0; i < irq_res->irq_vector_max; i++) {
			irq_res->irqs[i] = (uint16_t)res->Data.Irq.Interrupts[i];
		}

		irq_res->flags = arch_acpi_encode_irq_flags(res->Data.ExtendedIrq.Polarity,
							    res->Data.ExtendedIrq.Triggering);
	}

	return 0;
}

int acpi_device_mmio_get(struct acpi_dev *child_dev, struct acpi_mmio_resource *mmio_res)
{
	ACPI_RESOURCE *res = child_dev->res_lst;
	struct acpi_reg_base *reg_base = mmio_res->reg_base;
	int mmio_cnt = 0;

	do {
		if (!res->Length) {
			LOG_DBG("Found Acpi resource with zero length!");
			break;
		}

		switch (res->Type) {
		case ACPI_RESOURCE_TYPE_IO:
			reg_base[mmio_cnt].type = ACPI_RES_TYPE_IO;
			reg_base[mmio_cnt].port = (uint32_t)res->Data.Io.Minimum;
			reg_base[mmio_cnt++].length = res->Data.Io.AddressLength;
			break;

		case ACPI_RESOURCE_TYPE_FIXED_IO:
			reg_base[mmio_cnt].type = ACPI_RES_TYPE_IO;
			reg_base[mmio_cnt].port = (uint32_t)res->Data.FixedIo.Address;
			reg_base[mmio_cnt++].length = res->Data.FixedIo.AddressLength;
			break;

		case ACPI_RESOURCE_TYPE_MEMORY24:
			reg_base[mmio_cnt].type = ACPI_RES_TYPE_MEM;
			reg_base[mmio_cnt].mmio = (uintptr_t)res->Data.Memory24.Minimum;
			reg_base[mmio_cnt++].length = res->Data.Memory24.AddressLength;
			break;

		case ACPI_RESOURCE_TYPE_MEMORY32:
			reg_base[mmio_cnt].type = ACPI_RES_TYPE_MEM;
			reg_base[mmio_cnt].mmio = (uintptr_t)res->Data.Memory32.Minimum;
			reg_base[mmio_cnt++].length = res->Data.Memory32.AddressLength;
			break;

		case ACPI_RESOURCE_TYPE_FIXED_MEMORY32:
			reg_base[mmio_cnt].type = ACPI_RES_TYPE_MEM;
			reg_base[mmio_cnt].mmio = (uintptr_t)res->Data.FixedMemory32.Address;
			reg_base[mmio_cnt++].length = res->Data.FixedMemory32.AddressLength;
			break;
		}

		res = ACPI_NEXT_RESOURCE(res);
		if (mmio_cnt >= mmio_res->mmio_max &&
			 res->Type != ACPI_RESOURCE_TYPE_END_TAG) {
			return -ENOMEM;
		}
	} while (res->Type != ACPI_RESOURCE_TYPE_END_TAG);

	if (!mmio_cnt) {
		return -ENODEV;
	}

	mmio_res->mmio_max = mmio_cnt;

	return 0;
}

static int acpi_res_type(ACPI_RESOURCE *res)
{
	int type;

	switch (res->Type) {
	case ACPI_RESOURCE_TYPE_IO:
		type = ACPI_RESOURCE_TYPE_IO;
		break;
	case ACPI_RESOURCE_TYPE_FIXED_IO:
		type = ACPI_RESOURCE_TYPE_FIXED_IO;
		break;
	case ACPI_RESOURCE_TYPE_MEMORY24:
		type = ACPI_RESOURCE_TYPE_MEMORY24;
		break;
	case ACPI_RESOURCE_TYPE_MEMORY32:
		type = ACPI_RESOURCE_TYPE_MEMORY32;
		break;
	case ACPI_RESOURCE_TYPE_FIXED_MEMORY32:
		type = ACPI_RESOURCE_TYPE_FIXED_MEMORY32;
		break;
	case ACPI_RESOURCE_TYPE_ADDRESS16:
		type = ACPI_RESOURCE_TYPE_ADDRESS16;
		break;
	case ACPI_RESOURCE_TYPE_ADDRESS32:
		type = ACPI_RESOURCE_TYPE_ADDRESS32;
		break;
	case ACPI_RESOURCE_TYPE_ADDRESS64:
		type = ACPI_RESOURCE_TYPE_ADDRESS64;
		break;
	case ACPI_RESOURCE_TYPE_EXTENDED_ADDRESS64:
		type = ACPI_RESOURCE_TYPE_EXTENDED_ADDRESS64;
		break;
	default:
		type = ACPI_RESOURCE_TYPE_MAX;
	}

	return type;
}

int acpi_device_type_get(ACPI_RESOURCE *res)
{
	int type = ACPI_RESOURCE_TYPE_MAX;

	do {
		if (!res->Length) {
			LOG_ERR("Error: zero length found!");
			break;
		}
		type = acpi_res_type(res);
		if (type != ACPI_RESOURCE_TYPE_MAX) {
			break;
		}
		res = ACPI_NEXT_RESOURCE(res);
	} while (res->Type != ACPI_RESOURCE_TYPE_END_TAG);

	return type;
}

struct acpi_dev *acpi_device_get(const char *hid, const char *uid)
{
	struct acpi_dev *child_dev;
	int i = 0;

	LOG_DBG("");

	if (check_init_status()) {
		return NULL;
	}

	do {
		child_dev = &acpi.child_dev[i];
		if (!child_dev->path) {
			LOG_DBG("NULL device path found");
			continue;
		}

		if (!child_dev->res_lst || !child_dev->dev_info ||
		    !child_dev->dev_info->HardwareId.Length) {
			continue;
		}

		if (!strcmp(hid, child_dev->dev_info->HardwareId.String)) {
			if (uid && child_dev->dev_info->UniqueId.Length) {
				if (!strcmp(child_dev->dev_info->UniqueId.String, uid)) {
					return child_dev;
				}
			} else {
				return child_dev;
			}
		}
	} while (i++ < acpi.num_dev);

	return NULL;
}

struct acpi_dev *acpi_device_by_index_get(int index)
{
	return index < acpi.num_dev ? &acpi.child_dev[index] : NULL;
}

void *acpi_table_get(char *signature, int inst)
{
	ACPI_STATUS status;
	ACPI_TABLE_HEADER *table;

	if (!acpi.early_init) {
		status = acpi_early_init();
		if (status) {
			LOG_ERR("ACPI early init failed");
			return NULL;
		}
	}

	status = AcpiGetTable(signature, inst, &table);
	if (ACPI_FAILURE(status)) {
		LOG_ERR("ACPI get table failed: %d", status);
		return NULL;
	}

	return (void *)table;
}

static uint32_t acpi_get_subtable_entry_num(int type, ACPI_SUBTABLE_HEADER *subtable,
					    uintptr_t offset, uintptr_t base, uint32_t madt_len)
{
	uint32_t subtable_cnt = 0;

	while (offset < madt_len) {
		if (type == subtable->Type) {
			subtable_cnt++;
		}
		offset += subtable->Length;
		subtable = ACPI_ADD_PTR(ACPI_SUBTABLE_HEADER, base, offset);

		if (!subtable->Length) {
			break;
		}
	}

	return subtable_cnt;
}

int acpi_madt_entry_get(int type, ACPI_SUBTABLE_HEADER **tables, int *num_inst)
{
	ACPI_TABLE_HEADER *madt = acpi_table_get("APIC", 0);
	uintptr_t base = POINTER_TO_UINT(madt);
	uintptr_t offset = sizeof(ACPI_TABLE_MADT);
	ACPI_SUBTABLE_HEADER *subtable;

	if (!madt) {
		return -EIO;
	}

	subtable = ACPI_ADD_PTR(ACPI_SUBTABLE_HEADER, base, offset);
	while (offset < madt->Length) {

		if (type == subtable->Type) {
			*tables = subtable;
			*num_inst = acpi_get_subtable_entry_num(type, subtable, offset, base,
								madt->Length);
			return 0;
		}

		offset += subtable->Length;
		subtable = ACPI_ADD_PTR(ACPI_SUBTABLE_HEADER, base, offset);
	}

	return -ENODEV;
}

int acpi_dmar_entry_get(enum AcpiDmarType type, ACPI_SUBTABLE_HEADER **tables)
{
	struct acpi_table_dmar *dmar = acpi_table_get("DMAR", 0);
	uintptr_t base = POINTER_TO_UINT(dmar);
	uintptr_t offset = sizeof(ACPI_TABLE_DMAR);
	ACPI_DMAR_HEADER *subtable;

	if (!dmar) {
		LOG_ERR("error on get DMAR table");
		return -EIO;
	}

	subtable = ACPI_ADD_PTR(ACPI_DMAR_HEADER, base, offset);
	while (offset < dmar->Header.Length) {
		if (type == subtable->Type) {
			*tables = (struct acpi_subtable_header *)subtable;
			return 0;
		}
		offset += subtable->Length;
		subtable = ACPI_ADD_PTR(ACPI_DMAR_HEADER, base, offset);
	}

	return -ENODEV;
}

void acpi_dmar_foreach_subtable(ACPI_TABLE_DMAR *dmar,
				dmar_foreach_subtable_func_t func, void *arg)
{
	uint16_t length = dmar->Header.Length;
	uintptr_t offset = sizeof(ACPI_TABLE_DMAR);

	__ASSERT_NO_MSG(length >= offset);

	while (offset < length) {
		ACPI_DMAR_HEADER *subtable = ACPI_ADD_PTR(ACPI_DMAR_HEADER, dmar, offset);

		__ASSERT_NO_MSG(subtable->Length >= sizeof(*subtable));
		__ASSERT_NO_MSG(subtable->Length <= length - offset);

		func(subtable, arg);

		offset += subtable->Length;
	}
}

void acpi_dmar_foreach_devscope(ACPI_DMAR_HARDWARE_UNIT *hu,
				dmar_foreach_devscope_func_t func, void *arg)
{
	uint16_t length = hu->Header.Length;
	uintptr_t offset = sizeof(ACPI_DMAR_HARDWARE_UNIT);

	__ASSERT_NO_MSG(length >= offset);

	while (offset < length) {
		ACPI_DMAR_DEVICE_SCOPE *devscope = ACPI_ADD_PTR(ACPI_DMAR_DEVICE_SCOPE,
								hu, offset);

		__ASSERT_NO_MSG(devscope->Length >= sizeof(*devscope));
		__ASSERT_NO_MSG(devscope->Length <= length - offset);

		func(devscope, arg);

		offset += devscope->Length;
	}
}

static void devscope_handler(ACPI_DMAR_DEVICE_SCOPE *devscope, void *arg)
{
	ACPI_DMAR_PCI_PATH *dev_path;
	union acpi_dmar_id pci_path;

	ARG_UNUSED(arg); /* may be unused */

	if (devscope->EntryType == ACPI_DMAR_SCOPE_TYPE_IOAPIC) {
		uint16_t *ioapic_id = arg;

		dev_path = ACPI_ADD_PTR(ACPI_DMAR_PCI_PATH, devscope,
					sizeof(ACPI_DMAR_DEVICE_SCOPE));

		/* Get first entry */
		pci_path.bits.bus = devscope->Bus;
		pci_path.bits.device = dev_path->Device;
		pci_path.bits.function = dev_path->Function;

		*ioapic_id = pci_path.raw;
	}
}

static void subtable_handler(ACPI_DMAR_HEADER *subtable, void *arg)
{
	ARG_UNUSED(arg); /* may be unused */

	if (subtable->Type == ACPI_DMAR_TYPE_HARDWARE_UNIT) {
		ACPI_DMAR_HARDWARE_UNIT *hu;

		hu = CONTAINER_OF(subtable, ACPI_DMAR_HARDWARE_UNIT, Header);
		acpi_dmar_foreach_devscope(hu, devscope_handler, arg);
	}
}

int acpi_dmar_ioapic_get(uint16_t *ioapic_id)
{
	ACPI_TABLE_DMAR *dmar = acpi_table_get("DMAR", 0);
	uint16_t found_ioapic = USHRT_MAX;

	if (dmar == NULL) {
		return -ENODEV;
	}

	acpi_dmar_foreach_subtable(dmar, subtable_handler, &found_ioapic);
	if (found_ioapic != USHRT_MAX) {
		*ioapic_id = found_ioapic;
		return 0;
	}

	return -ENOENT;
}

int acpi_drhd_get(enum AcpiDmarScopeType scope, ACPI_DMAR_DEVICE_SCOPE *dev_scope,
		  union acpi_dmar_id *dmar_id, int *num_inst, int max_inst)
{
	uintptr_t offset = sizeof(ACPI_DMAR_HARDWARE_UNIT);
	uint32_t i = 0;
	ACPI_DMAR_HEADER *drdh;
	ACPI_DMAR_DEVICE_SCOPE *subtable;
	ACPI_DMAR_PCI_PATH *dev_path;
	int ret;
	uintptr_t base;
	int scope_size;

	ret = acpi_dmar_entry_get(ACPI_DMAR_TYPE_HARDWARE_UNIT,
				  (ACPI_SUBTABLE_HEADER **)&drdh);
	if (ret) {
		LOG_ERR("Error on retrieve DMAR table");
		return ret;
	}

	scope_size = drdh->Length - sizeof(ACPI_DMAR_HARDWARE_UNIT);
	base = (uintptr_t)((uintptr_t)drdh + offset);

	offset = 0;

	while (scope_size) {
		int num_path;

		subtable = ACPI_ADD_PTR(ACPI_DMAR_DEVICE_SCOPE, base, offset);
		if (!subtable->Length) {
			break;
		}

		if (scope == subtable->EntryType) {
			num_path = (subtable->Length - 6u) / 2u;
			dev_path = ACPI_ADD_PTR(ACPI_DMAR_PCI_PATH, subtable,
				sizeof(ACPI_DMAR_DEVICE_SCOPE));

			while (num_path--) {
				if (i >= max_inst) {
					LOG_ERR("DHRD not enough buffer size");
					return -ENOBUFS;
				}
				dmar_id[i].bits.bus = subtable->Bus;
				dmar_id[i].bits.device = dev_path[i].Device;
				dmar_id[i].bits.function = dev_path[i].Function;
				i++;
			}
			break;
		}

		offset += subtable->Length;

		if (scope_size < subtable->Length) {
			break;
		}
		scope_size -= subtable->Length;
	}

	*num_inst = i;
	if (!i) {
		LOG_ERR("Error on retrieve DRHD Info");
		return -ENODEV;
	}

	if (dev_scope && subtable) {
		memcpy(dev_scope, subtable, sizeof(struct acpi_dmar_device_scope));
	}

	return 0;
}

#define ACPI_CPU_FLAGS_ENABLED 0x01u

ACPI_MADT_LOCAL_APIC *acpi_local_apic_get(int cpu_num)
{
	ACPI_MADT_LOCAL_APIC *lapic;
	int cpu_cnt;
	int idx;

	if (acpi_madt_entry_get(ACPI_MADT_TYPE_LOCAL_APIC, (ACPI_SUBTABLE_HEADER **)&lapic,
				&cpu_cnt)) {
		/* Error on MAD table. */
		return NULL;
	}

	for (idx = 0; cpu_num >= 0 && idx < cpu_cnt; idx++) {
		if (lapic[idx].LapicFlags & ACPI_CPU_FLAGS_ENABLED) {
			if (cpu_num == 0) {
				return &lapic[idx];
			}

			cpu_num--;
		}
	}

	return NULL;
}

int acpi_invoke_method(char *path, ACPI_OBJECT_LIST *arg_list, ACPI_OBJECT *ret_obj)
{
	ACPI_STATUS status;
	ACPI_BUFFER ret_buff;

	ret_buff.Length = sizeof(*ret_obj);
	ret_buff.Pointer = ret_obj;

	status = AcpiEvaluateObject(NULL, path, arg_list, &ret_buff);
	if (ACPI_FAILURE(status)) {
		LOG_ERR("error While executing %s method: %d", path, status);
		return -EIO;
	}

	return 0;
}

static int acpi_init(void)
{
	ACPI_STATUS status;

	LOG_DBG("");

	/* For debug version only */
	ACPI_DEBUG_INITIALIZE();

	status = initialize_acpica();
	if (ACPI_FAILURE(status)) {
		LOG_ERR("Error in ACPI init:%d", status);
		goto exit;
	}

	/* Enable IO APIC mode */
	status = acpi_enable_pic_mode();
	if (ACPI_FAILURE(status)) {
		LOG_WRN("Error in enable pic mode acpi method:%d", status);
	}

	acpi_enum_devices();

exit:
	return status;
}
