clean up aml symbols

This commit is contained in:
Ron Williams
2023-03-29 01:41:13 -07:00
parent 23be7ed63c
commit 1baac63934
5 changed files with 522 additions and 278 deletions
Generated
+347 -155
View File
File diff suppressed because it is too large Load Diff
-1
View File
@@ -18,6 +18,5 @@ redox-log = "0.1.1"
redox_syscall = "0.3"
rustc-hash = "1.1.0"
thiserror = "1"
toml = "0.7"
serde_json = "1.0.94"
amlserde = { path = "../amlserde" }
+120 -83
View File
@@ -1,10 +1,9 @@
use amlserde::{AmlHandleLookup, AmlSerde};
use rustc_hash::FxHashMap;
use std::convert::{TryFrom, TryInto};
use std::fmt::Write;
use std::ops::Deref;
use std::sync::Arc;
use std::{fmt, mem};
use std::fmt::Write;
use syscall::flag::PhysmapFlags;
@@ -14,8 +13,9 @@ use syscall::io::{Io, Pio};
use parking_lot::{RwLock, RwLockReadGuard, RwLockWriteGuard};
use thiserror::Error;
use aml::{AmlContext, AmlError, AmlHandle, AmlName, AmlValue};
use amlserde::pretty_name;
use aml::{AmlContext, AmlError, AmlHandle, AmlName};
use amlserde::aml_serde_name::aml_to_symbol;
use amlserde::{AmlHandleLookup, AmlSerde};
pub mod dmar;
use self::dmar::Dmar;
@@ -54,8 +54,7 @@ impl SdtHeader {
}
}
pub fn length(&self) -> usize {
self
.length
self.length
.try_into()
.expect("expected usize to be at least 32 bits")
}
@@ -120,9 +119,7 @@ impl Deref for PhysmapGuard {
type Target = [u8];
fn deref(&self) -> &Self::Target {
unsafe {
std::slice::from_raw_parts(self.virt as *const u8, self.size)
}
unsafe { std::slice::from_raw_parts(self.virt as *const u8, self.size) }
}
}
impl Drop for PhysmapGuard {
@@ -247,8 +244,107 @@ pub struct Ssdt(Sdt);
pub struct AmlSymbols {
aml_context: AmlContext,
// k = name, v = description
symbols_cache: FxHashMap<String, String>,
pub symbols_str: String,
cache: FxHashMap<String, String>,
list: String,
}
impl AmlSymbols {
pub fn new() -> Self {
Self {
aml_context: AmlContext::new(Box::new(AmlPhysMemHandler), aml::DebugVerbosity::None),
cache: FxHashMap::default(),
list: "".to_string(),
}
}
pub fn mut_aml_context(&mut self) -> &mut AmlContext {
&mut self.aml_context
}
pub fn symbols_str(&self) -> &String {
&self.list
}
pub fn symbols_cache(&self) -> &FxHashMap<String, String> {
&self.cache
}
pub fn parse_table(&mut self, aml: &[u8]) -> Result<(), AmlError> {
self.aml_context.parse_table(aml)
}
pub fn lookup(&self, symbol: &str) -> Option<String> {
if let Some(description) = self.cache.get(symbol) {
log::trace!("Found symbol in cache, {}, {}", symbol, description);
return Some(description.to_owned());
}
None
}
pub fn build_cache(&mut self) {
let mut symbol_list: Vec<(AmlName, String, AmlHandle)> = Vec::with_capacity(5000);
if self
.aml_context
.namespace
.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()));
} else {
log::error!(
"AmlName resolve failed, {:?}:{:?}",
level_aml_name,
child_seg
);
}
}
Ok(true)
})
.is_err()
{
log::error!("Namespace traverse failed");
return;
}
let mut symbols_str = String::with_capacity(symbol_list.len() * 10);
let mut handle_lookup = AmlHandleLookup::new();
for (aml_name, name, handle) in &symbol_list {
let _ = writeln!(symbols_str, "{}", &name);
handle_lookup.insert(handle.to_owned(), aml_name.to_owned());
}
symbols_str.shrink_to_fit();
let mut symbol_cache: FxHashMap<String, String> = FxHashMap::default();
for (aml_name, name, handle) 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 Ok(ser_string) = serde_json::to_string_pretty(&ser_value) {
// replace the empty entry
symbol_cache.insert(name.to_owned(), ser_string);
}
}
}
// Cache the new list
log::trace!("Updating symbols list");
self.list = symbols_str;
self.cache = symbol_cache;
}
}
pub struct AcpiContext {
@@ -286,14 +382,7 @@ impl AcpiContext {
fadt: 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(),
}),
aml_symbols: RwLock::new(AmlSymbols::new()),
next_ctx: RwLock::new(0),
@@ -307,17 +396,16 @@ impl AcpiContext {
Fadt::init(&mut this);
//TODO (hangs on real hardware): Dmar::init(&this);
this.aml_symbols.write().aml_context = AcpiContext::build_aml_context(&this);
AcpiContext::build_aml_context(&this);
this
}
fn build_aml_context(acpi: &AcpiContext) -> AmlContext {
let mut aml_context =
AmlContext::new(Box::new(AmlPhysMemHandler), aml::DebugVerbosity::None);
fn build_aml_context(acpi: &AcpiContext) {
let mut aml_symbols = acpi.aml_symbols.write();
if let Some(dsdt) = acpi.dsdt() {
match aml_context.parse_table(dsdt.aml()) {
match aml_symbols.parse_table(dsdt.aml()) {
Ok(_) => log::trace!("Parsed DSDT"),
Err(e) => {
log::error!("DSDT: {:?}", e);
@@ -328,14 +416,13 @@ impl AcpiContext {
}
for ssdt in acpi.ssdts() {
match aml_context.parse_table(ssdt.aml()) {
match aml_symbols.parse_table(ssdt.aml()) {
Ok(_) => log::trace!("Parsed SSDT"),
Err(e) => {
log::error!("SSDT: {:?}", e);
}
}
}
aml_context
}
pub fn dsdt(&self) -> Option<&Dsdt> {
@@ -402,18 +489,16 @@ impl AcpiContext {
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());
}
aml_symbols.lookup(symbol)
} else {
None
}
None
}
pub fn aml_symbols(&self) -> Result<RwLockReadGuard<'_, AmlSymbols>, AmlError> {
// return the cached value if it exists
let symbols = self.aml_symbols.read();
if !symbols.symbols_cache.is_empty() {
if !symbols.symbols_cache().is_empty() {
return Ok(symbols);
}
// free the read lock
@@ -422,57 +507,9 @@ impl AcpiContext {
// List has not been initialized, we have to build it
log::trace!("Creating symbols list");
let mut symbol_list: Vec<(AmlName, String, AmlHandle)> = Vec::with_capacity(5000);
let mut aml_symbols = self.aml_symbols.write();
aml_symbols
.aml_context
.namespace
.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 = pretty_name(&aml_name);
symbol_list.push((aml_name, name, handle.to_owned()));
} else {
log::error!(
"AmlName resolve failed, {:?}:{:?}",
level_aml_name,
child_seg
);
}
}
Ok(true)
})?;
let mut symbols_str = String::with_capacity(symbol_list.len() * 10);
let mut handle_lookup = AmlHandleLookup::new();
for (_aml_name, name, handle) in &symbol_list {
let _ = writeln!(symbols_str, "{}", &name);
handle_lookup.insert(handle.to_owned(), name.to_owned());
}
symbols_str.shrink_to_fit();
let mut symbol_cache: FxHashMap<String, String> = FxHashMap::default();
for (_aml_name, name, handle) in &symbol_list {
if let Some(ser_value) = AmlSerde::from_aml(&aml_symbols.aml_context, &handle_lookup, handle) {
if let Ok(ser_string) = serde_json::to_string_pretty(&ser_value) {
symbol_cache.insert(name.to_owned(), ser_string);
}
}
}
// Cache the new list
log::trace!("Updating symbols list");
aml_symbols.symbols_str = symbols_str;
aml_symbols.symbols_cache = symbol_cache;
aml_symbols.build_cache();
// return the cached value
Ok(RwLockWriteGuard::downgrade(aml_symbols))
@@ -481,8 +518,8 @@ impl AcpiContext {
/// Discard any cached symbols list. To be called if the AML namespace changes.
pub fn aml_symbols_reset(&self) {
let mut aml_symbols = self.aml_symbols.write();
aml_symbols.symbols_cache = FxHashMap::default();
aml_symbols.symbols_str = "".to_string();
aml_symbols.cache = FxHashMap::default();
aml_symbols.list = "".to_string();
}
/// Set Power State
+2 -2
View File
@@ -45,7 +45,7 @@ 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(aml_symbols) => aml_symbols.symbols_str.len(),
Self::Symbols(aml_symbols) => aml_symbols.symbols_str().len(),
Self::Symbol(description) => description.len(),
})
}
@@ -287,7 +287,7 @@ impl SchemeMut for AcpiScheme<'_> {
}
HandleKind::Symbols(aml_symbols) => {
let symbols = &aml_symbols.symbols_str;
let symbols = aml_symbols.symbols_str();
let offset = std::cmp::min(symbols.len(), handle.offset);
let src_buf = &symbols.as_bytes()[offset..];
+53 -37
View File
@@ -1,7 +1,5 @@
use aml::{
value::{FieldAccessType, FieldUpdateRule, RegionSpace},
AmlContext, AmlHandle, AmlName, AmlValue,
};
use aml::value::{FieldAccessType, FieldUpdateRule, RegionSpace};
use aml::{AmlContext, AmlHandle, AmlName, AmlValue};
use rustc_hash::FxHashMap;
use serde::{Deserialize, Serialize};
@@ -75,9 +73,9 @@ pub enum AmlSerdeRegionSpace {
#[derive(Debug, Serialize, Deserialize)]
pub struct AmlSerdeFieldFlags {
access_type: AmlSerdeFieldAccessType,
lock_rule: bool,
update_rule: AmlSerdeFieldUpdateRule,
pub access_type: AmlSerdeFieldAccessType,
pub lock_rule: bool,
pub update_rule: AmlSerdeFieldUpdateRule,
}
#[derive(Debug, Serialize, Deserialize)]
@@ -106,16 +104,12 @@ impl AmlSerde {
}
pub fn from_aml(
aml_context: &AmlContext,
aml_context: &mut AmlContext,
aml_lookup: &AmlHandleLookup,
name: &String,
aml_name: &AmlName,
handle: &AmlHandle,
) -> Option<Self> {
let name = if let Some((name, _handle)) = aml_lookup.get(handle) {
name.to_owned()
} else {
return None;
};
let aml_value = if let Ok(aml_value) = aml_context.namespace.get(handle.clone()) {
aml_value
} else {
@@ -128,7 +122,10 @@ impl AmlSerde {
return None;
};
Some(AmlSerde { name, value })
Some(AmlSerde {
name: aml_name.to_string(),
value,
})
}
}
@@ -167,7 +164,7 @@ impl AmlSerdeValue {
offset: offset.to_owned(),
length: length.to_owned(),
parent_device: if let Some(parent) = parent_device {
Some(pretty_name(parent))
Some(parent.to_string())
} else {
None
},
@@ -180,7 +177,7 @@ impl AmlSerdeValue {
length,
} => AmlSerdeValue::Field {
region: if let Some((region, _handle)) = aml_lookup.get(region) {
region.to_owned()
region.to_string()
} else {
return None;
},
@@ -254,8 +251,42 @@ impl AmlSerdeValue {
}
}
pub mod aml_serde_name {
use aml::AmlName;
/// Add a leading backslash to make the name a valid
/// namespace reference
pub fn to_aml_format(pretty_name: &String) -> String {
format!("\\{}", pretty_name)
}
/// convert a string from AML namespace style to
/// acpi symbol style
pub fn to_symbol(aml_style_name: &String) -> String {
let mut name = aml_style_name.to_owned();
// remove leading slash
name = name.trim_start_matches("\\").to_owned();
// 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
}
/// Convert to string and remove
/// trailing underscores from each name segment
pub fn aml_to_symbol(aml_name: &AmlName) -> String {
to_symbol(&aml_name.as_string())
}
}
pub struct AmlHandleLookup {
map: FxHashMap<String, (String, AmlHandle)>,
map: FxHashMap<String, (AmlName, AmlHandle)>,
}
impl AmlHandleLookup {
@@ -269,27 +300,12 @@ impl AmlHandleLookup {
format!("{:?}", handle)
}
pub fn insert(&mut self, handle: AmlHandle, name: String) {
self.map.insert(self.handle_to_key(&handle), (name, 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<&(String, AmlHandle)> {
pub fn get(&self, handle: &AmlHandle) -> Option<&(AmlName, AmlHandle)> {
self.map.get(&self.handle_to_key(handle))
}
}
/// Remove trailing underscores from each name segment
pub fn pretty_name(aml_name: &AmlName) -> String {
let mut name = aml_name.as_string();
// remove leading slash
name = name.trim_start_matches("\\").to_owned();
// 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
}