a653rs_linux_core/
syscall.rs

1//! Common definitions for the execution of system calls
2
3use anyhow::{anyhow, Result};
4use byteorder::{NativeEndian, ReadBytesExt, WriteBytesExt};
5use enum_primitive::FromPrimitive;
6
7pub const SYSCALL_SOCKET_PATH: &str = "/syscall-a653";
8
9enum_from_primitive! {
10#[derive(Debug, Copy, Clone, PartialEq)]
11pub enum ApexSyscall {
12    /// P1-5 3.2.2.1 - GET_PARTITION_STATUS
13    GetPartitionStatus = 6530,
14    /// P1-5 3.2.2.2 - SET_PARTITION_MODE
15    SetPartitionMode = 6531,
16    /////////////////////
17    //* 10 Free Spaces */
18    /////////////////////
19    /// P1-5 3.3.2.1 - GET_PROCESS_ID
20    GetProcessId = 6542,
21    /// P1-5 3.3.2.2 - GET_PROCESS_STATUS
22    GetProcessStatus = 6543,
23    /// P1-5 3.3.2.3 - CREATE_PROCESS
24    CreateProcess = 6544,
25    /// P1-5 3.3.2.4 - SET_PRIORITY
26    SetPriority = 6545,
27    /// P1-5 3.3.2.5 - SUSPEND_SELF
28    SuspendSelf = 6546,
29    /// P1-5 3.3.2.6 - SUSPEND
30    Suspend = 6547,
31    /// P1-5 3.3.2.7 - RESUME
32    Resume = 6548,
33    /// P1-5 3.3.2.8 - STOP_SELF
34    StopSelf = 6549,
35    /// P1-5 3.3.2.9 - STOP
36    Stop = 6550,
37    /// P1-5 3.3.2.10 - START
38    Start = 6551,
39    /// P1-5 3.3.2.11 - DELAY_START
40    DelayStart = 6552,
41    /// P1-5 3.3.2.12 - LOCK_PREEMPTION
42    LockPreemption = 6553,
43    /// P1-5 3.3.2.13 - UNLOCK_PREEMPTION
44    UnlockPreemption = 6554,
45    /// P1-5 3.3.2.14 - GET_MY_ID
46    GetMyId = 6555,
47    /// P1-5 3.3.2.15 - INITIALIZE_PROCESS_CORE_AFFINITY
48    InitializeProcessCoreAffinity = 6556,
49    /// P1-5 3.3.2.16 - GET_MY_PROCESSOR_CORE_ID
50    GetMyProcessorCoreId = 6557,
51    /// P1-5 3.3.2.17 - GET_MY_INDEX
52    GetMyIndex = 6558,
53    /////////////////////
54    //* 10 Free Spaces */
55    /////////////////////
56    /// P1-5 3.4.2.1 - TIMED_WAIT
57    TimedWait = 6569,
58    /// P1-5 3.4.2.2 - PERIODIC_WAIT
59    PeriodicWait = 6570,
60    /// P1-5 3.4.2.3 - GET_TIME
61    GetTime = 6571,
62    /// P1-5 3.4.2.4 - REPLENISH
63    Replenish = 6572,
64    /////////////////////
65    //* 10 Free Spaces */
66    /////////////////////
67    /// P1-5 3.6.2.1.1 - CREATE_SAMPLING_PORT
68    CreateSamplingPort = 6583,
69    /// P1-5 3.6.2.1.2 - WRITE_SAMPLING_MESSAGE
70    WriteSamplingMessage = 6584,
71    /// P1-5 3.6.2.1.3 - READ_SAMPLING_MESSAGE
72    ReadSamplingMessage = 6585,
73    /// P1-5 3.6.2.1.4 - GET_SAMPLING_MESSAGE_PORT_ID
74    GetSamplingMessagePortId = 6586,
75    /// P1-5 3.6.2.1.5 - GET_SAMPLING_PORT_STATUS
76    GetSamplingPortStatus = 6587,
77    /////////////////////
78    //* 10 Free Spaces */
79    /////////////////////
80    /// P1-5 3.6.2.1.1 - CREATE_QUEUING_PORT
81    CreateQueuingPort = 6598,
82    /// P1-5 3.6.2.1.2 - SEND_QUEUING_MESSAGE
83    SendQueuingMessage = 6599,
84    /// P1-5 3.6.2.1.3 - RECEIVE_QUEUING_MESSAGE
85    ReceiveQueuingMessage = 6600,
86    /// P1-5 3.6.2.1.4 - GET_QUEUING_MESSAGE_PORT_ID
87    GetQueuingMessagePortId = 6601,
88    /// P1-5 3.6.2.1.5 - GET_QUEUING_PORT_STATUS
89    GetQueuingPortStatus = 6602,
90    /// P1-5 3.6.2.1.6 - CLEAR_QUEUING_PORT
91    ClearQueuingPort = 6603,
92    /////////////////////
93    //* 10 Free Spaces */
94    /////////////////////
95    /// P1-5 3.7.2.1.1 - CREATE_BUFFER
96    CreateBuffer = 6614,
97    /// P1-5 3.7.2.1.2 - SEND_BUFFER
98    SendBuffer = 6615,
99    /// P1-5 3.7.2.1.3 - RECEIVE_BUFFER
100    ReceiveBuffer = 6616,
101    /// P1-5 3.7.2.1.4 - GET_BUFFER_ID
102    GetBufferId = 6617,
103    /// P1-5 3.7.2.1.5 - GET_BUFFER_STATUS
104    GetBufferStatus = 6618,
105    /////////////////////
106    //* 10 Free Spaces */
107    /////////////////////
108    /// P1-5 3.7.2.2.1 - CREATE_BLACKBOARD
109    CreateBlackboard = 6629,
110    /// P1-5 3.7.2.2.2 - DISPLAY_BLACKBOARD
111    DisplayBlackboard = 6630,
112    /// P1-5 3.7.2.2.3 - READ_BLACKBOARD
113    ReadBlackboard = 6631,
114    /// P1-5 3.7.2.2.4 - CLEAR_BLACKBOARD
115    ClearBlackboard = 6632,
116    /// P1-5 3.7.2.2.5 - GET_BLACKBOARD_ID
117    GetBlackboardId = 6633,
118    /// P1-5 3.7.2.2.6 - GET_BLACKBOARD_STATUS
119    GetBlackboardStatus = 6634,
120    /////////////////////
121    //* 10 Free Spaces */
122    /////////////////////
123    /// P1-5 3.7.2.3.1 - CREATE_SEMAPHORE
124    CreateSemaphore = 6645,
125    /// P1-5 3.7.2.3.2 - WAIT_SEMAPHORE
126    WaitSemaphore = 6646,
127    /// P1-5 3.7.2.3.3 - SIGNAL_SEMAPHORE
128    SignalSemaphore = 6647,
129    /// P1-5 3.7.2.3.4 - GET_SEMAPHORE_ID
130    GetSemaphoreId = 6648,
131    /// P1-5 3.7.2.3.5 - GET_SEMAPHORE_STATUS
132    GetSemaphoreStatus = 6649,
133    /////////////////////
134    //* 10 Free Spaces */
135    /////////////////////
136    /// P1-5 3.7.2.4.1 - CREATE_EVENT
137    CreateEvent = 6660,
138    /// P1-5 3.7.2.4.2 - SET_EVENT
139    SetEvent = 6661,
140    /// P1-5 3.7.2.4.3 - RESET_EVENT
141    ResetEvent = 6662,
142    /// P1-5 3.7.2.4.4 - WAIT_EVENT
143    WaitEvent = 6663,
144    /// P1-5 3.7.2.4.5 - GET_EVENT_ID
145    GetEventId = 6664,
146    /// P1-5 3.7.2.4.6 - GET_EVENT_STATUS
147    GetEventStatus = 6665,
148    /////////////////////
149    //* 10 Free Spaces */
150    /////////////////////
151    /// P1-5 3.7.2.1.1 - CREATE_MUTEX
152    CreateMutex = 6676,
153    /// P1-5 3.7.2.1.2 - ACQUIRE_MUTEX
154    AcquireMutex = 6677,
155    /// P1-5 3.7.2.1.3 - RELEASE_MUTEX
156    ReleaseMutex = 6678,
157    /// P1-5 3.7.2.1.4 - RESET_MUTEX
158    ResetMutex = 6679,
159    /// P1-5 3.7.2.1.5 - GET_MUTEX_ID
160    GetMutexId = 6680,
161    /// P1-5 3.7.2.1.6 - GET_MUTEX_STATUS
162    GetMutexStatus = 6681,
163    /// P1-5 3.7.2.1.7 - GET_PROCIESS_MUTEX_STATE
164    GetProciessMutexState = 6682,
165    /////////////////////
166    //* 10 Free Spaces */
167    /////////////////////
168    /// P1-5 3.8.2.1 - REPORT_APPLICATION_MESSAGE
169    ReportApplicationMessage = 6693,
170    /// P1-5 3.8.2.2 - CREATE_ERROR_HANDLER
171    CreateErrorHandler = 6694,
172    /// P1-5 3.8.2.3 - GET_ERROR_STATUS
173    GetErrorStatus = 6695,
174    /// P1-5 3.8.2.4 - RAISE_APPLICATION_ERROR
175    RaiseApplicationError = 6696,
176    /// P1-5 3.8.2.5 - CONFIGURE_ERROR_HANDLER
177    ConfigureErrorHandler = 6697,
178}
179}
180
181#[derive(Debug, PartialEq)]
182pub struct SyscallRequest {
183    pub id: ApexSyscall,
184    pub params: Vec<u64>,
185}
186
187#[derive(Debug, PartialEq)]
188pub struct SyscallResponse {
189    pub id: ApexSyscall,
190    pub status: u64,
191}
192
193impl SyscallRequest {
194    /// Serializes a SyscallRequest into its binary representation
195    ///
196    /// The format for serializing a SyscallRequest is defined as follows:
197    /// ```text
198    /// id [u64]
199    /// nparams [u8]
200    /// params [u64 * nparams]
201    /// ```
202    ///
203    /// All integers are encoded in native endian.
204    pub fn serialize(&self) -> Result<Vec<u8>> {
205        let mut serialized: Vec<u8> = Vec::new();
206        serialized.write_u64::<NativeEndian>(self.id as u64)?;
207        serialized.write_u8(self.params.len().try_into()?)?;
208        for &param in &self.params {
209            serialized.write_u64::<NativeEndian>(param)?;
210        }
211
212        Ok(serialized)
213    }
214
215    /// Deserializes a serialized SyscallRequest back into its internal
216    /// representation
217    pub fn deserialize(serialized: &Vec<u8>) -> Result<Self> {
218        let mut serialized: &[u8] = serialized;
219
220        let id = ApexSyscall::from_u64(serialized.read_u64::<NativeEndian>()?)
221            .ok_or(anyhow!("deserialization of ApexSyscall failed"))?;
222
223        let nparams = serialized.read_u8()?;
224        let mut params: Vec<u64> = Vec::with_capacity(nparams as usize);
225        for _ in 0..nparams {
226            params.push(serialized.read_u64::<NativeEndian>()?);
227        }
228
229        Ok(SyscallRequest { id, params })
230    }
231}
232
233impl SyscallResponse {
234    /// Serializes a SyscallResponse into its binary representation
235    ///
236    /// The format for serializing a SyscallResponse is defined as follows:
237    /// ```text
238    /// id [u64]
239    /// status [u64]
240    /// ```
241    ///
242    /// All integers are encoded in native endian.
243    pub fn serialize(&self) -> Result<Vec<u8>> {
244        let mut serialized: Vec<u8> = Vec::new();
245        serialized.write_u64::<NativeEndian>(self.id as u64)?;
246        serialized.write_u64::<NativeEndian>(self.status)?;
247
248        Ok(serialized)
249    }
250
251    /// Deserializes a serialized SyscallResponse back into its internal
252    /// representation
253    pub fn deserialize(serialized: &Vec<u8>) -> Result<Self> {
254        let mut serialized: &[u8] = serialized;
255
256        let id = ApexSyscall::from_u64(serialized.read_u64::<NativeEndian>()?)
257            .ok_or(anyhow!("deserialization of ApexSyscall failed"))?;
258        let status = serialized.read_u64::<NativeEndian>()?;
259
260        Ok(SyscallResponse { id, status })
261    }
262}
263
264#[cfg(test)]
265mod tests {
266    use super::*;
267
268    #[test]
269    fn test_serialize_request() {
270        let request = SyscallRequest {
271            id: ApexSyscall::Start,
272            params: vec![1, 2, 3],
273        };
274        let serialized = request.serialize().unwrap();
275        let mut serialized: &[u8] = &serialized;
276
277        let id = serialized.read_u64::<NativeEndian>().unwrap();
278        assert_eq!(id, ApexSyscall::Start as u64);
279
280        let nparams = serialized.read_u8().unwrap();
281        assert_eq!(nparams, 3);
282
283        let params = [
284            serialized.read_u64::<NativeEndian>().unwrap(),
285            serialized.read_u64::<NativeEndian>().unwrap(),
286            serialized.read_u64::<NativeEndian>().unwrap(),
287        ];
288        assert_eq!(params, [1, 2, 3]);
289        assert!(serialized.is_empty());
290    }
291
292    #[test]
293    fn test_serialize_response() {
294        let response = SyscallResponse {
295            id: ApexSyscall::Start,
296            status: 42,
297        };
298        let serialized = response.serialize().unwrap();
299        let mut serialized: &[u8] = &serialized;
300
301        let id = serialized.read_u64::<NativeEndian>().unwrap();
302        assert_eq!(id, ApexSyscall::Start as u64);
303
304        let status = serialized.read_u64::<NativeEndian>().unwrap();
305        assert_eq!(status, 42);
306        assert!(serialized.is_empty());
307    }
308
309    #[test]
310    fn test_deserialize_request() {
311        let request = SyscallRequest {
312            id: ApexSyscall::Start,
313            params: vec![1, 2, 3],
314        };
315        let serialized = request.serialize().unwrap();
316        let deserialized = SyscallRequest::deserialize(&serialized).unwrap();
317        assert_eq!(request, deserialized);
318        assert!(!serialized.is_empty());
319    }
320
321    #[test]
322    fn test_deserialize_response() {
323        let response = SyscallResponse {
324            id: ApexSyscall::Start,
325            status: 42,
326        };
327        let serialized = response.serialize().unwrap();
328        let deserialized = SyscallResponse::deserialize(&serialized).unwrap();
329        assert_eq!(response, deserialized);
330        assert!(!serialized.is_empty());
331    }
332}