kernel: re-sync ACPI subsystem with upstream master
Phase A of the ACPI fork-sync plan (local/docs/ACPI-FORK-SYNC-STRATEGY-2026-06-30.md). Restores the kernel to the upstream Redox OS kernel main branch state for the ACPI subsystem: - Cargo.toml: switch redox_syscall from 0.7.4 (two versions behind) to a git ref of gitlab.redox-os.org/redox-os/syscall.git, matching the upstream master dependency. The crates.io 0.8.1 release predates the AcpiVerb enum that MR #613 / MR #275 introduced, so a crates.io pin is insufficient. - src/acpi/rsdp.rs: full rewrite to match upstream f49c7d99 (RSDP validation + NonNull + fail-softly): * signature check "RSD PTR " * 20-byte base checksum * full-length checksum for revision >= 2 * NonNull<u8> instead of *const u8 Fixes gap #1 from the 2026-06-30 ACPI assessment: the kernel was accepting any pointer from the bootloader without validation. - src/startup/mod.rs: acpi_rsdp() returns Option<NonNull<u8>> to match the new Rsdp::get_rsdp signature. - src/acpi/mod.rs: init() takes Option<NonNull<u8>>. - src/scheme/acpi.rs: full rewrite to upstream MR #613 (Simplify acpi scheme). Drops the /scheme/kernel.acpi/ filesystem surface in favor of a single Fd::open + call() interface with AcpiVerb verbs: * AcpiVerb::ReadRxsdt - returns the raw RXSDT bytes * AcpiVerb::CheckShutdown - returns whether shutdown is pending Uses HandleBits bitflags, atomic EXISTS_KSTOP_HANDLE, Mutex<L4> from crate::sync::ordered. Replaces /scheme/kernel.acpi/rxsdt and /scheme/kernel.acpi/kstop files. - src/scheme/mod.rs: KernelScheme::kcall signature updated to take fds: &[usize] instead of id: usize (matches upstream). kfpath now has a default body returning EOPNOTSUPP (matches upstream). - src/scheme/memory.rs, proc.rs, user.rs: kcall impls updated to match new trait signature, using fds.first() to extract the single handle for backward compat. - src/scheme/proc.rs: kcall dispatch adds _ => Err(EINVAL) catch-all for the new ProcSchemeVerb variants (RegsInt, RegsFloat, RegsEnv, SchedAffinity, Start) that the gitlab syscall crate adds. These verbs are not yet implemented in the proc scheme; the catch-all returns EINVAL cleanly instead of failing to compile. - src/syscall/fs.rs: SYS_CALL dispatcher now passes &[number] to scheme.kcall() to match the new trait signature. - Makefile: removed -Z json-target-spec flag (promoted to stable in nightly 2026-04-01; the flag is unknown in our pinned toolchain). Verified by `make` in local/sources/kernel/ with PATH including the prefix cross-toolchain: kernel builds and links successfully.
This commit is contained in:
Generated
+2
-3
@@ -201,9 +201,8 @@ checksum = "64072665120942deff5fd5425d6c1811b854f4939e7f1c01ce755f64432bbea7"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "redox_syscall"
|
name = "redox_syscall"
|
||||||
version = "0.7.4"
|
version = "0.8.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "git+https://gitlab.redox-os.org/redox-os/syscall.git#79cb6d9057642be31623677458a93aa88145864f"
|
||||||
checksum = "f450ad9c3b1da563fb6948a8e0fb0fb9269711c9c73d9ea1de5058c79c8d643a"
|
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bitflags 2.11.1",
|
"bitflags 2.11.1",
|
||||||
]
|
]
|
||||||
|
|||||||
+1
-1
@@ -19,7 +19,7 @@ fdt = { git = "https://github.com/repnop/fdt.git", rev = "2fb1409edd1877c714a0aa
|
|||||||
hashbrown = { version = "0.14.3", default-features = false, features = ["ahash", "inline-more"] }
|
hashbrown = { version = "0.14.3", default-features = false, features = ["ahash", "inline-more"] }
|
||||||
linked_list_allocator = "0.9.0"
|
linked_list_allocator = "0.9.0"
|
||||||
redox-path = "0.2.0"
|
redox-path = "0.2.0"
|
||||||
redox_syscall = { version = "0.7.4", default-features = false }
|
redox_syscall = { git = "https://gitlab.redox-os.org/redox-os/syscall.git", default-features = false }
|
||||||
rmm = { path = "rmm", default-features = false }
|
rmm = { path = "rmm", default-features = false }
|
||||||
slab = { version = "0.4", default-features = false }
|
slab = { version = "0.4", default-features = false }
|
||||||
smallvec = { version = "1.15.1", default-features = false }
|
smallvec = { version = "1.15.1", default-features = false }
|
||||||
|
|||||||
+3
-1
@@ -3,6 +3,8 @@
|
|||||||
|
|
||||||
use alloc::{boxed::Box, string::String, vec::Vec};
|
use alloc::{boxed::Box, string::String, vec::Vec};
|
||||||
|
|
||||||
|
use core::ptr::NonNull;
|
||||||
|
|
||||||
use hashbrown::HashMap;
|
use hashbrown::HashMap;
|
||||||
use spin::{Once, RwLock};
|
use spin::{Once, RwLock};
|
||||||
|
|
||||||
@@ -83,7 +85,7 @@ impl Rxsdt for RxsdtEnum {
|
|||||||
pub static RXSDT_ENUM: Once<RxsdtEnum> = Once::new();
|
pub static RXSDT_ENUM: Once<RxsdtEnum> = Once::new();
|
||||||
|
|
||||||
/// Parse the ACPI tables to gather CPU, interrupt, and timer information
|
/// Parse the ACPI tables to gather CPU, interrupt, and timer information
|
||||||
pub unsafe fn init(already_supplied_rsdp: Option<*const u8>) {
|
pub unsafe fn init(already_supplied_rsdp: Option<NonNull<u8>>) {
|
||||||
unsafe {
|
unsafe {
|
||||||
{
|
{
|
||||||
let mut sdt_ptrs = SDT_POINTERS.write();
|
let mut sdt_ptrs = SDT_POINTERS.write();
|
||||||
|
|||||||
+33
-5
@@ -1,3 +1,5 @@
|
|||||||
|
use core::ptr::NonNull;
|
||||||
|
|
||||||
use rmm::PhysicalAddress;
|
use rmm::PhysicalAddress;
|
||||||
|
|
||||||
/// RSDP
|
/// RSDP
|
||||||
@@ -9,17 +11,43 @@ pub struct Rsdp {
|
|||||||
_oemid: [u8; 6],
|
_oemid: [u8; 6],
|
||||||
revision: u8,
|
revision: u8,
|
||||||
rsdt_address: u32,
|
rsdt_address: u32,
|
||||||
_length: u32,
|
length: u32,
|
||||||
xsdt_address: u64,
|
xsdt_address: u64,
|
||||||
_extended_checksum: u8,
|
_extended_checksum: u8,
|
||||||
_reserved: [u8; 3],
|
_reserved: [u8; 3],
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Rsdp {
|
impl Rsdp {
|
||||||
pub unsafe fn get_rsdp(already_supplied_rsdp: Option<*const u8>) -> Option<Rsdp> {
|
pub unsafe fn get_rsdp(already_supplied_rsdp: Option<NonNull<u8>>) -> Option<Rsdp> {
|
||||||
already_supplied_rsdp.map(|rsdp_ptr| {
|
already_supplied_rsdp.and_then(|rsdp_ptr: NonNull<u8>| {
|
||||||
// TODO: Validate
|
let rsdp: Rsdp = unsafe { rsdp_ptr.cast().read() };
|
||||||
unsafe { *(rsdp_ptr as *const Rsdp) }
|
|
||||||
|
if rsdp.signature != *b"RSD PTR " {
|
||||||
|
error!("RSDP signature check failed");
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut sum: u8 = 0;
|
||||||
|
for i in 0..20 {
|
||||||
|
sum = sum.wrapping_add(unsafe { rsdp_ptr.add(i).read() });
|
||||||
|
}
|
||||||
|
if sum != 0 {
|
||||||
|
error!("RSDP checksum failed");
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
|
||||||
|
if rsdp.revision >= 2 {
|
||||||
|
let mut sum: u8 = 0;
|
||||||
|
for i in 0..rsdp.length as usize {
|
||||||
|
sum = sum.wrapping_add(unsafe { rsdp_ptr.add(i).read() });
|
||||||
|
}
|
||||||
|
if sum != 0 {
|
||||||
|
error!("XSDP checksum failed");
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Some(rsdp)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+79
-257
@@ -1,78 +1,59 @@
|
|||||||
use alloc::{boxed::Box, vec::Vec};
|
use alloc::boxed::Box;
|
||||||
use core::convert::TryInto;
|
use core::sync::atomic::{AtomicBool, Ordering};
|
||||||
|
|
||||||
use spin::{Mutex, Once};
|
use crate::sync::ordered::{Mutex, L4};
|
||||||
use syscall::{
|
use spin::Once;
|
||||||
data::GlobalSchemes,
|
|
||||||
dirent::{DirEntry, DirentBuf, DirentKind},
|
use syscall::data::GlobalSchemes;
|
||||||
EIO,
|
|
||||||
};
|
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
acpi::{RxsdtEnum, RXSDT_ENUM},
|
acpi::{RxsdtEnum, RXSDT_ENUM},
|
||||||
context::file::InternalFlags,
|
context::file::InternalFlags,
|
||||||
event,
|
scheme::{SchemeExt, StrOrBytes},
|
||||||
sync::{CleanLockToken, RwLock, WaitCondition, L1},
|
sync::CleanLockToken,
|
||||||
};
|
};
|
||||||
|
|
||||||
use crate::syscall::{
|
use crate::syscall::{
|
||||||
data::Stat,
|
error::{Error, Result, EACCES, EBADFD, EINVAL, ENOENT},
|
||||||
error::{Error, Result, EACCES, EBADF, EBADFD, EINTR, EINVAL, EISDIR, ENOENT, ENOTDIR, EROFS},
|
flag::{AcpiVerb, CallFlags, EventFlags},
|
||||||
flag::{
|
usercopy::UserSliceRw,
|
||||||
EventFlags, EVENT_READ, MODE_CHR, MODE_DIR, MODE_FILE, O_ACCMODE, O_CREAT, O_DIRECTORY,
|
|
||||||
O_EXCL, O_RDONLY, O_STAT, O_SYMLINK,
|
|
||||||
},
|
|
||||||
usercopy::UserSliceWo,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
use super::{CallerCtx, HandleMap, KernelScheme, OpenResult, SchemeExt, StrOrBytes};
|
use super::{CallerCtx, KernelScheme, OpenResult};
|
||||||
|
|
||||||
/// A scheme used to access the RSDT or XSDT, which is needed for e.g. `acpid` to function.
|
/// A scheme used to access the RSDT or XSDT, and listen for shutdown, which is needed for e.g. `acpid` to function.
|
||||||
pub struct AcpiScheme;
|
pub struct AcpiScheme;
|
||||||
|
|
||||||
#[derive(Clone, Copy)]
|
bitflags! {
|
||||||
struct Handle {
|
#[derive(PartialEq)]
|
||||||
kind: HandleKind,
|
struct HandleBits: usize {
|
||||||
stat: bool,
|
const CAN_READ_RXSDT = 1;
|
||||||
}
|
const CAN_REGISTER_KSTOP = 2;
|
||||||
#[derive(Clone, Copy, Eq, PartialEq)]
|
|
||||||
enum HandleKind {
|
// mutually exclusive with the other flags
|
||||||
TopLevel,
|
const KSTOP_HANDLE = 4;
|
||||||
Rxsdt,
|
}
|
||||||
ShutdownPipe,
|
|
||||||
SchemeRoot,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static HANDLES: RwLock<L1, HandleMap<Handle>> = RwLock::new(HandleMap::new());
|
static RXSDT_DATA: Once<Box<[u8]>> = Once::new();
|
||||||
|
|
||||||
static DATA: Once<Box<[u8]>> = Once::new();
|
static KSTOP_FLAG: Mutex<L4, bool> = Mutex::new(false);
|
||||||
|
static EXISTS_KSTOP_HANDLE: AtomicBool = AtomicBool::new(false);
|
||||||
static KSTOP_WAITCOND: WaitCondition = WaitCondition::new();
|
|
||||||
static KSTOP_FLAG: Mutex<bool> = Mutex::new(false);
|
|
||||||
|
|
||||||
pub fn register_kstop(token: &mut CleanLockToken) -> bool {
|
pub fn register_kstop(token: &mut CleanLockToken) -> bool {
|
||||||
*KSTOP_FLAG.lock() = true;
|
*KSTOP_FLAG.lock(token.token()) = true;
|
||||||
let mut waiters_awoken = KSTOP_WAITCOND.notify(token);
|
|
||||||
|
|
||||||
let fds: Vec<usize> = {
|
if !EXISTS_KSTOP_HANDLE.load(Ordering::Relaxed) {
|
||||||
HANDLES
|
|
||||||
.read(token.token())
|
|
||||||
.iter()
|
|
||||||
.filter(|(_, handle)| handle.kind == HandleKind::ShutdownPipe)
|
|
||||||
.map(|(fd, _)| *fd)
|
|
||||||
.collect()
|
|
||||||
};
|
|
||||||
|
|
||||||
for fd in fds {
|
|
||||||
event::trigger(GlobalSchemes::Acpi.scheme_id(), fd, EVENT_READ, token);
|
|
||||||
waiters_awoken += 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if waiters_awoken == 0 {
|
|
||||||
error!("No userspace ACPI handler was notified when trying to shutdown. This is bad.");
|
error!("No userspace ACPI handler was notified when trying to shutdown. This is bad.");
|
||||||
// Let the kernel shutdown without ACPI.
|
// Let the kernel shutdown without ACPI.
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
crate::event::trigger(
|
||||||
|
GlobalSchemes::Acpi.scheme_id(),
|
||||||
|
HandleBits::KSTOP_HANDLE.bits(),
|
||||||
|
EventFlags::EVENT_READ,
|
||||||
|
token,
|
||||||
|
);
|
||||||
|
|
||||||
// TODO: Context switch directly to the waiting context, to avoid annoying timeouts.
|
// TODO: Context switch directly to the waiting context, to avoid annoying timeouts.
|
||||||
true
|
true
|
||||||
@@ -86,7 +67,7 @@ impl AcpiScheme {
|
|||||||
|
|
||||||
let mut data_init = false;
|
let mut data_init = false;
|
||||||
|
|
||||||
DATA.call_once(|| {
|
RXSDT_DATA.call_once(|| {
|
||||||
data_init = true;
|
data_init = true;
|
||||||
|
|
||||||
let table = match RXSDT_ENUM.get() {
|
let table = match RXSDT_ENUM.get() {
|
||||||
@@ -108,229 +89,70 @@ impl AcpiScheme {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl KernelScheme for AcpiScheme {
|
impl KernelScheme for AcpiScheme {
|
||||||
fn scheme_root(&self, token: &mut CleanLockToken) -> Result<usize> {
|
fn scheme_root(&self, _token: &mut CleanLockToken) -> Result<usize> {
|
||||||
let fd = HANDLES.write(token.token()).insert(Handle {
|
Ok((HandleBits::CAN_READ_RXSDT | HandleBits::CAN_REGISTER_KSTOP).bits())
|
||||||
kind: HandleKind::SchemeRoot,
|
|
||||||
stat: false,
|
|
||||||
});
|
|
||||||
|
|
||||||
Ok(fd)
|
|
||||||
}
|
}
|
||||||
fn kopenat(
|
fn kopenat(
|
||||||
&self,
|
&self,
|
||||||
id: usize,
|
id: usize,
|
||||||
user_buf: StrOrBytes,
|
path: StrOrBytes,
|
||||||
flags: usize,
|
_flags: usize,
|
||||||
_fcntl_flags: u32,
|
_fcntl_flags: u32,
|
||||||
ctx: CallerCtx,
|
caller: CallerCtx,
|
||||||
token: &mut CleanLockToken,
|
_token: &mut CleanLockToken,
|
||||||
) -> Result<OpenResult> {
|
) -> Result<OpenResult> {
|
||||||
if !matches!(
|
let bits = HandleBits::from_bits_retain(id);
|
||||||
HANDLES.read(token.token()).get(id)?.kind,
|
|
||||||
HandleKind::SchemeRoot
|
let new_bits = match path.as_bytes() {
|
||||||
) {
|
b"" | b"/" => bits,
|
||||||
|
b"kstop" | b"/kstop" => {
|
||||||
|
// TODO: can the uid check be removed?
|
||||||
|
if caller.uid != 0 || !bits.contains(HandleBits::CAN_REGISTER_KSTOP) {
|
||||||
return Err(Error::new(EACCES));
|
return Err(Error::new(EACCES));
|
||||||
}
|
}
|
||||||
|
EXISTS_KSTOP_HANDLE.store(true, Ordering::Relaxed);
|
||||||
let path = user_buf
|
HandleBits::KSTOP_HANDLE
|
||||||
.as_str()
|
|
||||||
.or(Err(Error::new(EINVAL)))?
|
|
||||||
.trim_start_matches('/');
|
|
||||||
|
|
||||||
if ctx.uid != 0 {
|
|
||||||
return Err(Error::new(EACCES));
|
|
||||||
}
|
|
||||||
if flags & O_CREAT == O_CREAT {
|
|
||||||
return Err(Error::new(EROFS));
|
|
||||||
}
|
|
||||||
if flags & O_EXCL == O_EXCL || flags & O_SYMLINK == O_SYMLINK {
|
|
||||||
return Err(Error::new(EINVAL));
|
|
||||||
}
|
|
||||||
if flags & O_ACCMODE != O_RDONLY && flags & O_STAT != O_STAT {
|
|
||||||
return Err(Error::new(EROFS));
|
|
||||||
}
|
|
||||||
let (handle_kind, int_flags) = match path {
|
|
||||||
"" => {
|
|
||||||
if flags & O_DIRECTORY != O_DIRECTORY && flags & O_STAT != O_STAT {
|
|
||||||
return Err(Error::new(EISDIR));
|
|
||||||
}
|
|
||||||
|
|
||||||
(HandleKind::TopLevel, InternalFlags::POSITIONED)
|
|
||||||
}
|
|
||||||
"rxsdt" => {
|
|
||||||
if flags & O_DIRECTORY == O_DIRECTORY && flags & O_STAT != O_STAT {
|
|
||||||
return Err(Error::new(ENOTDIR));
|
|
||||||
}
|
|
||||||
(HandleKind::Rxsdt, InternalFlags::POSITIONED)
|
|
||||||
}
|
|
||||||
"kstop" => {
|
|
||||||
if flags & O_DIRECTORY == O_DIRECTORY && flags & O_STAT != O_STAT {
|
|
||||||
return Err(Error::new(ENOTDIR));
|
|
||||||
}
|
|
||||||
(HandleKind::ShutdownPipe, InternalFlags::empty())
|
|
||||||
}
|
}
|
||||||
_ => return Err(Error::new(ENOENT)),
|
_ => return Err(Error::new(ENOENT)),
|
||||||
};
|
};
|
||||||
|
Ok(OpenResult::SchemeLocal(
|
||||||
let fd = HANDLES.write(token.token()).insert(Handle {
|
new_bits.bits(),
|
||||||
kind: handle_kind,
|
InternalFlags::empty(),
|
||||||
// TODO: Redundant
|
))
|
||||||
stat: flags & O_STAT == O_STAT,
|
|
||||||
});
|
|
||||||
|
|
||||||
Ok(OpenResult::SchemeLocal(fd, int_flags))
|
|
||||||
}
|
}
|
||||||
fn fsize(&self, id: usize, token: &mut CleanLockToken) -> Result<u64> {
|
fn kcall(
|
||||||
let mut handles = HANDLES.write(token.token());
|
|
||||||
let handle = handles.get_mut(id)?;
|
|
||||||
|
|
||||||
if handle.stat {
|
|
||||||
return Err(Error::new(EBADF));
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok(match handle.kind {
|
|
||||||
HandleKind::Rxsdt => DATA.get().ok_or(Error::new(EBADFD))?.len() as u64,
|
|
||||||
HandleKind::ShutdownPipe => 1,
|
|
||||||
HandleKind::TopLevel => 0,
|
|
||||||
HandleKind::SchemeRoot => return Err(Error::new(EBADF))?,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
// TODO
|
|
||||||
fn fevent(
|
|
||||||
&self,
|
&self,
|
||||||
id: usize,
|
fds: &[usize],
|
||||||
_flags: EventFlags,
|
payload: UserSliceRw,
|
||||||
token: &mut CleanLockToken,
|
flags: CallFlags,
|
||||||
) -> Result<EventFlags> {
|
metadata: &[u64],
|
||||||
let handles = HANDLES.read(token.token());
|
|
||||||
let handle = handles.get(id)?;
|
|
||||||
|
|
||||||
if handle.stat {
|
|
||||||
return Err(Error::new(EBADF));
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok(EventFlags::empty())
|
|
||||||
}
|
|
||||||
fn close(&self, id: usize, token: &mut CleanLockToken) -> Result<()> {
|
|
||||||
HANDLES.write(token.token()).remove(id)?;
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
fn kreadoff(
|
|
||||||
&self,
|
|
||||||
id: usize,
|
|
||||||
dst_buf: UserSliceWo,
|
|
||||||
offset: u64,
|
|
||||||
_flags: u32,
|
|
||||||
_stored_flags: u32,
|
|
||||||
token: &mut CleanLockToken,
|
token: &mut CleanLockToken,
|
||||||
) -> Result<usize> {
|
) -> Result<usize> {
|
||||||
let Ok(offset) = usize::try_from(offset) else {
|
let [handle] = <&[usize; 1]>::try_from(fds)
|
||||||
return Ok(0);
|
.map_err(|_| Error::new(EINVAL))?
|
||||||
};
|
.map(HandleBits::from_bits_retain);
|
||||||
|
let verb = metadata
|
||||||
|
.get(0)
|
||||||
|
.copied()
|
||||||
|
.and_then(AcpiVerb::try_from_raw)
|
||||||
|
.ok_or(Error::new(EINVAL))?;
|
||||||
|
|
||||||
let handle = *HANDLES.read(token.token()).get(id)?;
|
match verb {
|
||||||
|
AcpiVerb::ReadRxsdt => {
|
||||||
if handle.stat {
|
if !handle.contains(HandleBits::CAN_READ_RXSDT) || !flags.contains(CallFlags::READ)
|
||||||
return Err(Error::new(EBADF));
|
{
|
||||||
|
return Err(Error::new(EINVAL));
|
||||||
}
|
}
|
||||||
|
let src = RXSDT_DATA.get().ok_or(Error::new(EBADFD))?;
|
||||||
let data = match handle.kind {
|
payload.copy_common_bytes_from_slice(src)?;
|
||||||
HandleKind::ShutdownPipe => {
|
Ok(src.len())
|
||||||
if dst_buf.is_empty() {
|
|
||||||
return Ok(0);
|
|
||||||
}
|
}
|
||||||
|
AcpiVerb::CheckShutdown => {
|
||||||
loop {
|
if handle != HandleBits::KSTOP_HANDLE {
|
||||||
let flag_guard = KSTOP_FLAG.lock();
|
return Err(Error::new(EINVAL));
|
||||||
let mut token = token.downgrade();
|
}
|
||||||
|
Ok(usize::from(*KSTOP_FLAG.lock(token.token())))
|
||||||
if *flag_guard {
|
|
||||||
break;
|
|
||||||
} else if !KSTOP_WAITCOND.wait(flag_guard, "waiting for kstop", &mut token) {
|
|
||||||
return Err(Error::new(EINTR));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return dst_buf.copy_exactly(&[0x42]).map(|()| 1);
|
|
||||||
}
|
|
||||||
HandleKind::Rxsdt => DATA.get().ok_or(Error::new(EBADFD))?,
|
|
||||||
HandleKind::TopLevel => return Err(Error::new(EISDIR)),
|
|
||||||
HandleKind::SchemeRoot => return Err(Error::new(EBADF)),
|
|
||||||
};
|
|
||||||
|
|
||||||
let src_offset = core::cmp::min(offset, data.len());
|
|
||||||
let src_buf = data
|
|
||||||
.get(src_offset..)
|
|
||||||
.expect("expected data to be at least data.len() bytes long");
|
|
||||||
|
|
||||||
dst_buf.copy_common_bytes_from_slice(src_buf)
|
|
||||||
}
|
|
||||||
fn getdents(
|
|
||||||
&self,
|
|
||||||
id: usize,
|
|
||||||
buf: UserSliceWo,
|
|
||||||
header_size: u16,
|
|
||||||
opaque: u64,
|
|
||||||
token: &mut CleanLockToken,
|
|
||||||
) -> Result<usize> {
|
|
||||||
let Handle {
|
|
||||||
kind: HandleKind::TopLevel,
|
|
||||||
..
|
|
||||||
} = HANDLES.read(token.token()).get(id)?
|
|
||||||
else {
|
|
||||||
return Err(Error::new(ENOTDIR));
|
|
||||||
};
|
|
||||||
|
|
||||||
let mut buf = DirentBuf::new(buf, header_size).ok_or(Error::new(EIO))?;
|
|
||||||
if opaque == 0 {
|
|
||||||
buf.entry(DirEntry {
|
|
||||||
kind: DirentKind::Regular,
|
|
||||||
name: "rxsdt",
|
|
||||||
inode: 0,
|
|
||||||
next_opaque_id: 1,
|
|
||||||
})?;
|
|
||||||
}
|
|
||||||
if opaque <= 1 {
|
|
||||||
buf.entry(DirEntry {
|
|
||||||
kind: DirentKind::Socket,
|
|
||||||
name: "kstop",
|
|
||||||
inode: 0,
|
|
||||||
next_opaque_id: u64::MAX,
|
|
||||||
})?;
|
|
||||||
}
|
|
||||||
Ok(buf.finalize())
|
|
||||||
}
|
|
||||||
fn kfpath(&self, _id: usize, buf: UserSliceWo, _token: &mut CleanLockToken) -> Result<usize> {
|
|
||||||
//TODO: construct useful path?
|
|
||||||
buf.copy_common_bytes_from_slice("/scheme/kernel.acpi/".as_bytes())
|
|
||||||
}
|
|
||||||
fn kfstat(&self, id: usize, buf: UserSliceWo, token: &mut CleanLockToken) -> Result<()> {
|
|
||||||
let handles = HANDLES.read(token.token());
|
|
||||||
let handle = handles.get(id)?;
|
|
||||||
|
|
||||||
buf.copy_exactly(&match handle.kind {
|
|
||||||
HandleKind::Rxsdt => {
|
|
||||||
let data = DATA.get().ok_or(Error::new(EBADFD))?;
|
|
||||||
|
|
||||||
Stat {
|
|
||||||
st_mode: MODE_FILE,
|
|
||||||
st_size: data.len().try_into().unwrap_or(u64::MAX),
|
|
||||||
..Default::default()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
HandleKind::TopLevel => Stat {
|
|
||||||
st_mode: MODE_DIR,
|
|
||||||
st_size: 0,
|
|
||||||
..Default::default()
|
|
||||||
},
|
|
||||||
HandleKind::ShutdownPipe => Stat {
|
|
||||||
st_mode: MODE_CHR,
|
|
||||||
st_size: 1,
|
|
||||||
..Default::default()
|
|
||||||
},
|
|
||||||
HandleKind::SchemeRoot => return Err(Error::new(EBADF)),
|
|
||||||
})?;
|
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -249,12 +249,13 @@ impl KernelScheme for MemoryScheme {
|
|||||||
}
|
}
|
||||||
fn kcall(
|
fn kcall(
|
||||||
&self,
|
&self,
|
||||||
id: usize,
|
fds: &[usize],
|
||||||
payload: UserSliceRw,
|
payload: UserSliceRw,
|
||||||
_flags: syscall::CallFlags,
|
_flags: syscall::CallFlags,
|
||||||
_metadata: &[u64],
|
_metadata: &[u64],
|
||||||
token: &mut CleanLockToken,
|
token: &mut CleanLockToken,
|
||||||
) -> Result<usize> {
|
) -> Result<usize> {
|
||||||
|
let id = fds.first().copied().ok_or(Error::new(EINVAL))?;
|
||||||
let (handle_ty, _, _) = u32::try_from(id)
|
let (handle_ty, _, _) = u32::try_from(id)
|
||||||
.ok()
|
.ok()
|
||||||
.and_then(from_raw)
|
.and_then(from_raw)
|
||||||
|
|||||||
+4
-2
@@ -590,7 +590,9 @@ pub trait KernelScheme: Send + Sync + 'static {
|
|||||||
) -> Result<usize> {
|
) -> Result<usize> {
|
||||||
Err(Error::new(EBADF))
|
Err(Error::new(EBADF))
|
||||||
}
|
}
|
||||||
fn kfpath(&self, id: usize, buf: UserSliceWo, token: &mut CleanLockToken) -> Result<usize>;
|
fn kfpath(&self, id: usize, buf: UserSliceWo, token: &mut CleanLockToken) -> Result<usize> {
|
||||||
|
Err(Error::new(EOPNOTSUPP))
|
||||||
|
}
|
||||||
fn kfutimens(&self, id: usize, buf: UserSliceRo, token: &mut CleanLockToken) -> Result<usize> {
|
fn kfutimens(&self, id: usize, buf: UserSliceRo, token: &mut CleanLockToken) -> Result<usize> {
|
||||||
Err(Error::new(EBADF))
|
Err(Error::new(EBADF))
|
||||||
}
|
}
|
||||||
@@ -686,7 +688,7 @@ pub trait KernelScheme: Send + Sync + 'static {
|
|||||||
}
|
}
|
||||||
fn kcall(
|
fn kcall(
|
||||||
&self,
|
&self,
|
||||||
id: usize,
|
fds: &[usize],
|
||||||
payload: UserSliceRw,
|
payload: UserSliceRw,
|
||||||
flags: CallFlags,
|
flags: CallFlags,
|
||||||
metadata: &[u64],
|
metadata: &[u64],
|
||||||
|
|||||||
+3
-1
@@ -632,12 +632,13 @@ impl KernelScheme for ProcScheme {
|
|||||||
}
|
}
|
||||||
fn kcall(
|
fn kcall(
|
||||||
&self,
|
&self,
|
||||||
id: usize,
|
fds: &[usize],
|
||||||
_payload: UserSliceRw,
|
_payload: UserSliceRw,
|
||||||
_flags: CallFlags,
|
_flags: CallFlags,
|
||||||
metadata: &[u64],
|
metadata: &[u64],
|
||||||
token: &mut CleanLockToken,
|
token: &mut CleanLockToken,
|
||||||
) -> Result<usize> {
|
) -> Result<usize> {
|
||||||
|
let id = fds.first().copied().ok_or(Error::new(EINVAL))?;
|
||||||
// TODO: simplify
|
// TODO: simplify
|
||||||
let handle = {
|
let handle = {
|
||||||
let mut handles = HANDLES.write(token.token());
|
let mut handles = HANDLES.write(token.token());
|
||||||
@@ -658,6 +659,7 @@ impl KernelScheme for ProcScheme {
|
|||||||
ProcSchemeVerb::Iopl => context::current()
|
ProcSchemeVerb::Iopl => context::current()
|
||||||
.write(token.token())
|
.write(token.token())
|
||||||
.set_userspace_io_allowed(true),
|
.set_userspace_io_allowed(true),
|
||||||
|
_ => return Err(Error::new(EINVAL)),
|
||||||
}
|
}
|
||||||
Ok(0)
|
Ok(0)
|
||||||
}
|
}
|
||||||
|
|||||||
+2
-1
@@ -1929,12 +1929,13 @@ impl KernelScheme for UserScheme {
|
|||||||
}
|
}
|
||||||
fn kcall(
|
fn kcall(
|
||||||
&self,
|
&self,
|
||||||
id: usize,
|
fds: &[usize],
|
||||||
payload: UserSliceRw,
|
payload: UserSliceRw,
|
||||||
_flags: CallFlags,
|
_flags: CallFlags,
|
||||||
metadata: &[u64],
|
metadata: &[u64],
|
||||||
token: &mut CleanLockToken,
|
token: &mut CleanLockToken,
|
||||||
) -> Result<usize> {
|
) -> Result<usize> {
|
||||||
|
let id = fds.first().copied().ok_or(Error::new(EINVAL))?;
|
||||||
let inner = self.inner.clone();
|
let inner = self.inner.clone();
|
||||||
|
|
||||||
let mut address = inner.capture_user(payload, token)?;
|
let mut address = inner.capture_user(payload, token)?;
|
||||||
|
|||||||
+3
-2
@@ -2,6 +2,7 @@ use core::{
|
|||||||
hint, slice,
|
hint, slice,
|
||||||
sync::atomic::{AtomicBool, Ordering},
|
sync::atomic::{AtomicBool, Ordering},
|
||||||
};
|
};
|
||||||
|
use core::ptr::NonNull;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
arch::interrupt,
|
arch::interrupt,
|
||||||
@@ -94,7 +95,7 @@ impl KernelArgs {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn acpi_rsdp(&self) -> Option<*const u8> {
|
pub(crate) fn acpi_rsdp(&self) -> Option<NonNull<u8>> {
|
||||||
if self.hwdesc_base != 0 {
|
if self.hwdesc_base != 0 {
|
||||||
let data = unsafe {
|
let data = unsafe {
|
||||||
slice::from_raw_parts(
|
slice::from_raw_parts(
|
||||||
@@ -104,7 +105,7 @@ impl KernelArgs {
|
|||||||
)
|
)
|
||||||
};
|
};
|
||||||
if data.starts_with(b"RSD PTR ") {
|
if data.starts_with(b"RSD PTR ") {
|
||||||
Some(data.as_ptr())
|
Some(NonNull::new(data.as_ptr() as *mut u8).unwrap())
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
|
|||||||
+1
-1
@@ -305,7 +305,7 @@ fn call_normal(
|
|||||||
if flags.contains(CallFlags::STD_FS) {
|
if flags.contains(CallFlags::STD_FS) {
|
||||||
scheme.translate_std_fs_call(number, file.description, payload, flags, metadata, token)
|
scheme.translate_std_fs_call(number, file.description, payload, flags, metadata, token)
|
||||||
} else {
|
} else {
|
||||||
scheme.kcall(number, payload, flags, metadata, token)
|
scheme.kcall(&[number], payload, flags, metadata, token)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user