diff --git a/Cargo.lock b/Cargo.lock index c218c6d4..cbd1b7d7 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -97,6 +97,12 @@ version = "1.0.100" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a23eb6b1614318a8071c9b2521f36b424b2c83db5eb3a0fead4a6c0809af6e61" +[[package]] +name = "arrayvec" +version = "0.7.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7c02d123df017efcdfbd739ef81735b36c5ba83ec3c59c80a9d7ecc718f92e50" + [[package]] name = "autocfg" version = "1.5.0" @@ -136,6 +142,17 @@ dependencies = [ "generic-array", ] +[[package]] +name = "byte-unit" +version = "5.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8c6d47a4e2961fb8721bcfc54feae6455f2f64e7054f9bc67e875f0e77f4c58d" +dependencies = [ + "rust_decimal", + "serde", + "utf8-width", +] + [[package]] name = "byteorder" version = "1.5.0" @@ -216,6 +233,18 @@ version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b05b61dc5112cbb17e4b6cd61790d9845d13888356391624cbe7e41efeac1e75" +[[package]] +name = "compression" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3a82b366ae14633c67a1cbb4aa3738210a23f77d2868a0fd50faa23a956f9ec4" +dependencies = [ + "cfg-if", + "lazy_static", + "log", + "num-traits", +] + [[package]] name = "const_fn" version = "0.4.11" @@ -383,15 +412,20 @@ checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" [[package]] name = "hermit-entry" version = "0.10.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "920f9bfe21a23408aade84f1cd2f550c0490be1ec90ae5151b919614808e2e85" +source = "git+https://github.com/fogti/hermit-entry.git?branch=image-reader#697f074a522cb6f21dd6d0b314c3d5b4928aa5bb" dependencies = [ "align-address", + "allocator-api2 0.3.1", + "byte-unit", + "compression", "const_parse", "goblin", "log", + "num-traits", "plain", + "serde", "time", + "toml", ] [[package]] @@ -407,6 +441,7 @@ dependencies = [ "fdt", "goblin", "hermit-entry", + "lazy_static", "log", "multiboot", "naked-function", @@ -450,6 +485,15 @@ version = "1.0.15" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4a5f13b858c8d314ee3e8f639011f7ccefe71f97f96e50151fb991f267928e2c" +[[package]] +name = "lazy_static" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" +dependencies = [ + "spin", +] + [[package]] name = "libc" version = "0.2.175" @@ -556,6 +600,15 @@ version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "51d515d32fb182ee37cda2ccdcb92950d6a3c2893aa280e540671c2cd0f3b1d9" +[[package]] +name = "num-traits" +version = "0.2.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841" +dependencies = [ + "autocfg", +] + [[package]] name = "objc2-core-foundation" version = "0.3.1" @@ -709,6 +762,16 @@ dependencies = [ "windows-sys 0.52.0", ] +[[package]] +name = "rust_decimal" +version = "1.39.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "35affe401787a9bd846712274d97654355d21b2a2c092a3139aabe31e9022282" +dependencies = [ + "arrayvec", + "num-traits", +] + [[package]] name = "rustix" version = "1.1.2" @@ -799,6 +862,45 @@ version = "0.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c1257cd4248b4132760d6524d6dda4e053bc648c9070b960929bf50cfb1e7add" +[[package]] +name = "serde" +version = "1.0.228" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a8e94ea7f378bd32cbbd37198a4a91436180c5bb472411e48b5ec2e2124ae9e" +dependencies = [ + "serde_core", + "serde_derive", +] + +[[package]] +name = "serde_core" +version = "1.0.228" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "41d385c7d4ca58e59fc732af25c3983b67ac852c1a25000afe1175de458b67ad" +dependencies = [ + "serde_derive", +] + +[[package]] +name = "serde_derive" +version = "1.0.228" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d540f220d3187173da220f885ab66608367b6574e925011a9353e4badda91d79" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "serde_spanned" +version = "1.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e24345aa0fe688594e73770a5f6d1b216508b4f93484c0026d521acd30134392" +dependencies = [ + "serde_core", +] + [[package]] name = "sha2" version = "0.10.9" @@ -816,6 +918,12 @@ version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" +[[package]] +name = "spin" +version = "0.9.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6980e8d7511241f8acf4aebddbb1ff938df5eebe98691418c4468d0b72a96a67" + [[package]] name = "sptr" version = "0.3.2" @@ -903,6 +1011,37 @@ version = "0.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b0293f99756f16ff352cc78c99673766a305bdb5ed7652e78df649e9967c885a" +[[package]] +name = "toml" +version = "0.9.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f0dc8b1fb61449e27716ec0e1bdf0f6b8f3e8f6b05391e8497b8b6d7804ea6d8" +dependencies = [ + "serde_core", + "serde_spanned", + "toml_datetime", + "toml_parser", + "winnow", +] + +[[package]] +name = "toml_datetime" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f2cdb639ebbc97961c51720f858597f7f24c4fc295327923af55b74c3c724533" +dependencies = [ + "serde_core", +] + +[[package]] +name = "toml_parser" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c0cbe268d35bdb4bb5a56a2de88d0ad0eb70af5384a99d648cd4b3d04039800e" +dependencies = [ + "winnow", +] + [[package]] name = "typenum" version = "1.18.0" @@ -1020,6 +1159,12 @@ version = "0.7.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "09cc8ee72d2a9becf2f2febe0205bbed8fc6615b7cb429ad062dc7b7ddd036a9" +[[package]] +name = "utf8-width" +version = "0.1.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1292c0d970b54115d14f2492fe0170adf21d68a1de108eebc51c1df4f346a091" + [[package]] name = "utf8parse" version = "0.2.2" @@ -1377,6 +1522,12 @@ version = "0.53.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "271414315aff87387382ec3d271b52d7ae78726f5d44ac98b4f4030c91880486" +[[package]] +name = "winnow" +version = "0.7.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5a5364e9d77fcdeeaa6062ced926ee3381faa2ee02d3eb83a5c27a8825540829" + [[package]] name = "x86" version = "0.52.0" diff --git a/Cargo.toml b/Cargo.toml index bf944702..64e7f2e6 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -11,7 +11,8 @@ align-address = "0.3" allocator-api2 = { version = "0.4", default-features = false } anstyle = { version = "1", default-features = false } cfg-if = "1" -hermit-entry = { version = "0.10", features = ["loader"] } +hermit-entry = { version = "0.10", git = "https://github.com/fogti/hermit-entry.git", branch = "image-reader", features = ["allocator-api2", "loader"] } +lazy_static = { version = "1.5.0", features = ["spin_no_std"] } log = "0.4" one-shot-mutex = "0.2" sptr = "0.3" diff --git a/src/arch/aarch64/mod.rs b/src/arch/aarch64/mod.rs index 7d0e9143..729befb5 100644 --- a/src/arch/aarch64/mod.rs +++ b/src/arch/aarch64/mod.rs @@ -20,7 +20,7 @@ use sptr::Strict; use crate::BootInfoExt; use crate::arch::paging::*; -use crate::os::CONSOLE; +use crate::os::{CONSOLE, ExtraBootInfo}; unsafe extern "C" { static mut loader_end: u8; @@ -110,12 +110,14 @@ pub fn find_kernel() -> &'static [u8] { } } -pub unsafe fn boot_kernel(kernel_info: LoadedKernel) -> ! { +pub unsafe fn boot_kernel(kernel_info: LoadedKernel, extra_info: ExtraBootInfo) -> ! { let LoadedKernel { load_info, entry_point, } = kernel_info; + assert!(extra_info.image.is_none()); + let dtb = unsafe { Fdt::from_ptr(sptr::from_exposed_addr(get_dtb_addr() as usize)) .expect(".dtb file has invalid header") diff --git a/src/arch/mod.rs b/src/arch/mod.rs index 7bf01322..87096952 100644 --- a/src/arch/mod.rs +++ b/src/arch/mod.rs @@ -5,7 +5,7 @@ cfg_if::cfg_if! { } else if #[cfg(target_arch = "riscv64")] { mod riscv64; pub use self::riscv64::*; - } else if #[cfg(all(target_arch = "x86_64"))] { + } else if #[cfg(target_arch = "x86_64")] { mod x86_64; pub use self::x86_64::*; } diff --git a/src/arch/riscv64/mod.rs b/src/arch/riscv64/mod.rs index 7edce752..fd0cb0f3 100644 --- a/src/arch/riscv64/mod.rs +++ b/src/arch/riscv64/mod.rs @@ -17,6 +17,7 @@ use log::info; use sptr::Strict; use crate::BootInfoExt; +use crate::os::ExtraBootInfo; fn find_kernel_linux(chosen: &FdtNode<'_, '_>) -> Option<&'static [u8]> { let initrd_start = chosen.property("linux,initrd-start")?.as_usize()?; @@ -90,7 +91,7 @@ pub unsafe fn get_memory(memory_size: u64) -> u64 { u64::try_from(start_address).unwrap() } -pub unsafe fn boot_kernel(kernel_info: LoadedKernel) -> ! { +pub unsafe fn boot_kernel(kernel_info: LoadedKernel, extra_info: ExtraBootInfo) -> ! { let LoadedKernel { load_info, entry_point, @@ -118,6 +119,8 @@ pub unsafe fn boot_kernel(kernel_info: LoadedKernel) -> ! { DeviceTreeAddress::new(fdt_addr.try_into().unwrap()) }; + assert!(extra_info.image.is_none()); + let boot_info = BootInfo { hardware_info: HardwareInfo { phys_addr_range, diff --git a/src/arch/x86_64/firecracker.rs b/src/arch/x86_64/firecracker.rs index c3b43c05..d7ad6a11 100644 --- a/src/arch/x86_64/firecracker.rs +++ b/src/arch/x86_64/firecracker.rs @@ -20,6 +20,7 @@ use super::physicalmem::PhysAlloc; use super::{KERNEL_STACK_SIZE, SERIAL_IO_PORT, paging}; use crate::BootInfoExt; use crate::fdt::Fdt; +use crate::os::ExtraBootInfo; unsafe extern "C" { static mut loader_end: u8; @@ -118,7 +119,7 @@ pub fn find_kernel() -> &'static [u8] { unsafe { slice::from_raw_parts(sptr::from_exposed_addr(elf_start), elf_len) } } -pub unsafe fn boot_kernel(kernel_info: LoadedKernel) -> ! { +pub unsafe fn boot_kernel(kernel_info: LoadedKernel, extra_info: ExtraBootInfo) -> ! { let LoadedKernel { load_info, entry_point, @@ -172,7 +173,12 @@ pub unsafe fn boot_kernel(kernel_info: LoadedKernel) -> ! { write_bytes(stack, 0, KERNEL_STACK_SIZE.try_into().unwrap()); } - let mut fdt = Fdt::new("firecracker").unwrap(); + let maybe_image = match extra_info.image { + None => &[], + Some(tar_image) => tar_image, + }; + + let mut fdt = Fdt::new("firecracker", maybe_image).unwrap(); // Load the boot_param memory-map information let linux_e820_entries = diff --git a/src/arch/x86_64/multiboot.rs b/src/arch/x86_64/multiboot.rs index aad9a38f..79deb233 100644 --- a/src/arch/x86_64/multiboot.rs +++ b/src/arch/x86_64/multiboot.rs @@ -18,6 +18,7 @@ use super::physicalmem::PhysAlloc; use crate::BootInfoExt; use crate::arch::x86_64::{KERNEL_STACK_SIZE, SERIAL_IO_PORT}; use crate::fdt::Fdt; +use crate::os::ExtraBootInfo; unsafe extern "C" { static mut loader_end: u8; @@ -55,7 +56,7 @@ impl MemoryManagement for Mem { pub struct DeviceTree; impl DeviceTree { - pub fn create() -> FdtWriterResult<&'static [u8]> { + pub fn create(extra_info: &ExtraBootInfo) -> FdtWriterResult<&'static [u8]> { let mut mem = Mem; let multiboot = unsafe { Multiboot::from_ptr(mb_info as u64, &mut mem).unwrap() }; @@ -63,7 +64,12 @@ impl DeviceTree { .memory_regions() .expect("Could not find a memory map in the Multiboot information"); - let mut fdt = Fdt::new("multiboot")?.memory_regions(memory_regions)?; + let maybe_image = match extra_info.image { + None => &[], + Some(tar_image) => tar_image, + }; + + let mut fdt = Fdt::new("multiboot", maybe_image)?.memory_regions(memory_regions)?; if let Some(cmdline) = multiboot.command_line() { fdt = fdt.bootargs(cmdline.to_owned())?; @@ -142,7 +148,7 @@ pub fn find_kernel() -> &'static [u8] { unsafe { slice::from_raw_parts(sptr::from_exposed_addr(elf_start), elf_len) } } -pub unsafe fn boot_kernel(kernel_info: LoadedKernel) -> ! { +pub unsafe fn boot_kernel(kernel_info: LoadedKernel, extra_info: ExtraBootInfo) -> ! { let LoadedKernel { load_info, entry_point, @@ -185,7 +191,7 @@ pub unsafe fn boot_kernel(kernel_info: LoadedKernel) -> ! { write_bytes(stack, 0, KERNEL_STACK_SIZE.try_into().unwrap()); } - let device_tree = DeviceTree::create().expect("Unable to create devicetree!"); + let device_tree = DeviceTree::create(&extra_info).expect("Unable to create devicetree!"); let device_tree = DeviceTreeAddress::new(u64::try_from(device_tree.as_ptr().expose_addr()).unwrap()); diff --git a/src/fdt.rs b/src/fdt.rs index f602d113..864288ef 100644 --- a/src/fdt.rs +++ b/src/fdt.rs @@ -9,31 +9,51 @@ pub struct Fdt { writer: FdtWriter, root_node: FdtWriterNode, bootargs: Option, + image_range: Option<(u64, u64)>, } impl Fdt { - pub fn new(platform: &str) -> FdtWriterResult { - let mut writer = FdtWriter::new()?; + pub fn new(platform: &str, maybe_image: &'static [u8]) -> FdtWriterResult { + let mut mem_reserved = Vec::new(); + + let image_range = if maybe_image.is_empty() { + None + } else { + let image_start = (&maybe_image[0]) as *const u8 as u64; + mem_reserved.push(vm_fdt::FdtReserveEntry::new( + image_start, + maybe_image.len() as u64, + )?); + Some((image_start, maybe_image.len() as u64)) + }; + + let mut writer = FdtWriter::new_with_mem_reserv(&mem_reserved[..])?; let root_node = writer.begin_node("")?; writer.property_string("compatible", &format!("hermit,{platform}"))?; writer.property_u32("#address-cells", 0x2)?; writer.property_u32("#size-cells", 0x2)?; - let bootargs = None; - Ok(Self { writer, root_node, - bootargs, + bootargs: None, + image_range, }) } pub fn finish(mut self) -> FdtWriterResult> { let chosen_node = self.writer.begin_node("chosen")?; + if let Some(bootargs) = &self.bootargs { self.writer.property_string("bootargs", bootargs)?; } + + if let Some((image_start, image_len)) = self.image_range { + self.writer + .property_array_u64("image_reg", &[image_start, image_len])?; + } + self.writer.end_node(chosen_node)?; self.writer.end_node(self.root_node)?; diff --git a/src/main.rs b/src/main.rs index 6e745e59..8b104981 100644 --- a/src/main.rs +++ b/src/main.rs @@ -12,7 +12,9 @@ use hermit_entry::boot_info::{BootInfo, RawBootInfo}; mod macros; mod arch; + mod bump_allocator; + #[cfg(any(target_os = "uefi", target_arch = "x86_64"))] mod fdt; mod log; @@ -45,3 +47,37 @@ fn _print(args: core::fmt::Arguments<'_>) { self::os::CONSOLE.lock().write_fmt(args).unwrap(); } + +/// Detects the input format are resolves the kernel +fn resolve_kernel<'a, A: allocator_api2::alloc::Allocator>( + input_blob: &'a [u8], + alloc: A, + buf: &'a mut Option>, +) -> (&'a [u8], Option) { + use hermit_entry::{Format, decompress_image_with_allocator, detect_format}; + match detect_format(input_blob) { + Some(Format::Elf) => (input_blob, None), + + Some(Format::Gzip) => { + *buf = Some( + decompress_image_with_allocator(input_blob, alloc) + .expect("Unable to decompress Hermit gzip image"), + ); + match *buf { + Some(ref mut tmp) => { + let (config, kernel) = hermit_entry::config::handle_config(tmp) + .expect("Unable to find Hermit image configuration + kernel"); + + // TODO: do we just let the kernel handle the config + + (kernel, Some(config)) + } + None => unreachable!(), + } + } + + None => { + panic!("Input BLOB has unknown magic bytes (neither Gzip nor ELF)") + } + } +} diff --git a/src/os/mod.rs b/src/os/mod.rs index 00b8faf2..8165f499 100644 --- a/src/os/mod.rs +++ b/src/os/mod.rs @@ -7,3 +7,9 @@ cfg_if::cfg_if! { pub use self::uefi::*; } } + +#[cfg_attr(not(any(target_os = "none", feature = "fc")), allow(dead_code))] +#[derive(Clone, Default)] +pub struct ExtraBootInfo { + pub(crate) image: Option<&'static [u8]>, +} diff --git a/src/os/none/allocator/mod.rs b/src/os/none/allocator/mod.rs index a284875b..349b710c 100644 --- a/src/os/none/allocator/mod.rs +++ b/src/os/none/allocator/mod.rs @@ -2,6 +2,8 @@ mod bootstrap; +pub mod oneshot; + use core::ptr; use core::ptr::NonNull; diff --git a/src/os/none/allocator/oneshot.rs b/src/os/none/allocator/oneshot.rs new file mode 100644 index 00000000..c44aa29b --- /dev/null +++ b/src/os/none/allocator/oneshot.rs @@ -0,0 +1,87 @@ +//! A one-shot allocator. +//! +//! This is a simple allocator design which can only allocate once. + +use core::cell::Cell; +use core::ptr::NonNull; + +use allocator_api2::alloc::{AllocError, Allocator, Layout}; + +/// A simple, `!Sync` implementation of a one-shot allocator. +/// +/// This allocator manages the provided memory. +pub struct OneshotAllocator { + mem: Cell<*mut u8>, + // TODO: perhaps provide maximum suitable address +} + +unsafe impl Allocator for OneshotAllocator { + fn allocate(&self, layout: Layout) -> Result, AllocError> { + assert!(layout.align() <= 8); + // `mem` is already aligned. + + let mid = layout.size(); + if mid >= (usize::MAX / 2) { + return Err(AllocError); + } + + match NonNull::new(self.mem.take()) { + None => Err(AllocError), + Some(mem) => Ok(NonNull::slice_from_raw_parts(mem, layout.size())), + } + } + + unsafe fn deallocate(&self, ptr: NonNull, _layout: Layout) { + if self.mem.get().is_null() { + self.mem.set(ptr.as_ptr()); + } else { + #[cfg(debug_assertions)] + panic!("Tried to deallocate pointer that was allocated from a different allocator"); + } + } + + unsafe fn grow( + &self, + ptr: NonNull, + old_layout: Layout, + new_layout: Layout, + ) -> Result, AllocError> { + assert!( + new_layout.size() >= old_layout.size(), + "`new_layout.size()` must be greater than or equal to `old_layout.size()`" + ); + assert!(new_layout.align() <= 8); + + Ok(NonNull::slice_from_raw_parts(ptr, new_layout.size())) + } + + unsafe fn grow_zeroed( + &self, + ptr: NonNull, + old_layout: Layout, + new_layout: Layout, + ) -> Result, AllocError> { + assert!( + new_layout.size() >= old_layout.size(), + "`new_layout.size()` must be greater than or equal to `old_layout.size()`" + ); + assert!(new_layout.align() <= 8); + + unsafe { + ptr.add(old_layout.size()) + .as_ptr() + .write_bytes(0, new_layout.size() - old_layout.size()) + }; + + Ok(NonNull::slice_from_raw_parts(ptr, new_layout.size())) + } +} + +impl OneshotAllocator { + pub fn new(ptr: NonNull) -> Self { + let align_offset = ptr.align_offset(8); + Self { + mem: Cell::new(unsafe { ptr.add(align_offset) }.as_ptr()), + } + } +} diff --git a/src/os/none/mod.rs b/src/os/none/mod.rs index dbe40a33..9e1c52fb 100644 --- a/src/os/none/mod.rs +++ b/src/os/none/mod.rs @@ -1,4 +1,4 @@ -mod allocator; +pub(crate) mod allocator; mod console; use core::fmt::Write; @@ -10,6 +10,7 @@ use log::info; pub use self::console::CONSOLE; use crate::arch; +use crate::os::ExtraBootInfo; unsafe extern "C" { static loader_end: u8; @@ -26,8 +27,19 @@ pub(crate) unsafe extern "C" fn loader_main() -> ! { } let kernel = arch::find_kernel(); + + let allocator = allocator::oneshot::OneshotAllocator::new(todo!()); + let mut buf = None; + let (kernel, _) = crate::resolve_kernel(kernel, allocator, &mut buf); + let kernel = KernelObject::parse(kernel).unwrap(); + let mut extra_info = ExtraBootInfo::default(); + if let Some(tar_image) = buf { + let tar_image = allocator_api2::boxed::Box::leak(tar_image); + extra_info.image = Some((&*tar_image).into()); + } + let mem_size = kernel.mem_size(); let kernel_addr = unsafe { arch::get_memory(mem_size as u64) }; let kernel_addr = kernel.start_addr().unwrap_or(kernel_addr); @@ -40,7 +52,7 @@ pub(crate) unsafe extern "C" fn loader_main() -> ! { let kernel_info = kernel.load_kernel(memory, memory.as_ptr() as u64); - unsafe { arch::boot_kernel(kernel_info) } + unsafe { arch::boot_kernel(kernel_info, extra_info) } } #[panic_handler] diff --git a/src/os/uefi/mod.rs b/src/os/uefi/mod.rs index 045b7dfb..274fe0f7 100644 --- a/src/os/uefi/mod.rs +++ b/src/os/uefi/mod.rs @@ -29,21 +29,38 @@ fn main() -> Status { uefi::helpers::init().unwrap(); crate::log::init(); - let kernel_image = read_app(); - let kernel = KernelObject::parse(&kernel_image).unwrap(); + let allocator = allocator_api2::alloc::Global; - let kernel_memory = alloc_page_slice(kernel.mem_size()).unwrap(); - let kernel_memory = &mut kernel_memory[..kernel.mem_size()]; + let kernel; + let kernel_memory; + let kernel_info; + let rsdp_: *const _; + let maybe_image: &[u8]; - let kernel_info = kernel.load_kernel(kernel_memory, kernel_memory.as_ptr() as u64); + { + let mut buf = None; + let kernel_image = read_app(); - let rsdp = rsdp(); + let (kernel_image2, _) = crate::resolve_kernel(&kernel_image, allocator, &mut buf); - drop(kernel_image); + kernel = KernelObject::parse(&kernel_image2).unwrap(); - let mut fdt = Fdt::new("uefi") + let kernel_memory2 = alloc_page_slice(kernel.mem_size()).unwrap(); + kernel_memory = &mut kernel_memory2[..kernel.mem_size()]; + + kernel_info = kernel.load_kernel(kernel_memory, kernel_memory.as_ptr() as u64); + + rsdp_ = rsdp(); + + maybe_image = match buf { + None => &[], + Some(tar_image) => (&*allocator_api2::boxed::Box::leak(tar_image)).into(), + } + } + + let mut fdt = Fdt::new("uefi", maybe_image) .unwrap() - .rsdp(u64::try_from(rsdp.expose_addr()).unwrap()) + .rsdp(u64::try_from(rsdp_.expose_addr()).unwrap()) .unwrap(); if let Some(bootargs) = read_bootargs() {