xref: /kvm-unit-tests/lib/acpi.c (revision b4e8c300aeef5bcdd329fc2b19c1a1b392280aca)
1372e3528SPaolo Bonzini #include "libcflat.h"
2372e3528SPaolo Bonzini #include "acpi.h"
3372e3528SPaolo Bonzini 
4f20589d6SZixuan Wang #ifdef TARGET_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 {
14f20589d6SZixuan Wang 	if (efi_rsdp == NULL) {
15b4e8c300SZixuan Wang 		printf("Can't find RSDP from UEFI, maybe set_efi_rsdp() was not called\n");
16f20589d6SZixuan Wang 	}
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 
25f20589d6SZixuan Wang 	for (addr = 0xf0000; addr < 0x100000; addr += 16) {
26f20589d6SZixuan Wang 		rsdp = (void *)addr;
27f20589d6SZixuan Wang 		if (rsdp->signature == RSDP_SIGNATURE_8BYTE)
28f20589d6SZixuan Wang 			break;
29f20589d6SZixuan Wang 	}
30b4e8c300SZixuan Wang 
31f20589d6SZixuan Wang 	if (addr == 0x100000) {
32f20589d6SZixuan Wang 		return NULL;
33f20589d6SZixuan Wang 	}
34b4e8c300SZixuan Wang 
35f20589d6SZixuan Wang 	return rsdp;
36f20589d6SZixuan Wang }
37f20589d6SZixuan Wang #endif /* TARGET_EFI */
38f20589d6SZixuan Wang 
39372e3528SPaolo Bonzini void* find_acpi_table_addr(u32 sig)
40372e3528SPaolo Bonzini {
41372e3528SPaolo Bonzini     struct rsdp_descriptor *rsdp;
42372e3528SPaolo Bonzini     struct rsdt_descriptor_rev1 *rsdt;
43372e3528SPaolo Bonzini     void *end;
44372e3528SPaolo Bonzini     int i;
45372e3528SPaolo Bonzini 
46372e3528SPaolo Bonzini     /* FACS is special... */
47372e3528SPaolo Bonzini     if (sig == FACS_SIGNATURE) {
48372e3528SPaolo Bonzini         struct fadt_descriptor_rev1 *fadt;
49372e3528SPaolo Bonzini         fadt = find_acpi_table_addr(FACP_SIGNATURE);
50372e3528SPaolo Bonzini         if (!fadt) {
51372e3528SPaolo Bonzini             return NULL;
52372e3528SPaolo Bonzini         }
53372e3528SPaolo Bonzini         return (void*)(ulong)fadt->firmware_ctrl;
54372e3528SPaolo Bonzini     }
55372e3528SPaolo Bonzini 
56f20589d6SZixuan Wang     rsdp = get_rsdp();
57f20589d6SZixuan Wang     if (rsdp == NULL) {
58372e3528SPaolo Bonzini         printf("Can't find RSDP\n");
59372e3528SPaolo Bonzini         return 0;
60372e3528SPaolo Bonzini     }
61372e3528SPaolo Bonzini 
62372e3528SPaolo Bonzini     if (sig == RSDP_SIGNATURE) {
63372e3528SPaolo Bonzini         return rsdp;
64372e3528SPaolo Bonzini     }
65372e3528SPaolo Bonzini 
66372e3528SPaolo Bonzini     rsdt = (void*)(ulong)rsdp->rsdt_physical_address;
67372e3528SPaolo Bonzini     if (!rsdt || rsdt->signature != RSDT_SIGNATURE)
68372e3528SPaolo Bonzini         return 0;
69372e3528SPaolo Bonzini 
70372e3528SPaolo Bonzini     if (sig == RSDT_SIGNATURE) {
71372e3528SPaolo Bonzini         return rsdt;
72372e3528SPaolo Bonzini     }
73372e3528SPaolo Bonzini 
74372e3528SPaolo Bonzini     end = (void*)rsdt + rsdt->length;
75372e3528SPaolo Bonzini     for (i=0; (void*)&rsdt->table_offset_entry[i] < end; i++) {
76372e3528SPaolo Bonzini         struct acpi_table *t = (void*)(ulong)rsdt->table_offset_entry[i];
77372e3528SPaolo Bonzini         if (t && t->signature == sig) {
78372e3528SPaolo Bonzini             return t;
79372e3528SPaolo Bonzini         }
80372e3528SPaolo Bonzini     }
81372e3528SPaolo Bonzini    return NULL;
82372e3528SPaolo Bonzini }
83