Skip to content
63 changes: 61 additions & 2 deletions devices/src/legacy/fw_cfg.rs
Original file line number Diff line number Diff line change
Expand Up @@ -79,12 +79,27 @@ pub const PORT_FW_CFG_WIDTH: u64 = 0x10;

const FW_CFG_SIGNATURE: u16 = 0x00;
const FW_CFG_ID: u16 = 0x01;
const FW_CFG_UUID: u16 = 0x02;
const FW_CFG_RAM_SIZE: u16 = 0x03;
const FW_CFG_NOGRAPHIC: u16 = 0x04;
const FW_CFG_NB_CPUS: u16 = 0x05;
const FW_CFG_MACHINE_ID: u16 = 0x06;
const FW_CFG_KERNEL_ADDR: u16 = 0x07;
const FW_CFG_KERNEL_SIZE: u16 = 0x08;
const FW_CFG_KERNEL_CMDLINE: u16 = 0x09;
const FW_CFG_INITRD_ADDR: u16 = 0x0a;
const FW_CFG_INITRD_SIZE: u16 = 0x0b;
const FW_CFG_BOOT_DEVICE: u16 = 0x0c;
const FW_CFG_NUMA: u16 = 0x0d;
const FW_CFG_BOOT_MENU: u16 = 0x0e;
const FW_CFG_MAX_CPUS: u16 = 0x0f;
const FW_CFG_KERNEL_ENTRY: u16 = 0x10;
const FW_CFG_KERNEL_DATA: u16 = 0x11;
const FW_CFG_INITRD_DATA: u16 = 0x12;
const FW_CFG_CMDLINE_ADDR: u16 = 0x13;
const FW_CFG_CMDLINE_SIZE: u16 = 0x14;
const FW_CFG_CMDLINE_DATA: u16 = 0x15;
const FW_CFG_SETUP_ADDR: u16 = 0x16;
const FW_CFG_SETUP_SIZE: u16 = 0x17;
const FW_CFG_SETUP_DATA: u16 = 0x18;
const FW_CFG_FILE_DIR: u16 = 0x19;
Expand Down Expand Up @@ -116,7 +131,9 @@ pub enum FwCfgContent {
Bytes(Vec<u8>),
Slice(&'static [u8]),
File(u64, File),
U64(u64),
U32(u32),
U16(u16),
}

struct FwCfgContentAccess<'a> {
Expand All @@ -139,10 +156,18 @@ impl Read for FwCfgContentAccess<'_> {
Some(mut s) => s.read(buf),
None => Err(ErrorKind::UnexpectedEof)?,
},
FwCfgContent::U64(n) => match n.to_le_bytes().get(self.offset as usize..) {
Some(mut s) => s.read(buf),
None => Err(ErrorKind::UnexpectedEof)?,
},
FwCfgContent::U32(n) => match n.to_le_bytes().get(self.offset as usize..) {
Some(mut s) => s.read(buf),
None => Err(ErrorKind::UnexpectedEof)?,
},
FwCfgContent::U16(n) => match n.to_le_bytes().get(self.offset as usize..) {
Some(mut s) => s.read(buf),
None => Err(ErrorKind::UnexpectedEof)?,
},
}
}
}
Expand All @@ -159,7 +184,9 @@ impl FwCfgContent {
FwCfgContent::Bytes(v) => v.len(),
FwCfgContent::File(offset, f) => (f.metadata()?.len() - offset) as usize,
FwCfgContent::Slice(s) => s.len(),
FwCfgContent::U64(n) => size_of_val(n),
FwCfgContent::U32(n) => size_of_val(n),
FwCfgContent::U16(n) => size_of_val(n),
};
u32::try_from(ret).map_err(|_| std::io::ErrorKind::InvalidInput.into())
}
Expand Down Expand Up @@ -419,10 +446,34 @@ impl FwCfg {
pub fn new(memory: GuestMemoryAtomic<GuestMemoryMmap<AtomicBitmap>>) -> FwCfg {
const DEFAULT_ITEM: FwCfgContent = FwCfgContent::Slice(&[]);
let mut known_items = [DEFAULT_ITEM; FW_CFG_KNOWN_ITEMS];
let file_buf = Vec::from(FwCfgFilesHeader { count_be: 0 }.as_mut_bytes());

known_items[FW_CFG_SIGNATURE as usize] = FwCfgContent::Slice(&FW_CFG_DMA_SIGNATURE);
known_items[FW_CFG_ID as usize] = FwCfgContent::Slice(&FW_CFG_FEATURE);
let file_buf = Vec::from(FwCfgFilesHeader { count_be: 0 }.as_mut_bytes());
known_items[FW_CFG_FILE_DIR as usize] = FwCfgContent::Bytes(file_buf);
known_items[FW_CFG_UUID as usize] = FwCfgContent::Bytes(Default::default()); /* TODO? */

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What are all these TODO's? Do we need those?

known_items[FW_CFG_RAM_SIZE as usize] = FwCfgContent::U64(0); /* TODO? */
known_items[FW_CFG_NOGRAPHIC as usize] = FwCfgContent::U16(0); /* TODO? */
known_items[FW_CFG_NB_CPUS as usize] = FwCfgContent::U16(0); /* TODO? */
known_items[FW_CFG_MACHINE_ID as usize] = FwCfgContent::U16(0); /* TODO? */
known_items[FW_CFG_KERNEL_ADDR as usize] = FwCfgContent::U32(0); /* TODO? */
known_items[FW_CFG_KERNEL_SIZE as usize] = FwCfgContent::U32(0); /* TODO? */
known_items[FW_CFG_KERNEL_CMDLINE as usize] = FwCfgContent::U32(0); /* TODO? */
known_items[FW_CFG_INITRD_ADDR as usize] = FwCfgContent::U32(0); /* TODO? */
known_items[FW_CFG_INITRD_SIZE as usize] = FwCfgContent::U32(0); /* TODO? */
known_items[FW_CFG_BOOT_DEVICE as usize] = FwCfgContent::U16(0); /* TODO? */
known_items[FW_CFG_NUMA as usize] = FwCfgContent::Bytes(Default::default()); /* TODO? */
known_items[FW_CFG_BOOT_MENU as usize] = FwCfgContent::U16(0); /* TODO? */
known_items[FW_CFG_MAX_CPUS as usize] = FwCfgContent::U16(255); /* TODO? */
known_items[FW_CFG_KERNEL_ENTRY as usize] = FwCfgContent::U32(0); /* TODO? */
known_items[FW_CFG_KERNEL_DATA as usize] = FwCfgContent::Bytes(Default::default()); /* TODO? */
known_items[FW_CFG_INITRD_DATA as usize] = FwCfgContent::Bytes(Default::default()); /* TODO? */
known_items[FW_CFG_CMDLINE_ADDR as usize] = FwCfgContent::U32(0); /* TODO? */
known_items[FW_CFG_CMDLINE_SIZE as usize] = FwCfgContent::U32(0); /* TODO? */
known_items[FW_CFG_CMDLINE_DATA as usize] = FwCfgContent::Bytes(Default::default()); /* TODO? */
known_items[FW_CFG_SETUP_ADDR as usize] = FwCfgContent::U32(0); /* TODO? */
known_items[FW_CFG_SETUP_SIZE as usize] = FwCfgContent::U32(0); /* TODO? */
known_items[FW_CFG_SETUP_DATA as usize] = FwCfgContent::Bytes(Default::default()); /* TODO? */
known_items[FW_CFG_FILE_DIR as usize] = FwCfgContent::Bytes(file_buf); /* TODO? */

FwCfg {
selector: 0,
Expand Down Expand Up @@ -737,10 +788,18 @@ impl FwCfg {
FwCfgContent::File(o, f) => {
f.read_exact_at(data, o + offset as u64).ok()?;
}
FwCfgContent::U64(n) => {
let bytes = n.to_le_bytes();
data.copy_from_slice(&bytes[start..end]);
}
FwCfgContent::U32(n) => {
let bytes = n.to_le_bytes();
data.copy_from_slice(&bytes[start..end]);
}
FwCfgContent::U16(n) => {
let bytes = n.to_le_bytes();
data.copy_from_slice(&bytes[start..end]);
}
}
Some(size as u8)
}
Expand Down
27 changes: 27 additions & 0 deletions vmm/src/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1370,6 +1370,7 @@ impl PciDeviceCommonConfig {
}

impl DiskConfig {
#[cfg(not(feature = "fw_cfg"))]
pub const SYNTAX: &'static str = "Disk parameters \
\"path=<disk_image_path>,readonly=on|off,direct=on|off,iommu=on|off,\
num_queues=<number_of_queues>,queue_size=<size_of_each_queue>,\
Expand All @@ -1382,6 +1383,20 @@ impl DiskConfig {
serial=<serial_number>,backing_files=on|off,sparse=on|off,\
image_type=<raw,qcow2,vhd,vhdx>,lock_granularity=byte-range|full";

#[cfg(feature = "fw_cfg")]
pub const SYNTAX: &'static str = "Disk parameters \

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would prefer a concatenation to the existing DiskConfig::SYNTAX, instead of duplicating and having to maintain both.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sadly, we depend on the pub const. Being a pub const, we do not have a nice way to modify it on runtime without at least implementing some adapter that makes code that consumes the SYNTAX string work.

As this is only a workaround until we make fw_cfg default functionality, I would leave it as is.

\"path=<disk_image_path>,readonly=on|off,direct=on|off,iommu=on|off,\
num_queues=<number_of_queues>,queue_size=<size_of_each_queue>,\
vhost_user=on|off,socket=<vhost_user_socket_path>,\
bw_size=<bytes>,bw_one_time_burst=<bytes>,bw_refill_time=<ms>,\
ops_size=<io_ops>,ops_one_time_burst=<io_ops>,ops_refill_time=<ms>,\
id=<device_id>,pci_segment=<segment_id>,pci_device_id=<pci_slot>,\
rate_limit_group=<group_id>,\
queue_affinity=<list_of_queue_indices_with_their_associated_cpuset>,\
serial=<serial_number>,backing_files=on|off,sparse=on|off,\
image_type=<raw,qcow2,vhd,vhdx>,lock_granularity=byte-range|full,\
bootindex=<index>";

pub fn parse(disk: &str) -> Result<Self> {
let mut parser = OptionParser::new();
parser
Expand Down Expand Up @@ -1409,6 +1424,9 @@ impl DiskConfig {
.add("lock_granularity")
.add_all(PciDeviceCommonConfig::OPTIONS_IOMMU);

#[cfg(feature = "fw_cfg")]
parser.add("bootindex");

parser.parse(disk).map_err(Error::ParseDisk)?;

let path = parser.get("path").map(PathBuf::from);
Expand Down Expand Up @@ -1538,6 +1556,11 @@ impl DiskConfig {

let pci_common = PciDeviceCommonConfig::parse(disk)?;

#[cfg(feature = "fw_cfg")]
let bootindex = parser
.convert::<u16>("bootindex")
.map_err(Error::ParseDisk)?;

Ok(DiskConfig {
pci_common,
path,
Expand All @@ -1557,6 +1580,8 @@ impl DiskConfig {
sparse,
image_type,
lock_granularity,
#[cfg(feature = "fw_cfg")]
bootindex,
})
}

Expand Down Expand Up @@ -4125,6 +4150,8 @@ mod unit_tests {
sparse: true,
image_type: ImageType::Unknown,
lock_granularity: LockGranularityChoice::default(),
#[cfg(feature = "fw_cfg")]
bootindex: Default::default(),
}
}

Expand Down
3 changes: 3 additions & 0 deletions vmm/src/vm_config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -383,6 +383,9 @@ pub struct DiskConfig {
pub image_type: ImageType,
#[serde(default)]
pub lock_granularity: LockGranularityChoice,
#[cfg(feature = "fw_cfg")]
#[serde(default)]
pub bootindex: Option<u16>,
}

impl ApplyLandlock for DiskConfig {
Expand Down