SVM Hypervisor in Rust, Part 6
Finishing up#
To finally finish writing our bootloader, let’s finish main.rs:
#![no_std]
#![no_main]
mod initial_paging;
mod loader;
const FILE_NAME: &str = "hv.bin";
use crate::{
initial_paging::copy_uefi_cr3,
loader::{load_boot_info_and_jump, map_elf_load_segments},
};
use log::info;
use uefi::{
CStr16, Status,
boot::{self, ScopedProtocol, open_protocol_exclusive},
entry,
fs::{FileSystem, Path},
proto::{loaded_image::LoadedImage, media::fs::SimpleFileSystem},
};
fn map_hv_binary(sfs: ScopedProtocol<SimpleFileSystem>) {
let mut fs = FileSystem::new(sfs);
let mut name_buffer = [0; 7];
let cstr = CStr16::from_str_with_buf(FILE_NAME, &mut name_buffer).unwrap();
let path = Path::new(&cstr);
let buffer = fs.read(path).unwrap();
let cr3 = copy_uefi_cr3();
let copied_pml4 = unsafe { *cr3 };
info!("Copied PML4 {:?}", copied_pml4[0]);
info!("Loading HV binary into memory...");
let entry = map_elf_load_segments(cr3, buffer.as_slice());
info!("entry point: va {:x}", entry);
load_boot_info_and_jump(cr3, entry, buffer.as_slice());
}
#[entry]
fn main() -> Status {
uefi::helpers::init().unwrap();
let loaded_image = open_protocol_exclusive::<LoadedImage>(boot::image_handle()).unwrap();
let sfs =
boot::open_protocol_exclusive::<SimpleFileSystem>(loaded_image.device().unwrap()).unwrap();
map_hv_binary(sfs);
panic!("we should have never gotten here");
}
This is all we need. Now, to actually boot our kernel we are going to add a couple stuff to our kernel directly, let’s go to main.rs in our hv kernel:
First, let’s add some packages we want, type:
cargo add com_logger
cargo add log
and in cargo.toml don’t forget to add our library as a dependency, so it should look like this:
[dependencies]
com_logger = "0.1.2"
log = "0.4.27"
lib = {path = "../lib"}
Now, in main.rs let’s put this:
#![no_main]
#![no_std]
use lib::{BootInfo, BOOT_MAGIC};
use log::{info, error};
#[panic_handler]
#[cfg(not(test))]
fn panic_handler(info: &core::panic::PanicInfo) -> ! {
if let Some(location) = info.location() {
error!("Panic in {} at {}", location.file(), location.line());
}
error!("Panic: {}", info);
loop {}
}
#[unsafe(no_mangle)]
pub extern "C" fn hventry(boot: *mut BootInfo) {
com_logger::init();
let info: &BootInfo = unsafe { &*boot };
if info.is_magic_same(BOOT_MAGIC) {
info!("Correct magic!");
};
loop {};
}
Now let’s compile it and see how it goes!

Hmm.. no panics or anything, which is good.. Let’s see when we click “view” and go to the serial output (serial0):

Yay! it works!
On the next blog post, we are going to be actually working more on our kernel and finally virtualizing our existing operating system.