mirror of
https://github.com/asterinas/asterinas.git
synced 2025-06-29 04:13:24 +00:00
123 lines
3.4 KiB
Rust
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();
|
|
}
|