From 5d661eab5959e79fc43e2fe28a936d20be08d098 Mon Sep 17 00:00:00 2001 From: 4lDO2 <4lDO2@protonmail.com> Date: Wed, 10 Mar 2021 14:37:06 +0100 Subject: [PATCH] Successfully load physical SDTs, and handle kstop* Well, while it does now wait for the kstop pipe, that is not to say that it actually performs the ACPI shutdown... yet. --- Cargo.lock | 13 +++++ acpid/Cargo.toml | 1 + acpid/src/acpi.rs | 20 ++++++-- acpid/src/aml/mod.rs | 6 ++- acpid/src/main.rs | 110 +++++++++++++++++++++++++++++++++++++++++-- 5 files changed, 141 insertions(+), 9 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 4322c741b9..ec0ff080d9 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -7,6 +7,7 @@ dependencies = [ "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", "parking_lot 0.11.1 (registry+https://github.com/rust-lang/crates.io-index)", "plain 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", + "redox-log 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "redox_syscall 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)", "thiserror 1.0.20 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1024,6 +1025,17 @@ dependencies = [ "termion 1.5.5 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "redox-log" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "chrono 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", + "smallvec 1.6.1 (registry+https://github.com/rust-lang/crates.io-index)", + "termion 1.5.5 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "redox_event" version = "0.1.0" @@ -1656,6 +1668,7 @@ dependencies = [ "checksum raw-window-handle 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "0a441a7a6c80ad6473bd4b74ec1c9a4c951794285bf941c2126f607c72e48211" "checksum rdrand 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "678054eb77286b51581ba43620cc911abf02758c91f93f479767aed0f90458b2" "checksum redox-log 0.1.0 (git+https://gitlab.redox-os.org/redox-os/redox-log.git?tag=v0.1.0)" = "" +"checksum redox-log 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "cbf6d33a003a5c0b94ec11f10c7c797303f236592964ddb1bfb93e1b438a1557" "checksum redox_event 0.1.0 (git+https://gitlab.redox-os.org/redox-os/event.git)" = "" "checksum redox_syscall 0.1.57 (registry+https://github.com/rust-lang/crates.io-index)" = "41cc0f7e4d5d4544e8861606a285bb08d3e70712ccc7d2b84d7c0ccfaf4b05ce" "checksum redox_syscall 0.2.0 (git+https://gitlab.redox-os.org/redox-os/syscall.git)" = "" diff --git a/acpid/Cargo.toml b/acpid/Cargo.toml index 30041ea4fd..3b990a92cf 100644 --- a/acpid/Cargo.toml +++ b/acpid/Cargo.toml @@ -10,5 +10,6 @@ edition = "2018" log = "0.4" parking_lot = "0.11.1" plain = "0.2.3" +redox-log = "0.1.1" redox_syscall = "0.2.5" thiserror = "1" diff --git a/acpid/src/acpi.rs b/acpid/src/acpi.rs index 40082226e3..0ff6a50732 100644 --- a/acpid/src/acpi.rs +++ b/acpid/src/acpi.rs @@ -1,8 +1,8 @@ use std::collections::HashMap; use std::convert::{TryFrom, TryInto}; -use std::mem; use std::ops::Deref; use std::sync::Arc; +use std::{fmt, mem}; use syscall::flag::PhysmapFlags; @@ -142,7 +142,7 @@ impl Sdt { assert!(pages.len() >= mem::size_of::()); let sdt_mem = &pages[physaddr_page_offset..]; - let sdt = plain::from_bytes::(&pages[mem::size_of::()..]) + let sdt = plain::from_bytes::(&sdt_mem[..mem::size_of::()]) .expect("either alignment is wrong, or the length is too short, both of which are already checked for"); let total_length = sdt.length(); @@ -156,18 +156,19 @@ impl Sdt { let mut left = extended_length; let mut offset = physaddr_start_page + page_table_count * PAGE_SIZE; + let length_per_iteration = PAGE_SIZE * SIMULTANEOUS_PAGE_COUNT; while left > 0 { let to_copy = std::cmp::min(left, length_per_iteration); - let pages = PhysmapGuard::map(offset, length_per_iteration)?; + let additional_pages = PhysmapGuard::map(offset, length_per_iteration)?; - loaded.extend(&pages[..to_copy]); + loaded.extend(&additional_pages[..to_copy]); left -= to_copy; offset += to_copy; } - assert_eq!(offset, loaded.len()); + assert_eq!(left, 0); Self::new(loaded.into()).map_err(Into::into) } @@ -188,6 +189,15 @@ impl Sdt { } } +impl fmt::Debug for Sdt { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_struct("Sdt") + .field("header", &*self as &SdtHeader) + .field("extra_len", &self.data().len()) + .finish() + } +} + pub struct Dsdt(Sdt); pub struct Ssdt(Sdt); diff --git a/acpid/src/aml/mod.rs b/acpid/src/aml/mod.rs index c56cc1dbcc..fa808729f7 100644 --- a/acpid/src/aml/mod.rs +++ b/acpid/src/aml/mod.rs @@ -94,7 +94,7 @@ fn init_namespace(context: &AcpiContext) -> HashMap { pub fn set_global_s_state(context: &AcpiContext, state: u8) { if state != 5 { - return + return; } let fadt = match context.fadt() { Some(fadt) => fadt, @@ -140,4 +140,8 @@ pub fn set_global_s_state(context: &AcpiContext, state: u8) { log::info!("Shutdown with ACPI outw(0x{:X}, 0x{:X})", port, val); Pio::::new(port).write(val); + + loop { + core::hint::spin_loop(); + } } diff --git a/acpid/src/main.rs b/acpid/src/main.rs index 54ebe96d1b..8a4baeeeea 100644 --- a/acpid/src/main.rs +++ b/acpid/src/main.rs @@ -1,7 +1,17 @@ -use std::convert::TryFrom; +#![feature(renamed_spin_loop)] + +use std::convert::{TryFrom, TryInto}; +use std::io::prelude::*; +use std::fs::{File, OpenOptions}; use std::mem; +use std::os::unix::io::AsRawFd; use std::sync::Arc; +use redox_log::RedoxLogger; + +use syscall::data::Event; +use syscall::flag::EventFlags; + mod acpi; mod aml; @@ -20,10 +30,57 @@ fn monotonic() -> (u64, u64) { (timespec.tv_sec as u64, timespec.tv_nsec as u64) } +fn setup_logging() -> Option<&'static RedoxLogger> { + use redox_log::OutputBuilder; + + let mut logger = RedoxLogger::new() + .with_output( + OutputBuilder::stderr() + .with_filter(log::LevelFilter::Trace) // limit global output to important info + .with_ansi_escape_codes() + .flush_on_newline(true) + .build() + ); + + #[cfg(target_os = "redox")] + match OutputBuilder::in_redox_logging_scheme("misc", "acpi", "acpid.log") { + Ok(b) => logger = logger.with_output( + // TODO: Add a configuration file for this + b.with_filter(log::LevelFilter::Trace) + .flush_on_newline(true) + .build() + ), + Err(error) => eprintln!("Failed to create xhci.log: {}", error), + } + + #[cfg(target_os = "redox")] + match OutputBuilder::in_redox_logging_scheme("misc", "acpi", "acpid.ansi.log") { + Ok(b) => logger = logger.with_output( + b.with_filter(log::LevelFilter::Trace) + .with_ansi_escape_codes() + .flush_on_newline(true) + .build() + ), + Err(error) => eprintln!("Failed to create acpid.ansi.log: {}", error), + } + + match logger.enable() { + Ok(logger_ref) => { + eprintln!("acpid: enabled logger"); + Some(logger_ref) + } + Err(error) => { + eprintln!("acpid: failed to set default logger: {}", error); + None + } + } +} fn main() { - let rxsdt_raw_data: Arc<[u8]> = std::fs::read("kernel/acpi:") - .expect("acpid: failed to read `kernel/acpi:`") + setup_logging(); + + let rxsdt_raw_data: Arc<[u8]> = std::fs::read("kernel/acpi:rxsdt") + .expect("acpid: failed to read `kernel/acpi:rxsdt`") .into(); let sdt = self::acpi::Sdt::new(rxsdt_raw_data) @@ -52,4 +109,51 @@ fn main() { _ => panic!("acpid: expected [RX]SDT from kernel to be either of those"), }; + for physaddr in physaddrs_iter { + let physaddr: usize = physaddr + .try_into() + .expect("expected ACPI addresses to be compatible with the current word size"); + + log::info!("TABLE AT {:#>08X}", physaddr); + + let sdt = self::acpi::Sdt::load_from_physical(physaddr) + .expect("failed to load physical SDT"); + dbg!(sdt); + } + + // TODO: I/O permission bitmap + unsafe { syscall::iopl(3) }.expect("acpid: failed to set I/O privilege level to Ring 3"); + + let shutdown_pipe = File::open("kernel/acpi:kstop") + .expect("acpid: failed to open `kernel/acpi:kstop`"); + + let mut event_queue = OpenOptions::new() + .write(true) + .read(true) + .create(false) + .open("event:") + .expect("acpid: failed to open event queue"); + + syscall::setrens(0, 0).expect("acpid: failed to enter null namespace"); + + event_queue.write_all(&Event { + id: shutdown_pipe.as_raw_fd() as usize, + flags: EventFlags::EVENT_READ, + data: 0, + }).expect("acpid: failed to register shutdown pipe for event queue"); + + loop { + let mut event = Event::default(); + event_queue.read_exact(&mut event).expect("acpid: failed to read from event queue"); + + if event.flags.contains(EventFlags::EVENT_READ) && event.id == shutdown_pipe.as_raw_fd() as usize { + break; + } + } + + drop(shutdown_pipe); + drop(event_queue); + + aml::set_global_s_state(todo!(), 5); + unreachable!(); }