diff --git a/src/acpi/aml/mod.rs b/src/acpi/aml/mod.rs index a6275db..1edab51 100644 --- a/src/acpi/aml/mod.rs +++ b/src/acpi/aml/mod.rs @@ -37,13 +37,13 @@ pub enum AmlError { AmlFatalError(u8, u16, AmlValue) } -pub fn parse_aml_table(sdt: &'static Sdt) -> Result, 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 { diff --git a/src/acpi/aml/namedobj.rs b/src/acpi/aml/namedobj.rs index 612d744..a99c82f 100644 --- a/src/acpi/aml/namedobj.rs +++ b/src/acpi/aml/namedobj.rs @@ -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, diff --git a/src/acpi/aml/namespace.rs b/src/acpi/aml/namespace.rs index 6b8c598..1c84f81 100644 --- a/src/acpi/aml/namespace.rs +++ b/src/acpi/aml/namespace.rs @@ -52,7 +52,7 @@ pub enum AmlValue { }, DDBHandle(u32), // Index into the XSDT DebugObject, - Device(BTreeMap), + Device(Vec), Event, FieldUnit { selector: FieldSelector, @@ -76,15 +76,15 @@ pub enum AmlValue { PowerResource { system_level: u8, resource_order: u16, - obj_list: BTreeMap + obj_list: Vec }, Processor { proc_id: u8, p_blk: Option, - obj_list: BTreeMap + obj_list: Vec }, RawDataBuffer(Vec), - ThermalZone(BTreeMap) + ThermalZone(Vec) } impl AmlValue { diff --git a/src/acpi/aml/parser.rs b/src/acpi/aml/parser.rs index 6c2468f..0b57f13 100644 --- a/src/acpi/aml/parser.rs +++ b/src/acpi/aml/parser.rs @@ -5,6 +5,8 @@ use collections::vec::Vec; use super::namespace::{ AmlValue, ObjectReference }; use super::AmlError; +use acpi::ACPI_TABLE; + pub type ParseResult = Result; pub type AmlParseType = AmlParseTypeGeneric; @@ -21,7 +23,6 @@ pub enum ExecutionState { } pub struct AmlExecutionContext { - pub namespace: BTreeMap, 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); + } } } diff --git a/src/acpi/fs.rs b/src/acpi/fs.rs new file mode 100644 index 0000000..2a6b608 --- /dev/null +++ b/src/acpi/fs.rs @@ -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 { + let path = str::from_utf8(url).unwrap_or("").trim_matches('/'); + diff --git a/src/acpi/mod.rs b/src/acpi/mod.rs index b9f7ba3..d246609 100644 --- a/src/acpi/mod.rs +++ b/src/acpi/mod.rs @@ -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, - pub namespace: Option>, - pub hpet: Option + pub fadt: RwLock>, + pub namespace: RwLock>>, + pub hpet: RwLock> } -pub static ACPI_TABLE: Mutex = 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)] diff --git a/src/device/mod.rs b/src/device/mod.rs index 965e083..568f395 100644 --- a/src/device/mod.rs +++ b/src/device/mod.rs @@ -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(); diff --git a/src/stop.rs b/src/stop.rs index 7e53f10..acd0179 100644 --- a/src/stop.rs +++ b/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::::new(port).write(val); } } } - - println!("Shutdown with ACPI outw(0x{:X}, 0x{:X})", port, val); - Pio::::new(port).write(val); } }