Skip to content

Commit

Permalink
Add SMBIOS OEM Strings support (aarch64 only)
Browse files Browse the repository at this point in the history
Add a new API `krun_set_smbios_oem_strings()` to set SMBIOS
OEM Strings (type 11), and all the internal machinery to
provide them to the firmware. The EDK2 firmware expect the
SMBIOS tables on address 0x4000_F000.

Currently, this is only supported on aarch64 architectures.

Signed-off-by: German Maglione <gmaglione@redhat.com>
  • Loading branch information
germag committed May 22, 2024
1 parent 89f349f commit 2f04e8b
Show file tree
Hide file tree
Showing 10 changed files with 84 additions and 1 deletion.
8 changes: 8 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
[workspace]
members = ["src/libkrun"]
members = ["src/libkrun", "src/smbios"]
resolver = "2"

[profile.dev]
Expand Down
13 changes: 13 additions & 0 deletions include/libkrun.h
Original file line number Diff line number Diff line change
Expand Up @@ -230,6 +230,19 @@ int32_t krun_set_gpu_options(uint32_t ctx_id, uint32_t virgl_flags);
*/
int32_t krun_set_rlimits(uint32_t ctx_id, const char *const rlimits[]);

/*
* Sets the SMBIOS OEM Strings.
*
* Arguments:
* "ctx_id" - the configuration context ID.
* "oem_strings" - an array of string pointers.
* "count" - number of elements in the array.
*
* Returns:
* Zero on success or a negative error number on failure.
*/
int32_t krun_set_smbios_oem_strings(uint32_t ctx_id, const char *const oem_strings[], char count);

/*
* Sets the working directory for the executable to be run inside the microVM.
*
Expand Down
1 change: 1 addition & 0 deletions src/arch/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ libc = ">=0.2.39"
vm-memory = { version = ">=0.13", features = ["backend-mmap"] }

arch_gen = { path = "../arch_gen" }
smbios = { path = "../smbios" }
utils = { path = "../utils" }

[target.'cfg(target_os = "linux")'.dependencies]
Expand Down
3 changes: 3 additions & 0 deletions src/arch/src/aarch64/layout.rs
Original file line number Diff line number Diff line change
Expand Up @@ -89,3 +89,6 @@ pub const GTIMER_PHYS: u32 = 12;
pub const MAPPED_IO_START: u64 = 1 << 30; // 1 GB
#[cfg(feature = "efi")]
pub const MAPPED_IO_START: u64 = 0x0a00_0000;

#[cfg(feature = "efi")]
pub const SMBIOS_START: u64 = 0x4000_F000;
14 changes: 14 additions & 0 deletions src/arch/src/aarch64/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,13 +24,20 @@ use self::gic::GICDevice;
use crate::ArchMemoryInfo;
use vm_memory::{Address, GuestAddress, GuestMemory, GuestMemoryMmap};

#[cfg(feature = "efi")]
use smbios;

/// Errors thrown while configuring aarch64 system.
#[derive(Debug)]
pub enum Error {
/// Failed to create a Flattened Device Tree for this aarch64 microVM.
SetupFDT(fdt::Error),
/// Failed to compute the initrd address.
InitrdAddress,

#[cfg(feature = "efi")]
/// SMBIOS Error
Smbios(smbios::Error),
}

/// The start of the memory area reserved for MMIO devices.
Expand Down Expand Up @@ -80,6 +87,7 @@ pub fn arch_memory_regions(size: usize) -> (ArchMemoryInfo, Vec<(GuestAddress, u
/// * `device_info` - A hashmap containing the attached devices for building FDT device nodes.
/// * `gic_device` - The GIC device.
/// * `initrd` - Information about an optional initrd.
#[allow(clippy::too_many_arguments)]
pub fn configure_system<T: DeviceInfoForFDT + Clone + Debug>(
guest_mem: &GuestMemoryMmap,
arch_memory_info: &ArchMemoryInfo,
Expand All @@ -88,6 +96,7 @@ pub fn configure_system<T: DeviceInfoForFDT + Clone + Debug>(
device_info: &HashMap<(DeviceType, String), T>,
gic_device: &Box<dyn GICDevice>,
initrd: &Option<super::InitrdConfig>,
_smbios_oem_strings: &Option<Vec<String>>,
) -> super::Result<()> {
fdt::create_fdt(
guest_mem,
Expand All @@ -99,6 +108,11 @@ pub fn configure_system<T: DeviceInfoForFDT + Clone + Debug>(
initrd,
)
.map_err(Error::SetupFDT)?;

#[cfg(feature = "efi")]
smbios::setup_smbios(guest_mem, layout::SMBIOS_START, _smbios_oem_strings)
.map_err(Error::Smbios)?;

Ok(())
}

Expand Down
36 changes: 36 additions & 0 deletions src/libkrun/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -876,6 +876,42 @@ pub unsafe extern "C" fn krun_set_console_output(ctx_id: u32, c_filepath: *const
}
}

#[allow(clippy::missing_safety_doc)]
#[no_mangle]
pub unsafe extern "C" fn krun_set_smbios_oem_strings(
ctx_id: u32,
oem_strings: *const *const c_char,
count: u8,
) -> i32 {
if oem_strings.is_null() {
return -libc::EINVAL;
}

let cstr_ptr_slice = slice::from_raw_parts(oem_strings, count as usize);

let mut oem_strings = Vec::new();

for cstr_ptr in cstr_ptr_slice {
if cstr_ptr.is_null() {
return -libc::EINVAL;
}
let Ok(s) = CStr::from_ptr(*cstr_ptr).to_str() else {
return -libc::EINVAL;
};
oem_strings.push(s.to_string());
}

match CTX_MAP.lock().unwrap().entry(ctx_id) {
Entry::Occupied(mut ctx_cfg) => {
ctx_cfg.get_mut().vmr.smbios_oem_strings =
(!oem_strings.is_empty()).then_some(oem_strings)
}
Entry::Vacant(_) => return -libc::ENOENT,
}

KRUN_SUCCESS
}

#[cfg(feature = "net")]
fn create_virtio_net(ctx_cfg: &mut ContextConfig, backend: VirtioNetBackend) {
let mac = if let Some(mac) = ctx_cfg.mac {
Expand Down
1 change: 1 addition & 0 deletions src/vmm/src/builder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -571,6 +571,7 @@ pub fn build_microvm(
mmio_device_manager,
#[cfg(target_arch = "x86_64")]
pio_device_manager,
_smbios_oem_strings: vm_resources.smbios_oem_strings.clone(),
};

#[cfg(not(feature = "tee"))]
Expand Down
4 changes: 4 additions & 0 deletions src/vmm/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -202,6 +202,8 @@ pub struct Vmm {
mmio_device_manager: MMIODeviceManager,
#[cfg(target_arch = "x86_64")]
pio_device_manager: PortIODeviceManager,

_smbios_oem_strings: Option<Vec<String>>,
}

impl Vmm {
Expand Down Expand Up @@ -292,6 +294,7 @@ impl Vmm {
self.mmio_device_manager.get_device_info(),
self.vm.get_irqchip(),
initrd,
&self._smbios_oem_strings,
)
.map_err(Error::ConfigureSystem)?;
}
Expand All @@ -307,6 +310,7 @@ impl Vmm {
self.mmio_device_manager.get_device_info(),
self.vm.get_irqchip(),
initrd,
&self._smbios_oem_strings,
)
.map_err(Error::ConfigureSystem)?;
}
Expand Down
3 changes: 3 additions & 0 deletions src/vmm/src/resources.rs
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,8 @@ pub struct VmResources {
pub gpu_virgl_flags: Option<u32>,
/// File to send console output.
pub console_output: Option<PathBuf>,
/// SMBIOS OEM Strings
pub smbios_oem_strings: Option<Vec<String>>,
}

impl VmResources {
Expand Down Expand Up @@ -317,6 +319,7 @@ mod tests {
net_builder: Default::default(),
gpu_virgl_flags: None,
console_output: None,
smbios_oem_strings: None,
}
}

Expand Down

0 comments on commit 2f04e8b

Please sign in to comment.