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