1use std::mem::size_of;
2
3use nix::{ioc, ioctl_readwrite_bad};
4
5#[repr(C)]
6#[derive(Clone, Debug)]
7pub struct GrantRef {
8 pub domid: u32,
9 pub reference: u32,
10}
11
12pub struct MapGrantRef {
13 pub count: u32,
14 pub pad: u32,
15 pub index: u64,
16 pub refs: Vec<GrantRef>,
17}
18
19impl MapGrantRef {
20 pub fn write(slice: &[GrantRef]) -> Vec<u32> {
21 let mut values = vec![slice.len() as u32, 0, 0, 0];
22 for r in slice {
23 values.push(r.domid);
24 values.push(r.reference);
25 }
26 values
27 }
28
29 pub fn read(count: u32, data: Vec<u32>) -> Option<MapGrantRef> {
30 let mut refs = Vec::new();
31
32 if data.len() < (4 + (count as u64 * 2)) as usize {
33 return None;
34 }
35
36 let index = (*data.get(2)? as u64) | (*data.get(3)? as u64) << 32;
37 for i in (4..data.len()).step_by(2) {
38 let Some(domid) = data.get(i) else {
39 break;
40 };
41 let Some(reference) = data.get(i + 1) else {
42 break;
43 };
44 refs.push(GrantRef {
45 domid: *domid,
46 reference: *reference,
47 });
48 }
49
50 Some(MapGrantRef {
51 count,
52 pad: 0,
53 index,
54 refs,
55 })
56 }
57}
58
59#[repr(C)]
60pub struct UnmapGrantRef {
61 pub index: u64,
62 pub count: u32,
63 pub pad: u32,
64}
65
66#[repr(C)]
67pub struct GetOffsetForVaddr {
68 pub vaddr: u64,
69 pub offset: u64,
70 pub count: u32,
71 pub pad: u32,
72}
73
74#[repr(C)]
75pub struct SetMaxGrants {
76 pub count: u32,
77}
78
79#[repr(C)]
80pub struct UnmapNotify {
81 pub index: u64,
82 pub action: u32,
83 pub port: u32,
84}
85
86pub const UNMAP_NOTIFY_CLEAR_BYTE: u32 = 0x1;
87pub const UNMAP_NOTIFY_SEND_EVENT: u32 = 0x2;
88
89ioctl_readwrite_bad!(map_grant_ref, ioc!(nix::sys::ioctl::NONE, 'G', 0, 24), u32);
90ioctl_readwrite_bad!(
91 unmap_grant_ref,
92 ioc!(nix::sys::ioctl::NONE, 'G', 1, size_of::<UnmapGrantRef>()),
93 UnmapGrantRef
94);
95ioctl_readwrite_bad!(
96 get_offset_for_vaddr,
97 ioc!(
98 nix::sys::ioctl::NONE,
99 'G',
100 2,
101 size_of::<GetOffsetForVaddr>()
102 ),
103 GetOffsetForVaddr
104);
105ioctl_readwrite_bad!(
106 set_max_grants,
107 ioc!(nix::sys::ioctl::NONE, 'G', 3, size_of::<SetMaxGrants>()),
108 SetMaxGrants
109);
110ioctl_readwrite_bad!(
111 unmap_notify,
112 ioc!(nix::sys::ioctl::NONE, 'G', 7, size_of::<UnmapNotify>()),
113 UnmapNotify
114);
115
116#[repr(C)]
117pub struct AllocGref {
118 pub domid: u16,
119 pub flags: u16,
120 pub count: u32,
121}
122
123impl AllocGref {
124 pub fn write(gref: AllocGref) -> Vec<u16> {
125 let mut values = vec![
126 gref.domid,
127 gref.flags,
128 (gref.count << 16) as u16,
129 gref.count as u16,
130 0,
131 0,
132 0,
133 0,
134 ];
135 for _ in 0..gref.count {
136 values.push(0);
137 values.push(0);
138 }
139 values
140 }
141
142 pub fn read(count: u32, data: Vec<u16>) -> Option<(u64, Vec<u32>)> {
143 let mut refs = Vec::new();
144
145 if data.len() < (8 + (count as u64 * 2)) as usize {
146 return None;
147 }
148
149 let index = (*data.get(4)? as u64)
150 | (*data.get(5)? as u64) << 16
151 | (*data.get(6)? as u64) << 32
152 | (*data.get(7)? as u64) << 48;
153 for i in (8..data.len()).step_by(2) {
154 let Some(bits_low) = data.get(i) else {
155 break;
156 };
157 let Some(bits_high) = data.get(i + 1) else {
158 break;
159 };
160 refs.push((*bits_low as u32) | (*bits_high as u32) << 16);
161 }
162 Some((index, refs))
163 }
164}
165
166#[repr(C)]
167pub struct DeallocGref {
168 pub index: u64,
169 pub count: u32,
170}
171
172ioctl_readwrite_bad!(alloc_gref, ioc!(nix::sys::ioctl::NONE, 'G', 5, 20), u16);
173ioctl_readwrite_bad!(
174 dealloc_gref,
175 ioc!(nix::sys::ioctl::NONE, 'G', 6, size_of::<DeallocGref>()),
176 DeallocGref
177);