From bc3a276b43e298fbe7043de8e12082912b64622e Mon Sep 17 00:00:00 2001 From: lizhaoxin1 Date: Thu, 4 Aug 2022 11:34:26 +0800 Subject: [PATCH] arch, vmm: Expose platform uuid via SMBIOS Parse and set uuid. Signed-off-by: lizhaoxin1 Signed-off-by: Rob Bradford --- Cargo.lock | 1 + arch/Cargo.toml | 1 + arch/src/x86_64/mod.rs | 64 +++++++++++++++++++++++++++++++++++---- arch/src/x86_64/smbios.rs | 33 +++++++++++++++----- vmm/src/vm.rs | 9 ++++++ 5 files changed, 95 insertions(+), 13 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index f6d9621d9..1a9e8a116 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -50,6 +50,7 @@ dependencies = [ "log", "serde", "thiserror", + "uuid", "versionize", "versionize_derive", "vm-fdt", diff --git a/arch/Cargo.toml b/arch/Cargo.toml index 65b46b52a..207064b70 100644 --- a/arch/Cargo.toml +++ b/arch/Cargo.toml @@ -17,6 +17,7 @@ linux-loader = { version = "0.4.0", features = ["elf", "bzimage", "pe"] } log = "0.4.17" serde = { version = "1.0.141", features = ["rc", "derive"] } thiserror = "1.0.31" +uuid = "1.1.1" versionize = "0.1.6" versionize_derive = "0.1.4" vm-memory = { version = "0.8.0", features = ["backend-mmap", "backend-bitmap"] } diff --git a/arch/src/x86_64/mod.rs b/arch/src/x86_64/mod.rs index d0ab6f298..8ccfaf75d 100644 --- a/arch/src/x86_64/mod.rs +++ b/arch/src/x86_64/mod.rs @@ -819,13 +819,14 @@ pub fn configure_system( rsdp_addr: Option, sgx_epc_region: Option, serial_number: Option<&str>, + uuid: Option<&str>, ) -> super::Result<()> { // Write EBDA address to location where ACPICA expects to find it guest_mem .write_obj((layout::EBDA_START.0 >> 4) as u16, layout::EBDA_POINTER) .map_err(Error::EbdaSetup)?; - let size = smbios::setup_smbios(guest_mem, serial_number).map_err(Error::SmbiosSetup)?; + let size = smbios::setup_smbios(guest_mem, serial_number, uuid).map_err(Error::SmbiosSetup)?; // Place the MP table after the SMIOS table aligned to 16 bytes let offset = GuestAddress(layout::SMBIOS_START).unchecked_add(size); @@ -1178,6 +1179,7 @@ mod tests { Some(layout::RSDP_POINTER), None, None, + None, ); assert!(config_err.is_err()); @@ -1191,7 +1193,17 @@ mod tests { .collect(); let gm = GuestMemoryMmap::from_ranges(&ram_regions).unwrap(); - configure_system(&gm, GuestAddress(0), &None, no_vcpus, None, None, None).unwrap(); + configure_system( + &gm, + GuestAddress(0), + &None, + no_vcpus, + None, + None, + None, + None, + ) + .unwrap(); // Now assigning some memory that is equal to the start of the 32bit memory hole. let mem_size = 3328 << 20; @@ -1202,9 +1214,29 @@ mod tests { .map(|r| (r.0, r.1)) .collect(); let gm = GuestMemoryMmap::from_ranges(&ram_regions).unwrap(); - configure_system(&gm, GuestAddress(0), &None, no_vcpus, None, None, None).unwrap(); + configure_system( + &gm, + GuestAddress(0), + &None, + no_vcpus, + None, + None, + None, + None, + ) + .unwrap(); - configure_system(&gm, GuestAddress(0), &None, no_vcpus, None, None, None).unwrap(); + configure_system( + &gm, + GuestAddress(0), + &None, + no_vcpus, + None, + None, + None, + None, + ) + .unwrap(); // Now assigning some memory that falls after the 32bit memory hole. let mem_size = 3330 << 20; @@ -1215,9 +1247,29 @@ mod tests { .map(|r| (r.0, r.1)) .collect(); let gm = GuestMemoryMmap::from_ranges(&ram_regions).unwrap(); - configure_system(&gm, GuestAddress(0), &None, no_vcpus, None, None, None).unwrap(); + configure_system( + &gm, + GuestAddress(0), + &None, + no_vcpus, + None, + None, + None, + None, + ) + .unwrap(); - configure_system(&gm, GuestAddress(0), &None, no_vcpus, None, None, None).unwrap(); + configure_system( + &gm, + GuestAddress(0), + &None, + no_vcpus, + None, + None, + None, + None, + ) + .unwrap(); } #[test] diff --git a/arch/src/x86_64/smbios.rs b/arch/src/x86_64/smbios.rs index cf5eb44a5..15de2c7c9 100644 --- a/arch/src/x86_64/smbios.rs +++ b/arch/src/x86_64/smbios.rs @@ -12,6 +12,7 @@ use std::fmt::{self, Display}; use std::mem; use std::result; use std::slice; +use uuid::Uuid; use vm_memory::ByteValued; use vm_memory::{Address, Bytes, GuestAddress}; @@ -27,6 +28,8 @@ pub enum Error { WriteSmbiosEp, /// Failure to write additional data to memory WriteData, + /// Failure to parse uuid, uuid format may be error + ParseUuid(uuid::Error), } impl std::error::Error for Error {} @@ -36,11 +39,16 @@ impl Display for Error { use self::Error::*; let description = match self { - NotEnoughMemory => "There was too little guest memory to store the SMBIOS table", - AddressOverflow => "The SMBIOS table has too little address space to be stored", - Clear => "Failure while zeroing out the memory for the SMBIOS table", - WriteSmbiosEp => "Failure to write SMBIOS entrypoint structure", - WriteData => "Failure to write additional data to memory", + NotEnoughMemory => { + "There was too little guest memory to store the SMBIOS table".to_string() + } + AddressOverflow => { + "The SMBIOS table has too little address space to be stored".to_string() + } + Clear => "Failure while zeroing out the memory for the SMBIOS table".to_string(), + WriteSmbiosEp => "Failure to write SMBIOS entrypoint structure".to_string(), + WriteData => "Failure to write additional data to memory".to_string(), + ParseUuid(e) => format!("Failure to parse uuid: {}", e), }; write!(f, "SMBIOS error: {}", description) @@ -161,7 +169,11 @@ fn write_string( Ok(curptr) } -pub fn setup_smbios(mem: &GuestMemoryMmap, serial_number: Option<&str>) -> Result { +pub fn setup_smbios( + mem: &GuestMemoryMmap, + serial_number: Option<&str>, + uuid: Option<&str>, +) -> Result { let physptr = GuestAddress(SMBIOS_START) .checked_add(mem::size_of::() as u64) .ok_or(Error::NotEnoughMemory)?; @@ -188,6 +200,12 @@ pub fn setup_smbios(mem: &GuestMemoryMmap, serial_number: Option<&str>) -> Resul { handle += 1; + + let uuid_number = uuid + .map(Uuid::parse_str) + .transpose() + .map_err(Error::ParseUuid)? + .unwrap_or(Uuid::nil()); let smbios_sysinfo = SmbiosSysInfo { typ: SYSTEM_INFORMATION, length: mem::size_of::() as u8, @@ -195,6 +213,7 @@ pub fn setup_smbios(mem: &GuestMemoryMmap, serial_number: Option<&str>) -> Resul manufacturer: 1, // First string written in this section product_name: 2, // Second string written in this section serial_number: serial_number.map(|_| 3).unwrap_or_default(), // 3rd string + uuid: uuid_number.to_bytes_le(), // set uuid ..Default::default() }; curptr = write_and_incr(mem, smbios_sysinfo, curptr)?; @@ -266,7 +285,7 @@ mod tests { fn entrypoint_checksum() { let mem = GuestMemoryMmap::from_ranges(&[(GuestAddress(SMBIOS_START), 4096)]).unwrap(); - setup_smbios(&mem, None).unwrap(); + setup_smbios(&mem, None, None).unwrap(); let smbios_ep: Smbios30Entrypoint = mem.read_obj(GuestAddress(SMBIOS_START)).unwrap(); diff --git a/vmm/src/vm.rs b/vmm/src/vm.rs index 9dec1cdee..49efa43ba 100644 --- a/vmm/src/vm.rs +++ b/vmm/src/vm.rs @@ -1119,6 +1119,14 @@ impl Vm { .as_ref() .and_then(|p| p.serial_number.clone()); + let uuid = self + .config + .lock() + .unwrap() + .platform + .as_ref() + .and_then(|p| p.uuid.clone()); + arch::configure_system( &mem, arch::layout::CMDLINE_START, @@ -1127,6 +1135,7 @@ impl Vm { rsdp_addr, sgx_epc_region, serial_number.as_deref(), + uuid.as_deref(), ) .map_err(Error::ConfigureSystem)?; Ok(())