1use zerocopy::{FromBytes, IntoBytes};
2
3#[derive(Debug, Clone, Copy, FromBytes, IntoBytes)]
4#[repr(C)]
5pub struct TimeSpec {
6 pub tv_sec: i64,
7 pub tv_nsec: i64,
8}
9
10impl TimeSpec {
11 pub const fn zero() -> Self {
13 Self {
14 tv_sec: 0,
15 tv_nsec: 0,
16 }
17 }
18
19 pub fn to_nanos(&self) -> u64 {
21 (self.tv_sec as u64)
22 .saturating_mul(1_000_000_000)
23 .saturating_add(self.tv_nsec as u64)
24 }
25
26 pub fn from_nanos(nanos: u64) -> Self {
28 Self {
29 tv_sec: (nanos / 1_000_000_000) as i64,
30 tv_nsec: (nanos % 1_000_000_000) as i64,
31 }
32 }
33}
34
35#[derive(Debug, Clone, Copy, FromBytes, IntoBytes)]
36#[repr(C)]
37pub struct Stat {
38 pub st_dev: u64,
39 pub st_ino: u64,
40 pub st_nlink: u64,
41 pub st_mode: u32,
42 pub st_uid: u32,
43 pub st_gid: u32,
44 pub _padding0: u32,
45 pub st_rdev: u64,
46 pub st_size: u64,
47 pub st_blksize: u64,
48 pub st_blocks: u64,
49 pub st_atime: TimeSpec,
50 pub st_mtime: TimeSpec,
51 pub st_ctime: TimeSpec,
52}
53
54#[derive(Debug, Clone, Copy, FromBytes, IntoBytes)]
55#[repr(C)]
56pub struct StatVfs {
57 pub f_bsize: u64,
58 pub f_frsize: u64,
59 pub f_blocks: u64,
60 pub f_bfree: u64,
61 pub f_bavail: u64,
62 pub f_files: u64,
63 pub f_ffree: u64,
64 pub f_favail: u64,
65 pub f_fsid: u64,
66 pub f_flag: u64,
67 pub f_namemax: u64,
68}
69
70#[derive(Debug, Clone, Copy, FromBytes, IntoBytes)]
71#[repr(C)]
72pub struct Map {
73 pub offset: usize,
74 pub size: usize,
75 pub flags: u32,
76 pub _reserved: u32,
77 pub addr: usize,
78}
79
80#[derive(Debug, Clone, Copy, FromBytes, IntoBytes)]
81#[repr(C)]
82pub struct HandleInfo {
83 pub resource_type: u32,
84 pub permissions: u32,
85 pub resource: u64,
86}
87
88pub const PCI_MATCH_VENDOR_ID: u32 = 1 << 0;
89pub const PCI_MATCH_DEVICE_ID: u32 = 1 << 1;
90pub const PCI_MATCH_CLASS_CODE: u32 = 1 << 2;
91pub const PCI_MATCH_SUBCLASS: u32 = 1 << 3;
92pub const PCI_MATCH_PROG_IF: u32 = 1 << 4;
93
94#[derive(Debug, Clone, Copy, FromBytes, IntoBytes)]
95#[repr(C, align(4))]
96pub struct PciAddress {
97 pub bus: u8,
98 pub device: u8,
99 pub function: u8,
100 pub _reserved: u8,
101}
102
103#[derive(Debug, Clone, Copy, FromBytes, IntoBytes)]
104#[repr(C)]
105pub struct PciProbeCriteria {
106 pub match_flags: u32,
107 pub vendor_id: u16,
108 pub device_id: u16,
109 pub class_code: u8,
110 pub subclass: u8,
111 pub prog_if: u8,
112 pub _reserved: u8,
113}
114
115#[derive(Debug, Clone, Copy, FromBytes, IntoBytes)]
116#[repr(C)]
117pub struct PciDeviceInfo {
118 pub address: PciAddress,
119 pub vendor_id: u16,
120 pub device_id: u16,
121 pub class_code: u8,
122 pub subclass: u8,
123 pub prog_if: u8,
124 pub revision: u8,
125 pub header_type: u8,
126 pub interrupt_line: u8,
127 pub interrupt_pin: u8,
128 pub _reserved: u8,
129}
130
131#[derive(Debug, Clone, Copy, FromBytes, IntoBytes)]
132#[repr(C)]
133pub struct FileStat {
134 pub st_dev: u64,
135 pub st_ino: u64,
136 pub st_mode: u32,
137 pub st_nlink: u32,
138 pub st_uid: u32,
139 pub st_gid: u32,
140 pub st_rdev: u64,
141 pub st_size: u64,
142 pub st_blksize: u64,
143 pub st_blocks: u64,
144 pub st_atime: TimeSpec,
145 pub st_mtime: TimeSpec,
146 pub st_ctime: TimeSpec,
147}
148
149impl FileStat {
150 pub const fn zeroed() -> Self {
152 FileStat {
153 st_dev: 0,
154 st_ino: 0,
155 st_mode: 0,
156 st_nlink: 0,
157 st_uid: 0,
158 st_gid: 0,
159 st_rdev: 0,
160 st_size: 0,
161 st_blksize: 0,
162 st_blocks: 0,
163 st_atime: TimeSpec::zero(),
164 st_mtime: TimeSpec::zero(),
165 st_ctime: TimeSpec::zero(),
166 }
167 }
168
169 pub fn is_dir(&self) -> bool {
171 (self.st_mode & 0o170000) == 0o040000
172 }
173
174 pub fn is_file(&self) -> bool {
176 (self.st_mode & 0o170000) == 0o100000
177 }
178}
179
180#[derive(Clone, Copy, FromBytes, IntoBytes)]
181#[repr(C, align(64))]
182pub struct IpcMessage {
183 pub sender: u64,
184 pub msg_type: u32,
185 pub flags: u32,
186 pub payload: [u8; 48],
187}
188
189impl IpcMessage {
190 pub const fn new(msg_type: u32) -> Self {
192 IpcMessage {
193 sender: 0,
194 msg_type,
195 flags: 0,
196 payload: [0u8; 48],
197 }
198 }
199
200 pub fn error_reply(sender: u64, status: i32) -> Self {
202 let mut msg = IpcMessage::new(0x80);
203 msg.sender = sender;
204 msg.payload[0..4].copy_from_slice(&(status as u32).to_le_bytes());
205 msg
206 }
207}
208
209impl core::fmt::Debug for IpcMessage {
210 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
212 f.debug_struct("IpcMessage")
213 .field("sender", &self.sender)
214 .field("msg_type", &format_args!("0x{:02x}", self.msg_type))
215 .field("flags", &self.flags)
216 .finish()
217 }
218}
219
220pub const SEEK_SET: usize = 0;
221pub const SEEK_CUR: usize = 1;
222pub const SEEK_END: usize = 2;
223
224pub const DT_UNKNOWN: u8 = 0;
226pub const DT_FIFO: u8 = 1;
227pub const DT_CHR: u8 = 2;
228pub const DT_DIR: u8 = 4;
229pub const DT_BLK: u8 = 6;
230pub const DT_REG: u8 = 8;
231pub const DT_LNK: u8 = 10;
232pub const DT_SOCK: u8 = 12;
233
234#[derive(Debug, Clone, Copy, FromBytes, IntoBytes)]
239#[repr(C, packed)]
240pub struct DirentHeader {
241 pub ino: u64,
242 pub file_type: u8,
243 pub name_len: u16,
244 pub _padding: u8,
245}
246
247impl DirentHeader {
248 pub const SIZE: usize = 12; pub const fn entry_size(&self) -> usize {
252 Self::SIZE + self.name_len as usize + 1
253 }
254}
255
256macro_rules! assert_abi_struct {
257 ($t:ty, $size:expr, $align:expr) => {
258 static_assertions::assert_eq_size!($t, [u8; $size]);
259 static_assertions::const_assert_eq!(core::mem::align_of::<$t>(), $align);
260 };
261}
262
263assert_abi_struct!(DirentHeader, 12, 1);
264assert_abi_struct!(Stat, 120, 8);
265assert_abi_struct!(StatVfs, 88, 8);
266assert_abi_struct!(Map, 32, 8);
267assert_abi_struct!(FileStat, 112, 8);
268assert_abi_struct!(IpcMessage, 64, 64);
269assert_abi_struct!(TimeSpec, 16, 8);
270assert_abi_struct!(HandleInfo, 16, 8);
271assert_abi_struct!(PciAddress, 4, 4);
272assert_abi_struct!(PciProbeCriteria, 12, 4);
273assert_abi_struct!(PciDeviceInfo, 16, 4);