-
Notifications
You must be signed in to change notification settings - Fork 1
Development #134
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Development #134
Changes from all commits
Commits
Show all changes
4 commits
Select commit
Hold shift + click to select a range
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,208 @@ | ||
#include "ACPI.h" | ||
#include "Console.h" | ||
#include "Io.h" | ||
#include "MemOps.h" | ||
#include "StringOps.h" | ||
#include "VMem.h" | ||
#include "TSC.h" | ||
|
||
static ACPIFADT* g_fadt = NULL; | ||
static bool g_acpi_initialized = false; | ||
|
||
// Find RSDP in BIOS memory areas | ||
static ACPIRSDPv1* FindRSDP(void) { | ||
// Search in EBDA (Extended BIOS Data Area) | ||
uint16_t ebda = 0; | ||
if (VMemGetPhysAddr(0x40E) != 0) { | ||
ebda = *(uint16_t*)0x40E; | ||
} | ||
if (ebda) { | ||
uint8_t* ebda_ptr = (uint8_t*)(ebda << 4); | ||
for (uint32_t i = 0; i < 1024; i += 16) { | ||
if (FastMemcmp(ebda_ptr + i, ACPI_RSDP_SIG, 8) == 0) { | ||
return (ACPIRSDPv1*)(ebda_ptr + i); | ||
} | ||
} | ||
} | ||
|
||
// Search in BIOS ROM area (0xE0000-0xFFFFF) | ||
for (uint32_t addr = 0xE0000; addr < 0x100000; addr += 16) { | ||
if (FastMemcmp((void*)addr, ACPI_RSDP_SIG, 8) == 0) { | ||
return (ACPIRSDPv1*)addr; | ||
} | ||
} | ||
|
||
return NULL; | ||
} | ||
|
||
// Validate ACPI table checksum | ||
static bool ValidateChecksum(void* table, uint32_t length) { | ||
uint8_t sum = 0; | ||
uint8_t* bytes = (uint8_t*)table; | ||
for (uint32_t i = 0; i < length; i++) { | ||
sum += bytes[i]; | ||
} | ||
return sum == 0; | ||
} | ||
|
||
// Map ACPI table to virtual memory | ||
static void* MapACPITable(uint32_t phys_addr, uint32_t size) { | ||
// Align to page boundaries | ||
uint32_t aligned_addr = phys_addr & ~0xFFF; | ||
uint32_t offset = phys_addr - aligned_addr; | ||
uint32_t aligned_size = ((size + offset + 0xFFF) & ~0xFFF); | ||
|
||
void* virt_addr = VMemAlloc(aligned_size); | ||
if (!virt_addr) return NULL; | ||
|
||
if (VMemUnmap((uint64_t)virt_addr, aligned_size) != VMEM_SUCCESS) { | ||
VMemFree(virt_addr, aligned_size); | ||
return NULL; | ||
} | ||
|
||
if (VMemMapMMIO((uint64_t)virt_addr, aligned_addr, aligned_size, PAGE_WRITABLE | PAGE_NOCACHE) != VMEM_SUCCESS) { | ||
VMemFree(virt_addr, aligned_size); | ||
return NULL; | ||
} | ||
|
||
return (uint8_t*)virt_addr + offset; | ||
} | ||
|
||
bool ACPIInit(void) { | ||
PrintKernel("ACPI: Initializing ACPI subsystem...\n"); | ||
|
||
// Find RSDP | ||
ACPIRSDPv1* rsdp = FindRSDP(); | ||
if (!rsdp) { | ||
PrintKernelError("ACPI: RSDP not found\n"); | ||
return false; | ||
} | ||
|
||
PrintKernel("ACPI: Found RSDP at 0x"); | ||
PrintKernelHex((uint64_t)rsdp); | ||
PrintKernel("\n"); | ||
|
||
// Validate RSDP checksum | ||
if (!ValidateChecksum(rsdp, sizeof(ACPIRSDPv1))) { | ||
PrintKernelError("ACPI: Invalid RSDP checksum\n"); | ||
return false; | ||
} | ||
|
||
ACPIRSDT* rsdt = (ACPIRSDT*)MapACPITable(rsdp->rsdt_address, | ||
sizeof(ACPISDTHeader)); | ||
if (!rsdt) { | ||
PrintKernelError("ACPI: Failed to map RSDT\n"); | ||
return false; | ||
} | ||
// Validate RSDT signature | ||
if (FastMemcmp(rsdt->header.signature, ACPI_RSDT_SIG, 4) != 0) { | ||
PrintKernelError("ACPI: Invalid RSDT signature\n"); | ||
// Clean up the initial header‐only mapping | ||
VMemUnmap((uint64_t)rsdt - (rsdp->rsdt_address & 0xFFF), | ||
((sizeof(ACPISDTHeader) + (rsdp->rsdt_address & 0xFFF) + 0xFFF) | ||
& ~0xFFF)); | ||
return false; | ||
} | ||
// Remap with the full table length | ||
uint32_t rsdt_size = rsdt->header.length; | ||
// Remember the old header mapping so we can free it afterward | ||
void* old_rsdt = rsdt; | ||
uint32_t old_offset = rsdp->rsdt_address & 0xFFF; | ||
rsdt = (ACPIRSDT*)MapACPITable(rsdp->rsdt_address, rsdt_size); | ||
// Now unmap the temporary header‐only region | ||
VMemUnmap((uint64_t)old_rsdt - old_offset, | ||
((sizeof(ACPISDTHeader) + old_offset + 0xFFF) & ~0xFFF)); | ||
|
||
PrintKernel("ACPI: RSDT mapped, length="); | ||
PrintKernelInt(rsdt_size); | ||
PrintKernel("\n"); | ||
|
||
// Find FADT | ||
uint32_t entries = (rsdt_size - sizeof(ACPISDTHeader)) / 4; | ||
for (uint32_t i = 0; i < entries; i++) { | ||
ACPISDTHeader* header = (ACPISDTHeader*)MapACPITable( | ||
rsdt->table_pointers[i], | ||
sizeof(ACPISDTHeader) | ||
); | ||
if (!header) continue; | ||
|
||
bool is_fadt = FastMemcmp(header->signature, ACPI_FADT_SIG, 4) == 0; | ||
uint32_t table_length = header->length; | ||
uint32_t header_offset = rsdt->table_pointers[i] & 0xFFF; | ||
|
||
// Unmap the header mapping now that we've inspected it | ||
VMemUnmap( | ||
(uint64_t)header - header_offset, | ||
( (sizeof(ACPISDTHeader) + header_offset + 0xFFF) & ~0xFFF ) | ||
); | ||
|
||
if (is_fadt) { | ||
PrintKernel("ACPI: Found FADT\n"); | ||
g_fadt = (ACPIFADT*)MapACPITable( | ||
rsdt->table_pointers[i], | ||
table_length | ||
); | ||
break; | ||
} | ||
} | ||
|
||
PrintKernelError("ACPI: FADT not found or invalid\n"); | ||
return false; | ||
} | ||
|
||
void ACPIShutdown(void) { | ||
if (!g_acpi_initialized || !g_fadt) { | ||
PrintKernel("ACPI: Shutdown not available, using fallback\n"); | ||
outw(0x604, 0x2000); | ||
return; | ||
} | ||
|
||
PrintKernel("ACPI: Initiating shutdown...\n"); | ||
|
||
// Enable ACPI mode if needed | ||
if (g_fadt->smi_command_port && g_fadt->acpi_enable) { | ||
PrintKernel("ACPI: Enabling ACPI mode via SMI\n"); | ||
outb(g_fadt->smi_command_port, g_fadt->acpi_enable); | ||
} | ||
|
||
// Try multiple shutdown methods | ||
uint16_t shutdown_values[] = {0x2000, 0x3C00, 0x1400, 0x0000}; | ||
|
||
for (int i = 0; i < 4; i++) { | ||
PrintKernel("ACPI: Trying shutdown value 0x"); | ||
PrintKernelHex(shutdown_values[i]); | ||
PrintKernel(" on port 0x"); | ||
PrintKernelHex(g_fadt->pm1a_control_block); | ||
PrintKernel("\n"); | ||
|
||
outw(g_fadt->pm1a_control_block, shutdown_values[i]); | ||
|
||
// Wait a bit | ||
delay(10); | ||
} | ||
|
||
// Fallback methods | ||
PrintKernel("ACPI: Trying QEMU shutdown\n"); | ||
outw(0x604, 0x2000); | ||
|
||
PrintKernel("ACPI: Trying Bochs shutdown\n"); | ||
outw(0xB004, 0x2000); | ||
|
||
PrintKernelError("ACPI: All shutdown methods failed\n"); | ||
} | ||
|
||
void ACPIReboot(void) { | ||
PrintKernel("ACPI: Initiating reboot...\n"); | ||
|
||
// Try keyboard controller reset | ||
outb(0x64, 0xFE); | ||
|
||
PrintKernel("ACPI: falling back to triple faulting...\n"); | ||
|
||
struct { | ||
uint16_t limit; | ||
uint64_t base; | ||
} __attribute__((packed)) invalid_idt = { 0, 0 }; | ||
__asm__ volatile("lidt %0; int $0x03" :: "m"(invalid_idt)); | ||
__builtin_unreachable(); | ||
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,85 @@ | ||
#pragma once | ||
#include "stdint.h" | ||
#include "stdbool.h" | ||
|
||
// ACPI Table signatures | ||
#define ACPI_RSDP_SIG "RSD PTR " | ||
#define ACPI_RSDT_SIG "RSDT" | ||
#define ACPI_FADT_SIG "FACP" | ||
|
||
// ACPI structures | ||
typedef struct { | ||
char signature[8]; | ||
uint8_t checksum; | ||
char oem_id[6]; | ||
uint8_t revision; | ||
uint32_t rsdt_address; | ||
} __attribute__((packed)) ACPIRSDPv1; | ||
|
||
typedef struct { | ||
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)) ACPISDTHeader; | ||
|
||
typedef struct { | ||
ACPISDTHeader header; | ||
uint32_t table_pointers[]; | ||
} __attribute__((packed)) ACPIRSDT; | ||
|
||
typedef struct { | ||
ACPISDTHeader header; | ||
uint32_t firmware_ctrl; | ||
uint32_t dsdt; | ||
uint8_t reserved; | ||
uint8_t preferred_pm_profile; | ||
uint16_t sci_interrupt; | ||
uint32_t smi_command_port; | ||
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 cstate_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; | ||
uint8_t reserved2; | ||
uint32_t flags; | ||
} __attribute__((packed)) ACPIFADT; | ||
|
||
// Power management defines | ||
#define ACPI_SLP_TYP_MASK 0x1C00 | ||
#define ACPI_SLP_EN 0x2000 | ||
|
||
// Function declarations | ||
bool ACPIInit(void); | ||
void ACPIShutdown(void); | ||
void ACPIReboot(void); |
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.