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