@@ -70,6 +70,21 @@ efi_status_t efi_exit_boot_services(void *handle, unsigned long mapkey)
return efi_bs_call(exit_boot_services, handle, mapkey);
}
+efi_status_t efi_get_system_config_table(efi_guid_t table_guid, void **table)
+{
+ size_t i;
+ efi_config_table_t *tables;
+
+ tables = (efi_config_table_t *)efi_system_table->tables;
+ for (i = 0; i < efi_system_table->nr_tables; i++) {
+ if (!memcmp(&table_guid, &tables[i].guid, sizeof(efi_guid_t))) {
+ *table = tables[i].table;
+ return EFI_SUCCESS;
+ }
+ }
+ return EFI_NOT_FOUND;
+}
+
efi_status_t efi_main(efi_handle_t handle, efi_system_table_t *sys_tab)
{
int ret;
@@ -16,6 +16,7 @@
efi_status_t _relocate(long ldbase, Elf64_Dyn *dyn, efi_handle_t handle, efi_system_table_t *sys_tab);
efi_status_t efi_get_memory_map(struct efi_boot_memmap *map);
efi_status_t efi_exit_boot_services(void *handle, unsigned long mapkey);
+efi_status_t efi_get_system_config_table(efi_guid_t table_guid, void **table);
efi_status_t efi_main(efi_handle_t handle, efi_system_table_t *sys_tab);
#endif /* _EFI_H_ */
@@ -58,6 +58,21 @@ typedef guid_t efi_guid_t;
(b) & 0xff, ((b) >> 8) & 0xff, \
(c) & 0xff, ((c) >> 8) & 0xff, d } }
+#define ACPI_TABLE_GUID EFI_GUID(0xeb9d2d30, 0x2d88, 0x11d3, 0x9a, 0x16, 0x00, 0x90, 0x27, 0x3f, 0xc1, 0x4d)
+
+typedef struct {
+ efi_guid_t guid;
+ u32 table;
+} efi_config_table_32_t;
+
+typedef union {
+ struct {
+ efi_guid_t guid;
+ void *table;
+ };
+ efi_config_table_32_t mixed_mode;
+} efi_config_table_t;
+
/*
* Generic EFI table header
*/
@@ -1,9 +1,37 @@
#include "libcflat.h"
#include "acpi.h"
+#ifdef TARGET_EFI
+struct rsdp_descriptor *efi_rsdp = NULL;
+
+void setup_efi_rsdp(struct rsdp_descriptor *rsdp) {
+ efi_rsdp = rsdp;
+}
+
+static struct rsdp_descriptor *get_rsdp(void) {
+ if (efi_rsdp == NULL) {
+ printf("Can't find RSDP from UEFI, maybe setup_efi_rsdp() was not called\n");
+ }
+ return efi_rsdp;
+}
+#else
+static struct rsdp_descriptor *get_rsdp(void) {
+ struct rsdp_descriptor *rsdp;
+ unsigned long addr;
+ for(addr = 0xf0000; addr < 0x100000; addr += 16) {
+ rsdp = (void*)addr;
+ if (rsdp->signature == RSDP_SIGNATURE_8BYTE)
+ break;
+ }
+ if (addr == 0x100000) {
+ return NULL;
+ }
+ return rsdp;
+}
+#endif /* TARGET_EFI */
+
void* find_acpi_table_addr(u32 sig)
{
- unsigned long addr;
struct rsdp_descriptor *rsdp;
struct rsdt_descriptor_rev1 *rsdt;
void *end;
@@ -19,12 +47,8 @@ void* find_acpi_table_addr(u32 sig)
return (void*)(ulong)fadt->firmware_ctrl;
}
- for(addr = 0xf0000; addr < 0x100000; addr += 16) {
- rsdp = (void*)addr;
- if (rsdp->signature == 0x2052545020445352LL)
- break;
- }
- if (addr == 0x100000) {
+ rsdp = get_rsdp();
+ if (rsdp == NULL) {
printf("Can't find RSDP\n");
return 0;
}
@@ -11,6 +11,13 @@
#define FACP_SIGNATURE ACPI_SIGNATURE('F','A','C','P')
#define FACS_SIGNATURE ACPI_SIGNATURE('F','A','C','S')
+
+#define ACPI_SIGNATURE_8BYTE(c1, c2, c3, c4, c5, c6, c7, c8) \
+ ((uint64_t)(ACPI_SIGNATURE(c1, c2, c3, c4))) | \
+ ((uint64_t)(ACPI_SIGNATURE(c5, c6, c7, c8)) << 32)
+
+#define RSDP_SIGNATURE_8BYTE (ACPI_SIGNATURE_8BYTE('R', 'S', 'D', ' ', 'P', 'T', 'R', ' '))
+
struct rsdp_descriptor { /* Root System Descriptor Pointer */
u64 signature; /* ACPI signature, contains "RSD PTR " */
u8 checksum; /* To make sum of struct == 0 */
@@ -101,4 +108,8 @@ struct facs_descriptor_rev1
void* find_acpi_table_addr(u32 sig);
+#ifdef TARGET_EFI
+void setup_efi_rsdp(struct rsdp_descriptor *rsdp);
+#endif /* TARGET_EFI */
+
#endif
@@ -6,6 +6,7 @@ unsigned long setup_tss(void);
#endif /* __x86_64__ */
#ifdef TARGET_EFI
+#include "x86/acpi.h"
#include "x86/apic.h"
#include "x86/smp.h"
#include "efi.h"
@@ -19,6 +20,7 @@ unsigned long setup_tss(void);
typedef struct {
phys_addr_t free_mem_start;
phys_addr_t free_mem_size;
+ struct rsdp_descriptor *rsdp;
} efi_bootinfo_t;
void setup_efi_bootinfo(efi_bootinfo_t *efi_bootinfo);
@@ -171,6 +171,7 @@ void setup_efi_bootinfo(efi_bootinfo_t *efi_bootinfo)
{
efi_bootinfo->free_mem_size = 0;
efi_bootinfo->free_mem_start = 0;
+ efi_bootinfo->rsdp = NULL;
}
static efi_status_t setup_pre_boot_memory(unsigned long *mapkey, efi_bootinfo_t *efi_bootinfo)
@@ -221,6 +222,11 @@ static efi_status_t setup_pre_boot_memory(unsigned long *mapkey, efi_bootinfo_t
return EFI_SUCCESS;
}
+static efi_status_t setup_pre_boot_rsdp(efi_bootinfo_t *efi_bootinfo)
+{
+ return efi_get_system_config_table(ACPI_TABLE_GUID, (void **)&efi_bootinfo->rsdp);
+}
+
efi_status_t setup_efi_pre_boot(unsigned long *mapkey, efi_bootinfo_t *efi_bootinfo)
{
efi_status_t status;
@@ -239,6 +245,12 @@ efi_status_t setup_efi_pre_boot(unsigned long *mapkey, efi_bootinfo_t *efi_booti
return status;
}
+ status = setup_pre_boot_rsdp(efi_bootinfo);
+ if (status != EFI_SUCCESS) {
+ printf("Cannot find RSDP in EFI system table\n");
+ return status;
+ }
+
return EFI_SUCCESS;
}
@@ -261,6 +273,7 @@ void setup_efi(efi_bootinfo_t *efi_bootinfo)
enable_x2apic();
smp_init();
phys_alloc_init(efi_bootinfo->free_mem_start, efi_bootinfo->free_mem_size);
+ setup_efi_rsdp(efi_bootinfo->rsdp);
}
#endif /* TARGET_EFI */