mirror of
https://github.com/cloud-hypervisor/cloud-hypervisor.git
synced 2026-08-05 02:19:16 +00:00
vmm:AArch64: load standalone firmware
A new firmware item has been added into payload config, we need extend ability to load standalone firmware on AArch64. "load_kernel" method will be the entry of image loading work including kernel and firmware. This change is back compatible. So, we can either load firmware through "-kernel" like before or "-firmware". Signed-off-by: Jianyong Wu <jianyong.wu@arm.com>
This commit is contained in:
committed by
Rob Bradford
parent
2054c8699a
commit
9b1452f258
+52
-25
@@ -301,7 +301,6 @@ pub enum Error {
|
|||||||
#[error("Error joining kernel loading thread")]
|
#[error("Error joining kernel loading thread")]
|
||||||
KernelLoadThreadJoin(std::boxed::Box<dyn std::any::Any + std::marker::Send>),
|
KernelLoadThreadJoin(std::boxed::Box<dyn std::any::Any + std::marker::Send>),
|
||||||
|
|
||||||
#[cfg(target_arch = "x86_64")]
|
|
||||||
#[error("Payload configuration is not bootable")]
|
#[error("Payload configuration is not bootable")]
|
||||||
InvalidPayload,
|
InvalidPayload,
|
||||||
|
|
||||||
@@ -458,7 +457,7 @@ pub fn physical_bits(max_phys_bits: u8) -> u8 {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub struct Vm {
|
pub struct Vm {
|
||||||
#[cfg(any(target_arch = "aarch64", feature = "tdx"))]
|
#[cfg(feature = "tdx")]
|
||||||
kernel: Option<File>,
|
kernel: Option<File>,
|
||||||
initramfs: Option<File>,
|
initramfs: Option<File>,
|
||||||
threads: Vec<thread::JoinHandle<()>>,
|
threads: Vec<thread::JoinHandle<()>>,
|
||||||
@@ -587,7 +586,7 @@ impl Vm {
|
|||||||
|
|
||||||
let on_tty = unsafe { libc::isatty(libc::STDIN_FILENO as i32) } != 0;
|
let on_tty = unsafe { libc::isatty(libc::STDIN_FILENO as i32) } != 0;
|
||||||
|
|
||||||
#[cfg(any(target_arch = "aarch64", feature = "tdx"))]
|
#[cfg(feature = "tdx")]
|
||||||
let kernel = config
|
let kernel = config
|
||||||
.lock()
|
.lock()
|
||||||
.unwrap()
|
.unwrap()
|
||||||
@@ -609,7 +608,7 @@ impl Vm {
|
|||||||
.map_err(Error::InitramfsFile)?;
|
.map_err(Error::InitramfsFile)?;
|
||||||
|
|
||||||
Ok(Vm {
|
Ok(Vm {
|
||||||
#[cfg(any(target_arch = "aarch64", feature = "tdx"))]
|
#[cfg(feature = "tdx")]
|
||||||
kernel,
|
kernel,
|
||||||
initramfs,
|
initramfs,
|
||||||
device_manager,
|
device_manager,
|
||||||
@@ -965,24 +964,42 @@ impl Vm {
|
|||||||
fn load_kernel(&mut self) -> Result<EntryPoint> {
|
fn load_kernel(&mut self) -> Result<EntryPoint> {
|
||||||
let guest_memory = self.memory_manager.lock().as_ref().unwrap().guest_memory();
|
let guest_memory = self.memory_manager.lock().as_ref().unwrap().guest_memory();
|
||||||
let mem = guest_memory.memory();
|
let mem = guest_memory.memory();
|
||||||
let mut kernel = self.kernel.as_ref().unwrap();
|
let payload = self
|
||||||
let entry_addr = match linux_loader::loader::pe::PE::load(
|
.config
|
||||||
mem.deref(),
|
.lock()
|
||||||
Some(arch::layout::KERNEL_START),
|
.unwrap()
|
||||||
&mut kernel,
|
.payload
|
||||||
None,
|
.as_ref()
|
||||||
) {
|
.unwrap()
|
||||||
Ok(entry_addr) => entry_addr.kernel_load,
|
.clone();
|
||||||
// Try to load the binary as kernel PE file at first.
|
let entry_addr = match (payload.firmware, payload.kernel) {
|
||||||
// If failed, retry to load it as UEFI binary.
|
(None, Some(kernel)) => {
|
||||||
// As the UEFI binary is formatless, it must be the last option to try.
|
let mut kernel = File::open(kernel).map_err(Error::KernelFile)?;
|
||||||
Err(linux_loader::loader::Error::Pe(InvalidImageMagicNumber)) => {
|
match linux_loader::loader::pe::PE::load(
|
||||||
self.load_firmware(kernel)?;
|
mem.deref(),
|
||||||
|
Some(arch::layout::KERNEL_START),
|
||||||
|
&mut kernel,
|
||||||
|
None,
|
||||||
|
) {
|
||||||
|
Ok(entry_addr) => entry_addr.kernel_load,
|
||||||
|
// Try to load the binary as kernel PE file at first.
|
||||||
|
// If failed, retry to load it as UEFI binary.
|
||||||
|
// As the UEFI binary is formatless, it must be the last option to try.
|
||||||
|
Err(linux_loader::loader::Error::Pe(InvalidImageMagicNumber)) => {
|
||||||
|
self.load_firmware(&kernel)?;
|
||||||
|
arch::layout::UEFI_START
|
||||||
|
}
|
||||||
|
Err(e) => {
|
||||||
|
return Err(Error::KernelLoad(e));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
(Some(firmware), None) => {
|
||||||
|
let firmware = File::open(firmware).map_err(Error::FirmwareFile)?;
|
||||||
|
self.load_firmware(&firmware)?;
|
||||||
arch::layout::UEFI_START
|
arch::layout::UEFI_START
|
||||||
}
|
}
|
||||||
Err(e) => {
|
_ => return Err(Error::InvalidPayload),
|
||||||
return Err(Error::KernelLoad(e));
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
Ok(EntryPoint {
|
Ok(EntryPoint {
|
||||||
@@ -2121,11 +2138,21 @@ impl Vm {
|
|||||||
|
|
||||||
#[cfg(target_arch = "aarch64")]
|
#[cfg(target_arch = "aarch64")]
|
||||||
fn entry_point(&mut self) -> Result<Option<EntryPoint>> {
|
fn entry_point(&mut self) -> Result<Option<EntryPoint>> {
|
||||||
Ok(if self.kernel.as_ref().is_some() {
|
let payload = self
|
||||||
Some(self.load_kernel()?)
|
.config
|
||||||
} else {
|
.lock()
|
||||||
None
|
.unwrap()
|
||||||
})
|
.payload
|
||||||
|
.as_ref()
|
||||||
|
.unwrap()
|
||||||
|
.clone();
|
||||||
|
Ok(
|
||||||
|
if payload.kernel.as_ref().is_some() || payload.firmware.as_ref().is_some() {
|
||||||
|
Some(self.load_kernel()?)
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
},
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn boot(&mut self) -> Result<()> {
|
pub fn boot(&mut self) -> Result<()> {
|
||||||
|
|||||||
Reference in New Issue
Block a user