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 | |
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.
-rw-r--r-- | src/kernel/acpi/acpi.c | 204 | ||||
-rw-r--r-- | src/kernel/acpi/acpi.h | 134 | ||||
-rw-r--r-- | src/kernel/cmos/rtc.c | 65 | ||||
-rw-r--r-- | src/kernel/cmos/rtc.h | 16 | ||||
-rw-r--r-- | src/kernel/interrupts/isr.c | 2 | ||||
-rw-r--r-- | src/kernel/kernel.c | 8 | ||||
-rw-r--r-- | src/kernel/lib/memory.c | 4 | ||||
-rw-r--r-- | src/kernel/memory/paging.c | 29 | ||||
-rw-r--r-- | src/kernel/multiboot.c | 9 |
9 files changed, 214 insertions, 257 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 diff --git a/src/kernel/cmos/rtc.c b/src/kernel/cmos/rtc.c index 13185b7..6108a1e 100644 --- a/src/kernel/cmos/rtc.c +++ b/src/kernel/cmos/rtc.c @@ -1,11 +1,13 @@ +#include <kernel/system.h> #include <kernel/io/io.h> +#include <kernel/acpi/acpi.h> #include <kernel/lib/stdio.h> -unsigned char second; -unsigned char minute; -unsigned char hour; -unsigned char day; -unsigned char month; +uint8_t second; +uint8_t minute; +uint8_t hour; +uint8_t day; +uint8_t month; unsigned int year; int get_update_in_progress_flag() @@ -14,7 +16,7 @@ int get_update_in_progress_flag() return (inb(0x71) & 0x80); } -unsigned char get_rtc_register(int reg) +uint8_t get_rtc_register(int reg) { outb(0x70, (uint8_t)reg); return inb(0x71); @@ -22,24 +24,27 @@ unsigned char get_rtc_register(int reg) void read_rtc() { + halt_loop(); unsigned int century = 20; // ... - unsigned char last_second; - unsigned char last_minute; - unsigned char last_hour; - unsigned char last_day; - unsigned char last_month; - unsigned char last_year; - unsigned char last_century; - unsigned char registerB; + uint8_t last_second; + uint8_t last_minute; + uint8_t last_hour; + uint8_t last_day; + uint8_t last_month; + uint8_t last_year; + uint8_t last_century; + uint8_t registerB; - while (get_update_in_progress_flag()) - ; + while (get_update_in_progress_flag()) { + }; + halt_loop(); second = get_rtc_register(0x00); minute = get_rtc_register(0x02); hour = get_rtc_register(0x04); day = get_rtc_register(0x07); month = get_rtc_register(0x08); year = get_rtc_register(0x09); + halt_loop(); // century = get_rtc_register(fadt->century); // TODO: Fix fadt table (page fault!) // Try until the values are the same (fix for RTC updates) @@ -49,11 +54,11 @@ void read_rtc() last_hour = hour; last_day = day; last_month = month; - last_year = (unsigned char)year; - last_century = (unsigned char)century; + last_year = (uint8_t)year; + last_century = (uint8_t)century; - while (get_update_in_progress_flag()) - ; + while (get_update_in_progress_flag()) { + }; second = get_rtc_register(0x00); minute = get_rtc_register(0x02); hour = get_rtc_register(0x04); @@ -68,12 +73,11 @@ void read_rtc() registerB = get_rtc_register(0x0B); if (!(registerB & 0x04)) { - second = (unsigned char)((second & 0x0F) + ((second / 16) * 10)); - minute = (unsigned char)((minute & 0x0F) + ((minute / 16) * 10)); - hour = (unsigned char)(((hour & 0x0F) + (((hour & 0x70) / 16) * 10)) | - (hour & 0x80)); - day = (unsigned char)((day & 0x0F) + ((day / 16) * 10)); - month = (unsigned char)((month & 0x0F) + ((month / 16) * 10)); + second = (uint8_t)((second & 0x0F) + ((second / 16) * 10)); + minute = (uint8_t)((minute & 0x0F) + ((minute / 16) * 10)); + hour = (uint8_t)(((hour & 0x0F) + (((hour & 0x70) / 16) * 10)) | (hour & 0x80)); + day = (uint8_t)((day & 0x0F) + ((day / 16) * 10)); + month = (uint8_t)((month & 0x0F) + ((month / 16) * 10)); year = (year & 0x0F) + ((year / 16) * 10); // century = (century & 0x0F) + ((century / 16) * 10); } @@ -82,12 +86,13 @@ void read_rtc() // Convert to 24h if necessary if (!(registerB & 0x02) && (hour & 0x80)) { - hour = (unsigned char)(((hour & 0x7F) + 12) % 24); + hour = (uint8_t)(((hour & 0x7F) + 12) % 24); } } -void write_time() +void rtc_print() { + log("%d", fadt->century); read_rtc(); - printf("Current time: %d:%d:%d %d/%d/%d\n", hour, minute, second, month, day, year); -}
\ No newline at end of file + info("Current time: %d:%d:%d %d/%d/%d", hour, minute, second, month, day, year); +} diff --git a/src/kernel/cmos/rtc.h b/src/kernel/cmos/rtc.h index ca80f4f..7604bb1 100644 --- a/src/kernel/cmos/rtc.h +++ b/src/kernel/cmos/rtc.h @@ -1,15 +1,17 @@ #ifndef MELVIX_RTC_H #define MELVIX_RTC_H -unsigned char second; -unsigned char minute; -unsigned char hour; -unsigned char day; -unsigned char month; +#include <stdint.h> + +uint8_t second; +uint8_t minute; +uint8_t hour; +uint8_t day; +uint8_t month; unsigned int year; void read_rtc(); -void write_time(); +void rtc_print(); -#endif
\ No newline at end of file +#endif diff --git a/src/kernel/interrupts/isr.c b/src/kernel/interrupts/isr.c index c34d951..2f134c1 100644 --- a/src/kernel/interrupts/isr.c +++ b/src/kernel/interrupts/isr.c @@ -119,7 +119,7 @@ void fault_handler(struct regs *r) strcat(message, " Exception"); // Show message if there wasn't an error in video memory - if (faulting_address != (uint32_t)fb) + if (faulting_address != (uint32_t)fb || fb == 0) panic(message); else halt_loop(); diff --git a/src/kernel/kernel.c b/src/kernel/kernel.c index 144ae8c..40d11b9 100644 --- a/src/kernel/kernel.c +++ b/src/kernel/kernel.c @@ -18,6 +18,7 @@ #include <kernel/fs/ata.h> #include <kernel/fs/ext2.h> #include <kernel/fs/vfs.h> +#include <kernel/cmos/rtc.h> void kernel_main(uint32_t magic, uint32_t multiboot_address) { @@ -36,15 +37,13 @@ void kernel_main(uint32_t magic, uint32_t multiboot_address) // Install features gdt_install(); init_serial(); - acpi_install(); idt_install(); isrs_install(); irq_install(); + multiboot_parse(multiboot_address); paging_install(); - memory_print(); - // Install drivers cli(); timer_install(); @@ -54,6 +53,9 @@ void kernel_main(uint32_t magic, uint32_t multiboot_address) network_install(); sti(); + memory_print(); + //rtc_print(); // TODO: Fix ACPI memory mapping! + vfs_init(); ata_init(); ext2_init("/dev/hda", "/"); diff --git a/src/kernel/lib/memory.c b/src/kernel/lib/memory.c index db26c47..b571b83 100644 --- a/src/kernel/lib/memory.c +++ b/src/kernel/lib/memory.c @@ -81,6 +81,10 @@ void memory_mmap_init(struct multiboot_tag_mmap *tag) ((struct multiboot_tag_mmap *)tag)->entry_size)) { if (mmap->type == MULTIBOOT_MEMORY_AVAILABLE) { sum += mmap->len; + } else if (mmap->type == MULTIBOOT_MEMORY_ACPI_RECLAIMABLE) { + log("ACPI reclaimable memory"); + } else if (mmap->type == MULTIBOOT_MEMORY_BADRAM) { + warn("Bad memory!"); } } total = sum >> 10; // I want kb diff --git a/src/kernel/memory/paging.c b/src/kernel/memory/paging.c index 8b5de59..4b87540 100644 --- a/src/kernel/memory/paging.c +++ b/src/kernel/memory/paging.c @@ -3,6 +3,7 @@ #include <kernel/system.h> #include <kernel/lib/lib.h> #include <kernel/io/io.h> +#include <kernel/acpi/acpi.h> int paging_enabled = 0; @@ -31,9 +32,9 @@ void paging_init() void paging_install() { // User paging - paging_switch_directory(1); - paging_init(); - paging_set_user(0, memory_get_all() >> 3); + //paging_switch_directory(1); + //paging_init(); + //paging_set_user(0, memory_get_all() >> 3); // Kernel paging paging_switch_directory(0); @@ -53,6 +54,16 @@ void paging_disable() paging_enabled = 0; } +void paging_enable() +{ + asm("mov %0, %%cr3" ::"r"(current_page_directory)); + uint32_t cr0; + asm("mov %%cr0, %0" : "=r"(cr0)); + cr0 |= 0x80000000; + asm("mov %0, %%cr0" ::"r"(cr0)); + paging_enabled = 1; +} + void paging_switch_directory(int user) { if (user == 1) { @@ -65,16 +76,6 @@ void paging_switch_directory(int user) asm("mov %0, %%cr3" ::"r"(current_page_directory)); } -void paging_enable() -{ - asm("mov %0, %%cr3" ::"r"(current_page_directory)); - uint32_t cr0; - asm("mov %%cr0, %0" : "=r"(cr0)); - cr0 |= 0x80000000; - asm("mov %0, %%cr0" ::"r"(cr0)); - paging_enabled = 1; -} - inline void invlpg(uint32_t addr) { asm("invlpg (%0)" ::"r"(addr) : "memory"); @@ -191,4 +192,4 @@ uint32_t paging_get_used_pages() } } return n; -}
\ No newline at end of file +} diff --git a/src/kernel/multiboot.c b/src/kernel/multiboot.c index 2df1d0e..01a2f66 100644 --- a/src/kernel/multiboot.c +++ b/src/kernel/multiboot.c @@ -2,6 +2,7 @@ #include <kernel/system.h> #include <kernel/multiboot.h> #include <kernel/smbios/smbios.h> +#include <kernel/acpi/acpi.h> #include <kernel/lib/lib.h> #include <kernel/lib/stdio.h> @@ -46,16 +47,18 @@ void multiboot_parse(uint32_t multiboot_address) case MULTIBOOT_TAG_TYPE_EFI32: info("Got EFI32"); break; - case MULTIBOOT_TAG_TYPE_SMBIOS: + case MULTIBOOT_TAG_TYPE_SMBIOS: // GRUB doesn't detect SMBIOS on QEMU! info("Got SMBIOS table"); smbios_init((struct multiboot_tag_smbios *)tag); break; case MULTIBOOT_TAG_TYPE_ACPI_OLD: - info("Got ACPI table"); + info("Got ACPI 1.0 table"); + acpi_old_init((struct multiboot_tag_old_acpi *)tag); break; case MULTIBOOT_TAG_TYPE_ACPI_NEW: - info("Got new ACPI table"); + info("Got ACPI 2.0 table"); + acpi_new_init((struct multiboot_tag_new_acpi *)tag); break; case MULTIBOOT_TAG_TYPE_NETWORK: info("Got network info"); |