fs/
messages.rs

1// SPDX-FileCopyrightText: 2025 Foundation Devices, Inc. <hello@foundation.xyz>
2// SPDX-License-Identifier: GPL-3.0-or-later
3
4use num_traits::{FromPrimitive, ToPrimitive};
5use server::{rkyv_with::WithAppId, SimpleMemoryMessage};
6use xous::{AppId, MemoryRange};
7
8use crate::{
9    DirEntry, DirHandle, Error, FileHandle, FileSystemEvent, Location, MappedFileInTheirSpace, Metadata,
10    OpenFlags, SeekFrom,
11};
12
13#[derive(Debug, server::Message, rkyv::Archive, rkyv::Serialize, rkyv::Deserialize)]
14#[response(Result<FileHandle, Error>)]
15pub struct OpenFileMessage {
16    pub path: String,
17    pub location: Location,
18    pub flags: OpenFlags,
19}
20
21#[derive(Debug, server::Message, rkyv::Archive, rkyv::Serialize, rkyv::Deserialize)]
22#[response(Result<DirHandle, Error>)]
23pub struct OpenDirMessage {
24    pub path: String,
25    pub location: Location,
26}
27
28#[derive(Debug, server::Message, rkyv::Archive, rkyv::Serialize, rkyv::Deserialize)]
29#[response(Result<DirHandle, Error>)]
30pub struct CreateDirMessage {
31    pub path: String,
32    pub location: Location,
33}
34
35#[derive(Debug, server::Message)]
36#[response(Result<(), Error>)]
37pub struct CloseFile(pub FileHandle);
38
39#[derive(Debug, server::Message)]
40#[response(Result<(), Error>)]
41pub struct CloseDir(pub DirHandle);
42
43#[derive(Debug, server::Message, rkyv::Archive, rkyv::Serialize, rkyv::Deserialize)]
44#[event(FileSystemEvent)]
45pub struct SubscribeFilesystemEvent(pub Location);
46
47#[derive(Debug, server::Message)]
48#[response(())]
49pub struct FormatEncryptedVolume;
50
51#[derive(Debug, server::Message)]
52#[response(Result<(), Error>)]
53pub struct Flush(pub FileHandle);
54
55#[derive(Debug, server::Message)]
56#[response(Result<(), Error>)]
57pub struct FlushFs(pub Location);
58
59#[derive(Debug, server::Message, rkyv::Archive, rkyv::Serialize, rkyv::Deserialize)]
60#[response(Result<MappedFileInTheirSpace, Error>)]
61pub struct MapFileMessage {
62    pub path: String,
63    pub location: Location,
64}
65
66#[derive(Debug, Clone, Copy, PartialEq, Eq, rkyv::Archive, rkyv::Serialize, rkyv::Deserialize)]
67pub enum AppResourcesRoot {
68    BuiltIn,
69    Sideloaded,
70}
71
72#[derive(Debug, server::Message, rkyv::Archive, rkyv::Serialize, rkyv::Deserialize)]
73#[response(Result<(), Error>)]
74pub struct RegisterAppResources {
75    #[rkyv(with = WithAppId)]
76    pub app_id: AppId,
77    pub root: AppResourcesRoot,
78    pub app_dir: String,
79}
80
81#[derive(Debug, server::Message, rkyv::Archive, rkyv::Serialize, rkyv::Deserialize)]
82#[response(Result<Metadata, Error>)]
83pub enum GetMetadata {
84    Path { path: String, location: Location },
85    Handle { handle: FileHandle },
86}
87
88#[derive(Debug, server::Message, rkyv::Archive, rkyv::Serialize, rkyv::Deserialize)]
89#[response(Result<Option<DirEntry>, Error>)]
90pub struct NextEntry(pub DirHandle);
91
92#[derive(Debug, server::Message)]
93#[response(Result<usize, Error>)]
94pub struct ReadBlocks {
95    pub buf: MemoryRange,
96    pub block_index: u32,
97    pub block_count: usize,
98    pub location: Location,
99}
100
101#[derive(Debug, server::Message)]
102#[response(Result<usize, Error>)]
103pub struct WriteBlocks {
104    pub buf: MemoryRange,
105    pub block_index: u32,
106    pub block_count: usize,
107    pub location: Location,
108}
109
110#[derive(Debug, server::Message)]
111#[response(Result<usize, Error>)]
112pub struct BlockCount(pub Location);
113
114#[derive(Debug, server::Message)]
115#[response(Result<usize, Error>)]
116pub struct ReadFile {
117    pub buf: MemoryRange,
118    pub handle: FileHandle,
119    pub read_len: usize,
120}
121
122#[derive(Debug, server::Message)]
123#[response(Result<usize, Error>)]
124pub struct WriteFile {
125    pub buf: MemoryRange,
126    pub handle: FileHandle,
127    pub write_len: usize,
128}
129
130#[derive(Debug, server::Message, rkyv::Archive, rkyv::Serialize, rkyv::Deserialize)]
131#[response(Result<u64, Error>)]
132pub struct SeekFile {
133    pub file: FileHandle,
134    pub pos: SeekFrom,
135}
136
137#[derive(Debug, server::Message, rkyv::Archive, rkyv::Serialize, rkyv::Deserialize)]
138#[response(Result<(), Error>)]
139pub struct Remove {
140    pub path: String,
141    pub location: Location,
142}
143
144#[derive(Debug, server::Message, rkyv::Archive, rkyv::Serialize, rkyv::Deserialize)]
145#[response(Result<(), Error>)]
146pub struct AtomicCopy {
147    pub src: String,
148    pub dest_dir: String,
149    pub rename: Option<String>,
150    pub location: Location,
151}
152
153#[derive(Debug, server::Message, rkyv::Archive, rkyv::Serialize, rkyv::Deserialize)]
154#[response(Result<(), Error>)]
155pub struct Rename {
156    pub location: Location,
157    pub from: String,
158    pub to: String,
159}
160
161#[derive(Debug, server::Message, rkyv::Archive, rkyv::Serialize, rkyv::Deserialize)]
162#[response(Result<(), Error>)]
163pub struct SetLen {
164    pub handle: FileHandle,
165    pub len: u64,
166}
167
168#[derive(Debug, server::Message, rkyv::Archive, rkyv::Serialize, rkyv::Deserialize)]
169#[response(Result<(), Error>)]
170pub struct TruncateFile(pub FileHandle);
171
172#[derive(Debug, server::Message, rkyv::Archive, rkyv::Serialize, rkyv::Deserialize)]
173#[response(Result<(), Error>)]
174pub struct SetMtime {
175    pub handle: FileHandle,
176    pub datetime: crate::DateTime,
177}
178
179#[derive(Debug, server::Message, rkyv::Archive, rkyv::Serialize, rkyv::Deserialize)]
180#[response(Result<Vec<u8>, Error>)]
181pub struct AsyncRead {
182    pub handle: FileHandle,
183    pub read_len: usize,
184}
185
186#[derive(Debug, server::Message, rkyv::Archive, rkyv::Serialize, rkyv::Deserialize)]
187#[response(Result<usize, Error>)]
188pub struct AsyncWrite {
189    pub handle: FileHandle,
190    pub buffer: Vec<u8>,
191}
192
193#[derive(Debug, server::Message)]
194#[response(Result<usize, Error>)]
195pub struct AsyncCopyBlock {
196    pub from: FileHandle,
197    pub to: FileHandle,
198    pub len: usize,
199}
200
201#[derive(Debug, server::Message)]
202#[response(Result<(), Error>)]
203pub struct MountAirlock(pub bool);
204
205#[derive(Debug, server::Message)]
206#[response(Result<(), Error>)]
207pub struct FormatAirlock;
208
209#[derive(Debug, server::Message)]
210#[response(Result<(), Error>)]
211pub struct FormatUsb;
212
213macro_rules! declare_msg {
214    ($name:ident) => {
215        #[derive(Debug, server::Message)]
216        #[response(())]
217        pub struct $name;
218    };
219}
220
221declare_msg!(GetUsbReadAccess);
222declare_msg!(GetUsbWriteAccess);
223declare_msg!(GetBootReadAccess);
224declare_msg!(GetBootWriteAccess);
225declare_msg!(GetUserReadAccess);
226declare_msg!(GetUserWriteAccess);
227declare_msg!(GetSystemReadAccess);
228declare_msg!(GetSystemWriteAccess);
229declare_msg!(GetSystemAppDataReadAccess);
230declare_msg!(GetSystemAppDataWriteAccess);
231declare_msg!(GetEncryptedRootReadAccess);
232declare_msg!(GetEncryptedRootWriteAccess);
233declare_msg!(GetAirlockReadAccess);
234declare_msg!(GetAirlockWriteAccess);
235
236impl From<SimpleMemoryMessage> for ReadBlocks {
237    fn from(msg: SimpleMemoryMessage) -> Self {
238        Self {
239            buf: msg.buf,
240            block_index: msg.arg1 as u32,
241            block_count: (msg.arg2 & 0xFFFFFF),
242            location: Location::from_usize(msg.arg2 >> 24).unwrap_or(Location::EncryptedRoot),
243        }
244    }
245}
246
247impl From<ReadBlocks> for SimpleMemoryMessage {
248    fn from(read: ReadBlocks) -> Self {
249        Self {
250            buf: read.buf,
251            arg1: read.block_index as usize,
252            arg2: (read.block_count & 0xFFFFFF) | (read.location.to_usize().unwrap() << 24),
253        }
254    }
255}
256
257impl From<SimpleMemoryMessage> for WriteBlocks {
258    fn from(msg: SimpleMemoryMessage) -> Self {
259        Self {
260            buf: msg.buf,
261            block_index: msg.arg1 as u32,
262            block_count: (msg.arg2 & 0xFFFFFF),
263            location: Location::from_usize(msg.arg2 >> 24).unwrap_or(Location::EncryptedRoot),
264        }
265    }
266}
267
268impl From<WriteBlocks> for SimpleMemoryMessage {
269    fn from(write: WriteBlocks) -> Self {
270        Self {
271            buf: write.buf,
272            arg1: write.block_index as usize,
273            arg2: (write.block_count & 0xFFFFFF) | (write.location.to_usize().unwrap() << 24),
274        }
275    }
276}
277
278impl From<SimpleMemoryMessage> for ReadFile {
279    fn from(msg: SimpleMemoryMessage) -> Self {
280        Self { buf: msg.buf, handle: FileHandle(msg.arg1 as u32), read_len: msg.arg2 }
281    }
282}
283
284impl From<ReadFile> for SimpleMemoryMessage {
285    fn from(read: ReadFile) -> Self {
286        Self { buf: read.buf, arg1: read.handle.0 as usize, arg2: read.read_len }
287    }
288}
289
290impl From<SimpleMemoryMessage> for WriteFile {
291    fn from(msg: SimpleMemoryMessage) -> Self {
292        Self { buf: msg.buf, handle: FileHandle(msg.arg1 as u32), write_len: msg.arg2 }
293    }
294}
295
296impl From<WriteFile> for SimpleMemoryMessage {
297    fn from(write: WriteFile) -> Self {
298        Self { buf: write.buf, arg1: write.handle.0 as usize, arg2: write.write_len }
299    }
300}
301
302// AsScalar/FromScalar implementations for blockingScalar messages
303impl server::AsScalar<4> for AsyncCopyBlock {
304    fn as_scalar(&self) -> [u32; 4] { [self.from.0, self.to.0, self.len as u32, 0] }
305}
306
307impl server::FromScalar<4> for AsyncCopyBlock {
308    fn from_scalar([from, to, len, _]: [u32; 4]) -> Self {
309        Self { from: FileHandle(from), to: FileHandle(to), len: len as usize }
310    }
311}