Skip to main content

ios_core/proto/
afc.rs

1use zerocopy::byteorder::{LittleEndian, U64};
2use zerocopy::{FromBytes, Immutable, IntoBytes, KnownLayout};
3
4/// AFC packet magic bytes: "CFA6LPAA" stored as LE u64
5/// Bytes: 43 46 41 36 4C 50 41 41 → 0x4141504C36414643 in LE
6pub const AFC_MAGIC: u64 = 0x4141504C36414643;
7
8/// AFC protocol header (40 bytes, all little-endian).
9///
10/// Wire format (matches go-ios ios/afc/afc.go `header` struct):
11///   Magic     [8] – 0x4141504C36414643
12///   EntireLen [8] – total packet bytes (header + header_payload + payload)
13///   ThisLen   [8] – header + header_payload bytes only
14///   PacketNum [8] – incrementing per-request counter
15///   Operation [8] – AfcOpcode
16#[derive(Debug, Clone, Copy, FromBytes, IntoBytes, KnownLayout, Immutable)]
17#[repr(C)]
18pub struct AfcHeader {
19    pub magic: U64<LittleEndian>,
20    pub entire_len: U64<LittleEndian>, // header + header_payload + payload
21    pub this_len: U64<LittleEndian>,   // header + header_payload
22    pub packet_num: U64<LittleEndian>,
23    pub operation: U64<LittleEndian>,
24}
25
26impl AfcHeader {
27    pub const SIZE: usize = 40;
28
29    /// Build a request header.
30    pub fn new(
31        packet_num: u64,
32        opcode: AfcOpcode,
33        header_payload_len: usize,
34        payload_len: usize,
35    ) -> Self {
36        let this_len = Self::SIZE as u64 + header_payload_len as u64;
37        let entire_len = this_len + payload_len as u64;
38        Self {
39            magic: U64::new(AFC_MAGIC),
40            entire_len: U64::new(entire_len),
41            this_len: U64::new(this_len),
42            packet_num: U64::new(packet_num),
43            operation: U64::new(opcode as u64),
44        }
45    }
46}
47
48/// AFC operation codes (matches go-ios afc.go constants)
49#[derive(Debug, Clone, Copy, PartialEq, Eq)]
50#[repr(u64)]
51pub enum AfcOpcode {
52    Status = 0x00000001,
53    Data = 0x00000002,
54    ReadDir = 0x00000003,
55    WritePart = 0x00000006,
56    TruncateFile = 0x00000007,
57    RemovePath = 0x00000008,
58    MakePath = 0x00000009,
59    GetFileInfo = 0x0000000A,
60    GetDeviceInfo = 0x0000000B,
61    WriteFile = 0x0000000C, // not in go-ios but common
62    FileRefOpen = 0x0000000D,
63    FileRefOpenResult = 0x0000000E,
64    FileRefRead = 0x0000000F,
65    FileRefWrite = 0x00000010,
66    FileRefSeek = 0x00000011,
67    FileRefTell = 0x00000012,
68    FileRefTellResult = 0x00000013,
69    FileRefClose = 0x00000014,
70    FileRefSetFileSize = 0x00000015,
71    GetConnectionInfo = 0x00000016,
72    SetConnectionOptions = 0x00000017,
73    RenamePath = 0x00000018,
74    SetFSBlockSize = 0x00000019,
75    SetSocketBlockSize = 0x0000001A,
76    FileRefLock = 0x0000001B,
77    MakeLink = 0x0000001C,
78    GetFileHash = 0x0000001D,
79    SetModTime = 0x0000001E,
80    GetFileHashRange = 0x0000001F,
81    FileRefFlush = 0x00000020,
82    SetFileModTime = 0x00000021,
83    RemovePathAndContents = 0x00000022,
84}