From 848ebe075bf39cae7cf8b681625282b4b0aa613c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Kr=C3=B6ning?= Date: Sat, 16 Nov 2024 11:31:46 +0100 Subject: [PATCH 1/6] refactor: move `crate::os::uefi::fdt` to `crate::fdt` MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Martin Kröning --- src/{os/uefi => }/fdt.rs | 0 src/main.rs | 2 ++ src/os/uefi/mod.rs | 3 +-- 3 files changed, 3 insertions(+), 2 deletions(-) rename src/{os/uefi => }/fdt.rs (100%) diff --git a/src/os/uefi/fdt.rs b/src/fdt.rs similarity index 100% rename from src/os/uefi/fdt.rs rename to src/fdt.rs diff --git a/src/main.rs b/src/main.rs index 20dd11e4..a082fcda 100644 --- a/src/main.rs +++ b/src/main.rs @@ -13,6 +13,8 @@ mod macros; mod arch; mod bump_allocator; +#[cfg(target_os = "uefi")] +mod fdt; mod log; mod os; diff --git a/src/os/uefi/mod.rs b/src/os/uefi/mod.rs index e88bea4a..8b16e6aa 100644 --- a/src/os/uefi/mod.rs +++ b/src/os/uefi/mod.rs @@ -1,6 +1,5 @@ mod allocator; mod console; -mod fdt; use alloc::vec::Vec; use core::ffi::c_void; @@ -20,7 +19,7 @@ use uefi::prelude::*; use uefi::table::cfg; pub use self::console::CONSOLE; -use self::fdt::Fdt; +use crate::fdt::Fdt; use crate::{arch, BootInfoExt}; // Entry Point of the Uefi Loader From 41688e655b25c8e48dbab3027a59734bba09de73 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Kr=C3=B6ning?= Date: Sat, 16 Nov 2024 11:36:32 +0100 Subject: [PATCH 2/6] refactor(fdt): feature-gate UEFI-specifics MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Martin Kröning --- src/fdt.rs | 142 ++++++++++++++++++++++++--------------------- src/os/uefi/mod.rs | 2 +- 2 files changed, 77 insertions(+), 67 deletions(-) diff --git a/src/fdt.rs b/src/fdt.rs index 90a793ab..86dcbd08 100644 --- a/src/fdt.rs +++ b/src/fdt.rs @@ -1,10 +1,6 @@ use alloc::format; use alloc::vec::Vec; -use core::fmt::{self, Write}; -use log::info; -use uefi::boot::{MemoryDescriptor, MemoryType, PAGE_SIZE}; -use uefi::mem::memory_map::{MemoryMap, MemoryMapMut}; use vm_fdt::{FdtWriter, FdtWriterNode, FdtWriterResult}; pub struct Fdt { @@ -13,11 +9,11 @@ pub struct Fdt { } impl Fdt { - pub fn new() -> FdtWriterResult { + pub fn new(platform: &str) -> FdtWriterResult { let mut writer = FdtWriter::new()?; let root_node = writer.begin_node("")?; - writer.property_string("compatible", "hermit,uefi")?; + writer.property_string("compatible", &format!("hermit,{platform}"))?; writer.property_u32("#address-cells", 0x2)?; writer.property_u32("#size-cells", 0x2)?; @@ -40,82 +36,96 @@ impl Fdt { Ok(self) } +} - pub fn memory_map(mut self, memory_map: &mut impl MemoryMapMut) -> FdtWriterResult { - memory_map.sort(); - info!("Memory map:\n{}", memory_map.display()); - - let entries = memory_map - .entries() - .filter(|entry| entry.ty == MemoryType::CONVENTIONAL); - - for entry in entries { - let memory_node = self - .writer - .begin_node(format!("memory@{:x}", entry.phys_start).as_str())?; - self.writer.property_string("device_type", "memory")?; - self.writer.property_array_u64( - "reg", - &[entry.phys_start, entry.page_count * PAGE_SIZE as u64], - )?; - self.writer.end_node(memory_node)?; - } +#[cfg(target_os = "uefi")] +mod uefi { + use alloc::format; + use core::fmt; + use core::fmt::Write; + + use log::info; + use uefi::boot::{MemoryDescriptor, MemoryType, PAGE_SIZE}; + use uefi::mem::memory_map::{MemoryMap, MemoryMapMut}; + use vm_fdt::FdtWriterResult; + + impl super::Fdt { + pub fn memory_map(mut self, memory_map: &mut impl MemoryMapMut) -> FdtWriterResult { + memory_map.sort(); + info!("Memory map:\n{}", memory_map.display()); + + let entries = memory_map + .entries() + .filter(|entry| entry.ty == MemoryType::CONVENTIONAL); + + for entry in entries { + let memory_node = self + .writer + .begin_node(format!("memory@{:x}", entry.phys_start).as_str())?; + self.writer.property_string("device_type", "memory")?; + self.writer.property_array_u64( + "reg", + &[entry.phys_start, entry.page_count * PAGE_SIZE as u64], + )?; + self.writer.end_node(memory_node)?; + } - Ok(self) + Ok(self) + } } -} -trait MemoryMapExt: MemoryMap { - fn display(&self) -> MemoryMapDisplay<'_, Self> { - MemoryMapDisplay { inner: self } + trait MemoryMapExt: MemoryMap { + fn display(&self) -> MemoryMapDisplay<'_, Self> { + MemoryMapDisplay { inner: self } + } } -} -impl MemoryMapExt for T where T: MemoryMap {} + impl MemoryMapExt for T where T: MemoryMap {} -struct MemoryMapDisplay<'a, T: ?Sized> { - inner: &'a T, -} + struct MemoryMapDisplay<'a, T: ?Sized> { + inner: &'a T, + } -impl<'a, T> fmt::Display for MemoryMapDisplay<'a, T> -where - T: MemoryMap, -{ - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - let mut has_fields = false; + impl<'a, T> fmt::Display for MemoryMapDisplay<'a, T> + where + T: MemoryMap, + { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + let mut has_fields = false; - for desc in self.inner.entries() { - if has_fields { - f.write_char('\n')?; - } - write!(f, "{}", desc.display())?; + for desc in self.inner.entries() { + if has_fields { + f.write_char('\n')?; + } + write!(f, "{}", desc.display())?; - has_fields = true; + has_fields = true; + } + Ok(()) } - Ok(()) } -} -trait MemoryDescriptorExt { - fn display(&self) -> MemoryDescriptorDisplay<'_>; -} + trait MemoryDescriptorExt { + fn display(&self) -> MemoryDescriptorDisplay<'_>; + } -impl MemoryDescriptorExt for MemoryDescriptor { - fn display(&self) -> MemoryDescriptorDisplay<'_> { - MemoryDescriptorDisplay { inner: self } + impl MemoryDescriptorExt for MemoryDescriptor { + fn display(&self) -> MemoryDescriptorDisplay<'_> { + MemoryDescriptorDisplay { inner: self } + } } -} -struct MemoryDescriptorDisplay<'a> { - inner: &'a MemoryDescriptor, -} + struct MemoryDescriptorDisplay<'a> { + inner: &'a MemoryDescriptor, + } -impl<'a> fmt::Display for MemoryDescriptorDisplay<'a> { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - write!( - f, - "start: {:#12x}, pages: {:#8x}, type: {:?}", - self.inner.phys_start, self.inner.page_count, self.inner.ty - ) + impl<'a> fmt::Display for MemoryDescriptorDisplay<'a> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!( + f, + "start: {:#12x}, pages: {:#8x}, type: {:?}", + self.inner.phys_start, self.inner.page_count, self.inner.ty + ) + } } } diff --git a/src/os/uefi/mod.rs b/src/os/uefi/mod.rs index 8b16e6aa..2c5e232c 100644 --- a/src/os/uefi/mod.rs +++ b/src/os/uefi/mod.rs @@ -40,7 +40,7 @@ fn main() -> Status { drop(kernel_image); - let fdt = Fdt::new() + let fdt = Fdt::new("uefi") .unwrap() .rsdp(u64::try_from(rsdp.expose_addr()).unwrap()) .unwrap(); From 7b0287aa94bae066991a086d0026da0981f1231c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Kr=C3=B6ning?= Date: Sat, 16 Nov 2024 11:37:04 +0100 Subject: [PATCH 3/6] refactor(fdt): extract `Fdt::memory` MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Martin Kröning --- src/fdt.rs | 24 +++++++++++++++--------- 1 file changed, 15 insertions(+), 9 deletions(-) diff --git a/src/fdt.rs b/src/fdt.rs index 86dcbd08..4cbe36d3 100644 --- a/src/fdt.rs +++ b/src/fdt.rs @@ -1,5 +1,6 @@ use alloc::format; use alloc::vec::Vec; +use core::ops::Range; use vm_fdt::{FdtWriter, FdtWriterNode, FdtWriterResult}; @@ -36,11 +37,22 @@ impl Fdt { Ok(self) } + + pub fn memory(mut self, memory: Range) -> FdtWriterResult { + let memory_node = self + .writer + .begin_node(format!("memory@{:x}", memory.start).as_str())?; + self.writer.property_string("device_type", "memory")?; + self.writer + .property_array_u64("reg", &[memory.start, memory.end - memory.start])?; + self.writer.end_node(memory_node)?; + + Ok(self) + } } #[cfg(target_os = "uefi")] mod uefi { - use alloc::format; use core::fmt; use core::fmt::Write; @@ -59,15 +71,9 @@ mod uefi { .filter(|entry| entry.ty == MemoryType::CONVENTIONAL); for entry in entries { - let memory_node = self - .writer - .begin_node(format!("memory@{:x}", entry.phys_start).as_str())?; - self.writer.property_string("device_type", "memory")?; - self.writer.property_array_u64( - "reg", - &[entry.phys_start, entry.page_count * PAGE_SIZE as u64], + self = self.memory( + entry.phys_start..entry.phys_start + entry.page_count * PAGE_SIZE as u64, )?; - self.writer.end_node(memory_node)?; } Ok(self) From 613e90a10ca3e0b282f7303df75d7e87aaa33077 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Kr=C3=B6ning?= Date: Sat, 16 Nov 2024 12:05:11 +0100 Subject: [PATCH 4/6] refactor(fdt): move `chosen` creation to `finish` MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Martin Kröning --- src/fdt.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/fdt.rs b/src/fdt.rs index 4cbe36d3..de163b74 100644 --- a/src/fdt.rs +++ b/src/fdt.rs @@ -18,13 +18,13 @@ impl Fdt { writer.property_u32("#address-cells", 0x2)?; writer.property_u32("#size-cells", 0x2)?; - let chosen_node = writer.begin_node("chosen")?; - writer.end_node(chosen_node)?; - Ok(Self { writer, root_node }) } pub fn finish(mut self) -> FdtWriterResult> { + let chosen_node = self.writer.begin_node("chosen")?; + self.writer.end_node(chosen_node)?; + self.writer.end_node(self.root_node)?; self.writer.finish() From d8dc66575f1d1fca2ec200e7b3217c120e2cbeed Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Kr=C3=B6ning?= Date: Sat, 16 Nov 2024 12:26:45 +0100 Subject: [PATCH 5/6] refactor(fdt): add support for bootargs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Martin Kröning --- src/fdt.rs | 26 ++++++++++++++++++++++---- 1 file changed, 22 insertions(+), 4 deletions(-) diff --git a/src/fdt.rs b/src/fdt.rs index de163b74..b2dc6dfd 100644 --- a/src/fdt.rs +++ b/src/fdt.rs @@ -4,12 +4,13 @@ use core::ops::Range; use vm_fdt::{FdtWriter, FdtWriterNode, FdtWriterResult}; -pub struct Fdt { +pub struct Fdt<'a> { writer: FdtWriter, root_node: FdtWriterNode, + bootargs: Option<&'a str>, } -impl Fdt { +impl<'a> Fdt<'a> { pub fn new(platform: &str) -> FdtWriterResult { let mut writer = FdtWriter::new()?; @@ -18,11 +19,20 @@ impl Fdt { writer.property_u32("#address-cells", 0x2)?; writer.property_u32("#size-cells", 0x2)?; - Ok(Self { writer, root_node }) + let bootargs = None; + + Ok(Self { + writer, + root_node, + bootargs, + }) } 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)?; + } self.writer.end_node(chosen_node)?; self.writer.end_node(self.root_node)?; @@ -30,6 +40,14 @@ impl Fdt { self.writer.finish() } + #[cfg_attr(target_os = "uefi", expect(unused))] + pub fn bootargs(mut self, bootargs: &'a str) -> FdtWriterResult { + assert!(self.bootargs.is_none()); + self.bootargs = Some(bootargs); + + Ok(self) + } + pub fn rsdp(mut self, rsdp: u64) -> FdtWriterResult { let rsdp_node = self.writer.begin_node(&format!("hermit,rsdp@{rsdp:x}"))?; self.writer.property_array_u64("reg", &[rsdp, 1])?; @@ -61,7 +79,7 @@ mod uefi { use uefi::mem::memory_map::{MemoryMap, MemoryMapMut}; use vm_fdt::FdtWriterResult; - impl super::Fdt { + impl super::Fdt<'_> { pub fn memory_map(mut self, memory_map: &mut impl MemoryMapMut) -> FdtWriterResult { memory_map.sort(); info!("Memory map:\n{}", memory_map.display()); From 9e655bdb7675926543e63d29b2cb9cce77d979db Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Kr=C3=B6ning?= Date: Sat, 16 Nov 2024 12:28:59 +0100 Subject: [PATCH 6/6] refactor(multiboot): use shared `Fdt` builder MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Martin Kröning --- src/arch/x86_64/multiboot.rs | 32 ++++++-------------------------- src/fdt.rs | 26 ++++++++++++++++++++++++++ src/main.rs | 2 +- 3 files changed, 33 insertions(+), 27 deletions(-) diff --git a/src/arch/x86_64/multiboot.rs b/src/arch/x86_64/multiboot.rs index 5e83136d..a97f3a85 100644 --- a/src/arch/x86_64/multiboot.rs +++ b/src/arch/x86_64/multiboot.rs @@ -1,4 +1,3 @@ -use alloc::format; use core::ptr::write_bytes; use core::{mem, ptr, slice}; @@ -8,14 +7,15 @@ use hermit_entry::boot_info::{ }; use hermit_entry::elf::LoadedKernel; use log::info; -use multiboot::information::{MemoryManagement, MemoryType, Multiboot, PAddr}; +use multiboot::information::{MemoryManagement, Multiboot, PAddr}; use sptr::Strict; -use vm_fdt::{FdtWriter, FdtWriterResult}; +use vm_fdt::FdtWriterResult; use x86_64::structures::paging::{PageSize, PageTableFlags, Size2MiB, Size4KiB}; use super::paging; use super::physicalmem::PhysAlloc; use crate::arch::x86_64::{KERNEL_STACK_SIZE, SERIAL_IO_PORT}; +use crate::fdt::Fdt; use crate::BootInfoExt; extern "C" { @@ -55,36 +55,16 @@ impl DeviceTree { let mut mem = Mem; let multiboot = unsafe { Multiboot::from_ptr(mb_info as u64, &mut mem).unwrap() }; - let all_regions = multiboot + let memory_regions = multiboot .memory_regions() .expect("Could not find a memory map in the Multiboot information"); - let ram_regions = all_regions.filter(|m| m.memory_type() == MemoryType::Available); - let mut fdt = FdtWriter::new()?; - - let root_node = fdt.begin_node("")?; - fdt.property_string("compatible", "linux,dummy-virt")?; - fdt.property_u32("#address-cells", 0x2)?; - fdt.property_u32("#size-cells", 0x2)?; + let mut fdt = Fdt::new("multiboot")?.memory_regions(memory_regions)?; if let Some(cmdline) = multiboot.command_line() { - let chosen_node = fdt.begin_node("chosen")?; - fdt.property_string("bootargs", cmdline)?; - fdt.end_node(chosen_node)?; + fdt = fdt.bootargs(cmdline)?; } - for m in ram_regions { - let start_address = m.base_address(); - let length = m.length(); - - let memory_node = fdt.begin_node(format!("memory@{:x}", start_address).as_str())?; - fdt.property_string("device_type", "memory")?; - fdt.property_array_u64("reg", &[start_address, length])?; - fdt.end_node(memory_node)?; - } - - fdt.end_node(root_node)?; - let fdt = fdt.finish()?; Ok(fdt.leak()) diff --git a/src/fdt.rs b/src/fdt.rs index b2dc6dfd..1f49212b 100644 --- a/src/fdt.rs +++ b/src/fdt.rs @@ -48,6 +48,7 @@ impl<'a> Fdt<'a> { Ok(self) } + #[cfg_attr(all(target_arch = "x86_64", not(target_os = "uefi")), expect(unused))] pub fn rsdp(mut self, rsdp: u64) -> FdtWriterResult { let rsdp_node = self.writer.begin_node(&format!("hermit,rsdp@{rsdp:x}"))?; self.writer.property_array_u64("reg", &[rsdp, 1])?; @@ -69,6 +70,31 @@ impl<'a> Fdt<'a> { } } +#[cfg(all(target_arch = "x86_64", not(target_os = "uefi"), not(feature = "fc")))] +mod x86_64 { + use multiboot::information::{MemoryMapIter, MemoryType}; + use vm_fdt::FdtWriterResult; + + impl super::Fdt<'_> { + pub fn memory_regions( + mut self, + memory_regions: MemoryMapIter<'_, '_>, + ) -> FdtWriterResult { + let memory_regions = + memory_regions.filter(|m| m.memory_type() == MemoryType::Available); + + for memory_region in memory_regions { + self = self.memory( + memory_region.base_address() + ..memory_region.base_address() + memory_region.length(), + )?; + } + + Ok(self) + } + } +} + #[cfg(target_os = "uefi")] mod uefi { use core::fmt; diff --git a/src/main.rs b/src/main.rs index a082fcda..89f8d77e 100644 --- a/src/main.rs +++ b/src/main.rs @@ -13,7 +13,7 @@ mod macros; mod arch; mod bump_allocator; -#[cfg(target_os = "uefi")] +#[cfg(any(target_os = "uefi", all(target_arch = "x86_64", not(feature = "fc"))))] mod fdt; mod log; mod os;