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
+127 -112
View File
@@ -1,7 +1,14 @@
use aml::value::{FieldAccessType, FieldUpdateRule, RegionSpace};
use aml::{AmlContext, AmlHandle, AmlName, AmlValue};
use rustc_hash::FxHashMap;
use acpi::{
aml::{
namespace::AmlName,
object::{FieldAccessType, FieldUnitKind, FieldUpdateRule, Object, ReferenceKind},
op_region::RegionSpace,
Interpreter,
},
Handler,
};
use serde::{Deserialize, Serialize};
use std::{ops::Deref, sync::atomic::Ordering};
#[derive(Debug, Serialize, Deserialize)]
pub struct AmlSerde {
@@ -11,7 +18,7 @@ pub struct AmlSerde {
#[derive(Debug, Serialize, Deserialize)]
pub enum AmlSerdeValue {
Boolean(bool),
Uninitialized,
Integer(u64),
String(String),
OpRegion {
@@ -21,14 +28,15 @@ pub enum AmlSerdeValue {
parent_device: Option<String>,
},
Field {
region: String,
kind: AmlSerdeFieldKind,
flags: AmlSerdeFieldFlags,
offset: u64,
length: u64,
},
Device,
Event(u64),
Method {
arg_count: u8,
arg_count: usize,
serialize: bool,
sync_level: u8,
},
@@ -36,7 +44,7 @@ pub enum AmlSerdeValue {
BufferField {
offset: u64,
length: u64,
data: Vec<u8>,
data: Option<Box<AmlSerdeValue>>,
},
Processor {
id: u8,
@@ -44,8 +52,13 @@ pub enum AmlSerdeValue {
pblk_len: u8,
},
Mutex {
mutex: u32,
sync_level: u8,
},
Reference {
kind: AmlSerdeReferenceKind,
inner: Option<Box<AmlSerdeValue>>,
},
Package {
contents: Vec<AmlSerdeValue>,
},
@@ -53,8 +66,9 @@ pub enum AmlSerdeValue {
system_level: u8,
resource_order: u16,
},
RawDataBuffer,
ThermalZone,
External,
Debug,
}
#[derive(Debug, Serialize, Deserialize)]
@@ -69,9 +83,26 @@ pub enum AmlSerdeRegionSpace {
IPMI,
GeneralPurposeIo,
GenericSerialBus,
Pcc,
OemDefined(u8),
}
#[derive(Debug, Serialize, Deserialize)]
pub enum AmlSerdeFieldKind {
Normal {
region: Option<Box<AmlSerdeValue>>,
},
Bank {
region: Option<Box<AmlSerdeValue>>,
bank: Option<Box<AmlSerdeValue>>,
bank_value: u64,
},
Index {
index: Option<Box<AmlSerdeValue>>,
data: Option<Box<AmlSerdeValue>>,
},
}
#[derive(Debug, Serialize, Deserialize)]
pub struct AmlSerdeFieldFlags {
pub access_type: AmlSerdeFieldAccessType,
@@ -96,6 +127,13 @@ pub enum AmlSerdeFieldUpdateRule {
WriteAsZeros,
}
#[derive(Debug, Serialize, Deserialize)]
pub enum AmlSerdeReferenceKind {
RefOf,
LocalOrArg,
Unresolved,
}
impl AmlSerde {
pub fn default() -> Self {
Self {
@@ -104,20 +142,15 @@ impl AmlSerde {
}
}
pub fn from_aml(
aml_context: &mut AmlContext,
aml_lookup: &AmlHandleLookup,
name: &String,
aml_name: &AmlName,
handle: &AmlHandle,
) -> Option<Self> {
let aml_value = if let Ok(aml_value) = aml_context.namespace.get(handle.clone()) {
pub fn from_aml<H: Handler>(aml_context: &Interpreter<H>, aml_name: &AmlName) -> Option<Self> {
//TODO: why does namespace.get not take a reference to aml_name
let aml_value = if let Ok(aml_value) = aml_context.namespace.lock().get(aml_name.clone()) {
aml_value
} else {
return None;
};
let value = if let Some(value) = AmlSerdeValue::from_aml_value(aml_value, aml_lookup) {
let value = if let Some(value) = AmlSerdeValue::from_aml_value(aml_value.deref()) {
value
} else {
return None;
@@ -135,55 +168,51 @@ impl AmlSerdeValue {
AmlSerdeValue::String("".to_owned())
}
fn from_aml_value(aml_value: &AmlValue, aml_lookup: &AmlHandleLookup) -> Option<Self> {
fn from_aml_value(aml_value: &Object) -> Option<Self> {
Some(match aml_value {
AmlValue::Boolean(b) => AmlSerdeValue::Boolean(b.to_owned()),
AmlValue::Integer(n) => AmlSerdeValue::Integer(n.to_owned()),
AmlValue::String(s) => AmlSerdeValue::String(s.to_owned()),
AmlValue::OpRegion {
region,
offset,
length,
parent_device,
} => AmlSerdeValue::OpRegion {
region: match region {
Object::Uninitialized => AmlSerdeValue::Uninitialized,
Object::Integer(n) => AmlSerdeValue::Integer(n.to_owned()),
Object::String(s) => AmlSerdeValue::String(s.to_owned()),
Object::OpRegion(region) => AmlSerdeValue::OpRegion {
region: match region.space {
RegionSpace::SystemMemory => AmlSerdeRegionSpace::SystemMemory,
RegionSpace::SystemIo => AmlSerdeRegionSpace::SystemIo,
RegionSpace::SystemIO => AmlSerdeRegionSpace::SystemIo,
RegionSpace::PciConfig => AmlSerdeRegionSpace::PciConfig,
RegionSpace::EmbeddedControl => AmlSerdeRegionSpace::EmbeddedControl,
RegionSpace::SMBus => AmlSerdeRegionSpace::SMBus,
RegionSpace::SmBus => AmlSerdeRegionSpace::SMBus,
RegionSpace::SystemCmos => AmlSerdeRegionSpace::SystemCmos,
RegionSpace::PciBarTarget => AmlSerdeRegionSpace::PciBarTarget,
RegionSpace::IPMI => AmlSerdeRegionSpace::IPMI,
RegionSpace::Ipmi => AmlSerdeRegionSpace::IPMI,
RegionSpace::GeneralPurposeIo => AmlSerdeRegionSpace::GeneralPurposeIo,
RegionSpace::GenericSerialBus => AmlSerdeRegionSpace::GenericSerialBus,
RegionSpace::OemDefined(n) => AmlSerdeRegionSpace::OemDefined(n.to_owned()),
},
offset: offset.to_owned(),
length: length.to_owned(),
parent_device: if let Some(parent) = parent_device {
Some(parent.to_string())
} else {
None
RegionSpace::Pcc => AmlSerdeRegionSpace::Pcc,
RegionSpace::Oem(n) => AmlSerdeRegionSpace::OemDefined(n.to_owned()),
},
offset: region.base,
length: region.length,
parent_device: Some(region.parent_device_path.to_string()),
},
AmlValue::Field {
region,
flags,
offset,
length,
} => AmlSerdeValue::Field {
region: if let Some((region, _handle)) = aml_lookup.get(region) {
region.to_string()
} else {
return None;
Object::FieldUnit(field) => AmlSerdeValue::Field {
kind: match &field.kind {
FieldUnitKind::Normal { region } => AmlSerdeFieldKind::Normal {
region: AmlSerdeValue::from_aml_value(region.deref()).map(Box::new),
},
FieldUnitKind::Bank {
region,
bank,
bank_value,
} => AmlSerdeFieldKind::Bank {
region: AmlSerdeValue::from_aml_value(region.deref()).map(Box::new),
bank: AmlSerdeValue::from_aml_value(bank.deref()).map(Box::new),
bank_value: bank_value.to_owned(),
},
FieldUnitKind::Index { index, data } => AmlSerdeFieldKind::Index {
index: AmlSerdeValue::from_aml_value(index.deref()).map(Box::new),
data: AmlSerdeValue::from_aml_value(data.deref()).map(Box::new),
},
},
flags: AmlSerdeFieldFlags {
access_type: match flags.access_type() {
access_type: match field.flags.access_type() {
Ok(FieldAccessType::Any) => AmlSerdeFieldAccessType::Any,
Ok(FieldAccessType::Byte) => AmlSerdeFieldAccessType::Byte,
Ok(FieldAccessType::Word) => AmlSerdeFieldAccessType::Word,
@@ -192,71 +221,82 @@ impl AmlSerdeValue {
Ok(FieldAccessType::Buffer) => AmlSerdeFieldAccessType::Buffer,
_ => return None,
},
lock_rule: flags.lock_rule(),
update_rule: match flags.field_update_rule() {
Ok(FieldUpdateRule::Preserve) => AmlSerdeFieldUpdateRule::Preserve,
Ok(FieldUpdateRule::WriteAsOnes) => AmlSerdeFieldUpdateRule::WriteAsOnes,
Ok(FieldUpdateRule::WriteAsZeros) => AmlSerdeFieldUpdateRule::WriteAsZeros,
_ => return None,
lock_rule: field.flags.lock_rule(),
update_rule: match field.flags.update_rule() {
FieldUpdateRule::Preserve => AmlSerdeFieldUpdateRule::Preserve,
FieldUpdateRule::WriteAsOnes => AmlSerdeFieldUpdateRule::WriteAsOnes,
FieldUpdateRule::WriteAsZeros => AmlSerdeFieldUpdateRule::WriteAsZeros,
},
},
offset: offset.to_owned(),
length: length.to_owned(),
offset: field.bit_index as u64,
length: field.bit_length as u64,
},
AmlValue::Device => AmlSerdeValue::Device,
AmlValue::Method { flags, code: _ } => AmlSerdeValue::Method {
Object::Device => AmlSerdeValue::Device,
Object::Event(event) => AmlSerdeValue::Event(event.load(Ordering::Relaxed)),
Object::Method { flags, code: _ } => AmlSerdeValue::Method {
arg_count: flags.arg_count(),
serialize: flags.serialize(),
sync_level: flags.sync_level(),
},
AmlValue::Buffer(buffer_data) => {
AmlSerdeValue::Buffer({ buffer_data.lock().to_owned() })
}
AmlValue::BufferField {
buffer_data,
//TODO: distinguish from Method?
Object::NativeMethod { f: _, flags } => AmlSerdeValue::Method {
arg_count: flags.arg_count(),
serialize: flags.serialize(),
sync_level: flags.sync_level(),
},
Object::Buffer(buffer_data) => AmlSerdeValue::Buffer(buffer_data.to_owned()),
Object::BufferField {
buffer,
offset,
length,
} => AmlSerdeValue::BufferField {
offset: offset.to_owned(),
length: length.to_owned(),
data: { buffer_data.lock().to_owned() },
offset: offset.to_owned() as u64,
length: length.to_owned() as u64,
data: AmlSerdeValue::from_aml_value(buffer.deref()).map(Box::new),
},
AmlValue::Processor {
id,
Object::Processor {
proc_id,
pblk_address,
pblk_len,
pblk_length,
} => AmlSerdeValue::Processor {
id: id.to_owned(),
id: proc_id.to_owned(),
pblk_address: pblk_address.to_owned(),
pblk_len: pblk_len.to_owned(),
pblk_len: pblk_length.to_owned(),
},
AmlValue::Mutex { sync_level } => AmlSerdeValue::Mutex {
Object::Mutex { mutex, sync_level } => AmlSerdeValue::Mutex {
mutex: mutex.0,
sync_level: sync_level.to_owned(),
},
AmlValue::Package(aml_contents) => AmlSerdeValue::Package {
Object::Reference { kind, inner } => AmlSerdeValue::Reference {
kind: match kind {
ReferenceKind::RefOf => AmlSerdeReferenceKind::RefOf,
ReferenceKind::LocalOrArg => AmlSerdeReferenceKind::LocalOrArg,
ReferenceKind::Unresolved => AmlSerdeReferenceKind::Unresolved,
},
inner: AmlSerdeValue::from_aml_value(inner.deref()).map(Box::new),
},
Object::Package(aml_contents) => AmlSerdeValue::Package {
contents: aml_contents
.iter()
.filter_map(|item| AmlSerdeValue::from_aml_value(item, aml_lookup))
.filter_map(|item| AmlSerdeValue::from_aml_value(item))
.collect(),
},
AmlValue::PowerResource {
Object::PowerResource {
system_level,
resource_order,
} => AmlSerdeValue::PowerResource {
system_level: system_level.to_owned(),
resource_order: resource_order.to_owned(),
},
AmlValue::ThermalZone => AmlSerdeValue::ThermalZone,
AmlValue::External => AmlSerdeValue::External,
Object::RawDataBuffer => AmlSerdeValue::RawDataBuffer,
Object::ThermalZone => AmlSerdeValue::ThermalZone,
Object::Debug => AmlSerdeValue::Debug,
})
}
}
pub mod aml_serde_name {
use aml::AmlName;
use acpi::aml::namespace::AmlName;
/// Add a leading backslash to make the name a valid
/// namespace reference
@@ -288,28 +328,3 @@ pub mod aml_serde_name {
to_symbol(&aml_name.as_string())
}
}
pub struct AmlHandleLookup {
map: FxHashMap<String, (AmlName, AmlHandle)>,
}
impl AmlHandleLookup {
pub fn new() -> Self {
Self {
map: FxHashMap::default(),
}
}
fn handle_to_key(&self, handle: &AmlHandle) -> String {
format!("{:?}", handle)
}
pub fn insert(&mut self, handle: AmlHandle, aml_name: AmlName) {
self.map
.insert(self.handle_to_key(&handle), (aml_name, handle));
}
pub fn get(&self, handle: &AmlHandle) -> Option<&(AmlName, AmlHandle)> {
self.map.get(&self.handle_to_key(handle))
}
}