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