Update to latest acpi crate

This commit is contained in:
Jeremy Soller
2025-09-28 08:53:18 -06:00
parent 6b335d4f90
commit 62fab168e5
6 changed files with 255 additions and 222 deletions
+29 -33
View File
@@ -1,6 +1,7 @@
use rustc_hash::FxHashMap;
use std::convert::{TryFrom, TryInto};
use std::ops::Deref;
use std::str::FromStr;
use std::sync::{Arc, Mutex};
use std::{fmt, mem};
use syscall::PAGE_SIZE;
@@ -11,9 +12,13 @@ use common::io::{Io, Pio};
use parking_lot::{RwLock, RwLockReadGuard, RwLockWriteGuard};
use thiserror::Error;
use aml::{AmlContext, AmlError, AmlHandle, AmlName};
use acpi::{
aml::{namespace::AmlName, AmlError, Interpreter},
platform::AcpiPlatform,
AcpiTables,
};
use amlserde::aml_serde_name::aml_to_symbol;
use amlserde::{AmlHandleLookup, AmlSerde};
use amlserde::AmlSerde;
#[cfg(target_arch = "x86_64")]
pub mod dmar;
@@ -232,7 +237,7 @@ pub struct Ssdt(Sdt);
// must empty the cache so it is rebuilt.
// If you modify an SDT, you must discard the aml_context and rebuild it.
pub struct AmlSymbols {
aml_context: AmlContext,
aml_context: Interpreter<AmlPhysMemHandler>,
// k = name, v = description
symbol_cache: FxHashMap<String, String>,
page_cache: Arc<Mutex<AmlPageCache>>,
@@ -241,17 +246,19 @@ pub struct AmlSymbols {
impl AmlSymbols {
pub fn new() -> Self {
let page_cache = Arc::new(Mutex::new(AmlPageCache::default()));
let handler = AmlPhysMemHandler::new(Arc::clone(&page_cache));
//TODO: use these parsed tables for the rest of acpid and return errors instead of unwrap
let rsdp_address = usize::from_str_radix(&std::env::var("RSDP_ADDR").unwrap(), 16).unwrap();
let tables = unsafe { AcpiTables::from_rsdp(handler.clone(), rsdp_address).unwrap() };
let platform = AcpiPlatform::new(tables, handler).unwrap();
Self {
aml_context: AmlContext::new(
Box::new(AmlPhysMemHandler::new(Arc::clone(&page_cache))),
aml::DebugVerbosity::None,
),
aml_context: Interpreter::new_from_platform(&platform).unwrap(),
symbol_cache: FxHashMap::default(),
page_cache,
}
}
pub fn mut_aml_context(&mut self) -> &mut AmlContext {
pub fn mut_aml_context(&mut self) -> &mut Interpreter<AmlPhysMemHandler> {
&mut self.aml_context
}
@@ -260,7 +267,7 @@ impl AmlSymbols {
}
pub fn parse_table(&mut self, aml: &[u8]) -> Result<(), AmlError> {
self.aml_context.parse_table(aml)
self.aml_context.load_table(aml)
}
pub fn lookup(&self, symbol: &str) -> Option<String> {
@@ -272,18 +279,19 @@ impl AmlSymbols {
}
pub fn build_cache(&mut self) {
let mut symbol_list: Vec<(AmlName, String, AmlHandle)> = Vec::with_capacity(5000);
let mut symbol_list: Vec<(AmlName, String)> = Vec::with_capacity(5000);
if self
.aml_context
.namespace
.lock()
.traverse(|level_aml_name, level| {
for (child_seg, handle) in level.values.iter() {
if let Ok(aml_name) =
AmlName::from_name_seg(child_seg.to_owned()).resolve(level_aml_name)
{
let name = aml_to_symbol(&aml_name);
symbol_list.push((aml_name, name, handle.to_owned()));
symbol_list.push((aml_name, name));
} else {
log::error!(
"AmlName resolve failed, {:?}:{:?}",
@@ -300,24 +308,12 @@ impl AmlSymbols {
return;
}
let mut handle_lookup = AmlHandleLookup::new();
for (aml_name, name, handle) in &symbol_list {
handle_lookup.insert(handle.to_owned(), aml_name.to_owned());
}
let mut symbol_cache: FxHashMap<String, String> = FxHashMap::default();
for (aml_name, name, handle) in &symbol_list {
for (aml_name, name) in &symbol_list {
// create an empty entry, in case something goes wrong with serialization
symbol_cache.insert(name.to_owned(), "".to_owned());
if let Some(ser_value) = AmlSerde::from_aml(
&mut self.aml_context,
&handle_lookup,
&aml_to_symbol(aml_name),
aml_name,
handle,
) {
if let Some(ser_value) = AmlSerde::from_aml(&mut self.aml_context, aml_name) {
if let Ok(ser_string) = ron::ser::to_string_pretty(&ser_value, Default::default()) {
// replace the empty entry
symbol_cache.insert(name.to_owned(), ser_string);
@@ -536,7 +532,7 @@ impl AcpiContext {
let aml_symbols = self.aml_symbols.read();
let s5_aml_name = match aml::AmlName::from_str("\\_S5") {
let s5_aml_name = match acpi::aml::namespace::AmlName::from_str("\\_S5") {
Ok(aml_name) => aml_name,
Err(error) => {
log::error!("Could not build AmlName for \\_S5, {:?}", error);
@@ -544,7 +540,7 @@ impl AcpiContext {
}
};
let s5 = match aml_symbols.aml_context.namespace.get_by_path(&s5_aml_name) {
let s5 = match aml_symbols.aml_context.namespace.lock().get(s5_aml_name) {
Ok(s5) => s5,
Err(error) => {
log::error!("Cannot set S-state, missing \\_S5, {:?}", error);
@@ -552,23 +548,23 @@ impl AcpiContext {
}
};
let package = match s5 {
aml::AmlValue::Package(package) => package,
let package = match s5.deref() {
acpi::aml::object::Object::Package(package) => package,
_ => {
log::error!("Cannot set S-state, \\_S5 is not a package");
return;
}
};
let slp_typa = match package[0] {
aml::AmlValue::Integer(i) => i,
let slp_typa = match package[0].deref() {
acpi::aml::object::Object::Integer(i) => i.to_owned(),
_ => {
log::error!("typa is not an Integer");
return;
}
};
let slp_typb = match package[1] {
aml::AmlValue::Integer(i) => i,
let slp_typb = match package[1].deref() {
acpi::aml::object::Object::Integer(i) => i.to_owned(),
_ => {
log::error!("typb is not an Integer");
return;
+80 -18
View File
@@ -1,9 +1,11 @@
use acpi::{aml::AmlError, Handle, PciAddress, PhysicalMapping};
#[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
use common::io::{Io, Pio};
use num_traits::PrimInt;
use rustc_hash::FxHashMap;
use std::fmt::LowerHex;
use std::mem::size_of;
use std::ptr::NonNull;
use std::sync::{Arc, Mutex};
use syscall::PAGE_SIZE;
@@ -21,7 +23,7 @@ impl MappedPage {
common::physmap(
phys_page,
PAGE_SIZE,
common::Prot::RO,
common::Prot::RW,
common::MemoryType::default(),
)
.map_err(|error| std::io::Error::from_raw_os_error(error.errno()))?
@@ -135,6 +137,7 @@ impl AmlPageCache {
}
}
#[derive(Clone)]
pub struct AmlPhysMemHandler {
page_cache: Arc<Mutex<AmlPageCache>>,
}
@@ -147,7 +150,35 @@ impl AmlPhysMemHandler {
}
}
impl aml::Handler for AmlPhysMemHandler {
impl acpi::Handler for AmlPhysMemHandler {
unsafe fn map_physical_region<T>(&self, phys: usize, size: usize) -> PhysicalMapping<Self, T> {
let phys_page = phys & PAGE_MASK;
let offset = phys & OFFSET_MASK;
let pages = (offset + size + PAGE_SIZE - 1) / PAGE_SIZE;
let map_size = pages * PAGE_SIZE;
let virt_page = common::physmap(
phys_page,
map_size,
common::Prot::RW,
common::MemoryType::default(),
)
.expect("failed to map physical region") as usize;
PhysicalMapping {
physical_start: phys,
virtual_start: NonNull::new((virt_page + offset) as *mut T).unwrap(),
region_length: size,
mapped_length: map_size,
handler: self.clone(),
}
}
fn unmap_physical_region<T>(region: &PhysicalMapping<Self, T>) {
let virt_page = region.virtual_start.addr().get() & PAGE_MASK;
unsafe {
libredox::call::munmap(virt_page as *mut (), region.mapped_length)
.expect("failed to unmap physical region")
}
}
fn read_u8(&self, address: usize) -> u8 {
log::trace!("read u8 {:X}", address);
if let Ok(mut page_cache) = self.page_cache.lock() {
@@ -189,7 +220,7 @@ impl aml::Handler for AmlPhysMemHandler {
0
}
fn write_u8(&mut self, address: usize, value: u8) {
fn write_u8(&self, address: usize, value: u8) {
log::trace!("write u8 {:X} = {:X}", address, value);
if let Ok(mut page_cache) = self.page_cache.lock() {
if page_cache.write_to_phys::<u8>(address, value).is_ok() {
@@ -198,7 +229,7 @@ impl aml::Handler for AmlPhysMemHandler {
}
log::error!("failed to write u8 {:#x}", address);
}
fn write_u16(&mut self, address: usize, value: u16) {
fn write_u16(&self, address: usize, value: u16) {
log::trace!("write u16 {:X} = {:X}", address, value);
if let Ok(mut page_cache) = self.page_cache.lock() {
if page_cache.write_to_phys::<u16>(address, value).is_ok() {
@@ -207,7 +238,7 @@ impl aml::Handler for AmlPhysMemHandler {
}
log::error!("failed to write u16 {:#x}", address);
}
fn write_u32(&mut self, address: usize, value: u32) {
fn write_u32(&self, address: usize, value: u32) {
log::trace!("write u32 {:X} = {:X}", address, value);
if let Ok(mut page_cache) = self.page_cache.lock() {
if page_cache.write_to_phys::<u32>(address, value).is_ok() {
@@ -216,7 +247,7 @@ impl aml::Handler for AmlPhysMemHandler {
}
log::error!("failed to write u32 {:#x}", address);
}
fn write_u64(&mut self, address: usize, value: u64) {
fn write_u64(&self, address: usize, value: u64) {
log::trace!("write u64 {:X} = {:X}", address, value);
if let Ok(mut page_cache) = self.page_cache.lock() {
if page_cache.write_to_phys::<u64>(address, value).is_ok() {
@@ -282,25 +313,56 @@ impl aml::Handler for AmlPhysMemHandler {
log::error!("cannot write 0x{value:08X} to port 0x{port:04X}");
}
fn read_pci_u8(&self, seg: u16, bus: u8, dev: u8, func: u8, off: u16) -> u8 {
log::error!("read pci u8 {seg:04X}:{bus:02X}:{dev:02X}.{func:01X}@{off:04X}");
fn read_pci_u8(&self, addr: PciAddress, off: u16) -> u8 {
log::error!("read pci u8 {addr}@{off:04X}");
0
}
fn read_pci_u16(&self, seg: u16, bus: u8, dev: u8, func: u8, off: u16) -> u16 {
log::error!("read pci u16 {seg:04X}:{bus:02X}:{dev:02X}.{func:01X}@{off:04X}");
fn read_pci_u16(&self, addr: PciAddress, off: u16) -> u16 {
log::error!("read pci u16 {addr}@{off:04X}");
0
}
fn read_pci_u32(&self, seg: u16, bus: u8, dev: u8, func: u8, off: u16) -> u32 {
log::error!("read pci u32 {seg:04X}:{bus:02X}:{dev:02X}.{func:01X}@{off:04X}");
fn read_pci_u32(&self, addr: PciAddress, off: u16) -> u32 {
log::error!("read pci u32 {addr}@{off:04X}");
0
}
fn write_pci_u8(&self, seg: u16, bus: u8, dev: u8, func: u8, off: u16, value: u8) {
log::error!("write pci u8 {seg:04X}:{bus:02X}:{dev:02X}.{func:01X}@{off:04X}={value:02X}");
fn write_pci_u8(&self, addr: PciAddress, off: u16, value: u8) {
log::error!("write pci u8 {addr}@{off:04X}={value:02X}");
}
fn write_pci_u16(&self, seg: u16, bus: u8, dev: u8, func: u8, off: u16, value: u16) {
log::error!("write pci u16 {seg:04X}:{bus:02X}:{dev:02X}.{func:01X}@{off:04X}={value:04X}");
fn write_pci_u16(&self, addr: PciAddress, off: u16, value: u16) {
log::error!("write pci u16 {addr}@{off:04X}={value:04X}");
}
fn write_pci_u32(&self, seg: u16, bus: u8, dev: u8, func: u8, off: u16, value: u32) {
log::error!("write pci u32 {seg:04X}:{bus:02X}:{dev:02X}.{func:01X}@{off:04X}={value:08X}");
fn write_pci_u32(&self, addr: PciAddress, off: u16, value: u32) {
log::error!("write pci u32 {addr}@{off:04X}={value:08X}");
}
fn nanos_since_boot(&self) -> u64 {
let ts = libredox::call::clock_gettime(libredox::flag::CLOCK_MONOTONIC)
.expect("failed to get time");
(ts.tv_sec as u64) * 1_000_000_000 + (ts.tv_nsec as u64)
}
fn stall(&self, microseconds: u64) {
let start = std::time::Instant::now();
while start.elapsed().as_micros() < microseconds.into() {
std::hint::spin_loop();
}
}
fn sleep(&self, milliseconds: u64) {
std::thread::sleep(std::time::Duration::from_millis(milliseconds));
}
fn create_mutex(&self) -> Handle {
log::warn!("TODO: Handler::create_mutex");
Handle(0)
}
fn acquire(&self, mutex: Handle, timeout: u16) -> Result<(), AmlError> {
log::warn!("TODO: Handler::aquire");
Ok(())
}
fn release(&self, mutex: Handle) {
log::warn!("TODO: Handler::release");
}
}