From ecc493332dfa07460f874ef9f35f90b2a2812139 Mon Sep 17 00:00:00 2001 From: tompro Date: Mon, 8 Apr 2024 22:35:59 +0200 Subject: [PATCH] Implements sockets, initializes rng, gc and camera devices --- src/kernel/build.rs | 2 +- src/kernel/src/dev/camera.rs | 92 ++++++++++++++++++++++++++++++++++ src/kernel/src/dev/dipsw.rs | 6 +-- src/kernel/src/dev/gc.rs | 56 +++++++++++++++++++-- src/kernel/src/dev/mod.rs | 2 + src/kernel/src/dev/rng.rs | 63 +++++++++++++++++++++-- src/kernel/src/fs/dev/mod.rs | 2 +- src/kernel/src/fs/ioctl.rs | 31 ++++++++++-- src/kernel/src/main.rs | 22 ++++++-- src/kernel/src/net/inet/mod.rs | 33 ++++++++++++ src/kernel/src/net/mod.rs | 4 ++ src/kernel/src/net/proto.rs | 44 ++++++++++++++++ src/kernel/src/net/socket.rs | 62 ++++++++++++++++------- 13 files changed, 380 insertions(+), 39 deletions(-) create mode 100644 src/kernel/src/dev/camera.rs create mode 100644 src/kernel/src/net/inet/mod.rs create mode 100644 src/kernel/src/net/proto.rs diff --git a/src/kernel/build.rs b/src/kernel/build.rs index 010eb8c89..4a61819fe 100644 --- a/src/kernel/build.rs +++ b/src/kernel/build.rs @@ -1,7 +1,7 @@ fn main() { match std::env::var("CARGO_CFG_TARGET_OS").unwrap().as_str() { "linux" | "android" => { - println!("cargo::rerun-if-changed=src/hv/linux/kvm.cpp"); + println!("cargo:rerun-if-changed=src/hv/linux/kvm.cpp"); cc::Build::new() .cpp(true) diff --git a/src/kernel/src/dev/camera.rs b/src/kernel/src/dev/camera.rs new file mode 100644 index 000000000..81e13791f --- /dev/null +++ b/src/kernel/src/dev/camera.rs @@ -0,0 +1,92 @@ +use crate::{ + errno::Errno, + fs::{ + make_dev, CharacterDevice, DeviceDriver, DriverFlags, IoCmd, MakeDevError, MakeDevFlags, + Mode, OpenFlags, Uio, UioMut, + }, + process::VThread, + ucred::{Gid, Uid}, +}; +use std::sync::Arc; +use thiserror::Error; + +#[derive(Debug)] +struct Camera {} + +impl Camera { + fn new() -> Self { + Self {} + } +} + +impl DeviceDriver for Camera { + #[allow(unused_variables)] // TODO: remove when implementing + fn open( + &self, + dev: &Arc, + mode: OpenFlags, + devtype: i32, + td: Option<&VThread>, + ) -> Result<(), Box> { + todo!() + } + + #[allow(unused_variables)] // TODO: remove when implementing + fn read( + &self, + dev: &Arc, + data: &mut UioMut, + td: Option<&VThread>, + ) -> Result<(), Box> { + todo!() + } + + #[allow(unused_variables)] // TODO: remove when implementing + fn write( + &self, + dev: &Arc, + data: &mut Uio, + td: Option<&VThread>, + ) -> Result<(), Box> { + todo!() + } + + #[allow(unused_variables)] // TODO: remove when implementing + fn ioctl( + &self, + dev: &Arc, + cmd: IoCmd, + td: Option<&VThread>, + ) -> Result<(), Box> { + todo!() + } +} + +pub struct CameraManager { + dipsw: Arc, +} + +impl CameraManager { + pub fn new() -> Result, CameraInitError> { + let dipsw = make_dev( + Camera::new(), + DriverFlags::from_bits_retain(0x80000004), + 0, + "camera", + Uid::ROOT, + Gid::ROOT, + Mode::new(0o666).unwrap(), + None, + MakeDevFlags::MAKEDEV_ETERNAL, + )?; + + Ok(Arc::new(Self { dipsw })) + } +} + +/// Represents an error when [`CameraManager`] fails to initialize. +#[derive(Debug, Error)] +pub enum CameraInitError { + #[error("cannot create camera device")] + CreateGcFailed(#[from] MakeDevError), +} diff --git a/src/kernel/src/dev/dipsw.rs b/src/kernel/src/dev/dipsw.rs index ee8c604ca..39a6e0615 100644 --- a/src/kernel/src/dev/dipsw.rs +++ b/src/kernel/src/dev/dipsw.rs @@ -33,7 +33,7 @@ impl DeviceDriver for Dipsw { if !td.cred().is_system() { match cmd { // TODO: properly implement this - IoCmd::DIPSWCHECK2(val) => *val = false as i32, + IoCmd::DIPSWCHECK2(val) | IoCmd::DIPSWUNK(val) => *val = false as i32, _ => todo!(), } } else { @@ -66,9 +66,9 @@ impl DipswManager { } } -/// Represents an error when [`TtyManager`] fails to initialize. +/// Represents an error when [`DipswManager`] fails to initialize. #[derive(Debug, Error)] pub enum DipswInitError { #[error("cannot create dipsw device")] - CreateConsoleFailed(#[from] MakeDevError), + CreateDipswFailed(#[from] MakeDevError), } diff --git a/src/kernel/src/dev/gc.rs b/src/kernel/src/dev/gc.rs index 83ed84c80..99481a208 100644 --- a/src/kernel/src/dev/gc.rs +++ b/src/kernel/src/dev/gc.rs @@ -1,13 +1,24 @@ use crate::{ errno::Errno, - fs::{CharacterDevice, DeviceDriver, IoCmd, OpenFlags}, + fs::{ + make_dev, CharacterDevice, DeviceDriver, DriverFlags, IoCmd, MakeDevError, MakeDevFlags, + Mode, OpenFlags, + }, process::VThread, + ucred::{Gid, Uid}, }; use std::sync::Arc; +use thiserror::Error; #[derive(Debug)] struct Gc {} +impl Gc { + fn new() -> Self { + Self {} + } +} + impl DeviceDriver for Gc { #[allow(unused_variables)] // TODO: remove when implementing fn open( @@ -20,13 +31,48 @@ impl DeviceDriver for Gc { todo!() } - #[allow(unused_variables)] // TODO: remove when implementing fn ioctl( &self, - dev: &Arc, + _: &Arc, cmd: IoCmd, - td: Option<&VThread>, + _: Option<&VThread>, ) -> Result<(), Box> { - todo!() + match cmd { + IoCmd::GC12(_) => todo!("GC12 ioctl"), + IoCmd::GC16(_) => todo!("GC16 ioctl"), + IoCmd::GC25(_) => todo!("GC25 ioctl"), + IoCmd::GC27(_) => todo!("GC32 ioctl"), + IoCmd::GC31(_) => todo!("GC31 ioctl"), + _ => todo!(), + } } } + +pub struct GcManager { + dipsw: Arc, +} + +impl GcManager { + pub fn new() -> Result, GcInitError> { + let gc = make_dev( + Gc::new(), + DriverFlags::from_bits_retain(0x80000004), + 0, + "gc", + Uid::ROOT, + Gid::ROOT, + Mode::new(0o666).unwrap(), + None, + MakeDevFlags::MAKEDEV_ETERNAL, + )?; + + Ok(Arc::new(Self { dipsw: gc })) + } +} + +/// Represents an error when [`GcManager`] fails to initialize. +#[derive(Debug, Error)] +pub enum GcInitError { + #[error("cannot create gc device")] + CreateGcFailed(#[from] MakeDevError), +} diff --git a/src/kernel/src/dev/mod.rs b/src/kernel/src/dev/mod.rs index 3708bda70..1936e9ec0 100644 --- a/src/kernel/src/dev/mod.rs +++ b/src/kernel/src/dev/mod.rs @@ -1,3 +1,4 @@ +pub use camera::*; pub use deci::*; pub use dipsw::*; pub use dmem::*; @@ -8,6 +9,7 @@ pub use rng::*; pub use sbl_srv::*; pub use ttyconsole::*; +mod camera; mod deci; mod dipsw; mod dmem; diff --git a/src/kernel/src/dev/rng.rs b/src/kernel/src/dev/rng.rs index f12a10782..ac4ef2b85 100644 --- a/src/kernel/src/dev/rng.rs +++ b/src/kernel/src/dev/rng.rs @@ -1,24 +1,79 @@ use crate::{ + arnd, errno::Errno, - fs::{CharacterDevice, DeviceDriver, IoCmd}, + fs::{ + make_dev, CharacterDevice, DeviceDriver, DriverFlags, IoCmd, MakeDevError, MakeDevFlags, + Mode, + }, process::VThread, + ucred::{Gid, Uid}, }; use std::sync::Arc; +use thiserror::Error; #[derive(Debug)] struct Rng {} +impl Rng { + fn new() -> Self { + Self {} + } +} + impl DeviceDriver for Rng { fn ioctl( &self, - dev: &Arc, + _: &Arc, cmd: IoCmd, _: Option<&VThread>, ) -> Result<(), Box> { match cmd { - IoCmd::RNGGETGENUINE(_) => todo!(), - IoCmd::RNGFIPS(_) => todo!(), + // TODO: these are separate algorithms, and should be implemented as such, + // however arc4rand seems sufficient for now + IoCmd::RNGGETGENUINE(input) | IoCmd::RNGFIPS(input) => { + input.error = 0; + + arnd::rand_bytes(&mut input.data); + + Ok(()) + } _ => todo!(), // ENOIOCTL, } } } + +#[derive(Debug)] +pub struct RngInput { + /// This field seems to be treated as an error + error: i32, + data: [u8; 64], +} + +pub struct RngManager { + dipsw: Arc, +} + +impl RngManager { + pub fn new() -> Result, RngInitError> { + let rng = make_dev( + Rng::new(), + DriverFlags::from_bits_retain(0x80000004), + 0, + "rng", + Uid::ROOT, + Gid::ROOT, + Mode::new(0o444).unwrap(), + None, + MakeDevFlags::MAKEDEV_ETERNAL, + )?; + + Ok(Arc::new(Self { dipsw: rng })) + } +} + +/// Represents an error when [`RngManager`] fails to initialize. +#[derive(Debug, Error)] +pub enum RngInitError { + #[error("cannot create rng device")] + CreateRngFailed(#[from] MakeDevError), +} diff --git a/src/kernel/src/fs/dev/mod.rs b/src/kernel/src/fs/dev/mod.rs index b93368751..4319b85d3 100644 --- a/src/kernel/src/fs/dev/mod.rs +++ b/src/kernel/src/fs/dev/mod.rs @@ -313,7 +313,7 @@ impl Devices { /// Represents an error when [`make_dev()`] is failed. #[derive(Debug, Error, Errno)] pub enum MakeDevError { - #[error("the device with the same name already exist")] + #[error("the device with the same name already exists")] #[errno(EEXIST)] AlreadyExist(String), } diff --git a/src/kernel/src/fs/ioctl.rs b/src/kernel/src/fs/ioctl.rs index 60587ac9c..61fa8e0f0 100644 --- a/src/kernel/src/fs/ioctl.rs +++ b/src/kernel/src/fs/ioctl.rs @@ -1,5 +1,5 @@ use super::FioDeviceGetNameArg; -use crate::dev::{DmemAllocate, DmemAvailable, DmemQuery, PrtAperture}; +use crate::dev::{DmemAllocate, DmemAvailable, DmemQuery, PrtAperture, RngInput}; use crate::dmem::{BlockpoolExpandArgs, BlockpoolStats}; use crate::errno::ENOTTY; use crate::syscalls::SysErr; @@ -113,6 +113,8 @@ commands! { DIPSWWRITE(&Unknown16) = 0x80108805, /// sceKernelCheckDipsw DIPSWCHECK2(&mut i32) = 0x40048806, + /// Unkown dipsw command + DIPSWUNK(&mut i32) = 0x40048807, /// Get total size? DMEMTOTAL(&mut usize) = 0x4008800a, @@ -145,15 +147,36 @@ commands! { FIOGETLBA(&mut i32) = 0x40046679, /// Get dev. name FIODGNAME(&FioDeviceGetNameArg) = 0x80106678, + /// Get # bytes (yet) to write + FIONWRITE(&mut i32) = 0x40046677, + /// Get space in send queue + FIONSPACE(&mut i32) = 0x40046676, /// Seek data. FIOSEEKDATA(&mut i64) = 0xC0086661, /// Seek hole. FIOSEEKHOLE(&mut i64) = 0xC0086662, + GC12(&mut Unknown16) = 0xc010810b, + /// Currently unknown gc command + GC16(&mut Unknown12) = 0xc00c8110, + /// Currently unknown gc command + GC25(&mut Unknown132) = 0xc0848119, + /// Currently unknown gc command + GC27(&mut Unknown8) = 0xc008811b, + /// Currently unknown gc command + GC31(&mut i32) = 0xc004811f, + /// Get genuine random - RNGGETGENUINE(&mut Unknown68) = 0x40445301, + RNGGETGENUINE(&mut RngInput) = 0x40445301, /// Fips186Prng - RNGFIPS(&mut Unknown68) = 0x40445302, + RNGFIPS(&mut RngInput) = 0x40445302, + + /// Cat oob mark? + SIOCATMARK(&mut i32) = 0x40047307, + /// Set process group + SIOCSPGRP(&i32) = 0x80047308, + /// Get process group + SIOCGPGRP(&mut i32) = 0x40047309, /// Become controlling terminal. TIOCSCTTY = 0x20007461, @@ -162,9 +185,11 @@ commands! { type Unknown2 = Unknown<2>; type Unknown8 = Unknown<8>; +type Unknown12 = Unknown<12>; type Unknown16 = Unknown<16>; type Unknown36 = Unknown<36>; type Unknown68 = Unknown<68>; +type Unknown132 = Unknown<132>; /// A dummy type to be used as a placeholder for unknown data. #[derive(Debug)] diff --git a/src/kernel/src/main.rs b/src/kernel/src/main.rs index 978c58b68..a216d48de 100644 --- a/src/kernel/src/main.rs +++ b/src/kernel/src/main.rs @@ -1,8 +1,8 @@ use crate::arch::MachDep; use crate::budget::{Budget, BudgetManager, ProcType}; use crate::dev::{ - DebugManager, DebugManagerInitError, DipswInitError, DipswManager, DmemContainer, TtyManager, - TtyManagerInitError, + CameraManager, DebugManager, DebugManagerInitError, DipswInitError, DipswManager, + DmemContainer, GcManager, RngManager, TtyManager, TtyManagerInitError, }; use crate::dmem::{DmemManager, DmemManagerInitError}; use crate::ee::native::NativeEngine; @@ -25,6 +25,7 @@ use crate::time::TimeManager; use crate::ucred::{AuthAttrs, AuthCaps, AuthInfo, AuthPaid, Gid, Ucred, Uid}; use crate::umtx::UmtxManager; use clap::Parser; +use dev::{CameraInitError, GcInitError, RngInitError}; use llt::{OsThread, SpawnError}; use macros::vpath; use param::Param; @@ -347,6 +348,12 @@ fn run() -> Result<(), KernelError> { let tty = TtyManager::new()?; #[allow(unused_variables)] // TODO: Remove this when someone uses dipsw. let dipsw = DipswManager::new()?; + #[allow(unused_variables)] // TODO: Remove this when someone uses gc. + let gc = GcManager::new()?; + #[allow(unused_variables)] // TODO: Remove this when someone uses camera. + let camera = CameraManager::new()?; + #[allow(unused_variables)] // TODO: Remove this when someone uses rng. + let rng = RngManager::new()?; // Initialize kernel components. #[allow(unused_variables)] // TODO: Remove this when someone uses debug. @@ -609,8 +616,17 @@ enum KernelError { #[error("debug manager initialization failed")] DebugManagerInitFailed(#[from] DebugManagerInitError), + #[error("gc manager initialization failed")] + GcManagerInitFailed(#[from] GcInitError), + + #[error("camera manager initialization failed")] + CameraManagerInitFailed(#[from] CameraInitError), + + #[error("rng manager initialization failed")] + RngManagerInitFailed(#[from] RngInitError), + #[error("dmem manager initialization failed")] - DmemManagerInitFailes(#[from] DmemManagerInitError), + DmemManagerInitFailed(#[from] DmemManagerInitError), #[error("couldn't create application process")] CreateProcessFailed(#[source] self::process::SpawnError), diff --git a/src/kernel/src/net/inet/mod.rs b/src/kernel/src/net/inet/mod.rs new file mode 100644 index 000000000..f319f7c1c --- /dev/null +++ b/src/kernel/src/net/inet/mod.rs @@ -0,0 +1,33 @@ +use super::{Socket, SocketBackend}; +use crate::errno::Errno; +use crate::fs::IoCmd; +use crate::process::VThread; +use std::sync::Arc; + +#[derive(Debug)] +pub(super) enum InetProtocol { + UdpP2P, +} + +impl SocketBackend for InetProtocol { + fn attach(&self, socket: &Arc, td: Option<&VThread>) -> Result<(), Box> { + //TODO: properly implement this. + Ok(()) + } + + fn control( + &self, + socket: &Arc, + cmd: IoCmd, + td: Option<&VThread>, + ) -> Result<(), Box> { + match self { + Self::UdpP2P => match cmd { + // TODO: properly implement this. It is difficult to judge what it currently does, + // because the socket is simply created, this ioctl is called and then the socket is immediately closed. + IoCmd::BNETUNK(_) => Ok(()), + _ => todo!(), + }, + } + } +} diff --git a/src/kernel/src/net/mod.rs b/src/kernel/src/net/mod.rs index c1602025b..35f543e42 100644 --- a/src/kernel/src/net/mod.rs +++ b/src/kernel/src/net/mod.rs @@ -16,8 +16,12 @@ use std::{ }; use thiserror::Error; +use self::inet::*; +use self::proto::*; pub use self::socket::*; +mod inet; +mod proto; mod socket; pub struct NetManager {} diff --git a/src/kernel/src/net/proto.rs b/src/kernel/src/net/proto.rs new file mode 100644 index 000000000..b06cc2c9b --- /dev/null +++ b/src/kernel/src/net/proto.rs @@ -0,0 +1,44 @@ +use super::{InetProtocol, Socket}; +use crate::errno::Errno; +use crate::fs::IoCmd; +use crate::process::VThread; +use std::sync::Arc; + +/// An implementation of the `pr_usrreqs` struct. This is subject to potential refactors, as it has to cover a lot of code +/// and therefore it is impossible to fully predict the correct implementation. In the future, this struct might end up containing functions from the +/// `protosw` struct as well. +pub(super) trait SocketBackend { + fn attach(&self, socket: &Arc, td: Option<&VThread>) -> Result<(), Box>; + + // TODO: a ifnet argument might have to be added in the future + fn control( + &self, + socket: &Arc, + cmd: IoCmd, + td: Option<&VThread>, + ) -> Result<(), Box>; +} +#[repr(u8)] +#[derive(Debug)] +pub(super) enum Protocol { + Inet(InetProtocol) = 2, +} + +impl SocketBackend for Protocol { + fn attach(&self, socket: &Arc, td: Option<&VThread>) -> Result<(), Box> { + match self { + Self::Inet(protocol) => protocol.attach(socket, td), + } + } + + fn control( + &self, + socket: &Arc, + cmd: IoCmd, + td: Option<&VThread>, + ) -> Result<(), Box> { + match self { + Self::Inet(protocol) => protocol.control(socket, cmd, td), + } + } +} diff --git a/src/kernel/src/net/socket.rs b/src/kernel/src/net/socket.rs index 587daf594..696d5802a 100644 --- a/src/kernel/src/net/socket.rs +++ b/src/kernel/src/net/socket.rs @@ -1,4 +1,4 @@ -use super::{GetOptError, SetOptError, SockOpt}; +use super::{GetOptError, InetProtocol, Protocol, SetOptError, SockOpt, SocketBackend}; use crate::fs::{ DefaultFileBackendError, FileBackend, IoCmd, PollEvents, Stat, TruncateLength, Uio, UioMut, VFile, @@ -8,7 +8,6 @@ use crate::{ errno::{Errno, EPIPE}, process::VThread, }; -use bitflags::bitflags; use macros::Errno; use std::num::NonZeroI32; use std::sync::Arc; @@ -16,10 +15,9 @@ use thiserror::Error; #[derive(Debug)] pub struct Socket { - ty: i32, // so_type - options: SocketOptions, // so_options - cred: Arc, // so_cred + cred: Arc, // so_cred name: Option>, + backend: Protocol, } impl Socket { @@ -33,11 +31,29 @@ impl Socket { td: &VThread, name: Option<&str>, ) -> Result, SocketCreateError> { - todo!() - } - - fn options(&self) -> SocketOptions { - self.options + let backend = match domain { + 2 => { + let protocol = match (ty, proto) { + (6, None) => InetProtocol::UdpP2P, + _ => todo!(), + }; + Protocol::Inet(protocol) + } + _ => todo!(), + }; + + let socket = Arc::new(Socket { + cred: Arc::clone(cred), + name: name.map(|s| s.to_string().into_boxed_str()), + backend, + }); + + socket + .backend + .attach(&socket, Some(td)) + .map_err(SocketCreateError::AttachError)?; + + Ok(socket) } /// See `sosetopt` on the PS4 for a reference. @@ -65,13 +81,6 @@ impl Socket { } } -bitflags! { - #[derive(Debug, Clone, Copy)] - struct SocketOptions: i16 { - const NOSIGPIPE = 0x0800; - } -} - impl FileBackend for Socket { #[allow(unused_variables)] // TODO: remove when implementing /// See soo_read on the PS4 for a reference. @@ -102,7 +111,19 @@ impl FileBackend for Socket { cmd: IoCmd, td: Option<&VThread>, ) -> Result<(), Box> { - todo!() + match cmd { + IoCmd::FIONBIO(_) => todo!("socket ioctl with FIONBIO"), + IoCmd::FIOASYNC(_) => todo!("socket ioctl with FIOASYNC"), + IoCmd::FIONREAD(_) => todo!("socket ioctl with FIONREAD"), + IoCmd::FIONWRITE(_) => todo!("socket ioctl with FIONWRITE"), + IoCmd::FIONSPACE(_) => todo!("socket ioctl with FIONSPACE"), + IoCmd::FIOSETOWN(_) => todo!("socket ioctl with FIOSETOWN"), + IoCmd::FIOGETOWN(_) => todo!("socket ioctl with FIOGETOWN"), + IoCmd::SIOCSPGRP(_) => todo!("socket ioctl with SIOCSPGRP"), + IoCmd::SIOCGPGRP(_) => todo!("socket ioctl with SIOCGPGRP"), + IoCmd::SIOCATMARK(_) => todo!("socket ioctl with SIOCATMARK"), + _ => self.backend.control(self, cmd, td), + } } #[allow(unused_variables)] // TODO: remove when implementing @@ -126,7 +147,10 @@ impl FileBackend for Socket { } #[derive(Debug, Error, Errno)] -pub enum SocketCreateError {} +pub enum SocketCreateError { + #[error("couldn't attach socket")] + AttachError(#[source] Box), +} #[derive(Debug, Error, Errno)] enum ReceiveError {}