Files
asterinas/ostd/src/arch/riscv/boot/mod.rs
2025-01-02 10:41:51 +08:00

123 lines
3.4 KiB
Rust

// SPDX-License-Identifier: MPL-2.0
//! The RISC-V boot module defines the entrypoints of Asterinas.
pub mod smp;
use core::arch::global_asm;
use fdt::Fdt;
use spin::Once;
use crate::{
boot::{
memory_region::{MemoryRegion, MemoryRegionArray, MemoryRegionType},
BootloaderAcpiArg, BootloaderFramebufferArg,
},
early_println,
mm::paddr_to_vaddr,
};
global_asm!(include_str!("boot.S"));
/// The Flattened Device Tree of the platform.
pub static DEVICE_TREE: Once<Fdt> = Once::new();
fn parse_bootloader_name() -> &'static str {
"Unknown"
}
fn parse_kernel_commandline() -> &'static str {
DEVICE_TREE.get().unwrap().chosen().bootargs().unwrap_or("")
}
fn parse_initramfs() -> Option<&'static [u8]> {
let Some((start, end)) = parse_initramfs_range() else {
return None;
};
let base_va = paddr_to_vaddr(start);
let length = end - start;
Some(unsafe { core::slice::from_raw_parts(base_va as *const u8, length) })
}
fn parse_acpi_arg() -> BootloaderAcpiArg {
BootloaderAcpiArg::NotProvided
}
fn parse_framebuffer_info() -> Option<BootloaderFramebufferArg> {
None
}
fn parse_memory_regions() -> MemoryRegionArray {
let mut regions = MemoryRegionArray::new();
for region in DEVICE_TREE.get().unwrap().memory().regions() {
if region.size.unwrap_or(0) > 0 {
regions.push(MemoryRegion::new(
region.starting_address as usize,
region.size.unwrap(),
MemoryRegionType::Usable,
));
}
}
if let Some(node) = DEVICE_TREE.get().unwrap().find_node("/reserved-memory") {
for child in node.children() {
if let Some(reg_iter) = child.reg() {
for region in reg_iter {
regions.push(MemoryRegion::new(
region.starting_address as usize,
region.size.unwrap(),
MemoryRegionType::Reserved,
));
}
}
}
}
// Add the kernel region.
regions.push(MemoryRegion::kernel());
// Add the initramfs region.
if let Some((start, end)) = parse_initramfs_range() {
regions.push(MemoryRegion::new(
start,
end - start,
MemoryRegionType::Module,
));
}
regions.into_non_overlapping()
}
fn parse_initramfs_range() -> Option<(usize, usize)> {
let chosen = DEVICE_TREE.get().unwrap().find_node("/chosen").unwrap();
let initrd_start = chosen.property("linux,initrd-start")?.as_usize()?;
let initrd_end = chosen.property("linux,initrd-end")?.as_usize()?;
Some((initrd_start, initrd_end))
}
/// The entry point of the Rust code portion of Asterinas.
#[no_mangle]
pub extern "C" fn riscv_boot(_hart_id: usize, device_tree_paddr: usize) -> ! {
early_println!("Enter riscv_boot");
let device_tree_ptr = paddr_to_vaddr(device_tree_paddr) as *const u8;
let fdt = unsafe { fdt::Fdt::from_ptr(device_tree_ptr).unwrap() };
DEVICE_TREE.call_once(|| fdt);
use crate::boot::{call_ostd_main, EarlyBootInfo, EARLY_INFO};
EARLY_INFO.call_once(|| EarlyBootInfo {
bootloader_name: parse_bootloader_name(),
kernel_cmdline: parse_kernel_commandline(),
initramfs: parse_initramfs(),
acpi_arg: parse_acpi_arg(),
framebuffer_arg: parse_framebuffer_info(),
memory_regions: parse_memory_regions(),
});
call_ostd_main();
}