aboutsummaryrefslogtreecommitdiff
path: root/src/kernel/acpi
diff options
context:
space:
mode:
authorMarvin Borner2020-04-18 00:07:37 +0200
committerMarvin Borner2020-04-18 00:07:37 +0200
commit8d78616a2b80c7625c1aa9ca4733e48a8bf8bf22 (patch)
tree894bddb357ca1976fcfd3b54d1e8fe48bbac569b /src/kernel/acpi
parent27c38d3f6e473d2bf7075fb364db148f22aca203 (diff)
Completely reworked ACPI tables
I'm too exhausted right now, but I rediscovered the memory mapping issue of my ACPI implementatio and need to fix it ASAP. Otherwise I won't be able to use any ACPI table without causing a page fault. I have no clue why exactly this is happening and the internet says that I shouldn't need to memory map them. Well, I'll look into it later.
Diffstat (limited to 'src/kernel/acpi')
-rw-r--r--src/kernel/acpi/acpi.c204
-rw-r--r--src/kernel/acpi/acpi.h134
2 files changed, 139 insertions, 199 deletions
diff --git a/src/kernel/acpi/acpi.c b/src/kernel/acpi/acpi.c
index 2bb097a..b348613 100644
--- a/src/kernel/acpi/acpi.c
+++ b/src/kernel/acpi/acpi.c
@@ -1,188 +1,60 @@
// Important specification: https://uefi.org/sites/default/files/resources/ACPI_6_2.pdf
// HPET: https://www.intel.com/content/dam/www/public/us/en/documents/technical-specifications/software-developers-hpet-spec-1-0a.pdf
-#include <kernel/io/io.h>
-#include <kernel/lib/lib.h>
-#include <kernel/timer/timer.h>
-#include <kernel/acpi/acpi.h>
#include <stddef.h>
#include <kernel/system.h>
+#include <kernel/multiboot.h>
+#include <kernel/io/io.h>
+#include <kernel/lib/lib.h>
+#include <kernel/lib/stdlib.h>
#include <kernel/lib/stdio.h>
+#include <kernel/acpi/acpi.h>
+#include <kernel/memory/paging.h>
-struct FADT *fadt;
-uint32_t *SMI_CMD;
-char ACPI_ENABLE;
-char ACPI_DISABLE;
-uint32_t *PM1a_CNT;
-uint32_t *PM1b_CNT;
-int SLP_TYPa;
-int SLP_TYPb;
-int SLP_EN;
-int SCI_EN;
-char PM1_CNT_LEN;
-
-unsigned int *acpi_check_rsd_ptr(unsigned int *ptr)
-{
- char *sig = "RSD PTR ";
- struct RSD_ptr *rsdp = (struct RSD_ptr *)ptr;
- char *bptr;
- char check = 0;
- unsigned int i;
-
- if (memcmp(sig, rsdp, 8) == 0) {
- bptr = (char *)ptr;
- for (i = 0; i < sizeof(struct RSD_ptr); i++) {
- check += *bptr;
- bptr++;
- }
-
- if (check == 0) {
- return (unsigned int *)rsdp->rsdt_address;
- }
- }
-
- return NULL;
-}
+struct rsdt *rsdt;
+struct fadt *fadt;
+struct hpet *hpet;
+struct apic *apic;
-unsigned int *acpi_get_rsd_ptr()
+void acpi_init(struct rsdp *rsdp)
{
- unsigned int *addr;
- unsigned int *rsdp;
-
- for (addr = (unsigned int *)0x000E0000; (int)addr < 0x00100000;
- addr += 0x10 / sizeof(addr)) {
- rsdp = acpi_check_rsd_ptr(addr);
- if (rsdp != NULL)
- return rsdp;
- }
-
- int ebda = *((short *)0x40E);
- ebda = ebda * 0x10 & 0x000FFFFF;
-
- for (addr = (unsigned int *)ebda; (int)addr < ebda + 1024; addr += 0x10 / sizeof(addr)) {
- rsdp = acpi_check_rsd_ptr(addr);
- if (rsdp != NULL)
- return rsdp;
- }
-
- return NULL;
-}
-
-int acpi_enable()
-{
- if ((inw((uint16_t)(unsigned int)PM1a_CNT) & SCI_EN) == 0) {
- if (SMI_CMD != 0 && ACPI_ENABLE != 0) {
- outb((uint16_t)(unsigned int)SMI_CMD, (uint8_t)ACPI_ENABLE); // Enable ACPI
- // Try 3s until ACPI is enabled
- int i;
- for (i = 0; i < 300; i++) {
- if ((inw((uint16_t)(unsigned int)PM1a_CNT) & SCI_EN) == 1)
- break;
- timer_wait(1);
- }
- if (PM1b_CNT != 0)
- for (; i < 300; i++) {
- if ((inw((uint16_t)(unsigned int)PM1b_CNT) & SCI_EN) == 1)
- break;
- timer_wait(1);
- }
- if (i < 300) {
- return 0; // Successfully enabled ACPI
- } else {
- warn("ACPI couldn't be enabled!");
- return -1; // ACPI couldn't be enabled
+ // TODO: Fix usage of ACPI tables after paging!
+ if (strncmp(rsdp->signature, "RSD PTR ", 8) == 0) {
+ rsdt = (struct rsdt *)rsdp->rsdt_address;
+ int entries = (rsdt->header.length - sizeof(rsdt->header)) / 4;
+
+ for (int i = 0; i < entries; i++) {
+ struct sdt_header *header = (struct sdt_header *)rsdt->sdt_pointer[i];
+ if (strncmp(header->signature, "FACP", 4) == 0) {
+ info("Found FADT");
+ fadt = (struct fadt *)header;
+ } else if (strncmp(header->signature, "HPET", 4) == 0) {
+ info("Found HPET");
+ hpet = (struct hpet *)header;
+ } else if (strncmp(header->signature, "APIC", 4) == 0) {
+ info("Found MADT");
+ apic = (struct apic *)header;
}
- } else {
- warn("ACPI is not supported!");
- return -1; // ACPI is not supported
}
} else {
- warn("ACPI was already enabled!");
- return 0; // ACPI was already enabled
+ warn("Wrong RSD signature!");
}
}
-int acpi_install()
+void acpi_old_init(struct multiboot_tag_old_acpi *tag)
{
- unsigned int *ptr = acpi_get_rsd_ptr();
-
- int success = 0;
-
- if (ptr != NULL && memcmp(ptr, "RSDT", 4) == 0) {
- int entries = *(ptr + 1);
- entries = (entries - 36) / 4;
- ptr += 36 / 4;
-
- while (0 < entries--) {
- if (memcmp((unsigned int *)*ptr, "FACP", 4) == 0) {
- fadt = (struct FADT
- *)*ptr; // TODO: Allocate ACPI tables after paging (page fault)!
- if (memcmp((unsigned int *)fadt->DSDT, "DSDT", 4) == 0) {
- char *S5Addr = (char *)fadt->DSDT + 36;
- int dsdt_length = (int)(*(fadt->DSDT + 1) - 36);
- while (0 < dsdt_length--) {
- if (memcmp(S5Addr, "_S5_", 4) == 0)
- break;
- S5Addr++;
- }
- if (dsdt_length > 0) {
- // TODO: Implement device detection via DSDT ACPI (p199 -> AML)
- if ((*(S5Addr - 1) == 0x08 ||
- (*(S5Addr - 2) == 0x08 &&
- *(S5Addr - 1) == '\\')) &&
- *(S5Addr + 4) == 0x12) {
- S5Addr += 5;
- S5Addr += ((*S5Addr & 0xC0) >> 6) + 2;
-
- if (*S5Addr == 0x0A)
- S5Addr++;
- SLP_TYPa = *(S5Addr) << 10;
- S5Addr++;
-
- if (*S5Addr == 0x0A)
- S5Addr++;
- SLP_TYPb = *(S5Addr) << 10;
-
- SMI_CMD = fadt->SMI_CMD;
-
- ACPI_ENABLE = fadt->ACPI_ENABLE;
- ACPI_DISABLE = fadt->ACPI_DISABLE;
-
- PM1a_CNT = fadt->PM1a_CNT_BLK;
- PM1b_CNT = fadt->PM1b_CNT_BLK;
-
- PM1_CNT_LEN = fadt->PM1_CNT_LEN;
-
- SLP_EN = 1 << 13;
- SCI_EN = 1;
-
- acpi_enable();
- vga_log("Installed ACPI");
-
- success = 1;
- } // Else: \_S5 parse error
- } // Else: \_S5 not present
- } // Else: DSDT invalid
- }
- if (memcmp((unsigned int *)*ptr, "HPET", 4) == 0) {
- hpet = (struct HPET *)*ptr;
- //log("%c%c%c%c", hpet->signature[0], hpet->signature[1],
- //hpet->signature[2], hpet->signature[3]);
- //log("%d", hpet->legacy_replacement);
- //log("%d", hpet->address.address);
- }
- ptr++;
- } // Else: no valid FADT present
- } else {
- warn("ACPI is not supported!");
- }
+ acpi_init((struct rsdp *)tag->rsdp);
+}
- return success == 1 ? 0 : -1;
+void acpi_new_init(struct multiboot_tag_new_acpi *tag)
+{
+ acpi_init((struct rsdp *)tag->rsdp);
}
void acpi_poweroff()
{
cli();
+ /*
if (SCI_EN == 0) {
warn("ACPI shutdown is not supported");
return;
@@ -197,14 +69,20 @@ void acpi_poweroff()
outw(0x604, 0x2000); // QEMU
outw(0x4004, 0x3400); // VirtualBox
}
+ */
}
void reboot()
{
cli();
+ outb(fadt->reset_reg.address, fadt->reset_value);
+ halt_loop();
+
+ /* else?
uint8_t good = 0x02;
while (good & 0x02)
good = inb(0x64);
outb(0x64, 0xFE);
halt_loop();
+ */
}
diff --git a/src/kernel/acpi/acpi.h b/src/kernel/acpi/acpi.h
index 1d3905f..886dc6c 100644
--- a/src/kernel/acpi/acpi.h
+++ b/src/kernel/acpi/acpi.h
@@ -1,11 +1,14 @@
#ifndef MELVIX_ACPI_H
#define MELVIX_ACPI_H
+#include <stdint.h>
+#include <kernel/multiboot.h>
+
/**
* Initialize the ACP interface
- * @return 0 if successful, otherwise -1
*/
-int acpi_install();
+void acpi_old_init(struct multiboot_tag_old_acpi *tag);
+void acpi_new_init(struct multiboot_tag_new_acpi *tag);
/**
* Activate a ACPI based device reboot
@@ -17,50 +20,101 @@ void reboot();
*/
void acpi_poweroff();
-struct RSD_ptr {
- char signature[8];
- char checksum;
- char oem_id[6];
- char revision;
- uint32_t *rsdt_address;
-};
-
-struct FADT {
- char signature[4];
- uint32_t length;
- char unneded1[40 - 8];
- uint32_t *DSDT;
- char unneded2[48 - 44];
- uint32_t *SMI_CMD;
- char ACPI_ENABLE;
- char ACPI_DISABLE;
- char unneded3[64 - 54];
- uint32_t *PM1a_CNT_BLK;
- uint32_t *PM1b_CNT_BLK;
- char unneded4[89 - 72];
- char PM1_CNT_LEN;
- char unneeded5[18];
- char century;
-};
-
struct address_structure {
uint8_t address_space_id;
uint8_t register_bit_width;
uint8_t register_bit_offset;
uint8_t reserved;
uint64_t address;
-} __attribute__((packed));
+};
+
+struct rsdp {
+ char signature[8];
+ char checksum;
+ char oem_id[6];
+ char revision;
+ uint32_t *rsdt_address;
+};
-struct HPET {
+struct sdt_header {
char signature[4];
uint32_t length;
uint8_t revision;
uint8_t checksum;
- char oemid[6];
- uint64_t oem_tableid;
+ char oem_id[6];
+ char oem_table_id[8];
uint32_t oem_revision;
uint32_t creator_id;
uint32_t creator_revision;
+};
+
+struct rsdt {
+ struct sdt_header header;
+ uint32_t sdt_pointer[0];
+};
+
+struct xsdt {
+ struct sdt_header header;
+ uint32_t sdt_pointer[0];
+};
+
+struct fadt {
+ struct sdt_header header;
+ uint32_t firmware_ctl;
+ uint32_t dsdt;
+ uint8_t reserved;
+ uint8_t preferred_power_management;
+ uint16_t sci_interrupt;
+ uint32_t smi_commandPort;
+ uint8_t acpi_enable;
+ uint8_t acpi_disable;
+ uint8_t S4BIOS_req;
+ uint8_t PSTATE_control;
+ uint32_t PM1a_event_block;
+ uint32_t PM1b_event_block;
+ uint32_t PM1a_control_block;
+ uint32_t PM1b_control_block;
+ uint32_t PM2_control_block;
+ uint32_t PM_timer_block;
+ uint32_t GPE0_block;
+ uint32_t GPE1_block;
+ uint8_t PM1_event_length;
+ uint8_t PM1_control_length;
+ uint8_t PM2_control_length;
+ uint8_t PM_timer_length;
+ uint8_t GPE0_length;
+ uint8_t GPE1_length;
+ uint8_t GPE1_base;
+ uint8_t C_state_control;
+ uint16_t worst_C2_latency;
+ uint16_t worst_C3_latency;
+ uint16_t flush_size;
+ uint16_t flush_stride;
+ uint8_t duty_offset;
+ uint8_t duty_width;
+ uint8_t day_alarm;
+ uint8_t month_alarm;
+ uint8_t century;
+ uint16_t boot_architecture_flags; // Reserved in 1.0
+ uint8_t reserved2;
+ uint32_t flags;
+ struct address_structure reset_reg;
+ uint8_t reset_value;
+ uint8_t reserved3[3];
+ uint64_t x_firmware_control; // Reserved in 1.0
+ uint64_t x_dsdt; // Reserved in 1.0
+ struct address_structure x_PM1a_event_block;
+ struct address_structure x_PM1b_event_block;
+ struct address_structure x_PM1a_control_block;
+ struct address_structure x_PM1b_control_block;
+ struct address_structure x_PM2_control_block;
+ struct address_structure x_PM_timer_block;
+ struct address_structure x_GPE0_block;
+ struct address_structure x_GPE1_block;
+};
+
+struct hpet {
+ struct sdt_header header;
uint8_t hardware_rev_id;
uint8_t comparator_count : 5;
uint8_t counter_size : 1;
@@ -71,10 +125,18 @@ struct HPET {
uint8_t hpet_number;
uint16_t minimum_tick;
uint8_t page_protection;
-} __attribute__((packed));
+};
-struct FADT *fadt;
+struct madt {
+ struct sdt_header header;
+ uint32_t address;
+ uint32_t flags;
+ // Interrupt devices...
+};
-struct HPET *hpet;
+struct rsdt *rsdt;
+struct fadt *fadt;
+struct hpet *hpet;
+struct madt *madt;
-#endif \ No newline at end of file
+#endif