Add acpi crate for early table parsing
All checks were successful
Build / build (push) Successful in 3m28s

This commit is contained in:
Mathieu Strypsteen 2024-11-09 12:26:21 +01:00
parent e648dab896
commit 264b58e6f3
9 changed files with 90 additions and 64 deletions

12
Cargo.lock generated
View file

@ -2,6 +2,17 @@
# It is not intended for manual editing.
version = 3
[[package]]
name = "acpi"
version = "5.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9e42f25ac5fa51f4188d14baf8f387a97dcd8639644b2f3df948bf5f6dd7d6fa"
dependencies = [
"bit_field",
"bitflags",
"log",
]
[[package]]
name = "acpica-rs"
version = "0.0.1"
@ -152,6 +163,7 @@ dependencies = [
name = "kernel"
version = "0.0.1"
dependencies = [
"acpi",
"acpica-rs",
"bitfield",
"bitvec",

View file

@ -5,6 +5,7 @@ edition = "2021"
license = "Unlicense"
[dependencies]
acpi = {version = "5.1.0", default-features = false}
acpica-rs = {path = "../lib/acpica-rs"}
bitfield = "0.17.0"
bitvec = {version = "1.0.1", default-features = false, features = ["alloc", "atomic"]}

View file

@ -135,7 +135,7 @@ fn map(pml4: &mut PageTable, virt: u64, phys: u64, user: bool, write: bool, exec
table.entries_phys[table_i].set_cache_disable(cache_disable as u64);
table.entries_phys[table_i].set_present(1);
}
pub unsafe fn unmap(address: u64) {
fn unmap(address: u64) {
let mut current_pml4 = CURRENT_PML4.lock();
let page = get_page(current_pml4.as_mut().unwrap(), address);
assert!(page.is_some(), "Page isn't mapped");
@ -166,6 +166,14 @@ pub unsafe fn map_physical(phys: u64, mut size: u64) -> u64 {
map_range(virt_start, phys_start, size, false, true, false, true);
virt_start + phys_offset
}
pub unsafe fn unmap_physical(address: u64, size: u64) {
let end = (address + size + 0xfff) / 0x1000 * 0x1000;
let start = address / 0x1000 * 0x1000;
let size = end - start;
for i in 0..size / 0x1000 {
unmap(start + i * 0x1000);
}
}
pub fn setup_paging(loader_struct: &LoaderStruct, phys_start: u64, heap_start: u64) {
HEAP_PHYS_START.store(heap_start, Ordering::Relaxed);
let mut memory_size = 0;

View file

@ -11,6 +11,7 @@ use core::{
sync::atomic::{AtomicU64, Ordering},
};
use acpi::AcpiTables;
use acpica_rs::AcpiInitializeTables;
use buddy_system_allocator::LockedHeap;
use cpu::{gdt::setup_gdt, idt::setup_idt, paging::setup_paging};
@ -22,7 +23,7 @@ use kernel_common::{
};
use log::{error, info};
use spin::Mutex;
use sys::{acpica_osl::AE_OK, hpet::setup_hpet, lapic::setup_lapic_timer, madt::parse_madt, pic::disable_pic, task::setup_multitasking};
use sys::{acpica_osl::AE_OK, early_acpi::EarlyACPIHandler, hpet::setup_hpet, lapic::setup_lapic_timer, madt::parse_madt, pic::disable_pic, task::setup_multitasking};
mod cpu;
mod misc;
@ -58,15 +59,19 @@ extern "C" fn early_main(temp_loader_struct: *const LoaderStruct) -> ! {
setup_paging(&loader_struct, loader_struct.phys_kernel_start, loader_struct.phys_heap_start);
disable_pic();
RSDP_ADDRESS.store(loader_struct.rsdp_address, Ordering::Relaxed);
let status = unsafe { AcpiInitializeTables(null_mut(), 16, 0) };
assert_eq!(status, AE_OK);
parse_madt();
setup_hpet();
let early_acpi_tables;
unsafe {
early_acpi_tables = AcpiTables::from_rsdp(EarlyACPIHandler {}, loader_struct.rsdp_address as usize).unwrap();
}
parse_madt(&early_acpi_tables);
setup_hpet(&early_acpi_tables);
setup_lapic_timer();
setup_multitasking();
}
fn main() {
info!("Starting main kernel task");
let status = unsafe { AcpiInitializeTables(null_mut(), 0, 0) };
assert_eq!(status, AE_OK);
}
#[panic_handler]
fn panic(info: &PanicInfo) -> ! {

View file

@ -9,7 +9,7 @@ use acpica_rs::{ACPI_PHYSICAL_ADDRESS, ACPI_PREDEFINED_NAMES, ACPI_SIZE, ACPI_ST
use kernel_common::log::log_raw;
use crate::{
cpu::paging::{map_physical, unmap},
cpu::paging::{map_physical, unmap_physical},
misc::wrapped_alloc::{wrapped_alloc, wrapped_dealloc},
RSDP_ADDRESS,
};
@ -158,14 +158,8 @@ extern "C" fn AcpiOsTerminate() -> ACPI_STATUS {
}
#[no_mangle]
extern "C" fn AcpiOsUnmapMemory(address: *mut c_void, size: ACPI_SIZE) {
let address = address as u64;
let end = (address + size + 0xfff) / 0x1000 * 0x1000;
let start = address / 0x1000 * 0x1000;
let size = end - start;
for i in 0..size / 0x1000 {
unsafe {
unmap(start + i * 0x1000);
}
unsafe {
unmap_physical(address as u64, size);
}
}
#[no_mangle]

View file

@ -0,0 +1,22 @@
use core::ptr::NonNull;
use acpi::{AcpiHandler, PhysicalMapping};
use crate::cpu::paging::{map_physical, unmap_physical};
#[derive(Clone, Copy)]
pub struct EarlyACPIHandler {}
impl AcpiHandler for EarlyACPIHandler {
unsafe fn map_physical_region<T>(&self, phys: usize, size: usize) -> PhysicalMapping<Self, T> {
unsafe {
let virt = map_physical(phys as u64, size as u64);
return PhysicalMapping::new(phys, NonNull::new(virt as *mut T).unwrap(), size, size, *self);
}
}
fn unmap_physical_region<T>(region: &PhysicalMapping<Self, T>) {
unsafe {
unmap_physical(region.virtual_start().as_ptr() as u64, region.mapped_length() as u64);
}
}
}

View file

@ -3,14 +3,15 @@ use core::{
sync::atomic::{AtomicBool, AtomicPtr, AtomicUsize, Ordering},
};
use acpica_rs::{acpi_table_header, acpi_table_hpet, AcpiGetTable};
use acpi::{AcpiTables, HpetInfo};
use alloc::vec::Vec;
use kernel_common::instructions::pause;
use spin::Mutex;
use crate::{cpu::paging::map_physical, sys::acpica_osl::AE_OK};
use crate::cpu::paging::map_physical;
use super::{
early_acpi::EarlyACPIHandler,
ioapic::register_isa_irq_handler,
scheduler::{schedule_task, yield_task},
sync::{lock_kernel, unlock_kernel},
@ -119,16 +120,9 @@ pub fn sleep_internal(task: Task) {
sleeping_list.sort_by(|a, b| a.sleep_until_us.cmp(&b.sleep_until_us));
schedule_hpet_interrupt(sleeping_list.first().unwrap().sleep_until_us);
}
pub fn setup_hpet() {
let signature = b"HPET" as *const u8;
let address;
let mut table_address: u64 = 0;
unsafe {
let status = AcpiGetTable(signature as *mut i8, 1, &mut table_address as *mut u64 as *mut *mut acpi_table_header);
assert_eq!(status, AE_OK);
let hpet_table = &*(table_address as *const acpi_table_hpet);
address = map_physical(hpet_table.Address.Address, 0x200) as *mut u64;
}
pub fn setup_hpet(tables: &AcpiTables<EarlyACPIHandler>) {
let hpet_info = HpetInfo::new(tables).unwrap();
let address = unsafe { map_physical(hpet_info.base_address as u64, 0x200) } as *mut u64;
ADDRESS.store(address, Ordering::Relaxed);
let period = unsafe { address.add(REGISTER_CAPABILITIES).read_volatile() >> 32 } as usize;
PERIOD.store(period, Ordering::Relaxed);

View file

@ -1,50 +1,39 @@
use core::mem::size_of;
use acpica_rs::{acpi_madt_interrupt_override, acpi_madt_io_apic, acpi_madt_local_apic_override, acpi_subtable_header, acpi_table_header, acpi_table_madt, AcpiGetTable};
use acpi::{
madt::{Madt, MadtEntry},
AcpiTables,
};
use kernel_common::instructions::sti;
use crate::sys::acpica_osl::AE_OK;
use super::{
early_acpi::EarlyACPIHandler,
ioapic::{set_irq_override, setup_ioapic},
lapic::setup_lapic,
};
fn process_subtables(subtable_address: u64, end_address: u64, subtable_type: u8, handler: &mut dyn FnMut(u64)) {
let mut subtable_address_i = subtable_address;
while subtable_address_i < end_address {
let subtable_header = unsafe { &*(subtable_address_i as *const acpi_subtable_header) };
if subtable_header.Type == subtable_type {
handler(subtable_address_i);
pub fn parse_madt(tables: &AcpiTables<EarlyACPIHandler>) {
let madt = tables.find_table::<Madt>().unwrap();
let mut lapic_address: u64 = madt.local_apic_address as u64;
for i in madt.entries() {
if let MadtEntry::LocalApicAddressOverride(lapic_override) = i {
lapic_address = lapic_override.local_apic_address;
}
subtable_address_i += subtable_header.Length as u64;
}
}
pub fn parse_madt() {
let madt: &acpi_table_madt;
let signature = b"APIC" as *const u8;
let mut address: u64 = 0;
unsafe {
let status = AcpiGetTable(signature as *mut i8, 1, &mut address as *mut u64 as *mut *mut acpi_table_header);
assert_eq!(status, AE_OK);
madt = &*(address as *const acpi_table_madt);
}
let mut lapic_address: u64 = madt.Address as u64;
let subtable_address = madt as *const acpi_table_madt as u64 + size_of::<acpi_table_madt>() as u64;
let end_address = madt as *const acpi_table_madt as u64 + madt.Header.Length as u64;
process_subtables(subtable_address, end_address, 5, &mut |addr| {
let subtable = unsafe { &*(addr as *const acpi_madt_local_apic_override) };
lapic_address = subtable.Address;
});
setup_lapic(lapic_address);
process_subtables(subtable_address, end_address, 1, &mut |addr| {
let subtable = unsafe { &*(addr as *const acpi_madt_io_apic) };
setup_ioapic(subtable.Id, subtable.Address as u64, subtable.GlobalIrqBase);
});
process_subtables(subtable_address, end_address, 2, &mut |addr| {
let subtable = unsafe { &*(addr as *const acpi_madt_interrupt_override) };
set_irq_override(subtable.GlobalIrq as usize, subtable.SourceIrq as usize, subtable.IntiFlags as u8 & 3, subtable.IntiFlags as u8 & 0xc);
});
for i in madt.entries() {
if let MadtEntry::IoApic(ioapic) = i {
setup_ioapic(ioapic.io_apic_id, ioapic.io_apic_address as u64, ioapic.global_system_interrupt_base);
}
}
for i in madt.entries() {
if let MadtEntry::InterruptSourceOverride(irq_override) = i {
set_irq_override(
irq_override.global_system_interrupt as usize,
irq_override.irq as usize,
irq_override.flags as u8 & 3,
irq_override.flags as u8 & 0xc,
);
}
}
unsafe {
sti();
}

View file

@ -1,4 +1,5 @@
pub mod acpica_osl;
pub mod early_acpi;
pub mod hpet;
mod ioapic;
pub mod lapic;