diff --git a/src/kernel/src/fs/dev/dipsw.rs b/src/kernel/src/fs/dev/dipsw.rs index 5aba4d43b..259bdd7d0 100644 --- a/src/kernel/src/fs/dev/dipsw.rs +++ b/src/kernel/src/fs/dev/dipsw.rs @@ -2,7 +2,6 @@ use crate::errno::{Errno, EINVAL}; use crate::fs::{IoctlCom, VFile, VFileOps, VPath}; use crate::process::VThread; use crate::ucred::Ucred; -use byteorder::{LittleEndian, WriteBytesExt}; use macros::vpath; use std::fmt::{Display, Formatter}; use std::num::NonZeroI32; @@ -15,22 +14,24 @@ pub struct Dipsw {} impl Dipsw { pub const PATH: &VPath = vpath!("/dev/dipsw"); + pub const DIPSW_GRP: u8 = 0x88; + + const COM1: IoctlCom = IoctlCom::iow::(Self::DIPSW_GRP, 1); //TODO: figure out actual type + const COM2: IoctlCom = IoctlCom::iow::(Self::DIPSW_GRP, 2); //TODO: figure out actual type + const COM3: IoctlCom = IoctlCom::iowr::(Self::DIPSW_GRP, 3); //TODO: figure out actual type + const COM4: IoctlCom = IoctlCom::iow::<(i64, i64)>(Self::DIPSW_GRP, 4); //TODO: figure out actual type, probably a struct + const COM5: IoctlCom = IoctlCom::iow::<(i64, i64)>(Self::DIPSW_GRP, 5); //TODO: figure out actual type, probably a struct + const COM6: IoctlCom = IoctlCom::ior::(Self::DIPSW_GRP, 6); + const COM7: IoctlCom = IoctlCom::ior::(Self::DIPSW_GRP, 7); //TODO: figure out actual type + const COM8: IoctlCom = IoctlCom::ior::(Self::DIPSW_GRP, 8); //TODO: figure out actual type + const COM9: IoctlCom = IoctlCom::ior::(Self::DIPSW_GRP, 9); //TODO: figure out actual type + const COM10: IoctlCom = IoctlCom::iow::<(i64, i64)>(Self::DIPSW_GRP, 10); //TODO: figure out actual type, probably a struct + pub fn new() -> Self { Self {} } } -const COM1: IoctlCom = IoctlCom::iow::(0x88, 1); //TODO: figure out actual type -const COM2: IoctlCom = IoctlCom::iow::(0x88, 2); //TODO: figure out actual type -const COM3: IoctlCom = IoctlCom::iowr::(0x88, 3); //TODO: figure out actual type -const COM4: IoctlCom = IoctlCom::iow::<(i64, i64)>(0x88, 4); //TODO: figure out actual type, probably a struct -const COM5: IoctlCom = IoctlCom::iow::<(i64, i64)>(0x88, 5); //TODO: figure out actual type, probably a struct -const COM6: IoctlCom = IoctlCom::ior::(0x88, 6); -const COM7: IoctlCom = IoctlCom::ior::(0x88, 7); //TODO: figure out actual type -const COM8: IoctlCom = IoctlCom::ior::(0x88, 8); //TODO: figure out actual type -const COM9: IoctlCom = IoctlCom::ior::(0x88, 9); //TODO: figure out actual type -const COM10: IoctlCom = IoctlCom::iow::<(i64, i64)>(0x88, 10); //TODO: figure out actual type, probably a struct - impl VFileOps for Dipsw { fn write( &self, @@ -46,25 +47,25 @@ impl VFileOps for Dipsw { &self, _: &VFile, com: IoctlCom, - mut data: &mut [u8], + data: &mut [u8], _: &Ucred, _: &VThread, ) -> Result<(), Box> { match com { - COM1 => todo!("dipsw ioctl 0x80028801"), - COM2 => todo!("dipsw ioctl 0x80028802"), - COM3 => todo!("dipsw ioctl 0xc0088803"), - COM4 => todo!("dipsw ioctl 0x80108804"), - COM5 => todo!("dipsw ioctl 0x80108805"), - COM6 => { + Self::COM1 => todo!("dipsw ioctl 0x80028801"), + Self::COM2 => todo!("dipsw ioctl 0x80028802"), + Self::COM3 => todo!("dipsw ioctl 0xc0088803"), + Self::COM4 => todo!("dipsw ioctl 0x80108804"), + Self::COM5 => todo!("dipsw ioctl 0x80108805"), + Self::COM6 => { //todo write the correct value if unk_func1() = false and // unk_func2() = true - data.write_i32::(false as i32).unwrap(); + data.copy_from_slice(&(false as i32).to_ne_bytes()); } - COM7 => todo!("dipsw ioctl 0x40048807"), - COM8 => todo!("dipsw ioctl 0x40088808"), - COM9 => todo!("dipsw ioctl 0x40088809"), - COM10 => todo!("dipsw ioctl 0x8010880a"), + Self::COM7 => todo!("dipsw ioctl 0x40048807"), + Self::COM8 => todo!("dipsw ioctl 0x40088808"), + Self::COM9 => todo!("dipsw ioctl 0x40088809"), + Self::COM10 => todo!("dipsw ioctl 0x8010880a"), _ => return Err(Box::new(IoctlErr::InvalidCommand)), } @@ -80,7 +81,7 @@ impl Display for Dipsw { #[derive(Error, Debug)] enum IoctlErr { - #[error("invalid command passed to Dipsw::ioctl")] + #[error("invalid command passed to dipsw ioctl")] InvalidCommand, } diff --git a/src/kernel/src/fs/dev/dmem1.rs b/src/kernel/src/fs/dev/dmem1.rs index a278bad68..a0d141c96 100644 --- a/src/kernel/src/fs/dev/dmem1.rs +++ b/src/kernel/src/fs/dev/dmem1.rs @@ -1,18 +1,33 @@ -use crate::errno::Errno; +use crate::errno::{Errno, EPERM}; use crate::fs::{IoctlCom, VFile, VFileOps, VPath}; -use crate::process::VThread; +use crate::process::{VProc, VThread}; use crate::ucred::Ucred; use macros::vpath; use std::fmt::{Display, Formatter}; +use std::num::NonZeroI32; +use std::sync::Arc; +use thiserror::Error; #[derive(Debug)] -pub struct Dmem1 {} +pub struct Dmem1 { + vp: Arc, + total_size: usize, + number: i32, +} impl Dmem1 { pub const PATH: &VPath = vpath!("/dev/dmem1"); - pub fn new() -> Self { - Self {} + pub const DMEM_GRP: u8 = 0x80; + + pub const COM10: IoctlCom = IoctlCom::ior::(Self::DMEM_GRP, 0xa); + + pub fn new(vp: &Arc) -> Self { + Self { + vp: vp.clone(), + total_size: 0x13C_000_000, // TODO figure out the real value + number: 1, + } } } @@ -24,12 +39,27 @@ impl VFileOps for Dmem1 { fn ioctl( &self, _: &crate::fs::VFile, - _com: IoctlCom, - _: &mut [u8], - _: &Ucred, + com: IoctlCom, + data: &mut [u8], + cred: &Ucred, _: &VThread, ) -> Result<(), Box> { - todo!() + if cred.is_unk1() || cred.is_unk2() { + return Err(Box::new(IoctlErr::BadCredentials)); + } + + if self.number != 2 && self.number != *self.vp.dmem_container() && !cred.is_system() { + return Err(Box::new(IoctlErr::BadCredentials)); + } + + match com { + Self::COM10 => { + data.copy_from_slice(&self.total_size.to_ne_bytes()); + } + _ => todo!("dmem1 ioctl with com = ({com})"), + } + + Ok(()) } } @@ -38,3 +68,17 @@ impl Display for Dmem1 { Self::PATH.fmt(f) } } + +#[derive(Error, Debug)] +enum IoctlErr { + #[error("bad credentials")] + BadCredentials, +} + +impl Errno for IoctlErr { + fn errno(&self) -> NonZeroI32 { + match self { + Self::BadCredentials => EPERM, + } + } +} diff --git a/src/kernel/src/fs/item.rs b/src/kernel/src/fs/item.rs index 1786e7dab..c8c1294e8 100644 --- a/src/kernel/src/fs/item.rs +++ b/src/kernel/src/fs/item.rs @@ -2,8 +2,11 @@ use super::{ dev::{deci_tty6::DeciTty6, dipsw::Dipsw, dmem0::Dmem0, dmem1::Dmem1, dmem2::Dmem2}, FsError, VFileOps, VPath, VPathBuf, }; -use crate::fs::dev::console::Console; -use std::path::{Path, PathBuf}; +use crate::{fs::dev::console::Console, process::VProc}; +use std::{ + path::{Path, PathBuf}, + sync::Arc, +}; /// An item in the virtual filesystem. pub enum FsItem { @@ -42,11 +45,11 @@ impl FsItem { } } - pub fn open(&self) -> Result, FsError> { + pub fn open(&self, vp: &Arc) -> Result, FsError> { match self { Self::Directory(_) => todo!("VFileOps for host directory"), Self::File(_) => todo!("VFileOps for host file"), - Self::Device(d) => d.open(), + Self::Device(d) => d.open(vp), } } } @@ -102,13 +105,13 @@ pub enum VDev { } impl VDev { - pub fn open(&self) -> Result, FsError> { + pub fn open(&self, vp: &Arc) -> Result, FsError> { let ops: Box = match self { Self::Console => Box::new(Console::new()), Self::Dipsw => Box::new(Dipsw::new()), Self::DeciTty6 => Box::new(DeciTty6::new()), Self::Dmem0 => Box::new(Dmem0::new()), - Self::Dmem1 => Box::new(Dmem1::new()), + Self::Dmem1 => Box::new(Dmem1::new(vp)), Self::Dmem2 => Box::new(Dmem2::new()), }; diff --git a/src/kernel/src/fs/mod.rs b/src/kernel/src/fs/mod.rs index 3385eb9ca..df027fcaf 100644 --- a/src/kernel/src/fs/mod.rs +++ b/src/kernel/src/fs/mod.rs @@ -340,7 +340,7 @@ impl Fs { }; *file.flags_mut() = flags.to_fflags(); - file.set_ops(Some(self.namei(&mut nd)?.open()?)); + file.set_ops(Some(self.namei(&mut nd)?.open(&self.vp)?)); // Install to descriptor table. let fd = self.vp.files().alloc(Arc::new(file)); diff --git a/src/kernel/src/process/mod.rs b/src/kernel/src/process/mod.rs index e3953b422..ab625fd1d 100644 --- a/src/kernel/src/process/mod.rs +++ b/src/kernel/src/process/mod.rs @@ -422,6 +422,8 @@ impl VProc { let name: Option<&str> = unsafe { i.args[1].to_str(32) }?; if tid == -1 { + info!("Setting process name to '{}'.", name.unwrap_or("NULL")); + self.set_name(name); } else { let threads = self.threads.read(); @@ -431,6 +433,12 @@ impl VProc { .find(|t| t.id().get() == tid) .ok_or(SysErr::Raw(ESRCH))?; + info!( + "Setting name of thread {} to '{}'.", + thr.id(), + name.unwrap_or("NULL") + ); + thr.set_name(name); } diff --git a/src/kernel/src/regmgr/key.rs b/src/kernel/src/regmgr/key.rs index 2ce006ec9..ed88c2a96 100644 --- a/src/kernel/src/regmgr/key.rs +++ b/src/kernel/src/regmgr/key.rs @@ -47,6 +47,7 @@ impl RegKey { pub const NET_WIFI_FREQ_BAND: Self = Self(0x141E0500); pub const NP_DEBUG: Self = Self(0x19810000); pub const BROWSER_DEBUG_NOTIFICATION: Self = Self(0x3CC80700); + pub const MORPHEUS_DEBUG_VR_CAPTURE: Self = Self(0x58800C00); pub const DEVENV_TOOL_BOOT_PARAM: Self = Self(0x78020300); pub const DEVENV_TOOL_TRC_NOTIFY: Self = Self(0x78026400); pub const DEVENV_TOOL_USE_DEFAULT_LIB: Self = Self(0x78028300); @@ -135,6 +136,9 @@ impl Display for RegKey { Self::BROWSER_DEBUG_NOTIFICATION => { f.write_str("SCE_REGMGR_ENT_KEY_BROWSER_DEBUG_notification") } + Self::MORPHEUS_DEBUG_VR_CAPTURE => { + f.write_str("SCE_REGMGR_ENT_KEY_MORPHEUS_DEBUG_vr_capture") + } Self::DEVENV_TOOL_BOOT_PARAM => { f.write_str("SCE_REGMGR_ENT_KEY_DEVENV_TOOL_boot_param") } diff --git a/src/kernel/src/sysctl/mod.rs b/src/kernel/src/sysctl/mod.rs index 1624cb411..d873edb8e 100644 --- a/src/kernel/src/sysctl/mod.rs +++ b/src/kernel/src/sysctl/mod.rs @@ -379,7 +379,7 @@ impl Sysctl { ) -> Result<(), SysErr> { //TODO write RuntimeLinker flags if unknown_function() = true - req.write(&(0u32).to_le_bytes())?; + req.write(&(0u32).to_ne_bytes())?; Ok(()) } diff --git a/src/kernel/src/ucred/auth.rs b/src/kernel/src/ucred/auth.rs index 2e7a7f19d..503725f00 100644 --- a/src/kernel/src/ucred/auth.rs +++ b/src/kernel/src/ucred/auth.rs @@ -4,7 +4,7 @@ pub struct AuthInfo { pub paid: AuthPaid, pub caps: AuthCaps, - pub attrs: [u64; 4], + pub attrs: AuthAttrs, pub unk: [u8; 0x40], } @@ -17,12 +17,12 @@ impl AuthInfo { 0x0000000000000000, 0x0000000000000000, ]), - attrs: [ + attrs: AuthAttrs([ 0x4000400080000000, 0x8000000000000000, 0x0800000000000000, 0xF0000000FFFF4000, - ], + ]), unk: [0; 0x40], }; @@ -45,12 +45,12 @@ impl AuthInfo { 0x0000000000000000, 0x0000000000000000, ]), - attrs: [ + attrs: AuthAttrs([ 0x4000400040000000, 0x4000000000000000, 0x0080000000000002, 0xF0000000FFFF4000, - ], + ]), unk: [0; 0x40], }) } @@ -90,6 +90,10 @@ impl AuthCaps { (self.0[0] & 0x4000000000000000) != 0 } + pub fn is_unk1(&self) -> bool { + (self.0[1] & 0x4000000000000000) != 0 + } + pub fn clear_non_type(&mut self) { self.0[0] &= 0x7000000000000000; self.0[1] = 0; @@ -97,3 +101,18 @@ impl AuthCaps { self.0[3] = 0; } } + +/// A wrapper type for `caps` field of [`AuthAttrs`]. +#[repr(transparent)] +#[derive(Debug, Clone)] +pub struct AuthAttrs([u64; 4]); + +impl AuthAttrs { + pub fn is_unk1(&self) -> bool { + (self.0[0] & 0x800000) != 0 + } + + pub fn is_unk2(&self) -> bool { + (self.0[0] & 0x400000) != 0 + } +} diff --git a/src/kernel/src/ucred/mod.rs b/src/kernel/src/ucred/mod.rs index 5fbf6d078..074e9c1d2 100644 --- a/src/kernel/src/ucred/mod.rs +++ b/src/kernel/src/ucred/mod.rs @@ -52,6 +52,14 @@ impl Ucred { self.auth.caps.is_system() } + pub fn is_unk1(&self) -> bool { + self.auth.caps.is_unk1() && self.auth.attrs.is_unk1() + } + + pub fn is_unk2(&self) -> bool { + self.auth.caps.is_unk1() && self.auth.attrs.is_unk2() + } + /// See `priv_check_cred` on the PS4 for a reference. pub fn priv_check(&self, p: Privilege) -> Result<(), PrivilegeError> { // TODO: Check suser_enabled.