mirror of
https://git.stationery.faith/corn/corn.git
synced 2024-11-21 19:02:17 +00:00
acpi table loading and shutdown works, plus mmap fix :3
This commit is contained in:
parent
85a9443704
commit
61e7fdf1eb
5 changed files with 140 additions and 126 deletions
|
@ -9,12 +9,12 @@
|
|||
#include "bindings.h"
|
||||
|
||||
struct acpi_header {
|
||||
char signature[4];
|
||||
uint32_t signature;
|
||||
uint32_t length;
|
||||
uint8_t revision;
|
||||
uint8_t checksum;
|
||||
char oem_id[6];
|
||||
char oem_table_id[8];
|
||||
uint8_t oem_id[6];
|
||||
uint8_t oem_table_id[8];
|
||||
uint32_t oem_revision;
|
||||
uint32_t creator_id;
|
||||
uint32_t creator_revision;
|
||||
|
@ -23,9 +23,9 @@ struct acpi_header {
|
|||
// root system descriptor pointer
|
||||
// ACPI 1.0
|
||||
struct rsdp {
|
||||
char signature[8];
|
||||
uint8_t signature[8];
|
||||
uint8_t checksum;
|
||||
char oemid[6];
|
||||
uint8_t oemid[6];
|
||||
uint8_t revision;
|
||||
uint32_t rsdt_addr;
|
||||
} __attribute__((packed));
|
||||
|
@ -38,11 +38,12 @@ struct xsdp {
|
|||
char oemid[6];
|
||||
uint8_t revision;
|
||||
uint32_t rsdt_addr;
|
||||
|
||||
uint32_t length;
|
||||
uint64_t xsdt_addr;
|
||||
uint8_t extendeid_checksum;
|
||||
uint8_t reserved[3];
|
||||
struct {
|
||||
uint32_t length;
|
||||
uint64_t xsdt_addr;
|
||||
uint8_t extendeid_checksum;
|
||||
uint8_t reserved[3];
|
||||
} ext;
|
||||
} __attribute__((packed));
|
||||
|
||||
// root system descriptor table
|
||||
|
@ -50,14 +51,14 @@ struct xsdp {
|
|||
struct rsdt {
|
||||
struct acpi_header h;
|
||||
uint32_t sdt_pointers[];
|
||||
};
|
||||
} __attribute__((packed));
|
||||
|
||||
// eXtended system descriptor table
|
||||
// ACPI 2.0
|
||||
struct xsdt {
|
||||
struct acpi_header h;
|
||||
uint64_t sdt_pointers[];
|
||||
};
|
||||
} __attribute__((packed));
|
||||
|
||||
|
||||
// generic address structure
|
||||
|
@ -69,6 +70,27 @@ struct gas {
|
|||
uint64_t address;
|
||||
};
|
||||
|
||||
// differentiated system description table
|
||||
struct dsdt {
|
||||
struct acpi_header h;
|
||||
char s5_addr[];
|
||||
} __attribute__((packed));
|
||||
|
||||
struct apic {
|
||||
struct acpi_header h;
|
||||
// todo
|
||||
} __attribute__((packed));
|
||||
|
||||
struct hept {
|
||||
struct acpi_header h;
|
||||
// todo
|
||||
} __attribute__((packed));
|
||||
|
||||
struct waet {
|
||||
struct acpi_header h;
|
||||
// todo
|
||||
} __attribute__((packed));
|
||||
|
||||
// fixed acpi description table
|
||||
struct fadt {
|
||||
struct acpi_header h;
|
||||
|
@ -135,15 +157,20 @@ struct fadt {
|
|||
struct gas x_pm_timer_block;
|
||||
struct gas x_gpe0_block;
|
||||
struct gas x_gpe1_block;
|
||||
};
|
||||
} __attribute__((packed));
|
||||
|
||||
struct acpi_state {
|
||||
union {
|
||||
struct xsdt *xsdt;
|
||||
struct rsdt *rsdt;
|
||||
} dst;
|
||||
} sdt;
|
||||
struct fadt *fadt;
|
||||
struct dsdt *dsdt;
|
||||
struct apic *apic;
|
||||
struct hept *hept;
|
||||
struct waet *waet;
|
||||
uint8_t version;
|
||||
struct fadt fadt;
|
||||
|
||||
uint16_t SLP_TYPa;
|
||||
uint16_t SLP_TYPb;
|
||||
uint16_t SLP_EN;
|
||||
|
@ -160,11 +187,10 @@ static bool checksum(uint8_t *data, size_t len) {
|
|||
return sum == 0;
|
||||
}
|
||||
|
||||
static int read_s5_addr(struct acpi_state *state) {
|
||||
uintptr_t ptr = state->fadt.dsdt;
|
||||
char *s5_addr = (void *) (ptr + 36);
|
||||
static int read_s5_addr(struct dsdt *dsdt) {
|
||||
char *s5_addr = dsdt->s5_addr;
|
||||
int dsdt_len = dsdt->h.length - sizeof(struct acpi_header);
|
||||
|
||||
int dsdt_len = *((int *) (ptr+1)) - 36;
|
||||
while (0 < dsdt_len--) {
|
||||
if (memcmp(s5_addr, "_S5_", 4) == 0)
|
||||
break;
|
||||
|
@ -179,15 +205,15 @@ static int read_s5_addr(struct acpi_state *state) {
|
|||
|
||||
if (*s5_addr == 0x0A)
|
||||
s5_addr++; // skip byteprefix
|
||||
state->SLP_TYPa = *(s5_addr)<<10;
|
||||
state.SLP_TYPa = *(s5_addr)<<10;
|
||||
s5_addr++;
|
||||
|
||||
if (*s5_addr == 0x0A)
|
||||
s5_addr++; // skip byteprefix
|
||||
state->SLP_TYPb = *(s5_addr)<<10;
|
||||
state.SLP_TYPb = *(s5_addr)<<10;
|
||||
|
||||
state->SLP_EN = 1<<13;
|
||||
state->SCI_EN = 1;
|
||||
state.SLP_EN = 1<<13;
|
||||
state.SCI_EN = 1;
|
||||
|
||||
} else {
|
||||
return -1;
|
||||
|
@ -199,129 +225,115 @@ static int read_s5_addr(struct acpi_state *state) {
|
|||
return -1;
|
||||
}
|
||||
|
||||
static void *acpi_find_table_rsdt(struct rsdt *rsdt, const char *identifier, int ident_len) {
|
||||
static void acpi_load_table(uint64_t addr);
|
||||
|
||||
static void acpi_load_rsdt_tables(struct rsdt *rsdt) {
|
||||
int entries = (rsdt->h.length - sizeof(rsdt->h)) / 4;
|
||||
|
||||
for (int i = 0; i < entries; i++) {
|
||||
struct acpi_header *h = (struct acpi_header *) (uintptr_t) rsdt->sdt_pointers[i];
|
||||
char buf[6];
|
||||
memcpy(buf, h->signature, 4);
|
||||
buf[4] = '\n';
|
||||
buf[5] = '\0';
|
||||
kputs(buf);
|
||||
if (!strncmp(h->signature, identifier, ident_len))
|
||||
return (void *)h;
|
||||
uint32_t addr = rsdt->sdt_pointers[i];
|
||||
acpi_load_table(addr);
|
||||
}
|
||||
|
||||
// TABLE NOT FOUND
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void *acpi_find_table_xsdt(struct xsdt *xsdt, const char *identifier, int ident_len) {
|
||||
static void acpi_load_xsdt_tables(struct xsdt *xsdt) {
|
||||
int entries = (xsdt->h.length - sizeof(xsdt->h)) / 8;
|
||||
|
||||
for (int i = 0; i < entries; i++) {
|
||||
struct acpi_header *h = (struct acpi_header *) (uintptr_t) xsdt->sdt_pointers[i];
|
||||
if (!strncmp(h->signature, identifier, ident_len))
|
||||
return (void *)h;
|
||||
uint64_t addr = xsdt->sdt_pointers[i];
|
||||
acpi_load_table(addr);
|
||||
}
|
||||
|
||||
// TABLE NOT FOUND
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int acpi_init_rsdt(struct rsdt *rsdt) {
|
||||
#define SIG_RSDT 0x54445352
|
||||
#define SIG_XSDT 0x54445358
|
||||
#define SIG_FACP 0x50434146
|
||||
#define SIG_DSDT 0x54445344
|
||||
#define SIG_APIC 0x43495041
|
||||
#define SIG_HEPT 0x54455048
|
||||
#define SIG_WAET 0x54454157
|
||||
|
||||
kprintf("RSDT: %#016lx\n", (size_t)rsdt);
|
||||
|
||||
rsdt = mmap(rsdt, sizeof(struct rsdt));
|
||||
|
||||
state.dst.rsdt = rsdt;
|
||||
state.version = 0;
|
||||
|
||||
if (!checksum((uint8_t *) &rsdt->h, rsdt->h.length))
|
||||
return -1;
|
||||
|
||||
struct fadt *fadt = acpi_find_table_rsdt(rsdt, "FACP", 4);
|
||||
if (!fadt)
|
||||
return -1;
|
||||
|
||||
if (!checksum((uint8_t *) &fadt->h, fadt->h.length))
|
||||
return -1;
|
||||
|
||||
state.fadt = *fadt;
|
||||
|
||||
return -1;
|
||||
static void acpi_handle_table(struct acpi_header *header) {
|
||||
switch (header->signature) {
|
||||
case SIG_RSDT:
|
||||
state.sdt.rsdt = (struct rsdt *) header;
|
||||
acpi_load_rsdt_tables(state.sdt.rsdt);
|
||||
break;
|
||||
case SIG_XSDT:
|
||||
state.sdt.xsdt = (struct xsdt *) header;
|
||||
acpi_load_xsdt_tables(state.sdt.xsdt);
|
||||
break;
|
||||
case SIG_FACP:
|
||||
state.fadt = (struct fadt *) header;
|
||||
acpi_load_table(state.fadt->dsdt);
|
||||
break;
|
||||
case SIG_DSDT:
|
||||
state.dsdt = (struct dsdt *) header;
|
||||
read_s5_addr(state.dsdt);
|
||||
break;
|
||||
case SIG_APIC:
|
||||
state.apic = (struct apic *) header;
|
||||
break;
|
||||
case SIG_HEPT:
|
||||
state.hept = (struct hept *) header;
|
||||
break;
|
||||
case SIG_WAET:
|
||||
state.waet = (struct waet *) header;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
int acpi_init_xsdt(struct xsdt *xsdt) {
|
||||
static void acpi_load_table(uint64_t addr) {
|
||||
struct acpi_header *temp, *mapped;
|
||||
uint32_t length;
|
||||
|
||||
xsdt = mmap(xsdt, sizeof(struct xsdt));
|
||||
return -1;
|
||||
state.dst.xsdt = xsdt;
|
||||
state.version = 2;
|
||||
|
||||
if (!checksum((uint8_t *) &xsdt->h, xsdt->h.length))
|
||||
return -1;
|
||||
|
||||
struct fadt *fadt = acpi_find_table_xsdt(xsdt, "FACP", 4);
|
||||
if (!fadt)
|
||||
return -1;
|
||||
|
||||
if (!checksum((uint8_t *) &fadt->h, fadt->h.length))
|
||||
return -1;
|
||||
|
||||
state.fadt = *fadt;
|
||||
|
||||
return 0;
|
||||
temp = (struct acpi_header * ) (uintptr_t) addr;
|
||||
mapped = mmap(temp, sizeof(struct acpi_header));
|
||||
length = mapped->length;
|
||||
unmap(mapped);
|
||||
mapped = mmap(temp, length);
|
||||
if (!checksum((uint8_t *) mapped, mapped->length)) {
|
||||
unmap(mapped);
|
||||
return;
|
||||
}
|
||||
kprintf("%.*s: %#016lx\n", 4, (char*)&mapped->signature, (size_t)temp);
|
||||
acpi_handle_table(mapped);
|
||||
}
|
||||
|
||||
int acpi_init(void *rootsdp) {
|
||||
|
||||
memset(&state, 0, sizeof(struct acpi_state));
|
||||
|
||||
struct rsdp *rsdp = (struct rsdp *) rootsdp;
|
||||
|
||||
if (!checksum((uint8_t *)rsdp, sizeof(struct rsdp)))
|
||||
return -1;
|
||||
|
||||
if (strncmp(rsdp->signature, "RSD PTR ", 8) != 0) {
|
||||
if (memcmp(rsdp->signature, "RSD PTR ", 8) != 0) {
|
||||
panic("invalid acpi rsdp signature: %.*s\n", 8, rsdp->signature);
|
||||
}
|
||||
|
||||
int res;
|
||||
|
||||
if (rsdp->revision == 0) {
|
||||
state.version = 0;
|
||||
kprintf("ACPI 1.0\n");
|
||||
kprintf("RSDP: %#016lx\n", (size_t)rsdp);
|
||||
res = acpi_init_rsdt(
|
||||
(struct rsdt *) (uintptr_t) rsdp->rsdt_addr
|
||||
);
|
||||
acpi_load_table(rsdp->rsdt_addr);
|
||||
} else if (rsdp->revision == 2) {
|
||||
state.version = 2;
|
||||
struct xsdp *xsdp = (struct xsdp *) rsdp;
|
||||
kprintf("ACPI 2.0\n");
|
||||
kprintf("XSDP: %#016lx\n", (size_t)xsdp);
|
||||
res = acpi_init_xsdt(
|
||||
(struct xsdt *) (uintptr_t) xsdp->xsdt_addr
|
||||
);
|
||||
acpi_load_table(xsdp->ext.xsdt_addr);
|
||||
} else {
|
||||
panic("invalid acpi rev: %d\n", rsdp->revision);
|
||||
}
|
||||
|
||||
if (res) {
|
||||
kprintf("...acpi failed to load\n\n");
|
||||
return res;
|
||||
}
|
||||
kprintf("\n");
|
||||
|
||||
kprintf("\n\n");
|
||||
|
||||
int ret = read_s5_addr(&state);
|
||||
if (!ret)
|
||||
return ret;
|
||||
|
||||
outb(state.fadt.smi_command_port,state.fadt.acpi_enable);
|
||||
outb(state.fadt->smi_command_port,state.fadt->acpi_enable);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int acpi_shutdown(void) {
|
||||
outw((unsigned int) state.fadt.pm1_a_control_block, state.SLP_TYPb | state.SLP_EN);
|
||||
outw((unsigned int) state.fadt->pm1_a_control_block, state.SLP_TYPb | state.SLP_EN);
|
||||
return -1;
|
||||
}
|
||||
|
|
|
@ -135,7 +135,7 @@ void idt_exception_handler(uint64_t exception, uint64_t code, struct isr_regs *s
|
|||
kprintf("Error code 0x%lX\n", code);
|
||||
|
||||
if (exception == EX_PAGE_FAULT) {
|
||||
kprintf("Page fault address: 0x%lX\n", cr2);
|
||||
kprintf("Page fault address: %#016lx\n", cr2);
|
||||
}
|
||||
|
||||
kputs("\n");
|
||||
|
|
|
@ -539,20 +539,20 @@ void paging_init(void) {
|
|||
|
||||
static inline void *page_align(void *addr) {
|
||||
uintptr_t a = (uintptr_t) addr;
|
||||
a += PAGE_SIZE - 1;
|
||||
a /= PAGE_SIZE;
|
||||
a *= PAGE_SIZE;
|
||||
return (void *) a;
|
||||
}
|
||||
|
||||
void *mmap(void *addr, size_t len) {
|
||||
len += (long)addr % PAGE_SIZE;
|
||||
long pages = (len + PAGE_SIZE - 1) / PAGE_SIZE;
|
||||
void *phys = page_align(addr);
|
||||
ptrdiff_t error = (char*)addr - (char*)phys;
|
||||
len += error;
|
||||
long pages = len / PAGE_SIZE + 1;
|
||||
void *virt = virtaddr_alloc(pages);
|
||||
if (virt == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
void *phys = page_align(addr);
|
||||
if (map_pages(
|
||||
kernel_pml4,
|
||||
virt,
|
||||
|
@ -563,7 +563,7 @@ void *mmap(void *addr, size_t len) {
|
|||
virtaddr_free(virt);
|
||||
return NULL;
|
||||
}
|
||||
return virt;
|
||||
return (char*)virt + error;
|
||||
}
|
||||
|
||||
void unmap(void *addr) {
|
||||
|
|
|
@ -15,12 +15,12 @@ void kmain(struct boot_info *info) {
|
|||
|
||||
kprintf("enterd kmain\n");
|
||||
|
||||
//acpi_shutdown();
|
||||
|
||||
// pages are allocated on write :3
|
||||
char *test = kalloc(5);
|
||||
*test = 1;
|
||||
|
||||
//log_backtrace();
|
||||
|
||||
while (1) {
|
||||
screen_redraw();
|
||||
// loop so we dont halt
|
||||
|
|
24
src/print.c
24
src/print.c
|
@ -95,6 +95,7 @@ static enum printtype conversion_to_printtype(enum format_conversion conversion)
|
|||
return OCTAL;
|
||||
case FMT_HEX:
|
||||
case FMT_HEX_UPPER:
|
||||
case FMT_PTR:
|
||||
return HEX;
|
||||
default:
|
||||
return NONE;
|
||||
|
@ -377,11 +378,12 @@ static void print_number_buffer(
|
|||
const char *buf, // buffer containing the text we want to print
|
||||
struct spacing spacing, // the spacing on the left right and middle
|
||||
enum printtype type,
|
||||
enum charcase cc
|
||||
enum charcase cc,
|
||||
enum format_flag flags
|
||||
) {
|
||||
|
||||
// put the 0x at the start of the string
|
||||
if (spacing.left && spacing.zero && type == HEX) {
|
||||
if (spacing.left && spacing.zero && type == HEX && (flags & FLG_ALTERNATE)) {
|
||||
if (cc == UPPERCASE) {
|
||||
kputs("0X");
|
||||
} else {
|
||||
|
@ -389,7 +391,7 @@ static void print_number_buffer(
|
|||
}
|
||||
}
|
||||
|
||||
if ((!spacing.left || !spacing.zero) && type == OCTAL) {
|
||||
if ((!spacing.left || !spacing.zero) && type == OCTAL && (flags & FLG_ALTERNATE)) {
|
||||
kputc('0');
|
||||
}
|
||||
|
||||
|
@ -397,7 +399,7 @@ static void print_number_buffer(
|
|||
spacing.zero ? kputc('0') : kputc(' ');
|
||||
}
|
||||
|
||||
if ((!spacing.left || !spacing.zero) && type == HEX) {
|
||||
if ((!spacing.left || !spacing.zero) && type == HEX && (flags & FLG_ALTERNATE)) {
|
||||
if (cc == UPPERCASE) {
|
||||
kputs("0X");
|
||||
} else {
|
||||
|
@ -457,18 +459,18 @@ static struct spacing get_spacing(
|
|||
}
|
||||
|
||||
unsigned gap = 0;
|
||||
if (max > length) {
|
||||
gap = max - length;
|
||||
if (min > length) {
|
||||
gap = min - length;
|
||||
}
|
||||
|
||||
spacing.length = length;
|
||||
|
||||
if (flags & FLG_LEFT_ALIGN) {
|
||||
spacing.left = gap;
|
||||
spacing.right = 0;
|
||||
} else {
|
||||
spacing.left = 0;
|
||||
spacing.right = gap;
|
||||
} else {
|
||||
spacing.left = gap;
|
||||
spacing.right = 0;
|
||||
}
|
||||
|
||||
spacing.zero = (flags & FLG_ZERO);
|
||||
|
@ -574,7 +576,7 @@ static void print_signed_number(
|
|||
unsigned length = strlen(ptr);
|
||||
struct spacing spacing =
|
||||
get_spacing(width, precision, flags, length);
|
||||
print_number_buffer(ptr, spacing, type, cc);
|
||||
print_number_buffer(ptr, spacing, type, cc, flags);
|
||||
}
|
||||
|
||||
static void print_unsigned_number(
|
||||
|
@ -591,7 +593,7 @@ static void print_unsigned_number(
|
|||
unsigned length = strlen(ptr);
|
||||
struct spacing spacing =
|
||||
get_spacing(width, precision, flags, length);
|
||||
print_number_buffer(ptr, spacing, type, cc);
|
||||
print_number_buffer(ptr, spacing, type, cc, flags);
|
||||
}
|
||||
|
||||
static bool is_conversion_number(enum format_conversion conversion) {
|
||||
|
|
Loading…
Reference in a new issue