1#![no_std]
26
27#[cfg(feature = "alloc")]
28#[macro_use]
29extern crate alloc;
30
31#[cfg(feature = "alloc")]
32use alloc::vec::Vec;
33
34use core::cell::UnsafeCell;
35use core::convert::TryFrom;
36use core::fmt;
37use core::mem::size_of;
38use core::sync::atomic::{compiler_fence, Ordering};
39
40#[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
41#[path = "x86.rs"]
42mod arch;
43
44mod selector_keys {
45 pub const SIGNATURE: u16 = 0x0000;
46 pub const FEATURE_BITMAP: u16 = 0x0001;
47 pub const DIR: u16 = 0x0019;
48}
49
50const SIGNATURE_DATA: &[u8] = b"QEMU";
51
52mod feature_bitmasks {
53 pub const _HAS_TRADITIONAL_INTERFACE: u32 = 1 << 0;
54 pub const HAS_DMA: u32 = 1 << 1;
55}
56
57#[derive(Debug, PartialEq, Eq)]
59#[non_exhaustive]
60pub enum FwCfgError {
61 InvalidSignature,
63}
64
65#[derive(Debug, PartialEq, Eq)]
67#[non_exhaustive]
68pub enum FwCfgWriteError {
69 DmaNotAvailable,
75 DmaFailed,
77}
78
79#[derive(Debug)]
81pub struct FwCfg {
82 mode: Mode,
83 feature_bitmap: Option<u32>,
84}
85
86#[derive(Debug)]
87enum Mode {
88 #[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
89 IOPort,
90 MemoryMapped(MemoryMappedDevice),
91}
92
93impl FwCfg {
94 #[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
104 pub unsafe fn new_for_x86() -> Result<FwCfg, FwCfgError> {
105 Self::new_for_mode(Mode::IOPort)
106 }
107
108 pub unsafe fn new_memory_mapped(base_ptr: *mut ()) -> Result<FwCfg, FwCfgError> {
116 let device = MemoryMappedDevice::new(base_ptr);
117 Self::new_for_mode(Mode::MemoryMapped(device))
118 }
119
120 unsafe fn new_for_mode(mode: Mode) -> Result<FwCfg, FwCfgError> {
121 let mut fw_cfg = FwCfg {
122 mode,
123 feature_bitmap: None,
124 };
125
126 let mut signature = [0u8; SIGNATURE_DATA.len()];
127 fw_cfg.select(selector_keys::SIGNATURE);
128 fw_cfg.read(&mut signature);
129
130 if signature != SIGNATURE_DATA {
131 return Err(FwCfgError::InvalidSignature);
132 }
133
134 Ok(fw_cfg)
135 }
136
137 fn feature_bitmap(&mut self) -> u32 {
140 self.feature_bitmap.unwrap_or_else(|| {
141 let mut buffer = [0u8; 4];
142 self.select(selector_keys::FEATURE_BITMAP);
143 self.read(&mut buffer);
144 let value = u32::from_le_bytes(buffer);
145 self.feature_bitmap = Some(value);
146 value
147 })
148 }
149
150 pub fn iter_files(&mut self) -> impl Iterator<Item = FwCfgFile> + '_ {
152 self.select(selector_keys::DIR);
153
154 let count = {
155 let mut buf = [0u8; size_of::<u32>()];
156 self.read(&mut buf);
157 u32::from_be_bytes(buf)
158 };
159 (0..count).map(move |_| {
160 let mut file = FwCfgFile::default();
161 self.read(file.as_mut_bytes());
162 file
163 })
164 }
165
166 pub fn find_files(&mut self, entries: &mut [(&str, Option<FwCfgFile>)]) {
185 for file in self.iter_files() {
186 let mut changed = false;
187
188 for (name, ret) in entries.iter_mut() {
189 if file.name() == *name {
190 *ret = Some(file.clone());
191 changed = true;
192 }
193 }
194
195 if changed && entries.iter().all(|entry| entry.1.is_some()) {
196 return;
197 }
198 }
199 }
200
201 pub fn find_file(&mut self, name: &str) -> Option<FwCfgFile> {
211 let mut entries = [(name, None)];
212 self.find_files(&mut entries);
213 entries[0].1.take()
214 }
215
216 pub fn read_file_to_buffer(&mut self, file: &FwCfgFile, buffer: &mut [u8]) {
222 let len = file.size().min(buffer.len());
223 self.select(file.key());
224 self.read(&mut buffer[..len]);
225 }
226
227 #[cfg(feature = "alloc")]
229 pub fn read_file(&mut self, file: &FwCfgFile) -> Vec<u8> {
230 let mut buf = vec![0u8; file.size()];
231 self.select(file.key());
232 self.read(&mut buf);
233 buf
234 }
235
236 pub fn write_to_file(&mut self, file: &FwCfgFile, data: &[u8]) -> Result<(), FwCfgWriteError> {
240 let has_dma = (self.feature_bitmap() & feature_bitmasks::HAS_DMA) != 0;
241 if !has_dma {
242 return Err(FwCfgWriteError::DmaNotAvailable);
243 }
244 let control = (file.key() as u32) << 16 | FwCfgDmaAccess::WRITE | FwCfgDmaAccess::SELECT;
245 let access = FwCfgDmaAccess::new(control, data.as_ptr() as _, data.len());
246 compiler_fence(Ordering::Release);
248 match &mut self.mode {
249 #[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
250 Mode::IOPort => unsafe { arch::start_dma(&access) },
251 Mode::MemoryMapped(device) => device.start_dma(&access),
252 }
253 loop {
254 let control = access.read_control();
255 if (control & FwCfgDmaAccess::ERROR) != 0 {
256 return Err(FwCfgWriteError::DmaFailed);
257 }
258 if control == 0 {
259 return Ok(());
260 }
261 }
262 }
263
264 fn select(&mut self, key: u16) {
265 match &mut self.mode {
266 #[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
267 Mode::IOPort => unsafe { arch::write_selector(key) },
268 Mode::MemoryMapped(device) => device.write_selector(key),
269 }
270 }
271
272 fn read(&mut self, buffer: &mut [u8]) {
273 match &mut self.mode {
274 #[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
275 Mode::IOPort => unsafe { arch::read_data(buffer) },
276 Mode::MemoryMapped(device) => device.read_data(buffer),
277 }
278 }
279}
280
281const _: () = assert!(size_of::<FwCfgFile>() == 64);
282
283#[derive(Clone, PartialEq, Eq)]
285#[repr(C)]
288pub struct FwCfgFile {
289 size_be: u32,
290 key_be: u16,
291 _reserved: u16,
292 name_bytes: [u8; 56],
293}
294
295impl Default for FwCfgFile {
299 fn default() -> Self {
300 Self {
301 size_be: 0,
302 key_be: 0,
303 _reserved: 0,
304 name_bytes: [0; 56],
305 }
306 }
307}
308
309impl FwCfgFile {
310 pub fn size(&self) -> usize {
312 u32::from_be(self.size_be) as usize
313 }
314
315 fn key(&self) -> u16 {
316 u16::from_be(self.key_be)
317 }
318
319 pub fn name(&self) -> &str {
321 let bytes = self.name_bytes.split(|&b| b == b'\x00').next().unwrap();
322 core::str::from_utf8(bytes).unwrap()
323 }
324
325 fn as_mut_bytes(&mut self) -> &mut [u8; size_of::<Self>()] {
326 let ptr: *mut Self = self;
327 let ptr: *mut [u8; size_of::<Self>()] = ptr.cast();
328 unsafe { &mut *ptr }
329 }
330}
331
332impl fmt::Debug for FwCfgFile {
333 fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
334 fmt.debug_struct("FwCfgFile")
335 .field("key", &self.key())
336 .field("size", &self.size())
337 .field("name", &self.name())
338 .finish()
339 }
340}
341
342#[derive(Debug)]
343struct MemoryMappedDevice {
344 base_ptr: *mut (),
345}
346
347impl MemoryMappedDevice {
348 unsafe fn new(base_ptr: *mut ()) -> Self {
349 Self { base_ptr }
350 }
351
352 fn register<T>(&self, offset_in_bytes: usize) -> *mut T {
353 let offset = offset_in_bytes / size_of::<T>();
354 unsafe { self.base_ptr.cast::<T>().add(offset) }
355 }
356
357 fn write_selector(&mut self, key: u16) {
358 let selector_offset = 8;
360 let selector_ptr = self.register::<u16>(selector_offset);
361 unsafe { selector_ptr.write_volatile(key.to_be()) }
362 }
363
364 fn read_data(&mut self, data: &mut [u8]) {
365 let data_offset = 0;
367 let data_ptr = self.register::<usize>(data_offset);
368 for chunk in data.chunks_mut(size_of::<usize>()) {
369 let word = unsafe { data_ptr.read_volatile() };
370 let bytes = word.to_ne_bytes();
373 chunk.copy_from_slice(&bytes[..chunk.len()]);
374 }
375 }
376
377 fn start_dma(&self, access: &FwCfgDmaAccess) {
378 let address = access as *const FwCfgDmaAccess as u64;
379 let offset = 16;
381 let dma_address_register: *mut u32 = self.register(offset);
382 unsafe {
383 let register_high = dma_address_register;
388 let register_low = dma_address_register.add(1); let address_high = (address >> 32) as u32;
390 let address_low = address as u32;
391 register_high.write_volatile(address_high.to_be());
392 compiler_fence(Ordering::AcqRel);
393 register_low.write_volatile(address_low.to_be());
394 }
395 }
396}
397
398#[derive(Debug)]
399#[repr(C)]
402struct FwCfgDmaAccess {
403 control_be: UnsafeCell<u32>,
404 length_be: u32,
405 address_be: u64,
406}
407
408impl FwCfgDmaAccess {
409 const ERROR: u32 = 1 << 0;
410 const _READ: u32 = 1 << 1;
411 const _SKIP: u32 = 1 << 2;
412 const SELECT: u32 = 1 << 3;
413 const WRITE: u32 = 1 << 4;
414
415 fn new(control: u32, ptr: *mut (), length: usize) -> Self {
416 Self {
417 control_be: UnsafeCell::new(control.to_be()),
418 length_be: u32::try_from(length).unwrap().to_be(),
419 address_be: u64::try_from(ptr as usize).unwrap().to_be(),
420 }
421 }
422
423 fn read_control(&self) -> u32 {
424 u32::from_be(unsafe { self.control_be.get().read_volatile() })
425 }
426}