x86_64: add a basic ACPI driver
This commit is contained in:
5
Makefile
5
Makefile
@@ -6,7 +6,6 @@ MAKEFILE_PATH := $(abspath $(lastword $(MAKEFILE_LIST)))
|
|||||||
ROOT_DIR := $(patsubst %/,%,$(dir $(MAKEFILE_PATH)))
|
ROOT_DIR := $(patsubst %/,%,$(dir $(MAKEFILE_PATH)))
|
||||||
|
|
||||||
include tools/make/gcc-cross-compile.mk
|
include tools/make/gcc-cross-compile.mk
|
||||||
include arch/$(ARCH)/config.mk
|
|
||||||
|
|
||||||
BUILD_DIR := build
|
BUILD_DIR := build
|
||||||
|
|
||||||
@@ -14,9 +13,7 @@ BUILD_DIR := build
|
|||||||
# Architecture-specific source files
|
# Architecture-specific source files
|
||||||
####################################
|
####################################
|
||||||
|
|
||||||
ARCH_C_FILES := $(wildcard arch/$(ARCH)/*.c)
|
include arch/$(ARCH)/config.mk
|
||||||
ARCH_ASM_FILES := $(wildcard arch/$(ARCH)/*.S)
|
|
||||||
ARCH_OBJ := $(addprefix $(BUILD_DIR)/,$(ARCH_C_FILES:.c=.o) $(ARCH_ASM_FILES:.S=.o))
|
|
||||||
|
|
||||||
####################################
|
####################################
|
||||||
# Platform-independent kernel source files
|
# Platform-independent kernel source files
|
||||||
|
|||||||
9
arch/x86_64/acpi/acpi.c
Normal file
9
arch/x86_64/acpi/acpi.c
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
#include <arch/acpi.h>
|
||||||
|
#include <socks/printk.h>
|
||||||
|
|
||||||
|
kern_status_t acpi_init(void)
|
||||||
|
{
|
||||||
|
struct acpi_sdt *fadt = acpi_find_sdt(ACPI_SIG_FADT);
|
||||||
|
printk("acpi: FADT=%p", fadt);
|
||||||
|
return KERN_OK;
|
||||||
|
}
|
||||||
102
arch/x86_64/acpi/rsdp.c
Normal file
102
arch/x86_64/acpi/rsdp.c
Normal file
@@ -0,0 +1,102 @@
|
|||||||
|
#include <arch/acpi.h>
|
||||||
|
#include <socks/vm.h>
|
||||||
|
#include <socks/printk.h>
|
||||||
|
#include <stddef.h>
|
||||||
|
|
||||||
|
static struct acpi_rsdp rsdp;
|
||||||
|
|
||||||
|
static struct acpi_rsdp_10 *search_for_rsdp(void)
|
||||||
|
{
|
||||||
|
uint64_t *start = vm_phys_to_virt(0x80000);
|
||||||
|
uint64_t *end = vm_phys_to_virt(0xFFFFF);
|
||||||
|
|
||||||
|
for (uint64_t *i = start; i < end; i++) {
|
||||||
|
if (*i == ACPI_SIG_RSDP) {
|
||||||
|
return (struct acpi_rsdp_10 *)i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int init_rsdt(void)
|
||||||
|
{
|
||||||
|
struct acpi_rsdp_10 *x = search_for_rsdp();
|
||||||
|
|
||||||
|
if (!x) {
|
||||||
|
printk("acpi: not available");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t *b = (uint8_t *)x;
|
||||||
|
size_t chksum = 0;
|
||||||
|
for (unsigned int i = 0; i < sizeof *x; i++) {
|
||||||
|
chksum += b[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
if (chksum & 0xFF) {
|
||||||
|
printk("acpi: not available");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (x->r_revision == 2) {
|
||||||
|
chksum = 0;
|
||||||
|
|
||||||
|
for (unsigned int i = sizeof *x; i < sizeof(struct acpi_rsdp_20); i++) {
|
||||||
|
chksum += b[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
if (chksum & 0xFF) {
|
||||||
|
printk("acpi: not available");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
memcpy(&rsdp.rsdp_20, x, sizeof rsdp.rsdp_20);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct acpi_sdt *find_via_rsdt(uint32_t sig)
|
||||||
|
{
|
||||||
|
struct acpi_rsdt *rsdt = vm_phys_to_virt(rsdp.rsdp_10.r_rsdt_ptr);
|
||||||
|
unsigned long nr_tables = (rsdt->r_header.s_length - sizeof(struct acpi_sdt)) / sizeof(uint32_t);
|
||||||
|
|
||||||
|
for (unsigned long i = 0; i < nr_tables; i++) {
|
||||||
|
struct acpi_sdt *table = vm_phys_to_virt(rsdt->r_tables[i]);
|
||||||
|
if (*(uint32_t *)table == sig) {
|
||||||
|
return table;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct acpi_sdt *find_via_xsdt(uint32_t sig)
|
||||||
|
{
|
||||||
|
struct acpi_xsdt *xsdt = vm_phys_to_virt(rsdp.rsdp_20.r_xsdt_ptr);
|
||||||
|
unsigned long nr_tables = (xsdt->x_header.s_length - sizeof(struct acpi_sdt)) / sizeof(uint64_t);
|
||||||
|
|
||||||
|
for (unsigned long i = 0; i < nr_tables; i++) {
|
||||||
|
struct acpi_sdt *table = vm_phys_to_virt(xsdt->x_tables[i]);
|
||||||
|
if (*(uint32_t *)table == sig) {
|
||||||
|
return table;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct acpi_sdt *acpi_find_sdt(uint32_t sig)
|
||||||
|
{
|
||||||
|
if (!rsdp.rsdp_10.r_sig[0]) {
|
||||||
|
if (init_rsdt() != 0) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (rsdp.rsdp_10.r_revision == 0) {
|
||||||
|
return find_via_rsdt(sig);
|
||||||
|
} else {
|
||||||
|
return find_via_xsdt(sig);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,2 +1,8 @@
|
|||||||
ARCH_CFLAGS := -z max-page-size=0x1000 -m64 -mcmodel=large -mno-red-zone -mno-mmx -mno-sse -mno-sse2 -D_64BIT -DBYTE_ORDER=1234
|
ARCH_CFLAGS := -z max-page-size=0x1000 -m64 -mcmodel=large -mno-red-zone -mno-mmx -mno-sse -mno-sse2 -D_64BIT -DBYTE_ORDER=1234
|
||||||
ARCH_LDFLAGS := -z max-page-size=0x1000 -T arch/x86_64/layout.ld
|
ARCH_LDFLAGS := -z max-page-size=0x1000 -T arch/x86_64/layout.ld
|
||||||
|
|
||||||
|
ARCH_DIR := arch/$(ARCH)
|
||||||
|
|
||||||
|
ARCH_C_FILES := $(wildcard $(ARCH_DIR)/*.c) $(wildcard $(ARCH_DIR)/acpi/*.c)
|
||||||
|
ARCH_ASM_FILES := $(wildcard $(ARCH_DIR)/*.S)
|
||||||
|
ARCH_OBJ := $(addprefix $(BUILD_DIR)/,$(ARCH_C_FILES:.c=.o) $(ARCH_ASM_FILES:.S=.o))
|
||||||
|
|||||||
61
arch/x86_64/include/arch/acpi.h
Normal file
61
arch/x86_64/include/arch/acpi.h
Normal file
@@ -0,0 +1,61 @@
|
|||||||
|
#ifndef ARCH_ACPI_H_
|
||||||
|
#define ARCH_ACPI_H_
|
||||||
|
|
||||||
|
#include <socks/compiler.h>
|
||||||
|
#include <socks/status.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
#define ACPI_SIG_RSDP 0x2052545020445352ULL
|
||||||
|
#define ACPI_SIG_FADT 0x50434146
|
||||||
|
|
||||||
|
struct acpi_rsdp_10 {
|
||||||
|
char r_sig[8];
|
||||||
|
uint8_t r_chksum;
|
||||||
|
char r_oem[6];
|
||||||
|
uint8_t r_revision;
|
||||||
|
uint32_t r_rsdt_ptr;
|
||||||
|
} __packed;
|
||||||
|
|
||||||
|
struct acpi_rsdp_20 {
|
||||||
|
struct acpi_rsdp_10 r_base;
|
||||||
|
|
||||||
|
uint32_t r_length;
|
||||||
|
uint64_t r_xsdt_ptr;
|
||||||
|
uint8_t r_chksum_ext;
|
||||||
|
uint8_t r_reserved[3];
|
||||||
|
} __packed;
|
||||||
|
|
||||||
|
struct acpi_rsdp {
|
||||||
|
union {
|
||||||
|
struct acpi_rsdp_10 rsdp_10;
|
||||||
|
struct acpi_rsdp_20 rsdp_20;
|
||||||
|
};
|
||||||
|
} __packed;
|
||||||
|
|
||||||
|
struct acpi_sdt {
|
||||||
|
char s_sig[4];
|
||||||
|
uint32_t s_length;
|
||||||
|
uint8_t s_revision;
|
||||||
|
uint8_t s_chksum;
|
||||||
|
char s_oem[6];
|
||||||
|
char s_oem_table[8];
|
||||||
|
uint32_t s_oem_revision;
|
||||||
|
uint32_t s_creator;
|
||||||
|
uint32_t s_creator_revision;
|
||||||
|
} __packed;
|
||||||
|
|
||||||
|
struct acpi_rsdt {
|
||||||
|
struct acpi_sdt r_header;
|
||||||
|
uint32_t r_tables[];
|
||||||
|
} __packed;
|
||||||
|
|
||||||
|
struct acpi_xsdt {
|
||||||
|
struct acpi_sdt x_header;
|
||||||
|
uint64_t x_tables[];
|
||||||
|
} __packed;
|
||||||
|
|
||||||
|
extern kern_status_t acpi_init(void);
|
||||||
|
|
||||||
|
extern struct acpi_sdt *acpi_find_sdt(uint32_t sig);
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -7,6 +7,7 @@
|
|||||||
#include <socks/printk.h>
|
#include <socks/printk.h>
|
||||||
#include <socks/machine/cpu.h>
|
#include <socks/machine/cpu.h>
|
||||||
#include <arch/vgacon.h>
|
#include <arch/vgacon.h>
|
||||||
|
#include <arch/acpi.h>
|
||||||
|
|
||||||
#define PTR32(x) ((void *)((uintptr_t)(x)))
|
#define PTR32(x) ((void *)((uintptr_t)(x)))
|
||||||
|
|
||||||
@@ -51,6 +52,8 @@ int ml_init(uintptr_t arg)
|
|||||||
|
|
||||||
pmap_bootstrap();
|
pmap_bootstrap();
|
||||||
|
|
||||||
|
acpi_init();
|
||||||
|
|
||||||
vm_zone_descriptor_t vm_zones[] = {
|
vm_zone_descriptor_t vm_zones[] = {
|
||||||
{ .zd_id = VM_ZONE_DMA, .zd_node = 0, .zd_name = "dma", .zd_base = 0x00, .zd_limit = 0xffffff },
|
{ .zd_id = VM_ZONE_DMA, .zd_node = 0, .zd_name = "dma", .zd_base = 0x00, .zd_limit = 0xffffff },
|
||||||
{ .zd_id = VM_ZONE_NORMAL, .zd_node = 0, .zd_name = "normal", .zd_base = 0x1000000, .zd_limit = UINTPTR_MAX },
|
{ .zd_id = VM_ZONE_NORMAL, .zd_node = 0, .zd_name = "normal", .zd_base = 0x1000000, .zd_limit = UINTPTR_MAX },
|
||||||
|
|||||||
Reference in New Issue
Block a user