acpid: update to redox_scheme

* Change symbol serialization to RON
This commit is contained in:
Kamil Koczurek
2024-09-26 17:01:55 +02:00
parent d2c82add9d
commit 56bfd63173
6 changed files with 311 additions and 286 deletions
Generated
+87 -47
View File
@@ -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",
+5 -2
View File
@@ -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"
+1 -14
View File
@@ -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<String, String>,
page_cache: Arc<Mutex<AmlPageCache>>,
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<String, String> {
&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<String, String> = 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
+11 -2
View File
@@ -10,11 +10,20 @@ pub struct DrhdPage {
}
impl DrhdPage {
pub fn map(base_phys: usize) -> syscall::Result<Self> {
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 })
+60 -102
View File
@@ -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::<u32>())
thirty_two_bit = sdt
.data()
.chunks(mem::size_of::<u32>())
// TODO: With const generics, the compiler has some way of doing this for static sizes.
.map(|chunk| <[u8; mem::size_of::<u32>()]>::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<Item = u64>
}
b"XSDT" => {
sixty_four_bit = sdt.data().chunks(mem::size_of::<u64>())
sixty_four_bit = sdt
.data()
.chunks(mem::size_of::<u64>())
.map(|chunk| <[u8; mem::size_of::<u64>()]>::try_from(chunk).unwrap())
.map(|chunk| u64::from_le_bytes(chunk));
&mut sixty_four_bit as &mut dyn Iterator<Item = u64>
},
}
_ => 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::<V2>::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::<Packet>() {
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::<Packet>() {
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;
}
}
+147 -119
View File
@@ -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<usize> {
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<u8> {
let hex = hex.to_ascii_lowercase();
@@ -78,7 +80,8 @@ fn parse_hex_digit(hex: u8) -> Option<u8> {
}
fn parse_hex_2digit(hex: &[u8]) -> Option<u8> {
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<SdtSignature> {
}
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<usize> {
fn xopen(&mut self, path: &str, flags: usize, _ctx: &CallerCtx) -> Result<OpenResult> {
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::<Vec<_>>();
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<usize> {
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<isize> {
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<usize> {
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<usize> {
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<usize> {
fn getdents<'buf>(
&mut self,
id: usize,
mut buf: DirentBuf<&'buf mut [u8]>,
opaque_offset: u64,
) -> Result<DirentBuf<&'buf mut [u8]>> {
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<usize> {
Err(Error::new(EBADF))
}
fn close(&mut self, id: usize) -> Result<usize> {
if self.handles.remove(&id).is_none() {
return Err(Error::new(EBADF));