xref: /kvm-unit-tests/lib/acpi.c (revision e2ad9858ea1841954c6bfa041d6214b81a3b5332)
1372e3528SPaolo Bonzini #include "libcflat.h"
2372e3528SPaolo Bonzini #include "acpi.h"
3372e3528SPaolo Bonzini 
4c98ce6e0SAlexandru Elisei #ifdef CONFIG_EFI
5f20589d6SZixuan Wang struct rsdp_descriptor *efi_rsdp = NULL;
6f20589d6SZixuan Wang 
7b4e8c300SZixuan Wang void set_efi_rsdp(struct rsdp_descriptor *rsdp)
8b4e8c300SZixuan Wang {
9f20589d6SZixuan Wang 	efi_rsdp = rsdp;
10f20589d6SZixuan Wang }
11f20589d6SZixuan Wang 
12b4e8c300SZixuan Wang static struct rsdp_descriptor *get_rsdp(void)
13b4e8c300SZixuan Wang {
14*e2ad9858SNikos Nikoleris 	if (efi_rsdp == NULL)
15b4e8c300SZixuan Wang 		printf("Can't find RSDP from UEFI, maybe set_efi_rsdp() was not called\n");
16*e2ad9858SNikos Nikoleris 
17f20589d6SZixuan Wang 	return efi_rsdp;
18f20589d6SZixuan Wang }
19f20589d6SZixuan Wang #else
20b4e8c300SZixuan Wang static struct rsdp_descriptor *get_rsdp(void)
21b4e8c300SZixuan Wang {
22f20589d6SZixuan Wang 	struct rsdp_descriptor *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 
31*e2ad9858SNikos 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 {
40372e3528SPaolo Bonzini 	struct rsdt_descriptor_rev1 *rsdt;
41*e2ad9858SNikos Nikoleris 	struct rsdp_descriptor *rsdp;
42372e3528SPaolo Bonzini 	void *end;
43372e3528SPaolo Bonzini 	int i;
44372e3528SPaolo Bonzini 
45372e3528SPaolo Bonzini 	/* FACS is special... */
46372e3528SPaolo Bonzini 	if (sig == FACS_SIGNATURE) {
47372e3528SPaolo Bonzini 		struct fadt_descriptor_rev1 *fadt;
48*e2ad9858SNikos 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];
74*e2ad9858SNikos Nikoleris 
75*e2ad9858SNikos Nikoleris 		if (t && t->signature == sig)
76372e3528SPaolo Bonzini 			return t;
77372e3528SPaolo Bonzini 	}
78*e2ad9858SNikos Nikoleris 
79372e3528SPaolo Bonzini 	return NULL;
80372e3528SPaolo Bonzini }
81