Verified Commit 5d661eab authored by 4lDO2's avatar 4lDO2 🖖

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.
parent df4a6aee
......@@ -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"
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();
}
}
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!();
}
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment