hvlite_core/worker/
rom.rs

1// Copyright (c) Microsoft Corporation.
2// Licensed under the MIT License.
3
4//! ROM implementation based on a shared memory object.
5//!
6//! FUTURE: Consider implementing the Hyper-V pseudo ROMs by putting them
7//! somewhere in guest memory that will be untouched during the early boot
8//! process. This will save having to allocate and migrate additional objects.
9
10use guestmem::MapRom;
11use guestmem::MappableGuestMemory;
12use guestmem::MemoryMapper;
13use guestmem::UnmapRom;
14use hvlite_pcat_locator::RomFileLocation;
15use std::io::Read;
16use std::io::Seek;
17use std::io::SeekFrom;
18
19pub struct Rom {
20    mapper: Box<dyn MemoryMapper>,
21    name: String,
22    len: u64,
23    backing: sparse_mmap::Mappable,
24}
25
26pub struct RomBuilder {
27    name: String,
28    mapper: Box<dyn MemoryMapper>,
29}
30
31impl RomBuilder {
32    pub fn new(name: String, mapper: Box<dyn MemoryMapper>) -> Self {
33        Self { name, mapper }
34    }
35
36    /// Constructs a ROM from the specified bytes in the specified file.
37    pub fn build_from_file_location(self, details: &RomFileLocation) -> std::io::Result<Rom> {
38        let mut file = &details.file;
39        file.seek(SeekFrom::Start(details.start))?;
40        let mut buf = vec![0; details.len];
41        file.read_exact(&mut buf)?;
42        self.build_from_slice(&buf)
43    }
44
45    /// Constructs a ROM from the specified data.
46    fn build_from_slice(self, data: &[u8]) -> std::io::Result<Rom> {
47        let backing = sparse_mmap::alloc_shared_memory(data.len())?;
48        let mapping = sparse_mmap::SparseMapping::new(data.len())?;
49        mapping.map_file(0, data.len(), &backing, 0, true)?;
50        mapping.write_at(0, data).unwrap();
51        Ok(Rom {
52            name: self.name,
53            mapper: self.mapper,
54            len: data.len() as u64,
55            backing,
56        })
57    }
58}
59
60impl MapRom for Rom {
61    fn map_rom(&self, gpa: u64, offset: u64, len: u64) -> std::io::Result<Box<dyn UnmapRom>> {
62        assert!(offset + len <= self.len);
63        let (mut memory, region) = self.mapper.new_region(len as usize, self.name.clone())?;
64        region.map(0, &self.backing, offset, len as usize, false)?;
65        memory.map_to_guest(gpa, false)?;
66        Ok(Box::new(MappedRom(memory)))
67    }
68
69    fn len(&self) -> u64 {
70        self.len
71    }
72}
73
74struct MappedRom(Box<dyn MappableGuestMemory>);
75
76impl UnmapRom for MappedRom {
77    fn unmap_rom(mut self) {
78        self.0.unmap_from_guest();
79    }
80}