Add description text in toml format for each symbol in acpi:/symbols
This commit is contained in:
Generated
+77
-8
@@ -19,6 +19,7 @@ dependencies = [
|
||||
name = "acpid"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"aml",
|
||||
"log",
|
||||
"num-derive",
|
||||
"num-traits",
|
||||
@@ -27,6 +28,7 @@ dependencies = [
|
||||
"redox-daemon",
|
||||
"redox-log",
|
||||
"redox_syscall 0.3.4",
|
||||
"rustc-hash",
|
||||
"thiserror",
|
||||
]
|
||||
|
||||
@@ -55,6 +57,19 @@ dependencies = [
|
||||
"redox_syscall 0.3.4",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "aml"
|
||||
version = "0.16.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e7450aaee7581251d456c0f283f4c3db13b09a95054572ae77b6d22f77216caf"
|
||||
dependencies = [
|
||||
"bit_field",
|
||||
"bitvec",
|
||||
"byteorder 1.4.3",
|
||||
"log",
|
||||
"spinning_top",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ansi_term"
|
||||
version = "0.12.1"
|
||||
@@ -134,12 +149,30 @@ dependencies = [
|
||||
"serde",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "bit_field"
|
||||
version = "0.10.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "dcb6dd1c2376d2e096796e234a70e17e94cc2d5d54ff8ce42b28cef1d0d359a4"
|
||||
|
||||
[[package]]
|
||||
name = "bitflags"
|
||||
version = "1.2.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "cf1de2fe8c75bc145a2f577add951f8134889b4795d47466a54a5c846d691693"
|
||||
|
||||
[[package]]
|
||||
name = "bitvec"
|
||||
version = "1.0.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1bc2832c24239b0141d5674bb9174f9d68a8b5b3f2753311927c172ca46f7e9c"
|
||||
dependencies = [
|
||||
"funty",
|
||||
"radium",
|
||||
"tap",
|
||||
"wyz",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "block-io-wrapper"
|
||||
version = "0.1.0"
|
||||
@@ -336,6 +369,12 @@ version = "0.3.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3dcaa9ae7725d12cdb85b3ad99a434db70b468c09ded17e012d86b5c1010f7a7"
|
||||
|
||||
[[package]]
|
||||
name = "funty"
|
||||
version = "2.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e6d5a32815ae3f33302d95fdcb2ce17862f8c65363dcfd29360480ba1001fc9c"
|
||||
|
||||
[[package]]
|
||||
name = "futures"
|
||||
version = "0.3.21"
|
||||
@@ -560,9 +599,8 @@ checksum = "a6f08839bc70ef4a3fe1d566d5350f519c5912ea86be0df1740a7d247c7fc0ef"
|
||||
|
||||
[[package]]
|
||||
name = "libc"
|
||||
version = "0.2.126"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "349d5a591cd28b49e1d1037471617a32ddcda5731b99419008085f72d5a53836"
|
||||
version = "0.2.137"
|
||||
source = "git+https://gitlab.redox-os.org/redox-os/liblibc.git?branch=rust-2022-03-18#6ba4d1a527c2b53bdd5554cb219a1cd7d315d518"
|
||||
|
||||
[[package]]
|
||||
name = "linked-hash-map"
|
||||
@@ -966,6 +1004,12 @@ dependencies = [
|
||||
"proc-macro2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "radium"
|
||||
version = "0.7.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "dc33ff2d4973d518d823d61aa239014831e521c75da58e3df4840d3f47749d09"
|
||||
|
||||
[[package]]
|
||||
name = "rand"
|
||||
version = "0.4.6"
|
||||
@@ -1194,6 +1238,12 @@ dependencies = [
|
||||
"redox_syscall 0.3.4",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rustc-hash"
|
||||
version = "1.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2"
|
||||
|
||||
[[package]]
|
||||
name = "rusttype"
|
||||
version = "0.2.4"
|
||||
@@ -1342,6 +1392,15 @@ dependencies = [
|
||||
"lock_api",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "spinning_top"
|
||||
version = "0.2.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "75adad84ee84b521fb2cca2d4fd0f1dab1d8d026bda3c5bea4ca63b5f9f9293c"
|
||||
dependencies = [
|
||||
"lock_api",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "stable_deref_trait"
|
||||
version = "1.2.0"
|
||||
@@ -1408,6 +1467,12 @@ dependencies = [
|
||||
"unicode-ident",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tap"
|
||||
version = "1.0.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "55937e1799185b12863d447f42597ed69d9928686b8d88a1df17376a097d8369"
|
||||
|
||||
[[package]]
|
||||
name = "termion"
|
||||
version = "1.5.6"
|
||||
@@ -1744,6 +1809,15 @@ dependencies = [
|
||||
"winapi-build",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "wyz"
|
||||
version = "0.5.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "05f360fc0b24296329c78fda852a1e9ae82de9cf7b27dae4b7f62f118f77b9ed"
|
||||
dependencies = [
|
||||
"tap",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "xhcid"
|
||||
version = "0.1.0"
|
||||
@@ -1766,8 +1840,3 @@ dependencies = [
|
||||
"thiserror",
|
||||
"toml",
|
||||
]
|
||||
|
||||
[[patch.unused]]
|
||||
name = "libc"
|
||||
version = "0.2.137"
|
||||
source = "git+https://gitlab.redox-os.org/redox-os/liblibc.git?branch=rust-2022-03-18#6ba4d1a527c2b53bdd5554cb219a1cd7d315d518"
|
||||
|
||||
+224
-122
@@ -1,8 +1,9 @@
|
||||
use rustc_hash::FxHashSet;
|
||||
use rustc_hash::FxHashMap;
|
||||
use std::convert::{TryFrom, TryInto};
|
||||
use std::ops::Deref;
|
||||
use std::sync::Arc;
|
||||
use std::{fmt, mem};
|
||||
use std::fmt::Write;
|
||||
|
||||
use syscall::flag::PhysmapFlags;
|
||||
|
||||
@@ -12,7 +13,7 @@ use syscall::io::{Io, Pio};
|
||||
use parking_lot::{RwLock, RwLockReadGuard, RwLockWriteGuard};
|
||||
use thiserror::Error;
|
||||
|
||||
use aml::{AmlContext, AmlName};
|
||||
use aml::{AmlContext, AmlName, AmlHandle, AmlValue};
|
||||
|
||||
pub mod dmar;
|
||||
use self::dmar::Dmar;
|
||||
@@ -229,9 +230,147 @@ pub enum SymbolListError {
|
||||
AmlInternalError,
|
||||
}
|
||||
|
||||
// Current AML implementation builds the aml_context.namespace at startup,
|
||||
// but the cache for symbols is lazy-loaded when someone
|
||||
// reads from the acpi:/symbols scheme.
|
||||
// If you dynamically add an SDT, you can add to the namespace, but you
|
||||
// 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,
|
||||
// k = name, v = description
|
||||
symbols_cache: FxHashMap<String, String>,
|
||||
pub symbols_str: String,
|
||||
symbols_hash: FxHashSet<String>,
|
||||
}
|
||||
|
||||
impl AmlSymbols {
|
||||
pub fn to_str(&self) -> &str {
|
||||
&self.symbols_str
|
||||
}
|
||||
|
||||
/// Format a value as toml, to use as file contents
|
||||
pub fn format_value(name: &str, value: &AmlValue, handle_lookup: &AmlHandleLookup) -> String {
|
||||
let mut value_str = String::with_capacity(256);
|
||||
let _ = write!(value_str, "[symbol]\nname = \"{}\"\n\n[value]\n", name);
|
||||
let _ = match value {
|
||||
AmlValue::Integer(n) =>
|
||||
write!(value_str, "type = \"Integer\"\nvalue = \"{:#x}\"\n", n),
|
||||
AmlValue::String(s) =>
|
||||
write!(value_str, "type = \"String\"\nvalue = \"{}\"\n", s),
|
||||
AmlValue::Processor { id, pblk_address, pblk_len } =>
|
||||
write!(value_str, "type = \"Processor\"\nid = \"{}\"\npblk_address = \"{}\"\npblk_len = \"{}\"\n",
|
||||
id, pblk_address, pblk_len),
|
||||
AmlValue::Method { flags, code } =>
|
||||
write!(value_str, "type = \"Method\"\nflags = \"{:?}\"\ncode = {}\n", flags, AmlSymbols::code_as_string(code)),
|
||||
AmlValue::OpRegion { region, offset, length, parent_device } =>
|
||||
write!(value_str, "type = \"OpRegion\"\nregion = \"{:?}\"\noffset = \"{:#x}\"\nlength = \"{:#x}\"\ndevice = \"{}\"\n",
|
||||
region, offset, length, AmlSymbols::device_option_as_string(parent_device)),
|
||||
AmlValue::Field { region, flags, offset, length } =>
|
||||
write!(value_str, "type = \"Field\"\nregion = \"{}\"\nflags = \"{:?}\"\noffset = \"{:#x}\"\nlength = \"{:#x}\"\n",
|
||||
handle_lookup.get_as_str(region), flags, offset, length),
|
||||
AmlValue::Package(contents) =>
|
||||
write!(value_str, "type = \"Package\"\ncontents = {}\n",
|
||||
AmlSymbols::contents_as_string(contents)),
|
||||
AmlValue::Device => write!(value_str, "type = \"Device\"\n"),
|
||||
AmlValue::Buffer(_) => write!(value_str, "type = \"Buffer\"\n"),
|
||||
other =>
|
||||
write!(value_str, "type = \"Other\"\ndebug = \"{:.64?}\"\n", other),
|
||||
};
|
||||
|
||||
value_str.shrink_to_fit();
|
||||
value_str
|
||||
}
|
||||
|
||||
fn device_option_as_string(device: &Option<AmlName>) -> String {
|
||||
if let Some(name) = device {
|
||||
format!("\"{}\"", AmlSymbols::pretty_name(name))
|
||||
} else {
|
||||
"\"None\"".to_string()
|
||||
}
|
||||
}
|
||||
|
||||
fn code_as_string(code: &aml::value::MethodCode) -> String {
|
||||
match code {
|
||||
aml::value::MethodCode::Aml(bytes) =>
|
||||
if bytes.len() > 15 {
|
||||
format!("\"AML({:x?}...)\"", &bytes[..15])
|
||||
} else {
|
||||
format!("\"AML({:x?})\"", bytes)
|
||||
},
|
||||
aml::value::MethodCode::Native(_) => format!("(native method)"),
|
||||
}
|
||||
}
|
||||
|
||||
fn contents_as_string(contents: &Vec<AmlValue>) -> String {
|
||||
let mut buf = String::with_capacity(128);
|
||||
let _ = write!(buf, "[ ");
|
||||
for value in contents {
|
||||
match value {
|
||||
AmlValue::Integer(n) => { let _ = write!(buf, "{:x}, ", n); },
|
||||
AmlValue::String(s) => { let _ = write!(buf, "\"{}\",", s); }
|
||||
_ => { let _ = write!(buf, "{:?}", value); },
|
||||
}
|
||||
if buf.len() > 58 {
|
||||
let _ = write!(buf, "...");
|
||||
break;
|
||||
}
|
||||
}
|
||||
let _ = write!(buf, "]");
|
||||
buf
|
||||
}
|
||||
|
||||
/// Remove trailing underscores from each name segment
|
||||
pub fn pretty_name(level_aml_name: &AmlName) -> String {
|
||||
let mut name = level_aml_name.as_string();
|
||||
// remove unnecessary underscores
|
||||
while let Some(index) = name.find("_.") {
|
||||
name.remove(index);
|
||||
}
|
||||
while name.len() > 0 && &name[name.len() - 1..] == "_" {
|
||||
name.pop();
|
||||
}
|
||||
name.shrink_to_fit();
|
||||
name
|
||||
}
|
||||
|
||||
pub fn child_symbol(level_name: &str, value_name: &str) -> String {
|
||||
format!("{}.{}", level_name, value_name.trim_end_matches('_'))
|
||||
}
|
||||
|
||||
pub fn root_symbol(value_name: &str) -> String {
|
||||
format!("\\{}", value_name.trim_end_matches('_'))
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
pub struct AmlHandleLookup {
|
||||
map: FxHashMap<String, String>,
|
||||
}
|
||||
|
||||
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, name: &String) {
|
||||
self.map.insert(self.handle_to_key(handle), name.to_owned());
|
||||
}
|
||||
|
||||
pub fn get(&self, handle: &AmlHandle) -> Option<&String> {
|
||||
self.map.get(&self.handle_to_key(handle))
|
||||
}
|
||||
|
||||
pub fn get_as_str(&self, handle: &AmlHandle) -> &str {
|
||||
if let Some(name) = self.get(handle) {
|
||||
&name[..]
|
||||
} else {
|
||||
"Unrecognized"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub struct AcpiContext {
|
||||
@@ -239,12 +378,7 @@ pub struct AcpiContext {
|
||||
dsdt: Option<Dsdt>,
|
||||
fadt: Option<Fadt>,
|
||||
|
||||
// the aml parser
|
||||
aml_context: RwLock<AmlContext>,
|
||||
|
||||
// Use to cache the symbols list, which doesn't change very often
|
||||
// Set it to None if the ACPI tables change e.g. due to PnP
|
||||
aml_symbols: RwLock<Option<AmlSymbols>>,
|
||||
aml_symbols: RwLock<AmlSymbols>,
|
||||
|
||||
// TODO: The kernel ACPI code seemed to use load_table quite ubiquitously, however ACPI 5.1
|
||||
// states that DDBHandles can only be obtained when loading XSDT-pointed tables. So, we'll
|
||||
@@ -273,8 +407,12 @@ impl AcpiContext {
|
||||
dsdt: None,
|
||||
fadt: None,
|
||||
|
||||
aml_context: RwLock::new(AmlContext::new(Box::new(AmlPhysMemHandler), aml::DebugVerbosity::None)),
|
||||
aml_symbols: RwLock::new(None),
|
||||
// Temporary values
|
||||
aml_symbols: RwLock::new(AmlSymbols {
|
||||
aml_context: AmlContext::new(Box::new(AmlPhysMemHandler), aml::DebugVerbosity::None),
|
||||
symbols_cache: FxHashMap::default(),
|
||||
symbols_str: "".to_string(),
|
||||
}),
|
||||
|
||||
next_ctx: RwLock::new(0),
|
||||
|
||||
@@ -287,32 +425,36 @@ impl AcpiContext {
|
||||
|
||||
Fadt::init(&mut this);
|
||||
//TODO (hangs on real hardware): Dmar::init(&this);
|
||||
|
||||
|
||||
if let Some(mut parser) = this.aml_context.try_write() {
|
||||
if let Some(dsdt) = this.dsdt() {
|
||||
match parser.parse_table(dsdt.aml()) {
|
||||
Ok(_) => log::trace!("Parsed DSDT"),
|
||||
Err(e) => {
|
||||
log::error!("DSDT: {:?}", e);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
log::error!("No DSDT for aml parsing");
|
||||
}
|
||||
this.aml_symbols.write().aml_context = AcpiContext::build_aml_context(&this);
|
||||
|
||||
for ssdt in this.ssdts() {
|
||||
match parser.parse_table(ssdt.aml()) {
|
||||
Ok(_) => log::trace!("Parsed SSDT"),
|
||||
Err(e) => {
|
||||
log::error!("SSDT: {:?}", e);
|
||||
}
|
||||
this
|
||||
}
|
||||
|
||||
fn build_aml_context(acpi: &AcpiContext) -> AmlContext {
|
||||
let mut aml_context = AmlContext::new(Box::new(AmlPhysMemHandler), aml::DebugVerbosity::None);
|
||||
|
||||
if let Some(dsdt) = acpi.dsdt() {
|
||||
match aml_context.parse_table(dsdt.aml()) {
|
||||
Ok(_) => log::trace!("Parsed DSDT"),
|
||||
Err(e) => {
|
||||
log::error!("DSDT: {:?}", e);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
log::error!("Failed to obtain aml_context");
|
||||
log::error!("No DSDT for aml parsing");
|
||||
}
|
||||
|
||||
this
|
||||
for ssdt in acpi.ssdts() {
|
||||
match aml_context.parse_table(ssdt.aml()) {
|
||||
Ok(_) => log::trace!("Parsed SSDT"),
|
||||
Err(e) => {
|
||||
log::error!("SSDT: {:?}", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
aml_context
|
||||
}
|
||||
|
||||
pub fn dsdt(&self) -> Option<&Dsdt> {
|
||||
@@ -354,77 +496,22 @@ impl AcpiContext {
|
||||
pub fn new_index(&self, signature: &SdtSignature) {
|
||||
self.sdt_order.write().push(Some(*signature));
|
||||
}
|
||||
fn aml_context(&self) -> RwLockReadGuard<'_, AmlContext>{
|
||||
self.aml_context.read()
|
||||
}
|
||||
fn aml_context_mut(&self) -> RwLockWriteGuard<'_, AmlContext> {
|
||||
self.aml_context.write()
|
||||
}
|
||||
pub fn aml_lookup(&self, symbol: &str) -> Option<AmlName> {
|
||||
let aml_name = match AmlName::from_str(symbol) {
|
||||
Ok(aml_name) => aml_name,
|
||||
Err(error) => {
|
||||
log::error!("Lookup failed to convert name to AmlName {}, {:?}", symbol, error);
|
||||
return None;
|
||||
}
|
||||
};
|
||||
|
||||
// Check the cache first
|
||||
if let Ok(symbols_option) = self.aml_symbols() {
|
||||
if let Some(symbols) = symbols_option.as_ref() {
|
||||
if symbols.symbols_hash.contains(symbol) {
|
||||
log::trace!("Found symbol in cache, {}", symbol);
|
||||
return Some(aml_name);
|
||||
}
|
||||
pub fn aml_lookup(&self, symbol: &str) -> Option<String> {
|
||||
if let Ok(aml_symbols) = self.aml_symbols() {
|
||||
if let Some(description) = aml_symbols.symbols_cache.get(symbol) {
|
||||
log::trace!("Found symbol in cache, {}, {}", symbol, description);
|
||||
return Some(description.to_owned());
|
||||
}
|
||||
}
|
||||
|
||||
// Symbol does not exactly match cache, allow lookup using namespace rules
|
||||
let aml_ctx = self.aml_context();
|
||||
let root = aml::AmlName::root();
|
||||
if aml_ctx.namespace.get_by_path(&aml_name).is_ok()
|
||||
|| aml_ctx.namespace.search_for_level(&aml_name, &root).is_ok()
|
||||
{
|
||||
Some(aml_name)
|
||||
} else {
|
||||
log::trace!("Lookup did not find {}", aml_name);
|
||||
None
|
||||
}
|
||||
None
|
||||
}
|
||||
|
||||
pub fn aml_symbols(&self) -> Result<RwLockReadGuard<'_, Option<AmlSymbols>>, SymbolListError> {
|
||||
// Some private functions for building the symbol name correctly and efficiently
|
||||
fn level_name(level_aml_name: &aml::AmlName) -> String {
|
||||
let mut name = level_aml_name.as_string();
|
||||
// remove unnecessary underscores
|
||||
while let Some(index) = name.find("_.") {
|
||||
name.remove(index);
|
||||
}
|
||||
while name.len() > 0 && &name[name.len() - 1..] == "_" {
|
||||
name.pop();
|
||||
}
|
||||
name.shrink_to_fit();
|
||||
name
|
||||
}
|
||||
fn child_symbol(level_name: &str, value_name: &str) -> String {
|
||||
let mut name = String::with_capacity(level_name.len() + 1 + value_name.len());
|
||||
name.push_str(level_name);
|
||||
name.push('.');
|
||||
name.push_str(value_name.trim_end_matches('_'));
|
||||
name.shrink_to_fit();
|
||||
name
|
||||
}
|
||||
fn root_symbol(value_name: &str) -> String {
|
||||
let mut name = String::with_capacity(1 + value_name.len());
|
||||
name.push('\\');
|
||||
name.push_str(value_name.trim_end_matches('_'));
|
||||
name.shrink_to_fit();
|
||||
name
|
||||
}
|
||||
|
||||
pub fn aml_symbols(&self) -> Result<RwLockReadGuard<'_, AmlSymbols>, SymbolListError> {
|
||||
|
||||
// return the cached value if it exists
|
||||
let symbols = self.aml_symbols.read();
|
||||
if symbols.is_some() {
|
||||
if !symbols.symbols_cache.is_empty() {
|
||||
return Ok(symbols);
|
||||
}
|
||||
// free the read lock
|
||||
@@ -435,28 +522,28 @@ impl AcpiContext {
|
||||
|
||||
let mut symbols_str: String = String::with_capacity(30000);
|
||||
|
||||
let mut symbols_hash: FxHashSet<String> = FxHashSet::default();
|
||||
let mut symbols_list: Vec<(String, AmlHandle)> = Vec::with_capacity(3000);
|
||||
|
||||
// Get write lock because traverse requires mut
|
||||
let mut aml_ctx = self.aml_context_mut();
|
||||
let mut aml_symbols = self.aml_symbols.write();
|
||||
|
||||
let root = aml::AmlName::root();
|
||||
let traverse = aml_ctx.namespace.traverse(| level_aml_name, level | {
|
||||
let level_is_root = level_aml_name.eq(&root);
|
||||
let level_name = level_name(level_aml_name);
|
||||
for (name, _handle) in level.values.iter() {
|
||||
// Create the name of the symbol as "\levelname.symbolname"
|
||||
let symbol = if level_is_root {
|
||||
root_symbol(name.as_str())
|
||||
} else {
|
||||
child_symbol(&level_name, name.as_str())
|
||||
};
|
||||
symbols_str.push_str(&symbol);
|
||||
symbols_str.push('\n');
|
||||
symbols_hash.insert(symbol);
|
||||
}
|
||||
Ok(true)
|
||||
});
|
||||
let traverse = aml_symbols.aml_context.namespace
|
||||
.traverse(| level_aml_name, level | {
|
||||
let level_is_root = level_aml_name.eq(&root);
|
||||
let level_name = AmlSymbols::pretty_name(level_aml_name);
|
||||
for (name, handle) in level.values.iter() {
|
||||
// Create the name of the symbol as "\levelname.symbolname"
|
||||
let symbol = if level_is_root {
|
||||
AmlSymbols::root_symbol(name.as_str())
|
||||
} else {
|
||||
AmlSymbols::child_symbol(&level_name, name.as_str())
|
||||
};
|
||||
symbols_str.push_str(&symbol);
|
||||
symbols_str.push('\n');
|
||||
symbols_list.push((symbol, handle.to_owned()));
|
||||
}
|
||||
Ok(true)
|
||||
});
|
||||
|
||||
match traverse {
|
||||
Err(error) => {
|
||||
@@ -465,25 +552,40 @@ impl AcpiContext {
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
|
||||
let mut handle_lookup = AmlHandleLookup::new();
|
||||
|
||||
for (name, handle) in &symbols_list {
|
||||
handle_lookup.insert(handle, name);
|
||||
}
|
||||
|
||||
let namespace = &aml_symbols.aml_context.namespace;
|
||||
|
||||
let mut symbols_cache: FxHashMap<String, String> = FxHashMap::default();
|
||||
|
||||
for (name, handle) in symbols_list {
|
||||
if let Ok(value) = namespace.get(handle.to_owned()) {
|
||||
symbols_cache.insert(name.to_owned(), AmlSymbols::format_value(&name, value, &handle_lookup));
|
||||
}
|
||||
}
|
||||
|
||||
symbols_str.shrink_to_fit();
|
||||
|
||||
// Cache the new list
|
||||
log::trace!("Updating symbols list");
|
||||
|
||||
let mut write_guarded_symbols = self.aml_symbols.write();
|
||||
*write_guarded_symbols = Some(AmlSymbols { symbols_str, symbols_hash });
|
||||
aml_symbols.symbols_str = symbols_str;
|
||||
aml_symbols.symbols_cache = symbols_cache;
|
||||
|
||||
// return the cached value
|
||||
Ok(RwLockWriteGuard::downgrade(write_guarded_symbols))
|
||||
Ok(RwLockWriteGuard::downgrade(aml_symbols))
|
||||
}
|
||||
|
||||
/// Discard any cached symbols list. To be called if the AML namespace changes.
|
||||
/// The caller must have at least a Read Lock on the aml context to ensure
|
||||
/// the cached list is not out of sync with the namespace.
|
||||
pub fn aml_symbols_reset(&self) {
|
||||
let mut symbols = self.aml_symbols.write();
|
||||
*symbols = None;
|
||||
let mut aml_symbols = self.aml_symbols.write();
|
||||
aml_symbols.symbols_cache = FxHashMap::default();
|
||||
aml_symbols.symbols_str = "".to_string();
|
||||
}
|
||||
|
||||
/// Set Power State
|
||||
@@ -505,14 +607,14 @@ impl AcpiContext {
|
||||
let port = fadt.pm1a_control_block as u16;
|
||||
let mut val = 1 << 13;
|
||||
|
||||
let aml_ctx = self.aml_context();
|
||||
let aml_symbols = self.aml_symbols.read();
|
||||
|
||||
let s5_aml_name = match aml::AmlName::from_str("\\_S5") {
|
||||
Ok(aml_name) => aml_name,
|
||||
Err(error) => { log::error!("Could not build AmlName for \\_S5, {:?}", error); return; }
|
||||
};
|
||||
|
||||
let s5 = match aml_ctx.namespace.get_by_path(&s5_aml_name) {
|
||||
let s5 = match aml_symbols.aml_context.namespace.get_by_path(&s5_aml_name) {
|
||||
Ok(s5) => s5,
|
||||
Err(error) => { log::error!("Cannot set S-state, missing \\_S5, {:?}", error); return; }
|
||||
};
|
||||
|
||||
+17
-26
@@ -26,8 +26,8 @@ enum HandleKind<'a> {
|
||||
TopLevel,
|
||||
Tables,
|
||||
Table(SdtSignature),
|
||||
Symbols(RwLockReadGuard<'a, Option<AmlSymbols>>),
|
||||
Symbol(aml::AmlName),
|
||||
Symbols(RwLockReadGuard<'a, AmlSymbols>),
|
||||
Symbol(String),
|
||||
}
|
||||
|
||||
impl HandleKind<'_> {
|
||||
@@ -45,13 +45,8 @@ impl HandleKind<'_> {
|
||||
Self::TopLevel => TOPLEVEL_CONTENTS.len(),
|
||||
Self::Tables => acpi_ctx.tables().len().checked_mul(TABLE_DENTRY_LENGTH).unwrap_or(usize::max_value()),
|
||||
Self::Table(signature) => acpi_ctx.sdt_from_signature(signature).ok_or(Error::new(EBADFD))?.length(),
|
||||
Self::Symbols(symbols_option) => {
|
||||
match symbols_option.as_ref() {
|
||||
Some(symbols) => symbols.symbols_str.len(),
|
||||
_ => 0,
|
||||
}
|
||||
},
|
||||
Self::Symbol(_) => 0,
|
||||
Self::Symbols(aml_symbols) => aml_symbols.to_str().len(),
|
||||
Self::Symbol(description) => description.len(),
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -159,15 +154,15 @@ impl SchemeMut for AcpiScheme<'_> {
|
||||
HandleKind::Table(signature)
|
||||
}
|
||||
|
||||
["symbols"] => if let Ok(symbols_option) = self.ctx.aml_symbols() {
|
||||
HandleKind::Symbols(symbols_option)
|
||||
["symbols"] => if let Ok(aml_symbols) = self.ctx.aml_symbols() {
|
||||
HandleKind::Symbols(aml_symbols)
|
||||
} else {
|
||||
return Err(Error::new(EIO))
|
||||
},
|
||||
|
||||
["symbols", symbol] => {
|
||||
if let Some(symbol) = self.ctx.aml_lookup(symbol) {
|
||||
HandleKind::Symbol(symbol)
|
||||
if let Some(description) = self.ctx.aml_lookup(symbol) {
|
||||
HandleKind::Symbol(description)
|
||||
} else {
|
||||
return Err(Error::new(ENOENT));
|
||||
}
|
||||
@@ -291,24 +286,20 @@ impl SchemeMut for AcpiScheme<'_> {
|
||||
return Ok(bytes_written);
|
||||
}
|
||||
|
||||
HandleKind::Symbols(symbols_option) => {
|
||||
match symbols_option.as_ref() {
|
||||
Some(symbols) => {
|
||||
let offset = std::cmp::min(symbols.symbols_str.len(), handle.offset);
|
||||
let src_buf = &symbols.symbols_str.as_bytes()[offset..];
|
||||
HandleKind::Symbols(aml_symbols) => {
|
||||
let symbols = aml_symbols.to_str();
|
||||
let offset = std::cmp::min(symbols.len(), handle.offset);
|
||||
let src_buf = &symbols.as_bytes()[offset..];
|
||||
|
||||
let to_copy = std::cmp::min(src_buf.len(), buf.len());
|
||||
buf[..to_copy].copy_from_slice(&src_buf[..to_copy]);
|
||||
let to_copy = std::cmp::min(src_buf.len(), buf.len());
|
||||
buf[..to_copy].copy_from_slice(&src_buf[..to_copy]);
|
||||
|
||||
handle.offset = handle.offset.checked_add(to_copy).ok_or(Error::new(EOVERFLOW))?;
|
||||
handle.offset = handle.offset.checked_add(to_copy).ok_or(Error::new(EOVERFLOW))?;
|
||||
|
||||
return Ok(to_copy);
|
||||
}
|
||||
_ => return Err(Error::new(EIO)),
|
||||
}
|
||||
return Ok(to_copy);
|
||||
}
|
||||
|
||||
HandleKind::Symbol(_) => b"",
|
||||
HandleKind::Symbol(description) => description.as_bytes(),
|
||||
|
||||
};
|
||||
|
||||
|
||||
Reference in New Issue
Block a user