Skip to content

Commit b547cf0

Browse files
committed
:wip: feat(ios/es): Start on implementing E-Ticket system ioctls
1 parent ab2b715 commit b547cf0

File tree

2 files changed

+224
-1
lines changed

2 files changed

+224
-1
lines changed

src/ios.rs

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,9 +11,14 @@ pub mod dolphin;
1111

1212
/// Filesystem IOS Device
1313
///
14-
/// '/dev/fs'' device helper functions.
14+
/// '/dev/fs' device helper functions.
1515
pub mod fs;
1616

17+
/// E-Ticket System IOS Device
18+
///
19+
/// `/dev/es` device hellper functions.
20+
pub mod es;
21+
1722
#[repr(u32)]
1823
/// Interprocess Control / IOS File Mode
1924
pub enum Mode {

src/ios/es.rs

Lines changed: 218 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,218 @@
1+
/// E-Ticket System Supported Ioctls
2+
pub enum Ioctl {
3+
AddTicket,
4+
AddTitleStart,
5+
AddContentStart,
6+
AddContentData,
7+
AddContentFinish,
8+
AddTitleFinish,
9+
GetDeviceId,
10+
Launch,
11+
OpenActiveTitleContent,
12+
ReadContent,
13+
CloseContent,
14+
GetOwnedTitleCount,
15+
GetOwnedTitles,
16+
GetTitleCount,
17+
GetTitles,
18+
GetViewCount,
19+
GetViews,
20+
GetTitleMetadataViewCount,
21+
GetTitleMetadataViews,
22+
GetConsumption,
23+
Deletetitle,
24+
DeleteTicket,
25+
DiskInterfaceGetTitleMetadataViewSize,
26+
DiskInterfaceGetTitleMetadataView,
27+
DiskInterfaceGetTicketView,
28+
DiskInterfaceVerify,
29+
GetTitleDir,
30+
GetDeviceCertificate,
31+
ImportBoot,
32+
GetTitleId,
33+
SetUid,
34+
DeleteTitleContent,
35+
SeekContent,
36+
OpenContent,
37+
LauchBackwardsCompatibility,
38+
ExportTitleInitalize,
39+
ExportContentBegin,
40+
ExportContentData,
41+
ExportContentEnd,
42+
ExportTitleDone,
43+
AddTitleMetadata,
44+
Encrypt,
45+
Decrypt,
46+
GetBoot2Version,
47+
AddTitleCancel,
48+
Sign,
49+
VerifySign,
50+
GetStoredContentCount,
51+
GetStoredContents,
52+
GetStoredTitleMetadataSize,
53+
GetStoredTitleMetadata,
54+
GetSharedContentCount,
55+
GetSharedContents,
56+
DeleteSharedContents,
57+
DiskInterfaceGetTitleMetadataSize,
58+
DiskInterfaceGetTitleMetadata,
59+
DiskInterfaceVerifyWithView,
60+
SetupStreamKey,
61+
DeleteStreamKey,
62+
DeleteContent,
63+
// Invalid3F
64+
GetVersion0TicketFromView,
65+
// Unknown41,
66+
// Unknown42,
67+
GetTicketSizeFromView,
68+
GetTicketFromView,
69+
CheckKoreaRegion,
70+
}
71+
72+
impl From<Ioctl> for i32 {
73+
fn from(value: Ioctl) -> Self {
74+
match value {
75+
Ioctl::AddTicket => todo!(),
76+
Ioctl::AddTitleStart => todo!(),
77+
Ioctl::AddContentStart => todo!(),
78+
Ioctl::AddContentData => todo!(),
79+
Ioctl::AddContentFinish => todo!(),
80+
Ioctl::AddTitleFinish => todo!(),
81+
Ioctl::GetDeviceId => todo!(),
82+
Ioctl::Launch => todo!(),
83+
Ioctl::OpenActiveTitleContent => todo!(),
84+
Ioctl::ReadContent => todo!(),
85+
Ioctl::CloseContent => todo!(),
86+
Ioctl::GetOwnedTitleCount => todo!(),
87+
Ioctl::GetOwnedTitles => todo!(),
88+
Ioctl::GetTitleCount => 14, //0xE
89+
Ioctl::GetTitles => 15, //0xF
90+
Ioctl::GetViewCount => todo!(),
91+
Ioctl::GetViews => todo!(),
92+
Ioctl::GetTitleMetadataViewCount => todo!(),
93+
Ioctl::GetTitleMetadataViews => todo!(),
94+
Ioctl::GetConsumption => todo!(),
95+
Ioctl::Deletetitle => todo!(),
96+
Ioctl::DeleteTicket => todo!(),
97+
Ioctl::DiskInterfaceGetTitleMetadataViewSize => todo!(),
98+
Ioctl::DiskInterfaceGetTitleMetadataView => todo!(),
99+
Ioctl::DiskInterfaceGetTicketView => todo!(),
100+
Ioctl::DiskInterfaceVerify => todo!(),
101+
Ioctl::GetTitleDir => todo!(),
102+
Ioctl::GetDeviceCertificate => todo!(),
103+
Ioctl::ImportBoot => todo!(),
104+
Ioctl::GetTitleId => todo!(),
105+
Ioctl::SetUid => todo!(),
106+
Ioctl::DeleteTitleContent => todo!(),
107+
Ioctl::SeekContent => todo!(),
108+
Ioctl::OpenContent => todo!(),
109+
Ioctl::LauchBackwardsCompatibility => todo!(),
110+
Ioctl::ExportTitleInitalize => todo!(),
111+
Ioctl::ExportContentBegin => todo!(),
112+
Ioctl::ExportContentData => todo!(),
113+
Ioctl::ExportContentEnd => todo!(),
114+
Ioctl::ExportTitleDone => todo!(),
115+
Ioctl::AddTitleMetadata => todo!(),
116+
Ioctl::Encrypt => todo!(),
117+
Ioctl::Decrypt => todo!(),
118+
Ioctl::GetBoot2Version => todo!(),
119+
Ioctl::AddTitleCancel => todo!(),
120+
Ioctl::Sign => todo!(),
121+
Ioctl::VerifySign => todo!(),
122+
Ioctl::GetStoredContentCount => todo!(),
123+
Ioctl::GetStoredContents => todo!(),
124+
Ioctl::GetStoredTitleMetadataSize => todo!(),
125+
Ioctl::GetStoredTitleMetadata => todo!(),
126+
Ioctl::GetSharedContentCount => todo!(),
127+
Ioctl::GetSharedContents => todo!(),
128+
Ioctl::DeleteSharedContents => todo!(),
129+
Ioctl::DiskInterfaceGetTitleMetadataSize => todo!(),
130+
Ioctl::DiskInterfaceGetTitleMetadata => todo!(),
131+
Ioctl::DiskInterfaceVerifyWithView => todo!(),
132+
Ioctl::SetupStreamKey => todo!(),
133+
Ioctl::DeleteStreamKey => todo!(),
134+
Ioctl::DeleteContent => todo!(),
135+
Ioctl::GetVersion0TicketFromView => todo!(),
136+
Ioctl::GetTicketSizeFromView => todo!(),
137+
Ioctl::GetTicketFromView => todo!(),
138+
Ioctl::CheckKoreaRegion => todo!(),
139+
}
140+
}
141+
}
142+
143+
static DEV_ES: &CStr = c"/dev/es";
144+
145+
use core::ffi::CStr;
146+
147+
use alloc::vec::Vec;
148+
149+
use crate::ios;
150+
151+
pub fn get_title_count() -> Result<u32, ios::Error> {
152+
let es = ios::open(DEV_ES, ios::Mode::None)?;
153+
154+
let mut out_buf = [0u8; 4];
155+
ios::ioctlv::<0, 1, 1>(es, Ioctl::GetTitleCount, &[], &mut [&mut out_buf])?;
156+
157+
let _ = ios::close(es);
158+
159+
Ok(u32::from_be_bytes(out_buf))
160+
}
161+
162+
pub fn get_titles(title_count: u32) -> Result<Vec<u64>, ios::Error> {
163+
let es = ios::open(DEV_ES, ios::Mode::None)?;
164+
165+
// TODO: Avoid allocation
166+
let mut out_buf = alloc::vec![0u8; title_count as usize * core::mem::size_of::<u64>()];
167+
168+
let count: [u8; 4] = title_count.to_be_bytes();
169+
ios::ioctlv::<1, 1, 2>(es, Ioctl::GetTitles, &[&count], &mut [&mut out_buf[..]])?;
170+
171+
let _ = ios::close(es);
172+
173+
// TODO: Avoid allocation
174+
Ok(out_buf
175+
.chunks_exact(core::mem::size_of::<u64>())
176+
.map(|bytes| u64::from_be_bytes(bytes.try_into().expect("should fit")))
177+
.collect())
178+
}
179+
180+
pub fn get_stored_title_metadata_size(title_id: u64) -> Result<u32, ios::Error> {
181+
let es = ios::open(DEV_ES, ios::Mode::None)?;
182+
183+
let in_buf = title_id.to_be_bytes();
184+
let mut out_buf = [0u8; 4];
185+
ios::ioctlv::<1, 1, 2>(
186+
es,
187+
Ioctl::GetStoredTitleMetadataSize,
188+
&[&in_buf],
189+
&mut [&mut out_buf],
190+
)?;
191+
192+
let _ = ios::close(es);
193+
194+
Ok(u32::from_be_bytes(
195+
out_buf.try_into().map_err(|_| ios::Error::Invalid)?,
196+
))
197+
}
198+
199+
// TODO: Proper enuming since there are different signature types and differing sizes for them
200+
pub fn get_stored_title_metadata(title_id: u64, size: u32) -> Result<Vec<u8>, ios::Error> {
201+
let es = ios::open(DEV_ES, ios::Mode::None)?;
202+
203+
let title_buf = title_id.to_be_bytes();
204+
let size_buf = size.to_be_bytes();
205+
let size_usize: usize = usize::try_from(size).map_err(|_| ios::Error::Invalid)?;
206+
// TODO: Avoid allocation
207+
let mut out_buf = alloc::vec![0u8; size_usize];
208+
ios::ioctlv::<2, 1, 3>(
209+
es,
210+
Ioctl::GetStoredTitleMetadata,
211+
&[&title_buf, &size_buf],
212+
&mut [&mut out_buf[..]],
213+
)?;
214+
215+
let _ = ios::close(es);
216+
217+
Ok(out_buf)
218+
}

0 commit comments

Comments
 (0)