Parallelized ACPI subsystem
This commit is contained in:
@@ -37,13 +37,13 @@ pub enum AmlError {
|
||||
AmlFatalError(u8, u16, AmlValue)
|
||||
}
|
||||
|
||||
pub fn parse_aml_table(sdt: &'static Sdt) -> Result<BTreeMap<String, AmlValue>, AmlError> {
|
||||
pub fn parse_aml_table(sdt: &'static Sdt) -> Result<(), AmlError> {
|
||||
let data = sdt.data();
|
||||
let mut ctx = AmlExecutionContext::new(String::from_str("\\").unwrap());
|
||||
|
||||
parse_term_list(data, &mut ctx)?;
|
||||
|
||||
Ok(ctx.namespace.clone())
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn is_aml_table(sdt: &'static Sdt) -> bool {
|
||||
|
||||
@@ -416,17 +416,17 @@ fn parse_def_device(data: &[u8],
|
||||
}
|
||||
|
||||
// TODO: How to handle local context deferreds
|
||||
// TODO: How to also handle local context reference to calling context
|
||||
parser_opcode_extended!(data, 0x82);
|
||||
|
||||
let (pkg_length, pkg_length_len) = parse_pkg_length(&data[2..])?;
|
||||
let name = parse_name_string(&data[2 + pkg_length_len .. 2 + pkg_length], ctx)?;
|
||||
|
||||
let mut local_ctx = AmlExecutionContext::new(String::new());
|
||||
let obj_list = parse_object_list(&data[2 + pkg_length_len + name.len .. 2 + pkg_length], &mut local_ctx)?;
|
||||
|
||||
|
||||
let local_scope_string = get_namespace_string(ctx.scope.clone(), name.val);
|
||||
ctx.add_to_namespace(local_scope_string, AmlValue::Device(local_ctx.namespace.clone()));
|
||||
let mut local_ctx = AmlExecutionContext::new(local_scope_string.clone());
|
||||
|
||||
parse_object_list(&data[2 + pkg_length_len + name.len .. 2 + pkg_length], &mut local_ctx)?;
|
||||
|
||||
ctx.add_to_namespace(local_scope_string, AmlValue::Device(local_ctx.namespace_delta.clone()));
|
||||
|
||||
Ok(AmlParseType {
|
||||
val: AmlValue::None,
|
||||
@@ -830,7 +830,6 @@ fn parse_def_power_res(data: &[u8],
|
||||
}
|
||||
|
||||
// TODO: How to handle local context deferreds
|
||||
// TODO: How to also handle local context reference to calling context
|
||||
parser_opcode_extended!(data, 0x84);
|
||||
|
||||
let (pkg_len, pkg_len_len) = parse_pkg_length(&data[2..])?;
|
||||
@@ -842,13 +841,13 @@ fn parse_def_power_res(data: &[u8],
|
||||
let resource_order: u16 = (data[3 + pkg_len_len + name.len] as u16) +
|
||||
((data[4 + pkg_len_len + name.len] as u16) << 8);
|
||||
|
||||
let mut local_ctx = AmlExecutionContext::new(String::new());
|
||||
let mut local_ctx = AmlExecutionContext::new(local_scope_string.clone());
|
||||
parse_object_list(&data[5 + pkg_len_len + name.len .. 2 + pkg_len], &mut local_ctx)?;
|
||||
|
||||
ctx.add_to_namespace(local_scope_string, AmlValue::PowerResource {
|
||||
system_level,
|
||||
resource_order,
|
||||
obj_list: local_ctx.namespace.clone()
|
||||
obj_list: local_ctx.namespace_delta.clone()
|
||||
});
|
||||
|
||||
Ok(AmlParseType {
|
||||
@@ -881,13 +880,13 @@ fn parse_def_processor(data: &[u8],
|
||||
((data[6 + pkg_len_len + name.len] as u32) << 24);
|
||||
let p_blk_len = data[7 + pkg_len_len + name.len];
|
||||
|
||||
let mut local_ctx = AmlExecutionContext::new(String::new());
|
||||
let mut local_ctx = AmlExecutionContext::new(local_scope_string.clone());
|
||||
parse_object_list(&data[8 + pkg_len_len + name.len .. 2 + pkg_len], &mut local_ctx)?;
|
||||
|
||||
ctx.add_to_namespace(local_scope_string, AmlValue::Processor {
|
||||
proc_id: proc_id,
|
||||
p_blk: if p_blk_len > 0 { Some(p_blk_addr) } else { None },
|
||||
obj_list: local_ctx.namespace.clone()
|
||||
obj_list: local_ctx.namespace_delta.clone()
|
||||
});
|
||||
|
||||
Ok(AmlParseType {
|
||||
@@ -913,10 +912,10 @@ fn parse_def_thermal_zone(data: &[u8],
|
||||
|
||||
let local_scope_string = get_namespace_string(ctx.scope.clone(), name.val);
|
||||
|
||||
let mut local_ctx = AmlExecutionContext::new(String::new());
|
||||
let mut local_ctx = AmlExecutionContext::new(local_scope_string.clone());
|
||||
parse_object_list(&data[2 + pkg_len_len + name.len .. 2 + pkg_len], &mut local_ctx)?;
|
||||
|
||||
ctx.add_to_namespace(local_scope_string, AmlValue::ThermalZone(local_ctx.namespace.clone()));
|
||||
ctx.add_to_namespace(local_scope_string, AmlValue::ThermalZone(local_ctx.namespace_delta.clone()));
|
||||
|
||||
Ok(AmlParseType {
|
||||
val: AmlValue::None,
|
||||
|
||||
@@ -52,7 +52,7 @@ pub enum AmlValue {
|
||||
},
|
||||
DDBHandle(u32), // Index into the XSDT
|
||||
DebugObject,
|
||||
Device(BTreeMap<String, AmlValue>),
|
||||
Device(Vec<String>),
|
||||
Event,
|
||||
FieldUnit {
|
||||
selector: FieldSelector,
|
||||
@@ -76,15 +76,15 @@ pub enum AmlValue {
|
||||
PowerResource {
|
||||
system_level: u8,
|
||||
resource_order: u16,
|
||||
obj_list: BTreeMap<String, AmlValue>
|
||||
obj_list: Vec<String>
|
||||
},
|
||||
Processor {
|
||||
proc_id: u8,
|
||||
p_blk: Option<u32>,
|
||||
obj_list: BTreeMap<String, AmlValue>
|
||||
obj_list: Vec<String>
|
||||
},
|
||||
RawDataBuffer(Vec<u8>),
|
||||
ThermalZone(BTreeMap<String, AmlValue>)
|
||||
ThermalZone(Vec<String>)
|
||||
}
|
||||
|
||||
impl AmlValue {
|
||||
|
||||
@@ -5,6 +5,8 @@ use collections::vec::Vec;
|
||||
use super::namespace::{ AmlValue, ObjectReference };
|
||||
use super::AmlError;
|
||||
|
||||
use acpi::ACPI_TABLE;
|
||||
|
||||
pub type ParseResult = Result<AmlParseType, AmlError>;
|
||||
pub type AmlParseType = AmlParseTypeGeneric<AmlValue>;
|
||||
|
||||
@@ -21,7 +23,6 @@ pub enum ExecutionState {
|
||||
}
|
||||
|
||||
pub struct AmlExecutionContext {
|
||||
pub namespace: BTreeMap<String, AmlValue>,
|
||||
pub scope: String,
|
||||
pub local_vars: [AmlValue; 8],
|
||||
pub arg_vars: [AmlValue; 8],
|
||||
@@ -32,7 +33,6 @@ pub struct AmlExecutionContext {
|
||||
impl AmlExecutionContext {
|
||||
pub fn new(scope: String) -> AmlExecutionContext {
|
||||
AmlExecutionContext {
|
||||
namespace: BTreeMap::new(),
|
||||
scope: scope,
|
||||
local_vars: [AmlValue::Uninitialized,
|
||||
AmlValue::Uninitialized,
|
||||
@@ -56,19 +56,29 @@ impl AmlExecutionContext {
|
||||
}
|
||||
|
||||
pub fn add_to_namespace(&mut self, name: String, value: AmlValue) -> Result<(), AmlError> {
|
||||
if self.namespace.contains_key(&name) {
|
||||
return Err(AmlError::AmlValueError);
|
||||
}
|
||||
let mut namespace = ACPI_TABLE.namespace.write();
|
||||
|
||||
if let Some(ref mut namespace) = *namespace {
|
||||
if namespace.contains_key(&name) {
|
||||
return Err(AmlError::AmlValueError);
|
||||
}
|
||||
|
||||
self.namespace_delta.push(name.clone());
|
||||
self.namespace.insert(name, value);
|
||||
self.namespace_delta.push(name.clone());
|
||||
namespace.insert(name, value);
|
||||
|
||||
Ok(())
|
||||
Ok(())
|
||||
} else {
|
||||
Err(AmlError::AmlValueError)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn clean_namespace(&mut self) {
|
||||
for k in &self.namespace_delta {
|
||||
self.namespace.remove(k);
|
||||
let mut namespace = ACPI_TABLE.namespace.write();
|
||||
|
||||
if let Some(ref mut namespace) = *namespace {
|
||||
for k in &self.namespace_delta {
|
||||
namespace.remove(k);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
19
src/acpi/fs.rs
Normal file
19
src/acpi/fs.rs
Normal file
@@ -0,0 +1,19 @@
|
||||
pub fn init_fs() {
|
||||
let schemes = schemes_mut().unwrap();
|
||||
schemes.insert(SchemeNamespace(0), Box::new(*b"acpi"), |_| Arc::new(Box::new(AcpiScheme::new()))).unwrap();
|
||||
}
|
||||
|
||||
struct AcpiScheme {
|
||||
|
||||
}
|
||||
|
||||
impl AcpiScheme {
|
||||
pub fn new() -> AcpiScheme {
|
||||
AcpiScheme
|
||||
}
|
||||
}
|
||||
|
||||
impl Scheme for AcpiScheme {
|
||||
fn open(&self, url: &[u8], flags: usize, uid: u32, gid: u32) -> Result<usize> {
|
||||
let path = str::from_utf8(url).unwrap_or("").trim_matches('/');
|
||||
|
||||
@@ -7,7 +7,7 @@ use collections::btree_map::BTreeMap;
|
||||
use collections::string::String;
|
||||
use alloc::boxed::Box;
|
||||
|
||||
use spin::Mutex;
|
||||
use spin::{Mutex, RwLock};
|
||||
|
||||
use device::local_apic::LOCAL_APIC;
|
||||
use interrupt;
|
||||
@@ -73,9 +73,12 @@ fn parse_sdt(sdt: &'static Sdt, active_table: &mut ActivePageTable) {
|
||||
|
||||
if let Some(fadt) = Fadt::new(sdt) {
|
||||
println!(": {:X}", fadt.dsdt);
|
||||
|
||||
let dsdt = get_sdt(fadt.dsdt as usize, active_table);
|
||||
parse_sdt(dsdt, active_table);
|
||||
ACPI_TABLE.lock().fadt = Some(fadt);
|
||||
|
||||
let mut fadt_t = ACPI_TABLE.fadt.write();
|
||||
*fadt_t = Some(fadt);
|
||||
} else if let Some(madt) = Madt::new(sdt) {
|
||||
println!(": {:>08X}: {}", madt.local_address, madt.flags);
|
||||
|
||||
@@ -202,20 +205,12 @@ fn parse_sdt(sdt: &'static Sdt, active_table: &mut ActivePageTable) {
|
||||
}
|
||||
} else if let Some(hpet) = Hpet::new(sdt) {
|
||||
println!(": {}", hpet.hpet_number);
|
||||
ACPI_TABLE.lock().hpet = Some(hpet);
|
||||
|
||||
let mut hpet_t = ACPI_TABLE.hpet.write();
|
||||
*hpet_t = Some(hpet);
|
||||
} else if is_aml_table(sdt) {
|
||||
match parse_aml_table(sdt) {
|
||||
Ok(res) => {
|
||||
println!(": Parsed");
|
||||
let ref mut namespace = ACPI_TABLE.lock().namespace;
|
||||
|
||||
if let Some(ref mut ns) = *namespace {
|
||||
let mut res = res.clone();
|
||||
ns.append(&mut res);
|
||||
} else {
|
||||
*namespace = Some(res);
|
||||
}
|
||||
},
|
||||
Ok(()) => println!(": Parsed"),
|
||||
Err(AmlError::AmlParseError(e)) => println!(": {}", e),
|
||||
Err(AmlError::AmlInvalidOpCode) => println!(": Invalid opcode"),
|
||||
Err(AmlError::AmlValueError) => println!(": Type constraints or value bounds not met"),
|
||||
@@ -229,6 +224,11 @@ fn parse_sdt(sdt: &'static Sdt, active_table: &mut ActivePageTable) {
|
||||
|
||||
/// Parse the ACPI tables to gather CPU, interrupt, and timer information
|
||||
pub unsafe fn init(active_table: &mut ActivePageTable) {
|
||||
{
|
||||
let mut namespace = ACPI_TABLE.namespace.write();
|
||||
*namespace = Some(BTreeMap::new());
|
||||
}
|
||||
|
||||
let start_addr = 0xE0000;
|
||||
let end_addr = 0xFFFFF;
|
||||
|
||||
@@ -283,12 +283,16 @@ pub unsafe fn init(active_table: &mut ActivePageTable) {
|
||||
}
|
||||
|
||||
pub struct Acpi {
|
||||
pub fadt: Option<Fadt>,
|
||||
pub namespace: Option<BTreeMap<String, AmlValue>>,
|
||||
pub hpet: Option<Hpet>
|
||||
pub fadt: RwLock<Option<Fadt>>,
|
||||
pub namespace: RwLock<Option<BTreeMap<String, AmlValue>>>,
|
||||
pub hpet: RwLock<Option<Hpet>>
|
||||
}
|
||||
|
||||
pub static ACPI_TABLE: Mutex<Acpi> = Mutex::new(Acpi { fadt: None, namespace: None, hpet: None });
|
||||
pub static ACPI_TABLE: Acpi = Acpi {
|
||||
fadt: RwLock::new(None),
|
||||
namespace: RwLock::new(None),
|
||||
hpet: RwLock::new(None)
|
||||
};
|
||||
|
||||
/// RSDP
|
||||
#[derive(Copy, Clone, Debug)]
|
||||
|
||||
@@ -17,7 +17,7 @@ pub unsafe fn init(active_table: &mut ActivePageTable){
|
||||
|
||||
pub unsafe fn init_noncore(active_table: &mut ActivePageTable) {
|
||||
{
|
||||
if let Some(ref hpet) = ACPI_TABLE.lock().hpet {
|
||||
if let Some(ref hpet) = *ACPI_TABLE.hpet.read() {
|
||||
hpet::init(hpet, active_table);
|
||||
} else {
|
||||
pit::init();
|
||||
|
||||
18
src/stop.rs
18
src/stop.rs
@@ -7,25 +7,29 @@ pub unsafe extern fn kstop() -> ! {
|
||||
|
||||
// ACPI shutdown
|
||||
{
|
||||
let acpi = acpi::ACPI_TABLE.lock();
|
||||
if let Some(ref fadt) = acpi.fadt {
|
||||
let fadt = acpi::ACPI_TABLE.fadt.read();
|
||||
|
||||
if let Some(ref fadt) = *fadt {
|
||||
let port = fadt.pm1a_control_block as u16;
|
||||
let mut val = 1 << 13;
|
||||
if let Some(ref namespace) = acpi.namespace {
|
||||
|
||||
let namespace = acpi::ACPI_TABLE.namespace.read();
|
||||
|
||||
if let Some(ref namespace) = *namespace {
|
||||
if let Some(s) = namespace.get("\\_S5") {
|
||||
if let Ok(p) = s.get_as_package() {
|
||||
println!("{:?}", p);
|
||||
let slp_typa = p[0].get_as_integer().expect("SLP_TYPa is not an integer");
|
||||
let slp_typb = p[1].get_as_integer().expect("SLP_TYPb is not an integer");
|
||||
|
||||
|
||||
println!("Shutdown SLP_TYPa {:X}, SLP_TYPb {:X}", slp_typa, slp_typb);
|
||||
val |= slp_typa as u16;
|
||||
|
||||
println!("Shutdown with ACPI outw(0x{:X}, 0x{:X})", port, val);
|
||||
Pio::<u16>::new(port).write(val);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
println!("Shutdown with ACPI outw(0x{:X}, 0x{:X})", port, val);
|
||||
Pio::<u16>::new(port).write(val);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user