diff options
author | Marvin Borner | 2020-04-18 00:07:37 +0200 |
---|---|---|
committer | Marvin Borner | 2020-04-18 00:07:37 +0200 |
commit | 8d78616a2b80c7625c1aa9ca4733e48a8bf8bf22 (patch) | |
tree | 894bddb357ca1976fcfd3b54d1e8fe48bbac569b /src/kernel/acpi | |
parent | 27c38d3f6e473d2bf7075fb364db148f22aca203 (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.c | 204 | ||||
-rw-r--r-- | src/kernel/acpi/acpi.h | 134 |
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 |