fix: move ACPI S3/battery methods from impl Drop to impl AcpiContext

The suspend_to_ram, read_battery_status, and read_battery_info methods
were incorrectly placed inside 'impl Drop for PhysmapGuard'. They
reference fields (aml_symbols, fadt) that only exist on AcpiContext.
Move them to impl AcpiContext and fix field access (self.fadt.as_ref()
instead of self.fadt()).
This commit is contained in:
Red Bear OS
2026-07-12 04:14:34 +03:00
parent 3fe7b12434
commit 1ed140e018
+79 -78
View File
@@ -128,84 +128,6 @@ impl Drop for PhysmapGuard {
let _ = libredox::call::munmap(self.virt as *mut (), self.size);
}
}
/// Suspend-to-RAM (S3 sleep state)
/// See ACPI 6.1 spec for SLP_TYPa/SLP_TYPb encoding
pub fn suspend_to_ram(&self) {
log::info!("ACPI: attempting suspend-to-RAM (S3)");
let fadt = match self.fadt() {
Some(f) => f,
None => { log::error!("ACPI S3: missing FADT"); return; }
};
let pm1a = fadt.pm1a_control_block as u16;
if pm1a == 0 {
log::error!("ACPI S3: PM1a port is zero");
return;
}
let aml_symbols = self.aml_symbols.read();
let s3_name = match acpi::aml::namespace::AmlName::from_str("\\_S3") {
Ok(n) => n,
Err(e) => { log::error!("ACPI S3: \\_S3 name error: {:?}", e); return; }
};
let s3 = match &aml_symbols.aml_context {
Some(ctx) => match ctx.namespace.lock().get(s3_name) {
Ok(s) => s,
Err(e) => { log::error!("ACPI S3: \\_S3 not found: {:?}", e); return; }
},
None => { log::error!("ACPI S3: AML context missing"); return; }
};
let pkg = match s3.deref() {
acpi::aml::object::Object::Package(p) => p,
_ => { log::error!("ACPI S3: \\_S3 not a package"); return; }
};
let slp_typa = match pkg[0].deref() {
acpi::aml::object::Object::Integer(i) => *i as u16,
_ => { log::error!("ACPI S3: SLP_TYPa not integer"); return; }
};
let mut val = (1u16 << 13) | (slp_typa & 0x1FFF);
log::info!("ACPI S3: writing PM1a=0x{:04X} val=0x{:04X}", pm1a, val);
#[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
{ Pio::<u16>::new(pm1a).write(val); }
}
/// Query ACPI battery via \\_SB_.BAT0._BST
/// Returns (remaining_capacity_mAh, present_voltage_mV) if available
pub fn read_battery_status(&self) -> Option<(u32, u32)> {
let aml_symbols = self.aml_symbols.read();
let ctx = aml_symbols.aml_context.as_ref()?;
let mut ns = ctx.namespace.lock();
let bst_name = acpi::aml::namespace::AmlName::from_str("\\_SB_.BAT0._BST").ok()?;
let bst = ns.get(bst_name).ok()?;
match bst.deref() {
acpi::aml::object::Object::Package(p) if p.len() >= 4 => {
let cap = match p[1].deref() { acpi::aml::object::Object::Integer(i) => *i as u32, _ => return None };
let volt = match p[2].deref() { acpi::aml::object::Object::Integer(i) => *i as u32, _ => return None };
Some((cap, volt))
}
_ => { log::warn!("ACPI: _BST not a valid battery package"); None }
}
}
/// Query ACPI battery info via \\_SB_.BAT0._BIF
/// Returns (design_capacity_mAh, last_full_capacity_mAh, design_voltage_mV) if available
pub fn read_battery_info(&self) -> Option<(u32, u32, u32)> {
let aml_symbols = self.aml_symbols.read();
let ctx = aml_symbols.aml_context.as_ref()?;
let mut ns = ctx.namespace.lock();
let bif_name = acpi::aml::namespace::AmlName::from_str("\\_SB_.BAT0._BIF").ok()?;
let bif = ns.get(bif_name).ok()?;
match bif.deref() {
acpi::aml::object::Object::Package(p) if p.len() >= 13 => {
let design = match p[1].deref() { acpi::aml::object::Object::Integer(i) => *i as u32, _ => return None };
let last = match p[2].deref() { acpi::aml::object::Object::Integer(i) => *i as u32, _ => return None };
let volt = match p[4].deref() { acpi::aml::object::Object::Integer(i) => *i as u32, _ => return None };
Some((design, last, volt))
}
_ => { log::warn!("ACPI: _BIF not a valid battery package"); None }
}
}
}
#[derive(Clone)]
@@ -1385,6 +1307,85 @@ impl AcpiContext {
Err(e) => Err(AmlEvalError::from(e)),
}
}
/// Suspend-to-RAM (S3 sleep state)
/// See ACPI 6.1 spec for SLP_TYPa/SLP_TYPb encoding
pub fn suspend_to_ram(&self) {
log::info!("ACPI: attempting suspend-to-RAM (S3)");
let fadt = match self.fadt.as_ref() {
Some(f) => f,
None => { log::error!("ACPI S3: missing FADT"); return; }
};
let pm1a = fadt.pm1a_control_block as u16;
if pm1a == 0 {
log::error!("ACPI S3: PM1a port is zero");
return;
}
let aml_symbols = self.aml_symbols.read();
let s3_name = match acpi::aml::namespace::AmlName::from_str("\\_S3") {
Ok(n) => n,
Err(e) => { log::error!("ACPI S3: \\_S3 name error: {:?}", e); return; }
};
let s3 = match &aml_symbols.aml_context {
Some(ctx) => match ctx.namespace.lock().get(s3_name) {
Ok(s) => s,
Err(e) => { log::error!("ACPI S3: \\_S3 not found: {:?}", e); return; }
},
None => { log::error!("ACPI S3: AML context missing"); return; }
};
use std::ops::Deref;
let pkg = match s3.deref() {
acpi::aml::object::Object::Package(p) => p,
_ => { log::error!("ACPI S3: \\_S3 not a package"); return; }
};
let slp_typa = match pkg[0].deref() {
acpi::aml::object::Object::Integer(i) => *i as u16,
_ => { log::error!("ACPI S3: SLP_TYPa not integer"); return; }
};
let val = (1u16 << 13) | (slp_typa & 0x1FFF);
log::info!("ACPI S3: writing PM1a=0x{:04X} val=0x{:04X}", pm1a, val);
#[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
{ Pio::<u16>::new(pm1a).write(val); }
}
/// Query ACPI battery via \\_SB_.BAT0._BST
/// Returns (remaining_capacity_mAh, present_voltage_mV) if available
pub fn read_battery_status(&self) -> Option<(u32, u32)> {
let aml_symbols = self.aml_symbols.read();
let ctx = aml_symbols.aml_context.as_ref()?;
let mut ns = ctx.namespace.lock();
let bst_name = acpi::aml::namespace::AmlName::from_str("\\_SB_.BAT0._BST").ok()?;
let bst = ns.get(bst_name).ok()?;
use std::ops::Deref;
match bst.deref() {
acpi::aml::object::Object::Package(p) if p.len() >= 4 => {
let cap = match p[1].deref() { acpi::aml::object::Object::Integer(i) => *i as u32, _ => return None };
let volt = match p[2].deref() { acpi::aml::object::Object::Integer(i) => *i as u32, _ => return None };
Some((cap, volt))
}
_ => { log::warn!("ACPI: _BST not a valid battery package"); None }
}
}
/// Query ACPI battery info via \\_SB_.BAT0._BIF
/// Returns (design_capacity_mAh, last_full_capacity_mAh, design_voltage_mV) if available
pub fn read_battery_info(&self) -> Option<(u32, u32, u32)> {
let aml_symbols = self.aml_symbols.read();
let ctx = aml_symbols.aml_context.as_ref()?;
let mut ns = ctx.namespace.lock();
let bif_name = acpi::aml::namespace::AmlName::from_str("\\_SB_.BAT0._BIF").ok()?;
let bif = ns.get(bif_name).ok()?;
use std::ops::Deref;
match bif.deref() {
acpi::aml::object::Object::Package(p) if p.len() >= 13 => {
let design = match p[1].deref() { acpi::aml::object::Object::Integer(i) => *i as u32, _ => return None };
let last = match p[2].deref() { acpi::aml::object::Object::Integer(i) => *i as u32, _ => return None };
let volt = match p[4].deref() { acpi::aml::object::Object::Integer(i) => *i as u32, _ => return None };
Some((design, last, volt))
}
_ => { log::warn!("ACPI: _BIF not a valid battery package"); None }
}
}
}
fn power_object_path(name: &str, method: &str) -> String {