Add acpi crate for early table parsing
All checks were successful
Build / build (push) Successful in 3m28s
All checks were successful
Build / build (push) Successful in 3m28s
This commit is contained in:
parent
e648dab896
commit
264b58e6f3
9 changed files with 90 additions and 64 deletions
12
Cargo.lock
generated
12
Cargo.lock
generated
|
@ -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",
|
||||
|
|
|
@ -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"]}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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) -> ! {
|
||||
|
|
|
@ -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]
|
||||
|
|
22
kernel/src/sys/early_acpi.rs
Normal file
22
kernel/src/sys/early_acpi.rs
Normal 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);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
pub mod acpica_osl;
|
||||
pub mod early_acpi;
|
||||
pub mod hpet;
|
||||
mod ioapic;
|
||||
pub mod lapic;
|
||||
|
|
Loading…
Add table
Reference in a new issue