mirror of https://github.com/vinc/moros.git
152 lines
4.7 KiB
Rust
152 lines
4.7 KiB
Rust
use crate::sys;
|
|
|
|
use acpi::{AcpiHandler, AcpiTables, PhysicalMapping};
|
|
use alloc::boxed::Box;
|
|
use aml::value::AmlValue;
|
|
use aml::{AmlContext, AmlName, DebugVerbosity, Handler};
|
|
use core::ptr::NonNull;
|
|
use x86_64::instructions::port::Port;
|
|
use x86_64::PhysAddr;
|
|
|
|
fn read_addr<T>(addr: usize) -> T where T: Copy {
|
|
let virtual_address = sys::mem::phys_to_virt(PhysAddr::new(addr as u64));
|
|
unsafe { *virtual_address.as_ptr::<T>() }
|
|
}
|
|
|
|
pub fn shutdown() {
|
|
let mut pm1a_control_block = 0;
|
|
let mut slp_typa = 0;
|
|
let slp_len = 1 << 13;
|
|
|
|
log!("ACPI Shutdown");
|
|
let res = unsafe { AcpiTables::search_for_rsdp_bios(MorosAcpiHandler) };
|
|
match res {
|
|
Ok(acpi) => {
|
|
if let Ok(fadt) = acpi.find_table::<acpi::fadt::Fadt>() {
|
|
if let Ok(block) = fadt.pm1a_control_block() {
|
|
pm1a_control_block = block.address as u32;
|
|
}
|
|
}
|
|
if let Ok(dsdt) = &acpi.dsdt() {
|
|
let phys_addr = PhysAddr::new(dsdt.address as u64);
|
|
let virt_addr = sys::mem::phys_to_virt(phys_addr);
|
|
let ptr = virt_addr.as_ptr();
|
|
let table = unsafe {
|
|
core::slice::from_raw_parts(ptr , dsdt.length as usize)
|
|
};
|
|
let handler = Box::new(MorosAmlHandler);
|
|
let mut aml = AmlContext::new(handler, DebugVerbosity::None);
|
|
if aml.parse_table(table).is_ok() {
|
|
let name = AmlName::from_str("\\_S5").unwrap();
|
|
let res = aml.namespace.get_by_path(&name);
|
|
if let Ok(AmlValue::Package(s5)) = res {
|
|
if let AmlValue::Integer(value) = s5[0] {
|
|
slp_typa = value as u16;
|
|
}
|
|
}
|
|
} else {
|
|
debug!("ACPI: Could not parse AML in DSDT");
|
|
// FIXME: AML parsing works on QEMU and Bochs but not
|
|
// on VirtualBox at the moment, so we use the following
|
|
// hardcoded value:
|
|
slp_typa = (5 & 7) << 10;
|
|
}
|
|
} else {
|
|
debug!("ACPI: Could not find DSDT in BIOS");
|
|
}
|
|
}
|
|
Err(_e) => {
|
|
debug!("ACPI: Could not find RDSP in BIOS");
|
|
}
|
|
};
|
|
|
|
let mut port: Port<u16> = Port::new(pm1a_control_block as u16);
|
|
unsafe {
|
|
port.write(slp_typa | slp_len);
|
|
}
|
|
}
|
|
|
|
#[derive(Clone)]
|
|
pub struct MorosAcpiHandler;
|
|
|
|
impl AcpiHandler for MorosAcpiHandler {
|
|
unsafe fn map_physical_region<T>(
|
|
&self,
|
|
addr: usize,
|
|
size: usize,
|
|
) -> PhysicalMapping<Self, T> {
|
|
let phys_addr = PhysAddr::new(addr as u64);
|
|
let virt_addr = sys::mem::phys_to_virt(phys_addr);
|
|
let ptr = NonNull::new(virt_addr.as_mut_ptr()).unwrap();
|
|
PhysicalMapping::new(addr, ptr, size, size, Self)
|
|
}
|
|
|
|
fn unmap_physical_region<T>(_region: &PhysicalMapping<Self, T>) {}
|
|
}
|
|
|
|
struct MorosAmlHandler;
|
|
|
|
impl Handler for MorosAmlHandler {
|
|
fn read_u8(&self, address: usize) -> u8 {
|
|
read_addr::<u8>(address)
|
|
}
|
|
fn read_u16(&self, address: usize) -> u16 {
|
|
read_addr::<u16>(address)
|
|
}
|
|
fn read_u32(&self, address: usize) -> u32 {
|
|
read_addr::<u32>(address)
|
|
}
|
|
fn read_u64(&self, address: usize) -> u64 {
|
|
read_addr::<u64>(address)
|
|
}
|
|
|
|
fn write_u8(&mut self, _: usize, _: u8) {
|
|
unimplemented!()
|
|
}
|
|
fn write_u16(&mut self, _: usize, _: u16) {
|
|
unimplemented!()
|
|
}
|
|
fn write_u32(&mut self, _: usize, _: u32) {
|
|
unimplemented!()
|
|
}
|
|
fn write_u64(&mut self, _: usize, _: u64) {
|
|
unimplemented!()
|
|
}
|
|
fn read_io_u8(&self, _: u16) -> u8 {
|
|
unimplemented!()
|
|
}
|
|
fn read_io_u16(&self, _: u16) -> u16 {
|
|
unimplemented!()
|
|
}
|
|
fn read_io_u32(&self, _: u16) -> u32 {
|
|
unimplemented!()
|
|
}
|
|
fn write_io_u8(&self, _: u16, _: u8) {
|
|
unimplemented!()
|
|
}
|
|
fn write_io_u16(&self, _: u16, _: u16) {
|
|
unimplemented!()
|
|
}
|
|
fn write_io_u32(&self, _: u16, _: u32) {
|
|
unimplemented!()
|
|
}
|
|
fn read_pci_u8(&self, _: u16, _: u8, _: u8, _: u8, _: u16) -> u8 {
|
|
unimplemented!()
|
|
}
|
|
fn read_pci_u16(&self, _: u16, _: u8, _: u8, _: u8, _: u16) -> u16 {
|
|
unimplemented!()
|
|
}
|
|
fn read_pci_u32(&self, _: u16, _: u8, _: u8, _: u8, _: u16) -> u32 {
|
|
unimplemented!()
|
|
}
|
|
fn write_pci_u8(&self, _: u16, _: u8, _: u8, _: u8, _: u16, _: u8) {
|
|
unimplemented!()
|
|
}
|
|
fn write_pci_u16(&self, _: u16, _: u8, _: u8, _: u8, _: u16, _: u16) {
|
|
unimplemented!()
|
|
}
|
|
fn write_pci_u32(&self, _: u16, _: u8, _: u8, _: u8, _: u16, _: u32) {
|
|
unimplemented!()
|
|
}
|
|
}
|