1// SPDX-License-Identifier: GPL-2.0
2/*
3 * Utility functions for ACPI
4 *
5 * Copyright 2023 Google LLC
6 */
7
8#include <mapmem.h>
9#include <acpi/acpi_table.h>
10#include <asm/global_data.h>
11
12DECLARE_GLOBAL_DATA_PTR;
13
14struct acpi_table_header *acpi_find_table(const char *sig)
15{
16	struct acpi_rsdp *rsdp;
17	struct acpi_rsdt *rsdt;
18	struct acpi_xsdt *xsdt;
19	int len, i, count;
20
21	rsdp = map_sysmem(gd_acpi_start(), 0);
22	if (!rsdp)
23		return NULL;
24	if (rsdp->xsdt_address) {
25		xsdt = nomap_sysmem(rsdp->xsdt_address, 0);
26		len = xsdt->header.length - sizeof(xsdt->header);
27		count = len / sizeof(u64);
28	} else {
29		if (!rsdp->rsdt_address)
30			return NULL;
31		rsdt = nomap_sysmem(rsdp->rsdt_address, 0);
32		len = rsdt->header.length - sizeof(rsdt->header);
33		count = len / sizeof(u32);
34	}
35	for (i = 0; i < count; i++) {
36		struct acpi_table_header *hdr;
37
38		if (rsdp->xsdt_address)
39			hdr = nomap_sysmem(xsdt->entry[i], 0);
40		else
41			hdr = nomap_sysmem(rsdt->entry[i], 0);
42		if (!memcmp(hdr->signature, sig, ACPI_NAME_LEN))
43			return hdr;
44		if (!memcmp(hdr->signature, "FACP", ACPI_NAME_LEN)) {
45			struct acpi_fadt *fadt = (struct acpi_fadt *)hdr;
46
47			if (!memcmp(sig, "DSDT", ACPI_NAME_LEN)) {
48				void *dsdt;
49
50				if (fadt->header.revision >= 3 && fadt->x_dsdt)
51					dsdt = nomap_sysmem(fadt->x_dsdt, 0);
52				else if (fadt->dsdt)
53					dsdt = nomap_sysmem(fadt->dsdt, 0);
54				else
55					dsdt = NULL;
56				return dsdt;
57			}
58
59			if (!memcmp(sig, "FACS", ACPI_NAME_LEN)) {
60				void *facs;
61
62				if (fadt->header.revision >= 3 &&
63				    fadt->x_firmware_ctrl)
64					facs = nomap_sysmem(fadt->x_firmware_ctrl, 0);
65				else if (fadt->firmware_ctrl)
66					facs = nomap_sysmem(fadt->firmware_ctrl, 0);
67				else
68					facs = NULL;
69				return facs;
70			}
71		}
72	}
73
74	return NULL;
75}
76