Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implements syscall 54 #384

Merged
merged 1 commit into from
Oct 4, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
29 changes: 27 additions & 2 deletions src/kernel/src/console/mod.rs
Original file line number Diff line number Diff line change
@@ -1,13 +1,38 @@
use crate::fs::VFileOps;
use crate::errno::Errno;
use crate::fs::{VFile, VFileOps, VPath};
use crate::process::VThread;
use crate::ucred::Ucred;
use macros::vpath;
use std::fmt::{Display, Formatter};

/// An implementation of `/dev/console`.
#[derive(Debug)]
pub struct Console {}

impl Console {
pub const PATH: &VPath = vpath!("/dev/console");

pub fn new() -> Self {
Self {}
}
}

impl VFileOps for Console {}
impl VFileOps for Console {
fn ioctl(
&self,
file: &VFile,
com: u64,
data: &[u8],
cred: &Ucred,
td: &VThread,
) -> Result<(), Box<dyn Errno>> {
// TODO: Implement this.
Ok(())
}
}

impl Display for Console {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
Self::PATH.fmt(f)
}
}
52 changes: 49 additions & 3 deletions src/kernel/src/fs/file.rs
Original file line number Diff line number Diff line change
@@ -1,22 +1,44 @@
use super::Fs;
use std::fmt::Debug;
use crate::errno::Errno;
use crate::process::VThread;
use crate::ucred::Ucred;
use bitflags::bitflags;
use std::fmt::{Debug, Display, Formatter};
use std::ops::Deref;
use std::sync::atomic::Ordering;

/// An implementation of `file` structure.
#[derive(Debug)]
pub struct VFile<'a> {
fs: &'a Fs,
ops: Option<Box<dyn VFileOps + 'a>>, // f_data + f_ops
flags: VFileFlags, // f_flag
}

impl<'a> VFile<'a> {
pub(super) fn new(fs: &'a Fs) -> Self {
Self { fs, ops: None }
Self {
fs,
flags: VFileFlags::empty(),
ops: None,
}
}

pub fn ops(&self) -> Option<&dyn VFileOps> {
self.ops.as_ref().map(|o| o.deref())
}

pub fn set_ops(&mut self, v: Option<Box<dyn VFileOps + 'a>>) {
self.ops = v;
}

pub fn flags(&self) -> VFileFlags {
self.flags
}

pub fn flags_mut(&mut self) -> &mut VFileFlags {
&mut self.flags
}
}

impl<'a> Drop for VFile<'a> {
Expand All @@ -25,5 +47,29 @@ impl<'a> Drop for VFile<'a> {
}
}

impl<'a> Display for VFile<'a> {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
Display::fmt(self.ops.as_ref().unwrap(), f)
}
}

/// An implementation of `fileops` structure.
pub trait VFileOps: Debug + Send + Sync {}
pub trait VFileOps: Debug + Send + Sync + Display {
fn ioctl(
&self,
file: &VFile,
com: u64,
data: &[u8],
cred: &Ucred,
td: &VThread,
) -> Result<(), Box<dyn Errno>>;
}

bitflags! {
/// Flags for [`VFile`].
#[derive(Debug, Clone, Copy)]
pub struct VFileFlags: u32 {
const FREAD = 0x00000001;
const FWRITE = 0x00000002;
}
}
3 changes: 1 addition & 2 deletions src/kernel/src/fs/item.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
use super::{Fs, FsError, VFileOps, VPath, VPathBuf};
use crate::console::Console;
use macros::vpath;
use std::path::{Path, PathBuf};

/// An item in the virtual filesystem.
Expand All @@ -25,7 +24,7 @@ impl<'a> FsItem<'a> {
Self::Directory(v) => &v.vpath,
Self::File(v) => &v.vpath,
Self::Device(d) => match d {
VDev::Console(_) => vpath!("/dev/console"),
VDev::Console(_) => Console::PATH,
},
}
}
Expand Down
17 changes: 15 additions & 2 deletions src/kernel/src/process/file.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ use std::sync::Arc;
/// An implementation of `filedesc` structure.
#[derive(Debug)]
pub struct VProcFiles {
files: GroupMutex<Vec<Option<VFile<'static>>>>, // fd_ofiles
files: GroupMutex<Vec<Option<Arc<VFile<'static>>>>>, // fd_ofiles
}

impl VProcFiles {
Expand All @@ -16,7 +16,7 @@ impl VProcFiles {
}

/// See `finstall` on the PS4 for a reference.
pub fn alloc(&self, file: VFile<'static>) -> i32 {
pub fn alloc(&self, file: Arc<VFile<'static>>) -> i32 {
// TODO: Implement fdalloc.
let mut files = self.files.write();

Expand All @@ -37,4 +37,17 @@ impl VProcFiles {
// This should never happened.
panic!("Too many files has been opened.");
}

/// See `fget` on the PS4 for a reference.
pub fn get(&self, fd: i32) -> Option<Arc<VFile<'static>>> {
// TODO: Check what we have missed here.
if fd < 0 {
return None;
}

let fd: usize = fd.try_into().unwrap();
let files = self.files.read();

files.get(fd)?.clone()
}
}
6 changes: 6 additions & 0 deletions src/kernel/src/syscalls/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,12 @@ impl Error {
}
}

impl From<Box<dyn Errno>> for Error {
fn from(value: Box<dyn Errno>) -> Self {
Self::Object(value)
}
}

impl<T: Errno + 'static> From<T> for Error {
fn from(value: T) -> Self {
Self::Object(Box::new(value))
Expand Down
15 changes: 14 additions & 1 deletion src/kernel/src/syscalls/input.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use crate::fs::VPathBuf;
use crate::fs::{VFileFlags, VPathBuf};
use bitflags::bitflags;
use std::fmt::{Display, Formatter};
use std::num::TryFromIntError;
Expand Down Expand Up @@ -29,6 +29,12 @@ impl<T> From<Arg> for *mut T {
}
}

impl From<Arg> for u64 {
fn from(v: Arg) -> Self {
v.0 as _
}
}

impl From<Arg> for usize {
fn from(v: Arg) -> Self {
v.0
Expand Down Expand Up @@ -82,6 +88,13 @@ bitflags! {
}
}

impl OpenFlags {
/// An implementation of `FFLAGS` macro.
pub fn to_fflags(self) -> VFileFlags {
VFileFlags::from_bits_truncate(self.bits() + 1)
}
}

impl TryFrom<Arg> for OpenFlags {
type Error = TryFromIntError;

Expand Down
79 changes: 76 additions & 3 deletions src/kernel/src/syscalls/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,10 @@ pub use input::*;
pub use output::*;

use self::error::Error;
use crate::errno::{EFAULT, EINVAL, ENAMETOOLONG, ENOENT, ENOMEM, ENOSYS, EPERM, ESRCH};
use crate::fs::{Fs, VPath, VPathBuf};
use crate::errno::{
EBADF, EFAULT, EINVAL, ENAMETOOLONG, ENOENT, ENOMEM, ENOSYS, ENOTTY, EPERM, ESRCH,
};
use crate::fs::{Fs, VFileFlags, VPath, VPathBuf};
use crate::log::print;
use crate::memory::{MappingFlags, MemoryManager, Protections};
use crate::process::{NamedObj, ProcObj, VProc, VProcGroup, VSession, VThread};
Expand Down Expand Up @@ -72,6 +74,11 @@ impl Syscalls {
),
20 => self.getpid(),
50 => self.setlogin(i.args[0].into()),
54 => self.ioctl(
i.args[0].try_into().unwrap(),
i.args[1].into(),
i.args[2].into(),
),
56 => self.revoke(i.args[0].into()),
147 => self.setsid(),
202 => self.sysctl(
Expand Down Expand Up @@ -179,10 +186,11 @@ impl Syscalls {
info!("Opening {path} with {flags}.");

// Lookup file.
*file.flags_mut() = flags.to_fflags();
file.set_ops(Some(self.fs.get(path)?.open()?));

// Install to descriptor table.
let fd = self.vp.files().alloc(file);
let fd = self.vp.files().alloc(Arc::new(file));

info!("File descriptor {fd} was allocated for {path}.");

Expand Down Expand Up @@ -216,6 +224,71 @@ impl Syscalls {
Ok(Output::ZERO)
}

unsafe fn ioctl(&self, fd: i32, mut com: u64, data: *const u8) -> Result<Output, Error> {
const IOC_VOID: u64 = 0x20000000;
const IOC_OUT: u64 = 0x40000000;
const IOC_IN: u64 = 0x80000000;
const IOCPARM_MASK: u64 = 0x1FFF;

if com > 0xffffffff {
com &= 0xffffffff;
}

let size = (com >> 16) & IOCPARM_MASK;

if com & (IOC_VOID | IOC_OUT | IOC_IN) == 0
|| com & (IOC_OUT | IOC_IN) != 0 && size == 0
|| com & IOC_VOID != 0 && size != 0 && size != 4
{
return Err(Error::Raw(ENOTTY));
}

// Get data.
let data = if size == 0 {
if com & IOC_IN != 0 {
todo!("ioctl with IOC_IN");
} else if com & IOC_OUT != 0 {
todo!("ioctl with IOC_OUT");
}

&[]
} else {
todo!("ioctl with size != 0");
};

// Get target file.
let file = self.vp.files().get(fd).ok_or(Error::Raw(EBADF))?;
let ops = file.ops().ok_or(Error::Raw(EBADF))?;

if !file
.flags()
.intersects(VFileFlags::FREAD | VFileFlags::FWRITE)
{
return Err(Error::Raw(EBADF));
}

// Execute the operation.
let td = VThread::current();

info!("Executing ioctl({com:#x}) on {file}.");

match com {
0x20006601 => todo!("ioctl with com = 0x20006601"),
0x20006602 => todo!("ioctl with com = 0x20006602"),
0x8004667d => todo!("ioctl with com = 0x8004667d"),
0x8004667e => todo!("ioctl with com = 0x8004667e"),
_ => {}
}

ops.ioctl(&file, com, data, td.cred(), &td)?;

if com & IOC_OUT != 0 {
todo!("ioctl with IOC_OUT");
}

Ok(Output::ZERO)
}

unsafe fn revoke(&self, path: *const c_char) -> Result<Output, Error> {
// Check current thread privilege.
VThread::current().priv_check(Privilege::SCE683)?;
Expand Down