1 #include "libcflat.h" 2 #include "acpi.h" 3 4 #ifdef CONFIG_EFI 5 struct acpi_table_rsdp *efi_rsdp = NULL; 6 set_efi_rsdp(struct acpi_table_rsdp * rsdp)7void set_efi_rsdp(struct acpi_table_rsdp *rsdp) 8 { 9 efi_rsdp = rsdp; 10 } 11 get_rsdp(void)12static struct acpi_table_rsdp *get_rsdp(void) 13 { 14 if (efi_rsdp == NULL) 15 printf("Can't find RSDP from UEFI, maybe set_efi_rsdp() was not called\n"); 16 17 return efi_rsdp; 18 } 19 #else get_rsdp(void)20static struct acpi_table_rsdp *get_rsdp(void) 21 { 22 struct acpi_table_rsdp *rsdp; 23 unsigned long addr; 24 25 for (addr = 0xe0000; addr < 0x100000; addr += 16) { 26 rsdp = (void *)addr; 27 if (rsdp->signature == RSDP_SIGNATURE_8BYTE) 28 break; 29 } 30 31 if (addr == 0x100000) 32 return NULL; 33 34 return rsdp; 35 } 36 #endif /* CONFIG_EFI */ 37 find_acpi_table_addr(u32 sig)38void *find_acpi_table_addr(u32 sig) 39 { 40 struct acpi_table_rsdt_rev1 *rsdt = NULL; 41 struct acpi_table_xsdt *xsdt = NULL; 42 struct acpi_table_rsdp *rsdp; 43 void *end; 44 int i; 45 46 /* FACS is special... */ 47 if (sig == FACS_SIGNATURE) { 48 struct acpi_table_fadt *fadt; 49 50 fadt = find_acpi_table_addr(FACP_SIGNATURE); 51 if (!fadt) 52 return NULL; 53 return (void *)(ulong) fadt->firmware_ctrl; 54 } 55 56 rsdp = get_rsdp(); 57 if (rsdp == NULL) { 58 printf("Can't find RSDP\n"); 59 return NULL; 60 } 61 62 if (sig == RSDP_SIGNATURE) 63 return rsdp; 64 65 rsdt = (void *)(ulong) rsdp->rsdt_physical_address; 66 if (rsdt && rsdt->signature != RSDT_SIGNATURE) 67 rsdt = NULL; 68 69 if (sig == RSDT_SIGNATURE) 70 return rsdt; 71 72 if (rsdp->revision >= 2) { 73 xsdt = (void *)(ulong) rsdp->xsdt_physical_address; 74 if (xsdt && xsdt->signature != XSDT_SIGNATURE) 75 xsdt = NULL; 76 } 77 78 if (sig == XSDT_SIGNATURE) 79 return xsdt; 80 81 /* 82 * When the system implements APCI 2.0 and above and XSDT is valid we 83 * have use XSDT to find other ACPI tables, otherwise, we use RSDT. 84 */ 85 if (xsdt) { 86 end = (void *)xsdt + xsdt->length; 87 for (i = 0; (void *)&xsdt->table_offset_entry[i] < end; i++) { 88 struct acpi_table *t = (void *)(ulong) xsdt->table_offset_entry[i]; 89 90 if (t && t->signature == sig) 91 return t; 92 } 93 } else if (rsdt) { 94 end = (void *)rsdt + rsdt->length; 95 for (i = 0; (void *)&rsdt->table_offset_entry[i] < end; i++) { 96 struct acpi_table *t = (void *)(ulong) rsdt->table_offset_entry[i]; 97 98 if (t && t->signature == sig) 99 return t; 100 } 101 } 102 103 return NULL; 104 } 105 acpi_table_parse_madt(enum acpi_madt_type mtype,acpi_table_handler handler)106int acpi_table_parse_madt(enum acpi_madt_type mtype, acpi_table_handler handler) 107 { 108 struct acpi_table_madt *madt; 109 struct acpi_subtable_header *header; 110 void *end; 111 int count = 0; 112 113 madt = find_acpi_table_addr(MADT_SIGNATURE); 114 assert(madt); 115 116 header = (void *)(ulong) madt + sizeof(struct acpi_table_madt); 117 end = (void *)((ulong) madt + madt->length); 118 119 while ((void *)header < end) { 120 if (header->type == mtype) { 121 handler(header); 122 count++; 123 } 124 125 header = (void *)(ulong) header + header->length; 126 } 127 128 return count; 129 } 130