Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
b547cf0
:wip: feat(ios/es): Start on implementing E-Ticket system ioctls
ProfElements May 12, 2025
adfd90a
:bug: fix(ios/es): Get some of the Ioctls their proper number, fix na…
ProfElements May 16, 2025
ee8bbf9
:sparkles: feat(ios/es): Add more Ioctl helpers
ProfElements May 16, 2025
9fb3ddf
:sparkles: feat(ios/es): Add even more Ioctl helpers
ProfElements May 19, 2025
a504cd2
:sparkles: feat(ios/es): Add `AddTicket` IOCTL
ProfElements May 27, 2025
a6050c6
:sparkles: feat(ios): Add `ioctlv_reboot` and `ioctlv_reboot_backgrou…
ProfElements May 28, 2025
2d91b70
:sparkles: feat(ios/es): Add Even more IOCTL helpers. Im not thinking…
ProfElements May 28, 2025
68f383f
:sparkles: feat(ios/es): Another one. More helpers
ProfElements Jun 7, 2025
4d11240
:bug: fix(ios/es): `Launch` never returns so use never type. I need t…
ProfElements Jun 7, 2025
15db3b8
:sparkles: feat(ios/es): Working through 'em. More IOCTL helpers
ProfElements Jun 8, 2025
fcd1c41
:sparkles: feat(ios/es): ioctling it up
ProfElements Jun 9, 2025
25adb23
:wip: chore(ios/es): Replace `todo!()` with IOCTL magic numbers
ProfElements Jun 11, 2025
250d8c2
sparkles: feat(ios/es): Add more ioctls
ProfElements Jun 12, 2025
98d8c4e
:wip: feat(ios/es): More IOCTLS
ProfElements Jun 22, 2025
da12761
:wip: feat(ios/es): THE REST OF THEM
ProfElements Jul 1, 2025
2ae94c0
:bug: fix(ios/es): Make sure it builds
ProfElements Jul 1, 2025
2b1b802
:memo: docs(ios/es): Add simple `Ioctl` docs
ProfElements Jul 6, 2025
4a8048d
:memo: docs(ios/es): Add some `Ioctl` func docs
ProfElements Jul 6, 2025
f509455
:wip: chore(ios/es): fix build
ProfElements Jul 6, 2025
4a9b12a
:memo: docs(ios/es): Add more documentation
ProfElements Jul 7, 2025
db11c27
:memo: docs(ios/es): Add more more docs
ProfElements Jul 9, 2025
f8cbdc9
:memo: docs(ios/es): Add docs
ProfElements Jul 14, 2025
0985d49
:memo: docs(ios/es): Add the rest of the docs
ProfElements Jul 22, 2025
f583137
:bug: fix(ios/es): Actually return the `content_file_descriptor` for …
ProfElements Jul 22, 2025
03c9c64
:bug: fix(ios/es): Make `ios::ioctlv` return i32 so that ES can get i…
ProfElements Jul 22, 2025
ee04b23
:sparkles: feat(mmio): Swap `u16` with `AlignedPhysPtrLow`, and `Alig…
ProfElements Jul 22, 2025
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
151 changes: 149 additions & 2 deletions src/ios.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,14 @@ pub mod dolphin;

/// Filesystem IOS Device
///
/// '/dev/fs'' device helper functions.
/// '/dev/fs' device helper functions.
pub mod fs;

/// E-Ticket System IOS Device
///
/// `/dev/es` device hellper functions.
pub mod es;

#[repr(u32)]
/// Interprocess Control / IOS File Mode
pub enum Mode {
Expand Down Expand Up @@ -314,7 +319,7 @@ pub fn ioctlv<
ioctl: impl Into<i32>,
buf_ins: &[&[u8]],
buf_outs: &mut [&mut [u8]],
) -> Result<(), Error> {
) -> Result<i32, Error> {
type Ioctlv = ogc_sys::_ioctlv;
debug_assert!(buf_ins.len() == COUNT_IN);
debug_assert!(buf_outs.len() == COUNT_OUT);
Expand Down Expand Up @@ -357,6 +362,148 @@ pub fn ioctlv<
.map_err(|_| Error::TooManyOutputs(COUNT_OUT))?,
ioctls.as_ptr().cast_mut(),
)
} {
val if { val == -4 || val == -5 || val == -6 || val == -8 || val == -22 } => {
Err(Error::try_from(val).map_err(|()| Error::UnknownErrorCode(val))?)
}
val if { val >= 0 } => Ok(val),
val => Err(Error::UnknownErrorCode(val)),
}
}

/// Attempts to call ioctl using a file descriptor with multiple input and output buffers
/// Reboots into a new `IOS` upon execution
///
/// Attempts to call `ioctl` using `fd` with `bufs_in` and `bufs_out`
///
/// # Errors
/// See [`Error`]
///
pub fn ioctlv_reboot<
const COUNT_IN: usize,
const COUNT_OUT: usize,
//Invariant: This must be COUNT_IN + COUNT_OUT (waiting for `generic_const_exprs` to be
//stabilizied)
const COUNT_IN_OUT: usize,
>(
fd: FileDescriptor,
ioctl: impl Into<i32>,
buf_ins: &[&[u8]],
buf_outs: &mut [&mut [u8]],
) -> Result<(), Error> {
type Ioctlv = ogc_sys::_ioctlv;
debug_assert!(buf_ins.len() == COUNT_IN);
debug_assert!(buf_outs.len() == COUNT_OUT);
debug_assert!(COUNT_IN + COUNT_OUT == COUNT_IN_OUT);

let mut ioctls = [Ioctlv {
data: core::ptr::null_mut(),
len: 0,
}; COUNT_IN_OUT];
//SAFETY: I promise that i don't modify the contents of in buffers up to COUNT_IN
for (i, buf_in) in buf_ins.iter().enumerate() {
ioctls[i] = Ioctlv {
data: buf_in.as_ptr().cast_mut().cast(),
len: buf_in
.len()
.try_into()
.map_err(|_| Error::BufferTooLong(buf_in.len()))?,
}
}

for (i, buf_out) in buf_outs.iter_mut().enumerate() {
ioctls[COUNT_IN + i] = Ioctlv {
data: buf_out.as_mut_ptr().cast(),
len: buf_out
.len()
.try_into()
.map_err(|_| Error::BufferTooLong(buf_out.len()))?,
}
}

match unsafe {
ogc_sys::IOS_IoctlvReboot(
fd.0,
ioctl.into(),
COUNT_IN
.try_into()
.map_err(|_| Error::TooManyInputs(COUNT_IN))?,
COUNT_OUT
.try_into()
.map_err(|_| Error::TooManyOutputs(COUNT_OUT))?,
ioctls.as_ptr().cast_mut(),
)
} {
val if { val == -4 || val == -5 || val == -6 || val == -8 || val == -22 } => {
Err(Error::try_from(val).map_err(|()| Error::UnknownErrorCode(val))?)
}
val if { val >= 0 } => Ok(()),
val => Err(Error::UnknownErrorCode(val)),
}
}

/// Attempts to call ioctl using a file descriptor with multiple input and output buffers
/// Restarts `IOS` in the background upon execution
///
/// Attempts to call `ioctl` using `fd` with `bufs_in` and `bufs_out`
///
/// # Errors
/// See [`Error`]
///
pub fn ioctlv_reboot_background<
const COUNT_IN: usize,
const COUNT_OUT: usize,
//Invariant: This must be COUNT_IN + COUNT_OUT (waiting for `generic_const_exprs` to be
//stabilizied)
const COUNT_IN_OUT: usize,
>(
fd: FileDescriptor,
ioctl: impl Into<i32>,
buf_ins: &[&[u8]],
buf_outs: &mut [&mut [u8]],
) -> Result<(), Error> {
type Ioctlv = ogc_sys::_ioctlv;
debug_assert!(buf_ins.len() == COUNT_IN);
debug_assert!(buf_outs.len() == COUNT_OUT);
debug_assert!(COUNT_IN + COUNT_OUT == COUNT_IN_OUT);

let mut ioctls = [Ioctlv {
data: core::ptr::null_mut(),
len: 0,
}; COUNT_IN_OUT];
//SAFETY: I promise that i don't modify the contents of in buffers up to COUNT_IN
for (i, buf_in) in buf_ins.iter().enumerate() {
ioctls[i] = Ioctlv {
data: buf_in.as_ptr().cast_mut().cast(),
len: buf_in
.len()
.try_into()
.map_err(|_| Error::BufferTooLong(buf_in.len()))?,
}
}

for (i, buf_out) in buf_outs.iter_mut().enumerate() {
ioctls[COUNT_IN + i] = Ioctlv {
data: buf_out.as_mut_ptr().cast(),
len: buf_out
.len()
.try_into()
.map_err(|_| Error::BufferTooLong(buf_out.len()))?,
}
}

match unsafe {
ogc_sys::IOS_IoctlvRebootBackground(
fd.0,
ioctl.into(),
COUNT_IN
.try_into()
.map_err(|_| Error::TooManyInputs(COUNT_IN))?,
COUNT_OUT
.try_into()
.map_err(|_| Error::TooManyOutputs(COUNT_OUT))?,
ioctls.as_ptr().cast_mut(),
)
} {
val if { val == -4 || val == -5 || val == -6 || val == -8 || val == -22 } => {
Err(Error::try_from(val).map_err(|()| Error::UnknownErrorCode(val))?)
Expand Down
Loading
Loading