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.
This commit is contained in:
Generated
+13
@@ -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)" = "<none>"
|
||||
"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)" = "<none>"
|
||||
"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)" = "<none>"
|
||||
|
||||
@@ -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"
|
||||
|
||||
+15
-5
@@ -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::<SdtHeader>());
|
||||
let sdt_mem = &pages[physaddr_page_offset..];
|
||||
|
||||
let sdt = plain::from_bytes::<SdtHeader>(&pages[mem::size_of::<SdtHeader>()..])
|
||||
let sdt = plain::from_bytes::<SdtHeader>(&sdt_mem[..mem::size_of::<SdtHeader>()])
|
||||
.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);
|
||||
|
||||
|
||||
@@ -94,7 +94,7 @@ fn init_namespace(context: &AcpiContext) -> HashMap<String, AmlValue> {
|
||||
|
||||
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::<u16>::new(port).write(val);
|
||||
|
||||
loop {
|
||||
core::hint::spin_loop();
|
||||
}
|
||||
}
|
||||
|
||||
+107
-3
@@ -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!();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user