diff --git a/Cargo.lock b/Cargo.lock index 583fab0341..a9d3c51e67 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -13,7 +13,7 @@ dependencies = [ "pcid", "redox-daemon", "redox_event", - "redox_syscall 0.5.3", + "redox_syscall 0.5.6", "spin", ] @@ -23,6 +23,7 @@ version = "0.1.0" dependencies = [ "aml", "amlserde", + "arrayvec 0.7.6", "common", "libredox 0.1.3", "log", @@ -31,9 +32,11 @@ dependencies = [ "parking_lot 0.11.2", "plain", "redox-daemon", - "redox_syscall 0.5.3", + "redox-scheme 0.2.2", + "redox_event", + "redox_syscall 0.5.6", + "ron", "rustc-hash", - "serde_json", "thiserror", ] @@ -49,9 +52,9 @@ dependencies = [ "log", "pcid", "redox-daemon", - "redox-scheme", + "redox-scheme 0.2.1", "redox_event", - "redox_syscall 0.5.3", + "redox_syscall 0.5.6", ] [[package]] @@ -72,7 +75,7 @@ dependencies = [ "libredox 0.1.3", "redox-daemon", "redox_event", - "redox_syscall 0.5.3", + "redox_syscall 0.5.6", ] [[package]] @@ -133,6 +136,12 @@ version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "23b62fc65de8e4e7f52534fb52b0f3ed04746ae267519eef2a83941e8085068b" +[[package]] +name = "arrayvec" +version = "0.7.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7c02d123df017efcdfbd739ef81735b36c5ba83ec3c59c80a9d7ecc718f92e50" + [[package]] name = "atty" version = "0.2.14" @@ -156,6 +165,12 @@ version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b41b7ea54a0c9d92199de89e20e58d49f02f8e699814ef3fdf266f6f748d15c7" +[[package]] +name = "base64" +version = "0.21.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9d297deb1925b89f2ccc13d7635fa0714f12c87adce1c75356b39ca9b7178567" + [[package]] name = "bcm2835-sdhcid" version = "0.1.0" @@ -165,9 +180,9 @@ dependencies = [ "fdt 0.1.5", "libredox 0.1.3", "redox-daemon", - "redox-scheme", + "redox-scheme 0.2.1", "redox_event", - "redox_syscall 0.5.3", + "redox_syscall 0.5.6", ] [[package]] @@ -179,7 +194,7 @@ dependencies = [ "orbclient", "pcid", "redox-daemon", - "redox_syscall 0.5.3", + "redox_syscall 0.5.6", ] [[package]] @@ -208,6 +223,9 @@ name = "bitflags" version = "2.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b048fb63fd8b5923fc5aa7b340d8e156aec7ec02f0c78fa8a6ddc2613f6f71de" +dependencies = [ + "serde", +] [[package]] name = "bitvec" @@ -297,7 +315,7 @@ dependencies = [ "libredox 0.1.3", "log", "redox-log", - "redox_syscall 0.5.3", + "redox_syscall 0.5.6", ] [[package]] @@ -362,7 +380,7 @@ name = "driver-block" version = "0.1.0" dependencies = [ "partitionlib", - "redox_syscall 0.5.3", + "redox_syscall 0.5.6", ] [[package]] @@ -370,7 +388,7 @@ name = "driver-network" version = "0.1.0" dependencies = [ "libredox 0.1.3", - "redox_syscall 0.5.3", + "redox_syscall 0.5.6", ] [[package]] @@ -384,7 +402,7 @@ dependencies = [ "pcid", "redox-daemon", "redox_event", - "redox_syscall 0.5.3", + "redox_syscall 0.5.6", ] [[package]] @@ -403,7 +421,7 @@ dependencies = [ "ransid", "redox-daemon", "redox_event", - "redox_syscall 0.5.3", + "redox_syscall 0.5.6", ] [[package]] @@ -601,9 +619,9 @@ dependencies = [ "log", "pcid", "redox-daemon", - "redox-scheme", + "redox-scheme 0.2.1", "redox_event", - "redox_syscall 0.5.3", + "redox_syscall 0.5.6", ] [[package]] @@ -617,7 +635,7 @@ dependencies = [ "pcid", "redox-daemon", "redox_event", - "redox_syscall 0.5.3", + "redox_syscall 0.5.6", "spin", ] @@ -641,7 +659,7 @@ dependencies = [ "log", "orbclient", "redox-daemon", - "redox_syscall 0.5.3", + "redox_syscall 0.5.6", "spin", ] @@ -671,7 +689,7 @@ dependencies = [ "pcid", "redox-daemon", "redox_event", - "redox_syscall 0.5.3", + "redox_syscall 0.5.6", ] [[package]] @@ -714,7 +732,7 @@ checksum = "c0ff37bd590ca25063e35af745c343cb7a0271906fb7b37e4813e8f79f00268d" dependencies = [ "bitflags 2.6.0", "libc", - "redox_syscall 0.5.3", + "redox_syscall 0.5.6", ] [[package]] @@ -724,9 +742,9 @@ dependencies = [ "anyhow", "libredox 0.1.3", "redox-daemon", - "redox-scheme", + "redox-scheme 0.2.1", "redox_event", - "redox_syscall 0.5.3", + "redox_syscall 0.5.6", ] [[package]] @@ -787,7 +805,7 @@ checksum = "b8f8bdf33df195859076e54ab11ee78a1b208382d3a26ec40d142ffc1ecc49ef" name = "nvmed" version = "0.1.0" dependencies = [ - "arrayvec", + "arrayvec 0.5.2", "bitflags 1.3.2", "common", "crossbeam-channel", @@ -798,9 +816,9 @@ dependencies = [ "partitionlib", "pcid", "redox-daemon", - "redox-scheme", + "redox-scheme 0.2.1", "redox_event", - "redox_syscall 0.5.3", + "redox_syscall 0.5.6", "smallvec 1.13.2", ] @@ -946,7 +964,7 @@ dependencies = [ "pci_types", "plain", "redox-daemon", - "redox_syscall 0.5.3", + "redox_syscall 0.5.6", "serde", "serde_json", "structopt", @@ -961,7 +979,7 @@ dependencies = [ "common", "libredox 0.1.3", "redox-daemon", - "redox_syscall 0.5.3", + "redox_syscall 0.5.6", ] [[package]] @@ -1025,7 +1043,7 @@ dependencies = [ "log", "orbclient", "redox-daemon", - "redox_syscall 0.5.3", + "redox_syscall 0.5.6", ] [[package]] @@ -1117,7 +1135,17 @@ version = "0.2.1" source = "git+https://gitlab.redox-os.org/redox-os/redox-scheme.git#79d9d54f572f53386981fb9b6ef054fd9e45110c" dependencies = [ "libredox 0.1.3", - "redox_syscall 0.5.3", + "redox_syscall 0.5.6", +] + +[[package]] +name = "redox-scheme" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "98d040cfa6370d9c6b1a5987247272f19ea4722f1064e66ad2e077c152b82ea3" +dependencies = [ + "libredox 0.1.3", + "redox_syscall 0.5.6", ] [[package]] @@ -1150,9 +1178,9 @@ dependencies = [ [[package]] name = "redox_syscall" -version = "0.5.3" +version = "0.5.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2a908a6e00f1fdd0dfd9c0eb08ce85126f6d8bbda50017e74bc4a4b7d4a926a4" +checksum = "355ae415ccd3a04315d3f8246e86d67689ea74d88d915576e1589a351062a13b" dependencies = [ "bitflags 2.6.0", ] @@ -1202,6 +1230,18 @@ dependencies = [ "ux", ] +[[package]] +name = "ron" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b91f7eff05f748767f183df4320a63d6936e9c6107d97c9e6bdd9784f4289c94" +dependencies = [ + "base64 0.21.7", + "bitflags 2.6.0", + "serde", + "serde_derive", +] + [[package]] name = "rtl8139d" version = "0.1.0" @@ -1214,7 +1254,7 @@ dependencies = [ "pcid", "redox-daemon", "redox_event", - "redox_syscall 0.5.3", + "redox_syscall 0.5.6", ] [[package]] @@ -1229,7 +1269,7 @@ dependencies = [ "pcid", "redox-daemon", "redox_event", - "redox_syscall 0.5.3", + "redox_syscall 0.5.6", ] [[package]] @@ -1254,7 +1294,7 @@ dependencies = [ "log", "redox-daemon", "redox_event", - "redox_syscall 0.5.3", + "redox_syscall 0.5.6", "spin", ] @@ -1581,7 +1621,7 @@ dependencies = [ "common", "log", "orbclient", - "redox_syscall 0.5.3", + "redox_syscall 0.5.6", "rehid", "xhcid", ] @@ -1592,7 +1632,7 @@ version = "0.1.0" dependencies = [ "common", "log", - "redox_syscall 0.5.3", + "redox_syscall 0.5.6", "xhcid", ] @@ -1600,12 +1640,12 @@ dependencies = [ name = "usbscsid" version = "0.1.0" dependencies = [ - "base64", + "base64 0.11.0", "libredox 0.1.3", "plain", "redox-daemon", - "redox-scheme", - "redox_syscall 0.5.3", + "redox-scheme 0.2.1", + "redox_syscall 0.5.6", "thiserror", "xhcid", ] @@ -1641,7 +1681,7 @@ dependencies = [ "pcid", "redox-daemon", "redox_event", - "redox_syscall 0.5.3", + "redox_syscall 0.5.6", ] [[package]] @@ -1672,7 +1712,7 @@ dependencies = [ "orbclient", "ransid", "redox-daemon", - "redox_syscall 0.5.3", + "redox_syscall 0.5.6", ] [[package]] @@ -1688,8 +1728,8 @@ dependencies = [ "partitionlib", "pcid", "redox-daemon", - "redox-scheme", - "redox_syscall 0.5.3", + "redox-scheme 0.2.1", + "redox_syscall 0.5.6", "spin", "static_assertions", "thiserror", @@ -1708,7 +1748,7 @@ dependencies = [ "log", "pcid", "redox_event", - "redox_syscall 0.5.3", + "redox_syscall 0.5.6", "static_assertions", "thiserror", ] @@ -1727,7 +1767,7 @@ dependencies = [ "paste", "pcid", "redox-daemon", - "redox_syscall 0.5.3", + "redox_syscall 0.5.6", "spin", "static_assertions", "virtio-core", @@ -1744,7 +1784,7 @@ dependencies = [ "log", "pcid", "redox-daemon", - "redox_syscall 0.5.3", + "redox_syscall 0.5.6", "static_assertions", "virtio-core", ] @@ -1947,7 +1987,7 @@ dependencies = [ "plain", "redox-daemon", "redox_event", - "redox_syscall 0.5.3", + "redox_syscall 0.5.6", "regex", "serde", "serde_json", diff --git a/acpid/Cargo.toml b/acpid/Cargo.toml index 0ba5a37b00..21b4f4268b 100644 --- a/acpid/Cargo.toml +++ b/acpid/Cargo.toml @@ -14,11 +14,14 @@ num-traits = "0.2" parking_lot = "0.11.1" plain = "0.2.3" redox-daemon = "0.1" -redox_syscall = "0.5" +redox_syscall = "0.5.6" +redox_event = "0.4.1" rustc-hash = "1.1.0" thiserror = "1" -serde_json = "1.0.94" +ron = "0.8.1" amlserde = { path = "../amlserde" } common = { path = "../common" } libredox = "0.1.3" +redox-scheme = "0.2.2" +arrayvec = "0.7.6" diff --git a/acpid/src/acpi.rs b/acpid/src/acpi.rs index 2564825b15..4071c92902 100644 --- a/acpid/src/acpi.rs +++ b/acpid/src/acpi.rs @@ -16,7 +16,6 @@ use amlserde::aml_serde_name::aml_to_symbol; use amlserde::{AmlHandleLookup, AmlSerde}; pub mod dmar; -use self::dmar::Dmar; use crate::aml_physmem::{AmlPageCache, AmlPhysMemHandler}; #[cfg(target_arch = "aarch64")] @@ -245,7 +244,6 @@ pub struct AmlSymbols { // k = name, v = description symbol_cache: FxHashMap, page_cache: Arc>, - list: String, } impl AmlSymbols { @@ -258,7 +256,6 @@ impl AmlSymbols { ), symbol_cache: FxHashMap::default(), page_cache, - list: "".to_string(), } } @@ -266,10 +263,6 @@ impl AmlSymbols { &mut self.aml_context } - pub fn symbols_str(&self) -> &String { - &self.list - } - pub fn symbols_cache(&self) -> &FxHashMap { &self.symbol_cache } @@ -315,16 +308,12 @@ impl AmlSymbols { return; } - let mut symbols_str = String::with_capacity(symbol_list.len() * 10); let mut handle_lookup = AmlHandleLookup::new(); for (aml_name, name, handle) in &symbol_list { - let _ = writeln!(symbols_str, "{}", &name); handle_lookup.insert(handle.to_owned(), aml_name.to_owned()); } - symbols_str.shrink_to_fit(); - let mut symbol_cache: FxHashMap = FxHashMap::default(); for (aml_name, name, handle) in &symbol_list { @@ -337,7 +326,7 @@ impl AmlSymbols { aml_name, handle, ) { - if let Ok(ser_string) = serde_json::to_string_pretty(&ser_value) { + if let Ok(ser_string) = ron::ser::to_string_pretty(&ser_value, Default::default()) { // replace the empty entry symbol_cache.insert(name.to_owned(), ser_string); } @@ -347,7 +336,6 @@ impl AmlSymbols { // Cache the new list log::trace!("Updating symbols list"); - self.list = symbols_str; self.symbol_cache = symbol_cache; } } @@ -533,7 +521,6 @@ impl AcpiContext { pub fn aml_symbols_reset(&self) { let mut aml_symbols = self.aml_symbols.write(); aml_symbols.symbol_cache = FxHashMap::default(); - aml_symbols.list = "".to_string(); } /// Set Power State diff --git a/acpid/src/acpi/dmar/drhd.rs b/acpid/src/acpi/dmar/drhd.rs index da51d4349c..cce735d0dd 100644 --- a/acpid/src/acpi/dmar/drhd.rs +++ b/acpid/src/acpi/dmar/drhd.rs @@ -10,11 +10,20 @@ pub struct DrhdPage { } impl DrhdPage { pub fn map(base_phys: usize) -> syscall::Result { - assert_eq!(base_phys % crate::acpi::PAGE_SIZE, 0, "DRHD registers must be page-aligned"); + assert_eq!( + base_phys % crate::acpi::PAGE_SIZE, + 0, + "DRHD registers must be page-aligned" + ); // TODO: Uncachable? Can reads have side-effects? let virt = unsafe { - common::physmap(base_phys, crate::acpi::PAGE_SIZE, common::Prot::RO, common::MemoryType::default())? + common::physmap( + base_phys, + crate::acpi::PAGE_SIZE, + common::Prot::RO, + common::MemoryType::default(), + )? } as *mut Drhd; Ok(Self { virt }) diff --git a/acpid/src/main.rs b/acpid/src/main.rs index 4c7024522f..a0b07ec895 100644 --- a/acpid/src/main.rs +++ b/acpid/src/main.rs @@ -1,34 +1,18 @@ #![feature(if_let_guard, int_roundings)] use std::convert::TryFrom; -use std::io::{self, prelude::*}; -use std::fs::{File, OpenOptions}; +use std::fs::File; use std::mem; -use std::os::unix::fs::OpenOptionsExt; -use std::os::unix::io::{AsRawFd, FromRawFd, RawFd}; +use std::os::unix::io::AsRawFd; use std::sync::Arc; -use syscall::scheme::SchemeMut; - -use syscall::data::{Event, Packet}; -use syscall::flag::{EventFlags, O_NONBLOCK}; +use event::{EventFlags, RawEventQueue}; +use redox_scheme::{RequestKind, SignalBehavior, Socket, V2}; +use syscall::{EAGAIN, EWOULDBLOCK}; mod acpi; -mod scheme; mod aml_physmem; - -fn monotonic() -> (u64, u64) { - use syscall::call::clock_gettime; - use syscall::data::TimeSpec; - use syscall::flag::CLOCK_MONOTONIC; - - let mut timespec = TimeSpec::default(); - - clock_gettime(CLOCK_MONOTONIC, &mut timespec) - .expect("failed to fetch monotonic time"); - - (timespec.tv_sec as u64, timespec.tv_nsec as u64) -} +mod scheme; fn daemon(daemon: redox_daemon::Daemon) -> ! { common::setup_logging( @@ -43,15 +27,16 @@ fn daemon(daemon: redox_daemon::Daemon) -> ! { .expect("acpid: failed to read `/scheme/kernel.acpi/rxsdt`") .into(); - let sdt = self::acpi::Sdt::new(rxsdt_raw_data) - .expect("acpid: failed to parse [RX]SDT"); + let sdt = self::acpi::Sdt::new(rxsdt_raw_data).expect("acpid: failed to parse [RX]SDT"); let mut thirty_two_bit; let mut sixty_four_bit; let physaddrs_iter = match &sdt.signature { b"RSDT" => { - thirty_two_bit = sdt.data().chunks(mem::size_of::()) + thirty_two_bit = sdt + .data() + .chunks(mem::size_of::()) // TODO: With const generics, the compiler has some way of doing this for static sizes. .map(|chunk| <[u8; mem::size_of::()]>::try_from(chunk).unwrap()) .map(|chunk| u32::from_le_bytes(chunk)) @@ -60,12 +45,14 @@ fn daemon(daemon: redox_daemon::Daemon) -> ! { &mut thirty_two_bit as &mut dyn Iterator } b"XSDT" => { - sixty_four_bit = sdt.data().chunks(mem::size_of::()) + sixty_four_bit = sdt + .data() + .chunks(mem::size_of::()) .map(|chunk| <[u8; mem::size_of::()]>::try_from(chunk).unwrap()) .map(|chunk| u64::from_le_bytes(chunk)); &mut sixty_four_bit as &mut dyn Iterator - }, + } _ => panic!("acpid: expected [RX]SDT from kernel to be either of those"), }; @@ -77,95 +64,66 @@ fn daemon(daemon: redox_daemon::Daemon) -> ! { let shutdown_pipe = File::open("/scheme/kernel.acpi/kstop") .expect("acpid: failed to open `/scheme/kernel.acpi/kstop`"); - let mut event_queue = OpenOptions::new() - .write(true) - .read(true) - .create(false) - .open("/scheme/event") - .expect("acpid: failed to open event queue"); - - let mut scheme_socket = OpenOptions::new() - .write(true) - .read(true) - .create(true) - .custom_flags(O_NONBLOCK as i32) - .open(":acpi") - .expect("acpid: failed to open scheme socket"); + let mut event_queue = RawEventQueue::new().expect("acpid: failed to create event queue"); + let socket = Socket::::nonblock("acpi").expect("acpid: failed to create disk scheme"); daemon.ready().expect("acpid: failed to notify parent"); libredox::call::setrens(0, 0).expect("acpid: failed to enter null namespace"); - let _ = event_queue.write(&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"); - - let _ = event_queue.write(&Event { - id: scheme_socket.as_raw_fd() as usize, - flags: EventFlags::EVENT_READ, - data: 1, - }).expect("acpid: failed to register scheme socket for event queue"); + event_queue + .subscribe(shutdown_pipe.as_raw_fd() as usize, 0, EventFlags::READ) + .expect("acpid: failed to register shutdown pipe for event queue"); + event_queue + .subscribe(socket.inner().raw(), 1, EventFlags::READ) + .expect("acpid: failed to register scheme socket for event queue"); let mut scheme = self::scheme::AcpiScheme::new(&acpi_context); - let mut event = Event::default(); - let mut packet = Packet::default(); + let mut mounted = true; + while mounted { + let Some(event) = event_queue + .next() + .transpose() + .expect("acpid: failed to read event file") + else { + break; + }; - 'events: loop { - 'packets: loop { - let bytes_read = 'eintr1: loop { - match scheme_socket.read(&mut packet) { - Ok(0) => { - log::info!("Terminating acpid driver, without shutting down the main system."); - break 'events; + if event.fd == socket.inner().raw() { + loop { + let sqe = match socket.next_request(SignalBehavior::Interrupt) { + Ok(None) => { + mounted = false; + break; } - Ok(n) => break 'eintr1 n, - Err(error) if error.kind() == io::ErrorKind::Interrupted => continue 'eintr1, - Err(error) if error.kind() == io::ErrorKind::WouldBlock => break 'packets, - Err(other) => { - log::error!("failed to read from scheme socket: {}", other); - break 'events; + Ok(Some(s)) => { + if let RequestKind::Call(call) = s.kind() { + call + } else { + continue; + } } - } - }; + Err(err) => { + if err.errno == EWOULDBLOCK || err.errno == EAGAIN { + break; + } else { + panic!("acpid: failed to read next request: {}", err); + } + } + }; - if bytes_read < mem::size_of::() { - log::error!("Scheme socket read less than a single packet."); + let response = sqe.handle_scheme_mut(&mut scheme); + socket + .write_response(response, SignalBehavior::Restart) + .expect("acpid: failed to write response"); } - - scheme.handle(&mut packet); - - let bytes_written = 'eintr2: loop { - match scheme_socket.write(&packet) { - Ok(0) => { - log::info!("Terminating acpid driver, without shutting down the main system."); - break 'events; - } - Ok(n) => break 'eintr2 n, - Err(error) if error.kind() == io::ErrorKind::Interrupted => continue 'eintr2, - Err(error) if error.kind() == io::ErrorKind::WouldBlock => break 'packets, - Err(other) => { - log::error!("failed to read from scheme socket: {}", other); - break 'events; - } - } - }; - - if bytes_written < mem::size_of::() { - log::error!("Scheme socket read less than a single packet."); - } - } - - let _ = event_queue.read(&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 { + } else if event.fd == shutdown_pipe.as_raw_fd() as usize { log::info!("Received shutdown request from kernel."); - break 'events; - } - if !event.flags.contains(EventFlags::EVENT_READ) || event.id != scheme_socket.as_raw_fd() as usize { - continue 'events; + mounted = false; + } else { + log::debug!("Received request to unknown fd: {}", event.fd); + continue; } } diff --git a/acpid/src/scheme.rs b/acpid/src/scheme.rs index a4d598fbc5..fec64bacee 100644 --- a/acpid/src/scheme.rs +++ b/acpid/src/scheme.rs @@ -1,15 +1,19 @@ +use core::str; +use parking_lot::RwLockReadGuard; +use redox_scheme::{CallerCtx, OpenResult, SchemeMut}; use std::collections::BTreeMap; use std::convert::{TryFrom, TryInto}; -use parking_lot::RwLockReadGuard; +use syscall::dirent::{DirEntry, DirentBuf, DirentKind}; +use syscall::schemev2::NewFdFlags; use syscall::data::Stat; -use syscall::error::{EIO, EBADF, EBADFD, EINVAL, EISDIR, ENOENT, ENOTDIR, EOVERFLOW}; use syscall::error::{Error, Result}; +use syscall::error::{EBADF, EBADFD, EINVAL, EIO, EISDIR, ENOENT, ENOTDIR}; +use syscall::flag::{MODE_DIR, MODE_FILE}; use syscall::flag::{O_ACCMODE, O_DIRECTORY, O_RDONLY, O_STAT, O_SYMLINK}; -use syscall::flag::{MODE_FILE, MODE_DIR, SEEK_CUR, SEEK_END, SEEK_SET}; -use syscall::scheme::SchemeMut; +use syscall::EOPNOTSUPP; -use crate::acpi::{AcpiContext, SdtSignature, AmlSymbols}; +use crate::acpi::{AcpiContext, AmlSymbols, SdtSignature}; pub struct AcpiScheme<'acpi> { ctx: &'acpi AcpiContext, @@ -18,7 +22,6 @@ pub struct AcpiScheme<'acpi> { } struct Handle<'a> { - offset: usize, kind: HandleKind<'a>, stat: bool, } @@ -42,11 +45,14 @@ impl HandleKind<'_> { } fn len(&self, acpi_ctx: &AcpiContext) -> Result { Ok(match self { - Self::TopLevel => TOPLEVEL_CONTENTS.len(), - Self::Tables => acpi_ctx.tables().len().checked_mul(TABLE_DENTRY_LENGTH).unwrap_or(usize::max_value()), - Self::Table(signature) => acpi_ctx.sdt_from_signature(signature).ok_or(Error::new(EBADFD))?.length(), - Self::Symbols(aml_symbols) => aml_symbols.symbols_str().len(), + // Files + Self::Table(signature) => acpi_ctx + .sdt_from_signature(signature) + .ok_or(Error::new(EBADFD))? + .length(), Self::Symbol(description) => description.len(), + // Directories + Self::TopLevel | Self::Symbols(_) | Self::Tables => 0, }) } } @@ -61,10 +67,6 @@ impl<'acpi> AcpiScheme<'acpi> { } } -const TOPLEVEL_CONTENTS: &[u8] = b"tables\nsymbols\n"; - -const TABLE_DENTRY_LENGTH: usize = 35; - fn parse_hex_digit(hex: u8) -> Option { let hex = hex.to_ascii_lowercase(); @@ -78,7 +80,8 @@ fn parse_hex_digit(hex: u8) -> Option { } fn parse_hex_2digit(hex: &[u8]) -> Option { - parse_hex_digit(hex[0]).and_then(|most_significant| Some((most_significant << 4) | parse_hex_digit(hex[1])?)) + parse_hex_digit(hex[0]) + .and_then(|most_significant| Some((most_significant << 4) | parse_hex_digit(hex[1])?)) } fn parse_oem_id(hex: [u8; 12]) -> Option<[u8; 6]> { @@ -123,27 +126,38 @@ fn parse_table(table: &[u8]) -> Option { } Some(SdtSignature { - signature: <[u8; 4]>::try_from(signature_part).expect("expected 4-byte slice to be convertible into [u8; 4]"), + signature: <[u8; 4]>::try_from(signature_part) + .expect("expected 4-byte slice to be convertible into [u8; 4]"), oem_id: { - let hex = <[u8; 12]>::try_from(oem_id_part).expect("expected 12-byte slice to be convertible into [u8; 12]"); + let hex = <[u8; 12]>::try_from(oem_id_part) + .expect("expected 12-byte slice to be convertible into [u8; 12]"); parse_oem_id(hex)? }, oem_table_id: { - let hex = <[u8; 16]>::try_from(oem_table_part).expect("expected 16-byte slice to be convertible into [u8; 16]"); + let hex = <[u8; 16]>::try_from(oem_table_part) + .expect("expected 16-byte slice to be convertible into [u8; 16]"); parse_oem_table_id(hex)? }, }) } impl SchemeMut for AcpiScheme<'_> { - fn open(&mut self, path: &str, flags: usize, _uid: u32, _gid: u32) -> Result { + fn xopen(&mut self, path: &str, flags: usize, _ctx: &CallerCtx) -> Result { let path = path.trim_start_matches('/'); let flag_stat = flags & O_STAT == O_STAT; let flag_dir = flags & O_DIRECTORY == O_DIRECTORY; // TODO: arrayvec - let components = path.split('/').collect::>(); + let components = { + let mut v = arrayvec::ArrayVec::<&str, 3>::new(); + let it = path.split('/'); + for component in it.take(3) { + v.push(component); + } + + v + }; let kind = match &*components { [""] => HandleKind::TopLevel, @@ -154,11 +168,13 @@ impl SchemeMut for AcpiScheme<'_> { HandleKind::Table(signature) } - ["symbols"] => if let Ok(aml_symbols) = self.ctx.aml_symbols() { - HandleKind::Symbols(aml_symbols) - } else { - return Err(Error::new(EIO)) - }, + ["symbols"] => { + if let Ok(aml_symbols) = self.ctx.aml_symbols() { + HandleKind::Symbols(aml_symbols) + } else { + return Err(Error::new(EIO)); + } + } ["symbols", symbol] => { if let Some(description) = self.ctx.aml_lookup(symbol) { @@ -188,18 +204,28 @@ impl SchemeMut for AcpiScheme<'_> { let fd = self.next_fd; self.next_fd += 1; - self.handles.insert(fd, Handle { - offset: 0, - stat: flag_stat, - kind, - }); + self.handles.insert( + fd, + Handle { + stat: flag_stat, + kind, + }, + ); - Ok(fd) + Ok(OpenResult::ThisScheme { + number: fd, + flags: NewFdFlags::POSITIONED, + }) } + fn fstat(&mut self, id: usize, stat: &mut Stat) -> Result { let handle = self.handles.get(&id).ok_or(Error::new(EBADF))?; - - stat.st_size = handle.kind.len(self.ctx)?.try_into().unwrap_or(u64::max_value()); + + stat.st_size = handle + .kind + .len(self.ctx)? + .try_into() + .unwrap_or(u64::max_value()); if handle.kind.is_dir() { stat.st_mode = MODE_DIR; @@ -209,35 +235,10 @@ impl SchemeMut for AcpiScheme<'_> { Ok(0) } - fn seek(&mut self, id: usize, pos: isize, whence: usize) -> Result { - let handle = self.handles.get_mut(&id).ok_or(Error::new(EBADF))?; - if handle.stat { - return Err(Error::new(EBADF)); - } + fn read(&mut self, id: usize, buf: &mut [u8], offset: u64, _fcntl: u32) -> Result { + let offset: usize = offset.try_into().map_err(|_| Error::new(EINVAL))?; - let file_len = handle.kind.len(self.ctx)?; - - let new_offset = match whence { - SEEK_SET => pos as usize, - SEEK_CUR => if pos < 0 { - handle.offset.checked_sub((-pos) as usize).ok_or(Error::new(EINVAL))? - } else { - handle.offset.saturating_add(pos as usize) - }, - SEEK_END => if pos < 0 { - file_len.checked_sub((-pos) as usize).ok_or(Error::new(EINVAL))? - } else { - file_len - } - - _ => return Err(Error::new(EINVAL)), - }; - - handle.offset = new_offset; - Ok(new_offset as isize) - } - fn read(&mut self, id: usize, buf: &mut [u8]) -> Result { let handle = self.handles.get_mut(&id).ok_or(Error::new(EBADF))?; if handle.stat { @@ -245,77 +246,104 @@ impl SchemeMut for AcpiScheme<'_> { } let src_buf = match &handle.kind { - HandleKind::TopLevel => TOPLEVEL_CONTENTS, - HandleKind::Table(ref signature) => self.ctx.sdt_from_signature(signature).ok_or(Error::new(EBADFD))?.as_slice(), - - HandleKind::Tables => { - use std::io::prelude::*; - - let tables_to_skip = handle.offset / TABLE_DENTRY_LENGTH; - let max_tables_to_fill = (buf.len() + TABLE_DENTRY_LENGTH - 1) / TABLE_DENTRY_LENGTH; - - let mut bytes_to_skip = handle.offset % TABLE_DENTRY_LENGTH; - - let mut src_buf = [0_u8; TABLE_DENTRY_LENGTH]; - let mut bytes_written = 0; - - for table in self.ctx.tables().iter().skip(tables_to_skip).take(max_tables_to_fill) { - let mut cursor = std::io::Cursor::new(&mut src_buf[..]); - cursor.write_all(&table.signature).unwrap(); - cursor.write_all(&[b'-']).unwrap(); - // TODO: Treat these IDs as strings? - for byte in table.oem_id.iter() { - write!(cursor, "{:>02X}", byte).unwrap(); - } - cursor.write_all(&[b'-']).unwrap(); - for byte in table.oem_table_id.iter() { - write!(cursor, "{:>02X}", byte).unwrap(); - } - cursor.write_all(&[b'\n']).unwrap(); - - let src_buf = &src_buf[bytes_to_skip..]; - let dst_buf = &mut buf[bytes_written..]; - let to_copy = std::cmp::min(src_buf.len(), dst_buf.len()); - dst_buf[..to_copy].copy_from_slice(&src_buf[..to_copy]); - bytes_written += to_copy; - bytes_to_skip = 0; - } - - handle.offset = handle.offset.checked_add(bytes_written).ok_or(Error::new(EOVERFLOW))?; - - return Ok(bytes_written); - } - - HandleKind::Symbols(aml_symbols) => { - let symbols = aml_symbols.symbols_str(); - let offset = std::cmp::min(symbols.len(), handle.offset); - let src_buf = &symbols.as_bytes()[offset..]; - - let to_copy = std::cmp::min(src_buf.len(), buf.len()); - buf[..to_copy].copy_from_slice(&src_buf[..to_copy]); - - handle.offset = handle.offset.checked_add(to_copy).ok_or(Error::new(EOVERFLOW))?; - - return Ok(to_copy); - } - + HandleKind::Table(ref signature) => self + .ctx + .sdt_from_signature(signature) + .ok_or(Error::new(EBADFD))? + .as_slice(), HandleKind::Symbol(description) => description.as_bytes(), - + _ => return Err(Error::new(EINVAL)), }; - let offset = std::cmp::min(src_buf.len(), handle.offset); + let offset = std::cmp::min(src_buf.len(), offset); let src_buf = &src_buf[offset..]; let to_copy = std::cmp::min(src_buf.len(), buf.len()); - buf[..to_copy].copy_from_slice(&src_buf[..to_copy]); - handle.offset = handle.offset.checked_add(to_copy).ok_or(Error::new(EOVERFLOW))?; + buf[..to_copy].copy_from_slice(&src_buf[..to_copy]); Ok(to_copy) } - fn write(&mut self, _id: usize, _buf: &[u8]) -> Result { + + fn getdents<'buf>( + &mut self, + id: usize, + mut buf: DirentBuf<&'buf mut [u8]>, + opaque_offset: u64, + ) -> Result> { + let handle = self.handles.get_mut(&id).ok_or(Error::new(EOPNOTSUPP))?; + + match &handle.kind { + HandleKind::TopLevel => { + const TOPLEVEL_ENTRIES: &[&str] = &["tables", "symbols"]; + + for (idx, name) in TOPLEVEL_ENTRIES + .iter() + .enumerate() + .skip(opaque_offset as usize) + { + buf.entry(DirEntry { + inode: 0, + next_opaque_id: idx as u64 + 1, + name, + kind: DirentKind::Directory, + })?; + } + } + HandleKind::Symbols(aml_symbols) => { + for (idx, (symbol_name, _value)) in aml_symbols + .symbols_cache() + .iter() + .enumerate() + .skip(opaque_offset as usize) + { + buf.entry(DirEntry { + inode: 0, + next_opaque_id: idx as u64 + 1, + name: symbol_name.as_str(), + kind: DirentKind::Regular, + })?; + } + } + HandleKind::Tables => { + for (idx, table) in self + .ctx + .tables() + .iter() + .enumerate() + .skip(opaque_offset as usize) + { + let utf8_or_eio = |bytes| str::from_utf8(bytes).map_err(|_| Error::new(EIO)); + + let mut name = String::new(); + name.push_str(utf8_or_eio(&table.signature[..])?); + name.push('-'); + for byte in table.oem_id.iter() { + std::fmt::write(&mut name, format_args!("{:>02X}", byte)).unwrap(); + } + name.push('-'); + for byte in table.oem_table_id.iter() { + std::fmt::write(&mut name, format_args!("{:>02X}", byte)).unwrap(); + } + + buf.entry(DirEntry { + inode: 0, + next_opaque_id: idx as u64 + 1, + name: &name, + kind: DirentKind::Regular, + })?; + } + } + _ => return Err(Error::new(EIO)), + } + + Ok(buf) + } + + fn write(&mut self, _id: usize, _buf: &[u8], _offset: u64, _fcntl: u32) -> Result { Err(Error::new(EBADF)) } + fn close(&mut self, id: usize) -> Result { if self.handles.remove(&id).is_none() { return Err(Error::new(EBADF));