xref: /kvm-unit-tests/lib/acpi.c (revision 169f786f4855b294504aed31e1d6095987f03cd8)
1372e3528SPaolo Bonzini #include "libcflat.h"
2372e3528SPaolo Bonzini #include "acpi.h"
3372e3528SPaolo Bonzini 
4c98ce6e0SAlexandru Elisei #ifdef CONFIG_EFI
5*169f786fSAlexandru Elisei struct acpi_table_rsdp *efi_rsdp = NULL;
6f20589d6SZixuan Wang 
7*169f786fSAlexandru Elisei void set_efi_rsdp(struct acpi_table_rsdp *rsdp)
8b4e8c300SZixuan Wang {
9f20589d6SZixuan Wang 	efi_rsdp = rsdp;
10f20589d6SZixuan Wang }
11f20589d6SZixuan Wang 
12*169f786fSAlexandru Elisei static struct acpi_table_rsdp *get_rsdp(void)
13b4e8c300SZixuan Wang {
14e2ad9858SNikos Nikoleris 	if (efi_rsdp == NULL)
15b4e8c300SZixuan Wang 		printf("Can't find RSDP from UEFI, maybe set_efi_rsdp() was not called\n");
16e2ad9858SNikos Nikoleris 
17f20589d6SZixuan Wang 	return efi_rsdp;
18f20589d6SZixuan Wang }
19f20589d6SZixuan Wang #else
20*169f786fSAlexandru Elisei static struct acpi_table_rsdp *get_rsdp(void)
21b4e8c300SZixuan Wang {
22*169f786fSAlexandru Elisei 	struct acpi_table_rsdp *rsdp;
23f20589d6SZixuan Wang 	unsigned long addr;
24b4e8c300SZixuan Wang 
2592a6c9b9SPaolo Bonzini 	for (addr = 0xe0000; addr < 0x100000; addr += 16) {
26f20589d6SZixuan Wang 		rsdp = (void *)addr;
27f20589d6SZixuan Wang 		if (rsdp->signature == RSDP_SIGNATURE_8BYTE)
28f20589d6SZixuan Wang 			break;
29f20589d6SZixuan Wang 	}
30b4e8c300SZixuan Wang 
31e2ad9858SNikos Nikoleris 	if (addr == 0x100000)
32f20589d6SZixuan Wang 		return NULL;
33b4e8c300SZixuan Wang 
34f20589d6SZixuan Wang 	return rsdp;
35f20589d6SZixuan Wang }
36c98ce6e0SAlexandru Elisei #endif /* CONFIG_EFI */
37f20589d6SZixuan Wang 
38372e3528SPaolo Bonzini void *find_acpi_table_addr(u32 sig)
39372e3528SPaolo Bonzini {
40*169f786fSAlexandru Elisei 	struct acpi_table_rsdt_rev1 *rsdt;
41*169f786fSAlexandru Elisei 	struct acpi_table_rsdp *rsdp;
42372e3528SPaolo Bonzini 	void *end;
43372e3528SPaolo Bonzini 	int i;
44372e3528SPaolo Bonzini 
45372e3528SPaolo Bonzini 	/* FACS is special... */
46372e3528SPaolo Bonzini 	if (sig == FACS_SIGNATURE) {
47*169f786fSAlexandru Elisei 		struct acpi_table_fadt_rev1 *fadt;
48e2ad9858SNikos Nikoleris 
49372e3528SPaolo Bonzini 		fadt = find_acpi_table_addr(FACP_SIGNATURE);
50b3e76d57SNikos Nikoleris 		if (!fadt)
51372e3528SPaolo Bonzini 			return NULL;
52372e3528SPaolo Bonzini 		return (void *)(ulong) fadt->firmware_ctrl;
53372e3528SPaolo Bonzini 	}
54372e3528SPaolo Bonzini 
55f20589d6SZixuan Wang 	rsdp = get_rsdp();
56f20589d6SZixuan Wang 	if (rsdp == NULL) {
57372e3528SPaolo Bonzini 		printf("Can't find RSDP\n");
58b3e76d57SNikos Nikoleris 		return NULL;
59372e3528SPaolo Bonzini 	}
60372e3528SPaolo Bonzini 
61b3e76d57SNikos Nikoleris 	if (sig == RSDP_SIGNATURE)
62372e3528SPaolo Bonzini 		return rsdp;
63372e3528SPaolo Bonzini 
64372e3528SPaolo Bonzini 	rsdt = (void *)(ulong) rsdp->rsdt_physical_address;
65372e3528SPaolo Bonzini 	if (!rsdt || rsdt->signature != RSDT_SIGNATURE)
66b3e76d57SNikos Nikoleris 		return NULL;
67372e3528SPaolo Bonzini 
68b3e76d57SNikos Nikoleris 	if (sig == RSDT_SIGNATURE)
69372e3528SPaolo Bonzini 		return rsdt;
70372e3528SPaolo Bonzini 
71372e3528SPaolo Bonzini 	end = (void *)rsdt + rsdt->length;
72372e3528SPaolo Bonzini 	for (i = 0; (void *)&rsdt->table_offset_entry[i] < end; i++) {
73372e3528SPaolo Bonzini 		struct acpi_table *t = (void *)(ulong) rsdt->table_offset_entry[i];
74e2ad9858SNikos Nikoleris 
75e2ad9858SNikos Nikoleris 		if (t && t->signature == sig)
76372e3528SPaolo Bonzini 			return t;
77372e3528SPaolo Bonzini 	}
78e2ad9858SNikos Nikoleris 
79372e3528SPaolo Bonzini 	return NULL;
80372e3528SPaolo Bonzini }
81