mirror of
https://github.com/JannisHeydemann/BoredOS.git
synced 2026-05-30 02:16:58 +00:00
pr: ACPI Power Shutdown Implemented (#14)
* Flush PS/2 Devices on boot to avoid Locking dependent on the out buffer on real hardware / emulated PS2 over USB Removed Slow and Unnessisarty flipping causing kconsole write slowdowns consequently speeding up the boot process * sod wc * ignoring dynamically created objects, added make run rule which will automatically detect the platform and then use the correct platform rule * ACPI Power Shutdown
This commit is contained in:
committed by
GitHub
parent
77744464e3
commit
b85bb900e6
@@ -5,6 +5,8 @@
|
||||
#include "wm.h"
|
||||
#include "io.h"
|
||||
|
||||
#include "../drivers/acpi.h"
|
||||
|
||||
void k_memset(void *dest, int val, size_t len) {
|
||||
unsigned char *ptr = (unsigned char *)dest;
|
||||
while (len-- > 0) *ptr++ = (unsigned char)val;
|
||||
@@ -16,6 +18,17 @@ void k_memcpy(void *dest, const void *src, size_t len) {
|
||||
while (len-- > 0) *d++ = *s++;
|
||||
}
|
||||
|
||||
int k_memcmp (const void *str1, const void *str2, size_t count) {
|
||||
register const unsigned char *s1 = (const unsigned char*)str1;
|
||||
register const unsigned char *s2 = (const unsigned char*)str2;
|
||||
|
||||
while (count-- > 0) {
|
||||
if (*s1++ != *s2++)
|
||||
return s1[-1] < s2[-1] ? -1 : 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
size_t k_strlen(const char *str) {
|
||||
size_t len = 0;
|
||||
while (str[len]) len++;
|
||||
@@ -118,9 +131,7 @@ void k_reboot(void) {
|
||||
}
|
||||
|
||||
void k_shutdown(void) {
|
||||
outw(0xB004, 0x2000); // QEMU older / some pc machines
|
||||
outw(0x604, 0x2000); // QEMU newer (i440fx/q35)
|
||||
outw(0x4004, 0x3400); // VirtualBox fallback
|
||||
acpi_shutdown();
|
||||
}
|
||||
|
||||
volatile uint64_t beep_end_tick = 0;
|
||||
|
||||
@@ -11,6 +11,7 @@
|
||||
// Kernel string utilities
|
||||
void k_memset(void *dest, int val, size_t len);
|
||||
void k_memcpy(void *dest, const void *src, size_t len);
|
||||
int k_memcmp (const void *str1, const void *str2, size_t count);
|
||||
size_t k_strlen(const char *str);
|
||||
int k_strcmp(const char *s1, const char *s2);
|
||||
int k_strncmp(const char *s1, const char *s2, size_t n);
|
||||
|
||||
@@ -26,6 +26,7 @@
|
||||
#include "smp.h"
|
||||
#include "work_queue.h"
|
||||
#include "lapic.h"
|
||||
#include "panic.h"
|
||||
#include "fs/sysfs.h"
|
||||
#include "fs/procfs.h"
|
||||
#include "fs/bootfs.h"
|
||||
@@ -34,6 +35,7 @@
|
||||
#include "sys/bootfs_state.h"
|
||||
#include "input/keymap.h"
|
||||
#include "input/keyboard.h"
|
||||
#include "../drivers/acpi.h"
|
||||
|
||||
extern void sysfs_init_subsystems(void);
|
||||
|
||||
@@ -78,6 +80,12 @@ static volatile struct limine_kernel_file_request kernel_file_request = {
|
||||
.revision = 0
|
||||
};
|
||||
|
||||
__attribute__((used, section(".requests")))
|
||||
volatile struct limine_rsdp_request acpi_rsdp_request = {
|
||||
.id = LIMINE_RSDP_REQUEST,
|
||||
.revision = 0
|
||||
};
|
||||
|
||||
__attribute__((used, section(".requests_start")))
|
||||
static volatile struct limine_request *const requests_start_marker[] = {
|
||||
(struct limine_request *)&framebuffer_request,
|
||||
@@ -86,6 +94,7 @@ static volatile struct limine_request *const requests_start_marker[] = {
|
||||
(struct limine_request *)&smp_request,
|
||||
(struct limine_request *)&bootloader_info_request,
|
||||
(struct limine_request *)&kernel_file_request,
|
||||
(struct limine_request *)&acpi_rsdp_request,
|
||||
NULL
|
||||
};
|
||||
|
||||
@@ -366,9 +375,9 @@ void kmain(void) {
|
||||
kconsole_set_color(0xFFFFFF55);
|
||||
serial_write("Welcome to BoredOS!\n");
|
||||
kconsole_set_color(0xFFFFFFFF);
|
||||
|
||||
acpi_init();
|
||||
|
||||
process_init();
|
||||
|
||||
|
||||
fat32_init();
|
||||
log_ok("FAT32 ready");
|
||||
|
||||
147
src/core/panic.c
147
src/core/panic.c
@@ -17,129 +17,98 @@ static void draw_string_centered(int y, const char *s, uint32_t color) {
|
||||
}
|
||||
|
||||
void kernel_panic(registers_t *regs, const char *error_name) {
|
||||
// Disable interrupts to prevent nested panics
|
||||
asm volatile("cli");
|
||||
|
||||
// Clear back buffer to black
|
||||
graphics_clear_back_buffer(0x00000000);
|
||||
|
||||
int sh = get_screen_height();
|
||||
int cy = sh / 2;
|
||||
|
||||
// Draw header
|
||||
// Header
|
||||
draw_string_centered(cy - 150, "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!", 0xFFFF0000);
|
||||
draw_string_centered(cy - 130, "KERNEL EXCEPTION OCCURRED", 0xFFFFFFFF);
|
||||
draw_string_centered(cy - 130, "KERNEL PANIC", 0xFFFFFFFF);
|
||||
draw_string_centered(cy - 110, "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!", 0xFFFF0000);
|
||||
|
||||
// Error name
|
||||
char err_buf[256];
|
||||
char buf[256];
|
||||
int pos = 0;
|
||||
const char *prefix = "Exception: ";
|
||||
while(prefix[pos]) { err_buf[pos] = prefix[pos]; pos++; }
|
||||
const char *prefix = "Error: ";
|
||||
while (prefix[pos]) { buf[pos] = prefix[pos]; pos++; }
|
||||
int i = 0;
|
||||
while(error_name[i]) { err_buf[pos++] = error_name[i++]; }
|
||||
err_buf[pos] = 0;
|
||||
draw_string_centered(cy - 70, err_buf, 0xFFFFCC00);
|
||||
while (error_name[i]) { buf[pos++] = error_name[i++]; }
|
||||
buf[pos] = 0;
|
||||
draw_string_centered(cy - 70, buf, 0xFFFFCC00);
|
||||
|
||||
// Details - simplified centering by drawing them as a block or individually centered
|
||||
char info_buf[64];
|
||||
|
||||
// Vector
|
||||
pos = 0;
|
||||
prefix = "Vector: ";
|
||||
while(prefix[pos]) { info_buf[pos] = prefix[pos]; pos++; }
|
||||
uint64_t v = regs->int_no;
|
||||
const char* digits = "0123456789ABCDEF";
|
||||
info_buf[pos++] = '0'; info_buf[pos++] = 'x';
|
||||
for (int i = 15; i >= 0; i--) {
|
||||
info_buf[pos + i] = digits[v & 0xF];
|
||||
v >>= 4;
|
||||
}
|
||||
info_buf[pos + 16] = 0;
|
||||
draw_string_centered(cy - 40, info_buf, 0xFFFFFFFF);
|
||||
if (regs != NULL) {
|
||||
// Exception details
|
||||
char info_buf[64];
|
||||
const char *digits = "0123456789ABCDEF";
|
||||
|
||||
// Error Code
|
||||
pos = 0;
|
||||
prefix = "Error Code: ";
|
||||
while(prefix[pos]) { info_buf[pos] = prefix[pos]; pos++; }
|
||||
v = regs->err_code;
|
||||
info_buf[pos++] = '0'; info_buf[pos++] = 'x';
|
||||
for (int i = 15; i >= 0; i--) {
|
||||
info_buf[pos + i] = digits[v & 0xF];
|
||||
v >>= 4;
|
||||
}
|
||||
info_buf[pos + 16] = 0;
|
||||
draw_string_centered(cy - 20, info_buf, 0xFFFFFFFF);
|
||||
#define FMT_HEX(prefix_str, value, color, y_offset) \
|
||||
do { \
|
||||
int pos = 0; \
|
||||
const char *pfx = (prefix_str); \
|
||||
while (pfx[pos]) { info_buf[pos] = pfx[pos]; pos++; } \
|
||||
info_buf[pos++] = '0'; info_buf[pos++] = 'x'; \
|
||||
uint64_t _v = (value); \
|
||||
for (int _i = 15; _i >= 0; _i--) { \
|
||||
info_buf[pos + _i] = digits[_v & 0xF]; _v >>= 4; \
|
||||
} \
|
||||
info_buf[pos + 16] = 0; \
|
||||
draw_string_centered((y_offset), info_buf, (color)); \
|
||||
} while (0)
|
||||
|
||||
// RIP
|
||||
pos = 0;
|
||||
prefix = "RIP: ";
|
||||
while(prefix[pos]) { info_buf[pos] = prefix[pos]; pos++; }
|
||||
v = regs->rip;
|
||||
info_buf[pos++] = '0'; info_buf[pos++] = 'x';
|
||||
for (int i = 15; i >= 0; i--) {
|
||||
info_buf[pos + i] = digits[v & 0xF];
|
||||
v >>= 4;
|
||||
}
|
||||
info_buf[pos + 16] = 0;
|
||||
draw_string_centered(cy, info_buf, 0xFFFFFFFF);
|
||||
FMT_HEX("Vector: ", regs->int_no, 0xFFFFFFFF, cy - 40);
|
||||
FMT_HEX("Error Code: ", regs->err_code, 0xFFFFFFFF, cy - 20);
|
||||
FMT_HEX("RIP: ", regs->rip, 0xFFFFFFFF, cy);
|
||||
|
||||
// CR2 for page faults
|
||||
if (regs->int_no == 14) {
|
||||
uint64_t cr2;
|
||||
asm volatile("mov %%cr2, %0" : "=r"(cr2));
|
||||
pos = 0;
|
||||
prefix = "CR2: ";
|
||||
while(prefix[pos]) { info_buf[pos] = prefix[pos]; pos++; }
|
||||
info_buf[pos++] = '0'; info_buf[pos++] = 'x';
|
||||
for (int i = 15; i >= 0; i--) {
|
||||
info_buf[pos + i] = digits[cr2 & 0xF];
|
||||
cr2 >>= 4;
|
||||
if (regs->int_no == 14) {
|
||||
uint64_t cr2;
|
||||
asm volatile("mov %%cr2, %0" : "=r"(cr2));
|
||||
FMT_HEX("CR2: ", cr2, 0xFFFF5555, cy + 20);
|
||||
}
|
||||
info_buf[pos + 16] = 0;
|
||||
draw_string_centered(cy + 20, info_buf, 0xFFFF5555);
|
||||
|
||||
#undef FMT_HEX
|
||||
}
|
||||
|
||||
// Message
|
||||
draw_string_centered(cy + 100, "The system has been halted to prevent damage.", 0xFFFFFFFF);
|
||||
draw_string_centered(cy + 120, "Please restart your computer.", 0xFFAAAAAA);
|
||||
|
||||
|
||||
// Flip buffer to screen
|
||||
graphics_mark_screen_dirty();
|
||||
graphics_flip_buffer();
|
||||
|
||||
char hex_buf[17];
|
||||
serial_write("\n*** KERNEL PANIC ***\n");
|
||||
serial_write(error_name);
|
||||
serial_write("\n");
|
||||
|
||||
serial_write("Vector: 0x");
|
||||
k_itoa_hex(regs->int_no, hex_buf);
|
||||
serial_write(hex_buf);
|
||||
serial_write("\n");
|
||||
if (regs != NULL) {
|
||||
char hex_buf[17];
|
||||
|
||||
serial_write("Error Code: 0x");
|
||||
k_itoa_hex(regs->err_code, hex_buf);
|
||||
serial_write(hex_buf);
|
||||
serial_write("\n");
|
||||
|
||||
serial_write("RIP: 0x");
|
||||
k_itoa_hex(regs->rip, hex_buf);
|
||||
serial_write(hex_buf);
|
||||
serial_write("\n");
|
||||
|
||||
if (regs->int_no == 14) {
|
||||
uint64_t cr2;
|
||||
asm volatile("mov %%cr2, %0" : "=r"(cr2));
|
||||
serial_write("CR2: 0x");
|
||||
k_itoa_hex(cr2, hex_buf);
|
||||
serial_write("Vector: 0x");
|
||||
k_itoa_hex(regs->int_no, hex_buf);
|
||||
serial_write(hex_buf);
|
||||
serial_write("\n");
|
||||
|
||||
serial_write("Error Code: 0x");
|
||||
k_itoa_hex(regs->err_code, hex_buf);
|
||||
serial_write(hex_buf);
|
||||
serial_write("\n");
|
||||
|
||||
serial_write("RIP: 0x");
|
||||
k_itoa_hex(regs->rip, hex_buf);
|
||||
serial_write(hex_buf);
|
||||
serial_write("\n");
|
||||
|
||||
if (regs->int_no == 14) {
|
||||
uint64_t cr2;
|
||||
asm volatile("mov %%cr2, %0" : "=r"(cr2));
|
||||
serial_write("CR2: 0x");
|
||||
k_itoa_hex(cr2, hex_buf);
|
||||
serial_write(hex_buf);
|
||||
serial_write("\n");
|
||||
}
|
||||
}
|
||||
|
||||
// Halt
|
||||
while(1) {
|
||||
while (1) {
|
||||
asm volatile("cli; hlt");
|
||||
}
|
||||
}
|
||||
|
||||
10
src/core/panic.h
Normal file
10
src/core/panic.h
Normal file
@@ -0,0 +1,10 @@
|
||||
#ifndef PANIC_H
|
||||
#define PANIC_H
|
||||
|
||||
#include "io.h"
|
||||
#include "kutils.h"
|
||||
#include "../sys/syscall.h"
|
||||
|
||||
void kernel_panic(registers_t *regs, const char *error_name);
|
||||
|
||||
#endif
|
||||
220
src/drivers/acpi.c
Normal file
220
src/drivers/acpi.c
Normal file
@@ -0,0 +1,220 @@
|
||||
#include <stdint.h>
|
||||
#include <stddef.h>
|
||||
|
||||
#include "acpi_structures.h"
|
||||
#include "acpi.h"
|
||||
#include "../sys/idt.h"
|
||||
#include "../core/limine.h"
|
||||
#include "../core/panic.h"
|
||||
#include "../core/platform.h"
|
||||
#include "../core/kconsole.h"
|
||||
|
||||
#define MAX_ISO 16
|
||||
|
||||
static struct acpi_rsdp *acpi_rsdp = NULL;
|
||||
static struct acpi_madt *acpi_madt = NULL;
|
||||
|
||||
static fadt_t *acpi_fadt = NULL; // my header file sucks ill make this nicer but its fine
|
||||
|
||||
static struct {
|
||||
uint8_t source;
|
||||
uint32_t gsi;
|
||||
uint16_t flags;
|
||||
} iso_table[MAX_ISO];
|
||||
static uint8_t iso_count = 0;
|
||||
|
||||
/*
|
||||
Each ACPI table contains an 8-bit checksum field.
|
||||
When all bytes in the table are added together (including the checksum byte),
|
||||
the lower 8 bits of the total sum must be zero for it to pass.
|
||||
*/
|
||||
static int acpi_checksum(void *ptr, size_t len) {
|
||||
uint8_t sum = 0;
|
||||
uint8_t *p = ptr;
|
||||
for (size_t i = 0; i < len; i++)
|
||||
sum += p[i];
|
||||
return sum == 0;
|
||||
}
|
||||
|
||||
static void *acpi_get_rsdp(void){
|
||||
extern volatile struct limine_rsdp_request acpi_rsdp_request;
|
||||
|
||||
if (!acpi_rsdp_request.response)
|
||||
kernel_panic(NULL, "ACPI RSDP not provided by the Bootloader");
|
||||
if (!acpi_rsdp_request.response->address)
|
||||
kernel_panic(NULL, "ACPI Invalid RSDP address provided by Bootloader");
|
||||
|
||||
return acpi_rsdp_request.response->address;
|
||||
}
|
||||
|
||||
static struct acpi_sdt *acpi_get_sdt(const char signature[4]) {
|
||||
if (acpi_rsdp->revision >= 2 && acpi_rsdp->xsdt_address) {
|
||||
struct acpi_xsdt *acpi_xsdt = (struct acpi_xsdt *)p2v(acpi_rsdp->xsdt_address);
|
||||
if (acpi_checksum(acpi_xsdt, acpi_xsdt->header.length)) {
|
||||
size_t entries = (acpi_xsdt->header.length - sizeof(struct acpi_sdt)) / 8;
|
||||
for (size_t i = 0; i < entries; i++) {
|
||||
struct acpi_sdt *tbl = (struct acpi_sdt *)p2v(acpi_xsdt->tables[i]);
|
||||
if (!tbl) continue;
|
||||
if (!k_memcmp(tbl->signature, signature, 4))
|
||||
return tbl;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// RSDT fallback
|
||||
if (!acpi_rsdp->rsdt_address)
|
||||
return NULL;
|
||||
|
||||
struct acpi_sdt *acpi_rsdt = (struct acpi_sdt *)p2v(acpi_rsdp->rsdt_address);
|
||||
if (!acpi_checksum(acpi_rsdt, acpi_rsdt->length))
|
||||
return NULL;
|
||||
|
||||
uint32_t *tables = (uint32_t *)((uint8_t *)acpi_rsdt + sizeof(struct acpi_sdt));
|
||||
size_t entries = (acpi_rsdt->length - sizeof(struct acpi_sdt)) / 4;
|
||||
for (size_t i = 0; i < entries; i++) {
|
||||
struct acpi_sdt *tbl = (struct acpi_sdt *)p2v(tables[i]);
|
||||
if (!tbl) continue;
|
||||
if (!k_memcmp(tbl->signature, signature, 4))
|
||||
return tbl;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static uint16_t SLP_TYPa = 0;
|
||||
static uint16_t SLP_TYPb = 0;
|
||||
|
||||
void acpi_parse_s5(void) {
|
||||
if (!acpi_fadt || !acpi_fadt->dsdt) return;
|
||||
|
||||
char *dsdt = (char *)p2v((uintptr_t)acpi_fadt->dsdt);
|
||||
|
||||
if (k_memcmp(dsdt, "DSDT", 4) != 0) return;
|
||||
|
||||
uint32_t dsdt_len = *(uint32_t*)(dsdt + 4);
|
||||
char *ptr = dsdt + 36;
|
||||
char *end = dsdt + dsdt_len;
|
||||
|
||||
while (ptr < end) {
|
||||
if (k_memcmp(ptr, "_S5_", 4) == 0) {
|
||||
ptr += 4;
|
||||
if (*ptr == 0x12) {
|
||||
ptr += 3;
|
||||
|
||||
if (*ptr == 0x0A) ptr++;
|
||||
SLP_TYPa = (*(uint8_t*)ptr) << 10;
|
||||
ptr++;
|
||||
|
||||
if (*ptr == 0x0A) ptr++;
|
||||
SLP_TYPb = (*(uint8_t*)ptr) << 10;
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
ptr++;
|
||||
}
|
||||
}
|
||||
|
||||
__attribute__((noreturn))
|
||||
void acpi_shutdown(void) {
|
||||
if (SLP_TYPa == 0) acpi_parse_s5();
|
||||
if (SLP_TYPa == 0) SLP_TYPa = (5 << 10);
|
||||
|
||||
outw((uint16_t)acpi_fadt->pm1a_cnt_blk, SLP_TYPa | SLP_EN);
|
||||
|
||||
if (acpi_fadt->pm1b_cnt_blk != 0) {
|
||||
outw((uint16_t)acpi_fadt->pm1b_cnt_blk, SLP_TYPb | SLP_EN);
|
||||
}
|
||||
|
||||
//virtulizers last just incase these have some sort of unintended effect on real hw
|
||||
outw(0xB004, 0x2000); // bochs
|
||||
outw(0x4004, 0x3400); // vbox
|
||||
outw(0x604, 0x2000); // QEMU
|
||||
outw(0x600, 0x34); // Cloud Hypervisor
|
||||
|
||||
asm volatile("cli");
|
||||
for(;;) asm volatile("hlt");
|
||||
}
|
||||
|
||||
int acpi_init(void){
|
||||
acpi_rsdp = acpi_get_rsdp();
|
||||
if (!acpi_rsdp)
|
||||
kernel_panic(NULL, "ACPI does not provide a required RSDP");
|
||||
|
||||
size_t rsdp_len = acpi_rsdp->revision >= 2 ? acpi_rsdp->length : 20;
|
||||
if (!acpi_checksum(acpi_rsdp, rsdp_len))
|
||||
kernel_panic(NULL, "bad RSDP checksum");
|
||||
|
||||
acpi_fadt = (struct acpi_fadt *)acpi_get_sdt("FACP");
|
||||
if (!acpi_fadt)
|
||||
kernel_panic(NULL, "FADT not found");
|
||||
|
||||
if (!acpi_checksum(acpi_fadt, acpi_fadt->header.length))
|
||||
kernel_panic(NULL, "bad FADT checksum");
|
||||
|
||||
if (acpi_fadt->smi_cmd && acpi_fadt->acpi_enable) {
|
||||
outb(acpi_fadt->smi_cmd, acpi_fadt->acpi_enable);
|
||||
|
||||
int timeout = 1000000;
|
||||
while (!(inw(acpi_fadt->pm1a_cnt_blk) & 1) && timeout-- > 0)
|
||||
asm("pause");
|
||||
if (timeout <= 0) {
|
||||
kernel_panic(NULL, "Enable timeout");
|
||||
}
|
||||
}
|
||||
|
||||
acpi_madt = (struct acpi_madt *)acpi_get_sdt("APIC");
|
||||
if (!acpi_madt)
|
||||
kernel_panic(NULL, "MADT not found");
|
||||
|
||||
if (!acpi_checksum(acpi_madt, acpi_madt->header.length))
|
||||
kernel_panic(NULL, "bad MADT checksum");
|
||||
|
||||
uint8_t *ptr = acpi_madt->entries;
|
||||
uint8_t *end = (uint8_t *)acpi_madt + acpi_madt->header.length;
|
||||
|
||||
while (ptr < end) {
|
||||
struct madt_entry_header *h = (void *)ptr;
|
||||
if (h->length < sizeof(struct madt_entry_header))
|
||||
break;
|
||||
if (ptr + h->length > end)
|
||||
break;
|
||||
|
||||
switch (h->type) {
|
||||
case 2: {
|
||||
if (iso_count < MAX_ISO) {
|
||||
struct madt_iso *iso = (void *)ptr;
|
||||
iso_table[iso_count].source = iso->source;
|
||||
iso_table[iso_count].gsi = iso->gsi;
|
||||
iso_table[iso_count].flags = iso->flags;
|
||||
iso_count++;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
ptr += h->length;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint32_t acpi_irq_to_gsi(uint32_t irq) {
|
||||
for (size_t i = 0; i < iso_count; i++) {
|
||||
if (iso_table[i].source == irq)
|
||||
return iso_table[i].gsi;
|
||||
}
|
||||
return irq;
|
||||
}
|
||||
|
||||
uint16_t acpi_irq_flags(uint32_t irq) {
|
||||
for (size_t i = 0; i < iso_count; i++) {
|
||||
if (iso_table[i].source == irq)
|
||||
return iso_table[i].flags;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
25
src/drivers/acpi.h
Normal file
25
src/drivers/acpi.h
Normal file
@@ -0,0 +1,25 @@
|
||||
#ifndef ACPI_H
|
||||
#define ACPI_H
|
||||
|
||||
int acpi_init(void);
|
||||
|
||||
__attribute__((noreturn)) void acpi_shutdown(void);
|
||||
__attribute__((noreturn)) void acpi_reboot(void);
|
||||
|
||||
uint32_t acpi_irq_to_gsi(uint32_t irq);
|
||||
uint16_t acpi_irq_flags(uint32_t irq);
|
||||
|
||||
//power stuff
|
||||
|
||||
#define PM1A_CNT fadt->pm1a_cnt_blk
|
||||
#define PM1B_CNT fadt->pm1b_cnt_blk
|
||||
|
||||
#define ACPI_S5 0x5
|
||||
#define SLP_EN (1 << 13)
|
||||
|
||||
#define ACPI_PM1_SLEEP_CMD(slp_typ) (((slp_typ) << 10) | SLP_EN)
|
||||
|
||||
void acpi_parse_s5(void);
|
||||
__attribute__((noreturn)) void acpi_shutdown(void);
|
||||
|
||||
#endif
|
||||
129
src/drivers/acpi_structures.h
Normal file
129
src/drivers/acpi_structures.h
Normal file
@@ -0,0 +1,129 @@
|
||||
#ifndef ACPI_STRUCTURES_H
|
||||
#define ACPI_STRUCTURES_H
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
struct acpi_sdt {
|
||||
char signature[4];
|
||||
uint32_t length;
|
||||
uint8_t revision;
|
||||
uint8_t checksum;
|
||||
char oem_id[6];
|
||||
char oem_table_id[8];
|
||||
uint32_t oem_revision;
|
||||
uint32_t creator_id;
|
||||
uint32_t creator_revision;
|
||||
} __attribute__((packed));
|
||||
|
||||
struct acpi_rsdp {
|
||||
char signature[8];
|
||||
uint8_t checksum;
|
||||
char oem_id[6];
|
||||
uint8_t revision;
|
||||
uint32_t rsdt_address;
|
||||
|
||||
// acpi2
|
||||
uint32_t length;
|
||||
uint64_t xsdt_address;
|
||||
uint8_t extended_checksum;
|
||||
uint8_t reserved[3];
|
||||
} __attribute__((packed));
|
||||
|
||||
struct acpi_xsdt {
|
||||
struct acpi_sdt header;
|
||||
uint64_t tables[];
|
||||
} __attribute__((packed));
|
||||
|
||||
typedef struct
|
||||
{
|
||||
uint8_t address_space_id;
|
||||
uint8_t register_bit_width;
|
||||
uint8_t register_bit_offset;
|
||||
uint8_t access_size;
|
||||
uint64_t address;
|
||||
} __attribute__((packed)) GenericAddressStructure;
|
||||
|
||||
typedef struct acpi_fadt
|
||||
{
|
||||
struct acpi_sdt header;
|
||||
uint32_t firmware_ctrl;
|
||||
uint32_t dsdt;
|
||||
uint8_t __reserved;
|
||||
uint8_t preferred_pm_profile;
|
||||
uint16_t sci_int;
|
||||
uint32_t smi_cmd;
|
||||
uint8_t acpi_enable;
|
||||
uint8_t acpi_disable;
|
||||
uint8_t s4bios_req;
|
||||
uint8_t pstate_cnt;
|
||||
uint32_t pm1a_evt_blk;
|
||||
uint32_t pm1b_evt_blk;
|
||||
uint32_t pm1a_cnt_blk;
|
||||
uint32_t pm1b_cnt_blk;
|
||||
uint32_t pm2_cnt_blk;
|
||||
uint32_t pm_tmr_blk;
|
||||
uint32_t gpe0_blk;
|
||||
uint32_t gpe1_blk;
|
||||
uint8_t pm1_evt_len;
|
||||
uint8_t pm1_cnt_len;
|
||||
uint8_t pm2_cnt_len;
|
||||
uint8_t pm_tmr_len;
|
||||
uint8_t gpe0_blk_len;
|
||||
uint8_t gpe1_blk_len;
|
||||
uint8_t gpe1_base;
|
||||
uint8_t cst_cnt;
|
||||
uint16_t p_lvl2_lat;
|
||||
uint16_t p_lvl3_lat;
|
||||
uint16_t flush_size;
|
||||
uint16_t flush_stride;
|
||||
uint8_t duty_offset;
|
||||
uint8_t duty_width;
|
||||
uint8_t day_alrm;
|
||||
uint8_t mon_alrm;
|
||||
uint8_t century;
|
||||
uint16_t iapc_boot_arch;
|
||||
uint8_t __reserved2;
|
||||
uint32_t flags;
|
||||
GenericAddressStructure reset_reg;
|
||||
uint8_t reset_value;
|
||||
uint16_t arm_boot_arch;
|
||||
uint8_t fadt_minor_version;
|
||||
uint64_t x_firmware_ctrl;
|
||||
uint64_t x_dsdt;
|
||||
uint8_t x_pm1a_evt_blk[12];
|
||||
uint8_t x_pm1b_evt_blk[12];
|
||||
uint8_t x_pm1a_cnt_blk[12];
|
||||
uint8_t x_pm1b_cnt_blk[12];
|
||||
uint8_t x_pm2_cnt_blk[12];
|
||||
uint8_t x_pm_tmr_blk[12];
|
||||
uint8_t x_gpe0_blk[12];
|
||||
uint8_t x_gpe1_blk[12];
|
||||
uint8_t sleep_control_reg[12];
|
||||
uint8_t sleep_status_reg[12];
|
||||
uint64_t hypervison_vendor_identity;
|
||||
} __attribute__((packed)) fadt_t;
|
||||
|
||||
struct acpi_madt {
|
||||
struct acpi_sdt header;
|
||||
uint32_t lapic_addr;
|
||||
uint32_t flags;
|
||||
uint8_t entries[];
|
||||
} __attribute__((packed));
|
||||
|
||||
struct madt_iso {
|
||||
uint8_t type;
|
||||
uint8_t length;
|
||||
uint8_t bus;
|
||||
uint8_t source;
|
||||
uint32_t gsi;
|
||||
uint16_t flags;
|
||||
} __attribute__((packed));
|
||||
|
||||
struct madt_entry_header {
|
||||
uint8_t type;
|
||||
uint8_t length;
|
||||
} __attribute__((packed));
|
||||
|
||||
struct acpi_sdt *acpi_find_sdt(const char sig[4]);
|
||||
|
||||
#endif
|
||||
@@ -4,15 +4,13 @@
|
||||
#include "idt.h"
|
||||
#include "io.h"
|
||||
#include "kutils.h"
|
||||
#include "../core/panic.h"
|
||||
|
||||
extern void serial_write(const char *str);
|
||||
|
||||
#include "process.h"
|
||||
#include "cmd.h"
|
||||
|
||||
|
||||
void kernel_panic(registers_t *regs, const char *error_name);
|
||||
|
||||
static const char *exception_messages[] = {
|
||||
"Division By Zero",
|
||||
"Debug",
|
||||
|
||||
Reference in New Issue
Block a user