From 431fdf1c4348dc41a3b4521a4b20c4486047e5f2 Mon Sep 17 00:00:00 2001 From: Putta Khunchalee Date: Sat, 11 May 2024 22:27:32 +0700 Subject: [PATCH] Adds fdrop for 11.00 --- korbis-1100/src/file.rs | 14 ++++++++++++++ korbis-1100/src/lib.rs | 6 ++++++ korbis-macros/src/offset.rs | 6 +++--- korbis/src/file/mod.rs | 29 +++++++++++++++++++++++++++++ korbis/src/lib.rs | 10 ++++++++++ 5 files changed, 62 insertions(+), 3 deletions(-) create mode 100644 korbis-1100/src/file.rs create mode 100644 korbis/src/file/mod.rs diff --git a/korbis-1100/src/file.rs b/korbis-1100/src/file.rs new file mode 100644 index 0000000..c16e44e --- /dev/null +++ b/korbis-1100/src/file.rs @@ -0,0 +1,14 @@ +use core::sync::atomic::AtomicU32; + +/// Implementation of [`korbis::file::File`] for 11.00. +#[repr(C)] +pub struct File { + pad: [u8; 0x28], + refcnt: AtomicU32, +} + +impl korbis::file::File for File { + fn refcnt(&self) -> &AtomicU32 { + &self.refcnt + } +} diff --git a/korbis-1100/src/lib.rs b/korbis-1100/src/lib.rs index 7212b61..52ff4cd 100644 --- a/korbis-1100/src/lib.rs +++ b/korbis-1100/src/lib.rs @@ -1,10 +1,12 @@ #![no_std] +use self::file::File; use self::thread::Thread; use core::ffi::{c_char, c_int}; use korbis::offset; use korbis::uio::UioSeg; +mod file; mod thread; /// Implementation of [`ps4k::Kernel`] for 11.00. @@ -12,6 +14,7 @@ mod thread; pub struct Kernel(&'static [u8]); impl korbis::Kernel for Kernel { + type File = File; type Thread = Thread; unsafe fn new(base: *const u8) -> Self { @@ -22,6 +25,9 @@ impl korbis::Kernel for Kernel { self.0 } + #[offset(0x4161B0)] + unsafe fn fdrop(self, fp: *mut Self::File, td: *mut Self::Thread) -> c_int; + #[offset(0xE63B0)] unsafe fn kern_openat( self, diff --git a/korbis-macros/src/offset.rs b/korbis-macros/src/offset.rs index ad7a31c..4e3e721 100644 --- a/korbis-macros/src/offset.rs +++ b/korbis-macros/src/offset.rs @@ -22,9 +22,9 @@ fn transform_method(args: LitInt, item: Method) -> syn::Result { Ok(quote! { #unsafety fn #ident(#receiver, #params) #ret { - let ad = unsafe { self.elf().as_ptr().add(#offset) }; - let fp: unsafe extern "C" fn(#params) #ret = unsafe { core::mem::transmute(ad) }; - unsafe { fp(#args) } + let _addr = unsafe { self.elf().as_ptr().add(#offset) }; + let _fp: unsafe extern "C" fn(#params) #ret = unsafe { core::mem::transmute(_addr) }; + unsafe { _fp(#args) } } }) } diff --git a/korbis/src/file/mod.rs b/korbis/src/file/mod.rs new file mode 100644 index 0000000..8cd1ae6 --- /dev/null +++ b/korbis/src/file/mod.rs @@ -0,0 +1,29 @@ +use crate::thread::Thread; +use crate::Kernel; +use core::sync::atomic::{fence, AtomicU32, Ordering}; + +/// Represents `file` structure. +pub trait File: Sized { + /// Returns `f_count` field. + fn refcnt(&self) -> &AtomicU32; +} + +/// RAII struct to decrease `file::f_count` when dropped. +pub struct OwnedFile { + kernel: K, + file: *mut K::File, +} + +impl Drop for OwnedFile { + fn drop(&mut self) { + // See Drop implementation on Arc how this thing work. + if unsafe { (*self.file).refcnt().fetch_sub(1, Ordering::Release) } != 1 { + return; + } + + fence(Ordering::Acquire); + + // The kernel itself does not check if fdrop is success so we don't need to. + unsafe { self.kernel.fdrop(self.file, K::Thread::current()) }; + } +} diff --git a/korbis/src/lib.rs b/korbis/src/lib.rs index 3f8f8c9..5b01d1a 100644 --- a/korbis/src/lib.rs +++ b/korbis/src/lib.rs @@ -1,6 +1,7 @@ #![no_std] use self::elf::ProgramType; +use self::file::File; use self::thread::Thread; use self::uio::UioSeg; use core::ffi::{c_char, c_int}; @@ -8,11 +9,13 @@ use core::ffi::{c_char, c_int}; pub use korbis_macros::*; pub mod elf; +pub mod file; pub mod thread; pub mod uio; /// Provides methods to access the PS4 kernel for a specific version. pub trait Kernel: Copy + Send + Sync + 'static { + type File: File; type Thread: Thread; /// # Safety @@ -30,6 +33,13 @@ pub trait Kernel: Copy + Send + Sync + 'static { /// can mutate at any time. The whole slice is guarantee to be readable. unsafe fn elf(self) -> &'static [u8]; + /// # Panics + /// If [`File::refcnt()`] of `fp` is not zero. + /// + /// # Safety + /// - `fp` cannot be null. + unsafe fn fdrop(self, fp: *mut Self::File, td: *mut Self::Thread) -> c_int; + /// # Safety /// - `td` cannot be null. /// - `path` cannot be null and must point to a null-terminated string if `seg` is [`UioSeg::Kernel`].