1#[cfg(not(any(
4 feature = "plugin-api-v0",
5 feature = "plugin-api-v1",
6 feature = "plugin-api-v2",
7 feature = "plugin-api-v3",
8)))]
9use crate::Error;
10#[cfg(not(feature = "plugin-api-v0"))]
11use crate::Result;
12#[cfg(not(any(
13 feature = "plugin-api-v0",
14 feature = "plugin-api-v1",
15 feature = "plugin-api-v2",
16 feature = "plugin-api-v3",
17 feature = "plugin-api-v4"
18)))]
19use crate::sys::qemu_plugin_hwaddr_operation_result;
20#[cfg(not(any(
21 feature = "plugin-api-v0",
22 feature = "plugin-api-v1",
23 feature = "plugin-api-v2",
24 feature = "plugin-api-v3"
25)))]
26use crate::sys::{GByteArray, qemu_plugin_mem_value, qemu_plugin_mem_value_type};
27use crate::sys::{qemu_plugin_hwaddr, qemu_plugin_meminfo_t};
28use std::marker::PhantomData;
29
30#[derive(Debug, Clone)]
31pub struct MemoryInfo<'a> {
38 memory_info: qemu_plugin_meminfo_t,
39 marker: PhantomData<&'a ()>,
40}
41
42impl<'a> From<qemu_plugin_meminfo_t> for MemoryInfo<'a> {
43 fn from(info: qemu_plugin_meminfo_t) -> Self {
44 Self {
45 memory_info: info,
46 marker: PhantomData,
47 }
48 }
49}
50
51impl<'a> MemoryInfo<'a> {
52 pub fn size_shift(&self) -> usize {
55 (unsafe { crate::sys::qemu_plugin_mem_size_shift(self.memory_info) }) as usize
56 }
57
58 pub fn sign_extended(&self) -> bool {
60 unsafe { crate::sys::qemu_plugin_mem_is_sign_extended(self.memory_info) }
61 }
62
63 pub fn big_endian(&self) -> bool {
65 unsafe { crate::sys::qemu_plugin_mem_is_big_endian(self.memory_info) }
66 }
67
68 pub fn is_store(&self) -> bool {
70 unsafe { crate::sys::qemu_plugin_mem_is_store(self.memory_info) }
71 }
72
73 pub fn hwaddr(&'a self, vaddr: u64) -> Option<HwAddr<'a>> {
76 let hwaddr = unsafe { crate::sys::qemu_plugin_get_hwaddr(self.memory_info, vaddr) };
77 if hwaddr.is_null() {
78 None
79 } else {
80 Some(HwAddr::from(hwaddr))
81 }
82 }
83
84 #[cfg(not(any(
86 feature = "plugin-api-v0",
87 feature = "plugin-api-v1",
88 feature = "plugin-api-v2",
89 feature = "plugin-api-v3"
90 )))]
91 pub fn value(&self) -> MemValue {
92 let qemu_mem_value = unsafe { crate::sys::qemu_plugin_mem_get_value(self.memory_info) };
93 MemValue::from(qemu_mem_value)
94 }
95}
96
97#[cfg(not(any(
98 feature = "plugin-api-v0",
99 feature = "plugin-api-v1",
100 feature = "plugin-api-v2",
101 feature = "plugin-api-v3"
102)))]
103#[derive(Clone)]
104pub enum MemValue {
108 U8(u8),
110 U16(u16),
112 U32(u32),
114 U64(u64),
116 U128(u128),
118}
119
120#[cfg(not(any(
121 feature = "plugin-api-v0",
122 feature = "plugin-api-v1",
123 feature = "plugin-api-v2",
124 feature = "plugin-api-v3"
125)))]
126impl From<qemu_plugin_mem_value> for MemValue {
127 fn from(value: qemu_plugin_mem_value) -> Self {
128 unsafe {
129 match value.type_ {
130 qemu_plugin_mem_value_type::QEMU_PLUGIN_MEM_VALUE_U8 => Self::U8(value.data.u8_),
131 qemu_plugin_mem_value_type::QEMU_PLUGIN_MEM_VALUE_U16 => Self::U16(value.data.u16_),
132 qemu_plugin_mem_value_type::QEMU_PLUGIN_MEM_VALUE_U32 => Self::U32(value.data.u32_),
133 qemu_plugin_mem_value_type::QEMU_PLUGIN_MEM_VALUE_U64 => Self::U64(value.data.u64_),
134 qemu_plugin_mem_value_type::QEMU_PLUGIN_MEM_VALUE_U128 => {
135 let high = value.data.u128_.high as u128;
136 let low = value.data.u128_.low as u128;
137 Self::U128(high << 64 | low)
138 }
139 }
140 }
141 }
142}
143
144#[derive(Debug, Clone)]
145pub struct HwAddr<'a> {
152 hwaddr: usize,
153 marker: PhantomData<&'a ()>,
154}
155
156impl<'a> From<*mut qemu_plugin_hwaddr> for HwAddr<'a> {
157 fn from(hwaddr: *mut qemu_plugin_hwaddr) -> Self {
158 Self {
159 hwaddr: hwaddr as usize,
160 marker: PhantomData,
161 }
162 }
163}
164
165impl<'a> HwAddr<'a> {
166 pub fn is_io(&self) -> bool {
169 unsafe { crate::sys::qemu_plugin_hwaddr_is_io(self.hwaddr as *mut qemu_plugin_hwaddr) }
170 }
171
172 #[cfg(not(feature = "plugin-api-v0"))]
173 pub fn hwaddr(&self) -> u64 {
175 unsafe { crate::sys::qemu_plugin_hwaddr_phys_addr(self.hwaddr as *mut qemu_plugin_hwaddr) }
176 }
177
178 #[cfg(not(feature = "plugin-api-v0"))]
179 pub fn device_name(&self) -> Result<Option<String>> {
181 let device_name = unsafe {
182 crate::sys::qemu_plugin_hwaddr_device_name(self.hwaddr as *mut qemu_plugin_hwaddr)
183 };
184
185 if device_name.is_null() {
186 Ok(None)
187 } else {
188 let device_name_string = unsafe {
189 use std::ffi::CStr;
190 CStr::from_ptr(device_name)
191 }
192 .to_str()?
193 .to_string();
194 Ok(Some(device_name_string))
196 }
197 }
198}
199
200#[cfg(not(any(
201 feature = "plugin-api-v0",
202 feature = "plugin-api-v1",
203 feature = "plugin-api-v2",
204 feature = "plugin-api-v3"
205)))]
206pub fn qemu_plugin_read_memory_vaddr(addr: u64, buf: &mut [u8]) -> Result<()> {
208 let mut buf = GByteArray {
209 data: buf.as_mut_ptr(),
210 len: buf.len() as u32,
211 };
212
213 if unsafe {
214 crate::sys::qemu_plugin_read_memory_vaddr(
215 addr,
216 &mut buf as *mut GByteArray,
217 buf.len as usize,
218 )
219 } {
220 Ok(())
221 } else {
222 Err(Error::VaddrReadError { addr, len: buf.len })
223 }
224}
225
226#[cfg(not(any(
227 feature = "plugin-api-v0",
228 feature = "plugin-api-v1",
229 feature = "plugin-api-v2",
230 feature = "plugin-api-v3",
231 feature = "plugin-api-v4"
232)))]
233pub fn qemu_plugin_write_memory_vaddr(addr: u64, buf: &mut [u8]) -> Result<()> {
235 let mut buf = GByteArray {
236 data: buf.as_mut_ptr(),
237 len: buf.len() as u32,
238 };
239
240 if unsafe { crate::sys::qemu_plugin_write_memory_vaddr(addr, &mut buf as *mut GByteArray) } {
241 Ok(())
242 } else {
243 Err(Error::VaddrWriteError { addr, len: buf.len })
244 }
245}
246
247#[cfg(not(any(
248 feature = "plugin-api-v0",
249 feature = "plugin-api-v1",
250 feature = "plugin-api-v2",
251 feature = "plugin-api-v3",
252 feature = "plugin-api-v4"
253)))]
254#[derive(thiserror::Error, Debug, Clone, Copy, PartialEq, Eq)]
255pub enum HwaddrOperationResult {
257 #[error("Operation completed successfully")]
258 Ok = 0,
260 #[error("Unspecified error")]
261 Error = 1,
263 #[error("Device error")]
264 DeviceError = 2,
266 #[error("Access denied")]
267 AccessDenied = 3,
269 #[error("Invalid address")]
271 InvalidAddress = 4,
272 #[error("Invalid address space")]
274 InvalidAddressSpace = 5,
275}
276
277#[cfg(not(any(
278 feature = "plugin-api-v0",
279 feature = "plugin-api-v1",
280 feature = "plugin-api-v2",
281 feature = "plugin-api-v3",
282 feature = "plugin-api-v4"
283)))]
284impl From<qemu_plugin_hwaddr_operation_result> for HwaddrOperationResult {
285 fn from(value: qemu_plugin_hwaddr_operation_result) -> Self {
286 match value {
287 qemu_plugin_hwaddr_operation_result::QEMU_PLUGIN_HWADDR_OPERATION_OK => Self::Ok,
288 qemu_plugin_hwaddr_operation_result::QEMU_PLUGIN_HWADDR_OPERATION_ERROR => Self::Error,
289 qemu_plugin_hwaddr_operation_result::QEMU_PLUGIN_HWADDR_OPERATION_DEVICE_ERROR => Self::DeviceError,
290 qemu_plugin_hwaddr_operation_result::QEMU_PLUGIN_HWADDR_OPERATION_ACCESS_DENIED => Self::AccessDenied,
291 qemu_plugin_hwaddr_operation_result::QEMU_PLUGIN_HWADDR_OPERATION_INVALID_ADDRESS => Self::InvalidAddress,
292 qemu_plugin_hwaddr_operation_result::QEMU_PLUGIN_HWADDR_OPERATION_INVALID_ADDRESS_SPACE => Self::InvalidAddressSpace,
293 }
294 }
295}
296
297#[cfg(not(any(
298 feature = "plugin-api-v0",
299 feature = "plugin-api-v1",
300 feature = "plugin-api-v2",
301 feature = "plugin-api-v3",
302 feature = "plugin-api-v4"
303)))]
304pub fn qemu_plugin_read_memory_hwaddr(addr: u64, buf: &mut [u8]) -> Result<()> {
306 let mut buf = GByteArray {
307 data: buf.as_mut_ptr(),
308 len: buf.len() as u32,
309 };
310
311 match unsafe {
312 crate::sys::qemu_plugin_read_memory_hwaddr(
313 addr,
314 &mut buf as *mut GByteArray,
315 buf.len as usize,
316 )
317 }
318 .into()
319 {
320 HwaddrOperationResult::Ok => Ok(()),
321 error => Err(Error::HwaddrReadError {
322 addr,
323 len: buf.len,
324 result: error,
325 }),
326 }
327}
328
329#[cfg(not(any(
330 feature = "plugin-api-v0",
331 feature = "plugin-api-v1",
332 feature = "plugin-api-v2",
333 feature = "plugin-api-v3",
334 feature = "plugin-api-v4"
335)))]
336pub fn qemu_plugin_write_memory_hwaddr(addr: u64, buf: &mut [u8]) -> Result<()> {
338 let mut buf = GByteArray {
339 data: buf.as_mut_ptr(),
340 len: buf.len() as u32,
341 };
342
343 match unsafe { crate::sys::qemu_plugin_write_memory_hwaddr(addr, &mut buf as *mut GByteArray) }
344 .into()
345 {
346 HwaddrOperationResult::Ok => Ok(()),
347 error => Err(Error::HwaddrWriteError {
348 addr,
349 len: buf.len,
350 result: error,
351 }),
352 }
353}
354
355#[cfg(not(any(
356 feature = "plugin-api-v0",
357 feature = "plugin-api-v1",
358 feature = "plugin-api-v2",
359 feature = "plugin-api-v3",
360 feature = "plugin-api-v4"
361)))]
362pub fn qemu_plugin_translate_vaddr(vaddr: u64) -> Result<u64> {
365 let mut hwaddr: u64 = 0;
366 if unsafe { crate::sys::qemu_plugin_translate_vaddr(vaddr, &mut hwaddr as *mut _) } {
367 Ok(hwaddr)
368 } else {
369 Err(Error::VaddrTranslateError { vaddr })
370 }
371}