diff --git a/vmm/src/vm.rs b/vmm/src/vm.rs index 938bec875..af1ddaaa4 100644 --- a/vmm/src/vm.rs +++ b/vmm/src/vm.rs @@ -1173,18 +1173,22 @@ impl Vm { } #[cfg(any(target_arch = "aarch64", target_arch = "riscv64"))] - fn load_firmware(mut firmware: &File, memory_manager: Arc>) -> Result<()> { + fn load_firmware( + mut firmware: &File, + memory_manager: Arc>, + ) -> Result { let uefi_flash = memory_manager.lock().as_ref().unwrap().uefi_flash(); let mem = uefi_flash.memory(); arch::uefi::load_uefi(mem.deref(), arch::layout::UEFI_START, &mut firmware) .map_err(Error::UefiLoad)?; - Ok(()) + Ok(EntryPoint { + entry_addr: arch::layout::UEFI_START, + }) } #[cfg(any(target_arch = "aarch64", target_arch = "riscv64"))] fn load_kernel( - firmware: Option, - kernel: Option, + mut kernel: File, memory_manager: Arc>, ) -> Result { let guest_memory = memory_manager.lock().as_ref().unwrap().guest_memory(); @@ -1192,32 +1196,25 @@ impl Vm { let alignment = 0x20_0000; let aligned_kernel_addr = (arch::layout::KERNEL_START.0 + (alignment - 1)) & !(alignment - 1); - let entry_addr = match (firmware, kernel) { - (None, Some(mut kernel)) => { - match linux_loader::loader::pe::PE::load( - mem.deref(), - Some(GuestAddress(aligned_kernel_addr)), - &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, memory_manager)?; - arch::layout::UEFI_START - } - Err(e) => { - return Err(Error::KernelLoad(e)); - } + let entry_addr = { + match linux_loader::loader::pe::PE::load( + mem.deref(), + Some(GuestAddress(aligned_kernel_addr)), + &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, memory_manager)?; + arch::layout::UEFI_START + } + Err(e) => { + return Err(Error::KernelLoad(e)); } } - (Some(firmware), None) => { - Self::load_firmware(&firmware, memory_manager)?; - arch::layout::UEFI_START - } - _ => unreachable!("Unsupported boot configuration: programming error from 'PayloadConfigError::validate()'"), }; Ok(EntryPoint { entry_addr }) @@ -1254,6 +1251,9 @@ impl Vm { Ok(entry_point) } + /// Loads the kernel or a firmware file. + /// + /// For x86_64, the boot path is the same. #[cfg(target_arch = "x86_64")] fn load_kernel( mut kernel: File, @@ -1357,11 +1357,11 @@ impl Vm { match (&payload.firmware, &payload.kernel) { (Some(firmware), None) => { let firmware = File::open(firmware).map_err(Error::FirmwareFile)?; - Self::load_kernel(Some(firmware), None, memory_manager) + Self::load_firmware(&firmware, memory_manager) } (None, Some(kernel)) => { let kernel = File::open(kernel).map_err(Error::KernelFile)?; - Self::load_kernel(None, Some(kernel), memory_manager) + Self::load_kernel(kernel, memory_manager) } _ => unreachable!("Unsupported boot configuration: programming error from 'PayloadConfigError::validate()'"), }