mirror of
https://github.com/asterinas/asterinas.git
synced 2025-06-22 00:43:24 +00:00
Refactor boot and add placeholder kcmdline struct
This commit is contained in:
committed by
Tate, Hongliang Tian
parent
eb8eb440b3
commit
69cbfc72f5
@ -4,84 +4,6 @@
|
||||
//! We currently support Multiboot2. The support for Linux Boot Protocol is
|
||||
//! on its way.
|
||||
//!
|
||||
//! In this module, we use println! to print information on screen rather
|
||||
//! than logging since the logger is not initialized here.
|
||||
//!
|
||||
|
||||
pub mod multiboot2;
|
||||
use self::multiboot2::init_global_boot_statics;
|
||||
|
||||
pub mod memory_region;
|
||||
use self::memory_region::MemoryRegion;
|
||||
|
||||
use alloc::{string::String, vec::Vec};
|
||||
use spin::Once;
|
||||
|
||||
/// The boot crate can choose either providing the raw RSDP physical address or
|
||||
/// providing the RSDT/XSDT physical address after parsing RSDP.
|
||||
/// This is because bootloaders differ in such behaviors.
|
||||
#[derive(Copy, Clone, Debug)]
|
||||
pub enum BootloaderAcpiArg {
|
||||
/// Physical address of the RSDP.
|
||||
Rsdp(usize),
|
||||
/// Address of RSDT provided in RSDP v1.
|
||||
Rsdt(usize),
|
||||
/// Address of XSDT provided in RSDP v2+.
|
||||
Xsdt(usize),
|
||||
}
|
||||
|
||||
/// The framebuffer arguments.
|
||||
#[derive(Copy, Clone, Debug)]
|
||||
pub struct BootloaderFramebufferArg {
|
||||
pub address: usize,
|
||||
pub width: usize,
|
||||
pub height: usize,
|
||||
/// Bits per pixel of the buffer.
|
||||
pub bpp: usize,
|
||||
}
|
||||
|
||||
/// After initializing the boot module, the get_* functions could be called.
|
||||
/// The initialization must be done after the heap is set and before physical
|
||||
/// mappings are cancelled.
|
||||
pub fn init() {
|
||||
init_global_boot_statics();
|
||||
}
|
||||
|
||||
// The public get_* APIs.
|
||||
|
||||
static BOOTLOADER_NAME: Once<String> = Once::new();
|
||||
/// Get the name and the version of the bootloader.
|
||||
pub fn get_bootloader_name() -> String {
|
||||
BOOTLOADER_NAME.get().unwrap().clone()
|
||||
}
|
||||
|
||||
static KERNEL_COMMANDLINE: Once<String> = Once::new();
|
||||
/// Get the raw unparsed kernel commandline string.
|
||||
pub fn get_kernel_commandline() -> String {
|
||||
KERNEL_COMMANDLINE.get().unwrap().clone()
|
||||
}
|
||||
|
||||
static INITRAMFS: Once<&'static [u8]> = Once::new();
|
||||
/// The slice of the bootloader-loaded init ram disk.
|
||||
pub fn get_initramfs() -> &'static [u8] {
|
||||
INITRAMFS.get().unwrap()
|
||||
}
|
||||
|
||||
static ACPI_RSDP: Once<BootloaderAcpiArg> = Once::new();
|
||||
/// The ACPI RDSP/XSDT address.
|
||||
pub fn get_acpi_rsdp() -> BootloaderAcpiArg {
|
||||
ACPI_RSDP.get().unwrap().clone()
|
||||
}
|
||||
|
||||
static FRAMEBUFFER_INFO: Once<BootloaderFramebufferArg> = Once::new();
|
||||
/// Framebuffer information.
|
||||
pub fn get_framebuffer_info() -> BootloaderFramebufferArg {
|
||||
FRAMEBUFFER_INFO.get().unwrap().clone()
|
||||
}
|
||||
|
||||
static MEMORY_REGIONS: Once<Vec<MemoryRegion>> = Once::new();
|
||||
/// Get memory regions.
|
||||
/// The returned usable memory regions are guarenteed to not overlap with other unusable ones.
|
||||
pub fn get_memory_regions() -> Vec<MemoryRegion> {
|
||||
MEMORY_REGIONS.get().unwrap().clone()
|
||||
}
|
||||
pub use self::multiboot2::init_boot_args;
|
||||
|
@ -1,10 +1,9 @@
|
||||
use alloc::{string::ToString, vec::Vec};
|
||||
use alloc::{string::{ToString, String}, vec::Vec};
|
||||
use multiboot2::{BootInformation, BootInformationHeader, MemoryAreaType};
|
||||
|
||||
use super::{
|
||||
use crate::boot::{
|
||||
memory_region::{MemoryRegion, MemoryRegionType},
|
||||
BootloaderAcpiArg, BootloaderFramebufferArg, ACPI_RSDP, BOOTLOADER_NAME, FRAMEBUFFER_INFO,
|
||||
INITRAMFS, KERNEL_COMMANDLINE, MEMORY_REGIONS,
|
||||
kcmdline::KCmdlineArg, BootloaderAcpiArg, BootloaderFramebufferArg,
|
||||
};
|
||||
use core::{arch::global_asm, mem::swap};
|
||||
use spin::Once;
|
||||
@ -17,8 +16,8 @@ const MULTIBOOT2_ENTRY_MAGIC: u32 = 0x36d76289;
|
||||
|
||||
static MB2_INFO: Once<BootInformation> = Once::new();
|
||||
|
||||
fn init_bootloader_name() {
|
||||
BOOTLOADER_NAME.call_once(|| {
|
||||
fn init_bootloader_name(bootloader_name: &'static Once<String>) {
|
||||
bootloader_name.call_once(|| {
|
||||
MB2_INFO
|
||||
.get()
|
||||
.unwrap()
|
||||
@ -30,8 +29,8 @@ fn init_bootloader_name() {
|
||||
});
|
||||
}
|
||||
|
||||
fn init_kernel_commandline() {
|
||||
KERNEL_COMMANDLINE.call_once(|| {
|
||||
fn init_kernel_commandline(kernel_cmdline: &'static Once<KCmdlineArg>) {
|
||||
kernel_cmdline.call_once(|| {
|
||||
MB2_INFO
|
||||
.get()
|
||||
.unwrap()
|
||||
@ -39,11 +38,11 @@ fn init_kernel_commandline() {
|
||||
.expect("Kernel commandline not found from the Multiboot2 header!")
|
||||
.cmdline()
|
||||
.expect("UTF-8 error: failed to parse kernel commandline!")
|
||||
.to_string()
|
||||
.into()
|
||||
});
|
||||
}
|
||||
|
||||
fn init_initramfs() {
|
||||
fn init_initramfs(initramfs: &'static Once<&'static [u8]>) {
|
||||
let mb2_module_tag = MB2_INFO
|
||||
.get()
|
||||
.unwrap()
|
||||
@ -58,11 +57,11 @@ fn init_initramfs() {
|
||||
base_addr
|
||||
};
|
||||
let length = mb2_module_tag.module_size() as usize;
|
||||
INITRAMFS.call_once(|| unsafe { core::slice::from_raw_parts(base_va as *const u8, length) });
|
||||
initramfs.call_once(|| unsafe { core::slice::from_raw_parts(base_va as *const u8, length) });
|
||||
}
|
||||
|
||||
fn init_acpi_rsdp() {
|
||||
ACPI_RSDP.call_once(|| {
|
||||
fn init_acpi_arg(acpi: &'static Once<BootloaderAcpiArg>) {
|
||||
acpi.call_once(|| {
|
||||
if let Some(v2_tag) = MB2_INFO.get().unwrap().rsdp_v2_tag() {
|
||||
// check for rsdp v2
|
||||
BootloaderAcpiArg::Xsdt(v2_tag.xsdt_address())
|
||||
@ -75,9 +74,9 @@ fn init_acpi_rsdp() {
|
||||
});
|
||||
}
|
||||
|
||||
fn init_framebuffer_info() {
|
||||
fn init_framebuffer_info(framebuffer_arg: &'static Once<BootloaderFramebufferArg>) {
|
||||
let fb_tag = MB2_INFO.get().unwrap().framebuffer_tag().unwrap().unwrap();
|
||||
FRAMEBUFFER_INFO.call_once(|| BootloaderFramebufferArg {
|
||||
framebuffer_arg.call_once(|| BootloaderFramebufferArg {
|
||||
address: fb_tag.address() as usize,
|
||||
width: fb_tag.width() as usize,
|
||||
height: fb_tag.height() as usize,
|
||||
@ -97,7 +96,7 @@ impl From<MemoryAreaType> for MemoryRegionType {
|
||||
}
|
||||
}
|
||||
|
||||
fn init_memory_regions() {
|
||||
fn init_memory_regions(memory_regions: &'static Once<Vec<MemoryRegion>>) {
|
||||
// We should later use regions in `regions_unusable` to truncate all
|
||||
// regions in `regions_usable`.
|
||||
// The difference is that regions in `regions_usable` could be used by
|
||||
@ -179,7 +178,7 @@ fn init_memory_regions() {
|
||||
}
|
||||
|
||||
// Initialize with regions_unusable + regions_src
|
||||
MEMORY_REGIONS.call_once(move || {
|
||||
memory_regions.call_once(move || {
|
||||
let mut all_regions = regions_unusable;
|
||||
all_regions.append(regions_src);
|
||||
all_regions
|
||||
@ -188,13 +187,20 @@ fn init_memory_regions() {
|
||||
|
||||
/// Initialize the global boot static varaiables in the boot module to allow
|
||||
/// other modules to get the boot information.
|
||||
pub fn init_global_boot_statics() {
|
||||
init_bootloader_name();
|
||||
init_kernel_commandline();
|
||||
init_initramfs();
|
||||
init_acpi_rsdp();
|
||||
init_framebuffer_info();
|
||||
init_memory_regions();
|
||||
pub fn init_boot_args(
|
||||
bootloader_name: &'static Once<String>,
|
||||
kernel_cmdline: &'static Once<KCmdlineArg>,
|
||||
initramfs: &'static Once<&'static [u8]>,
|
||||
acpi: &'static Once<BootloaderAcpiArg>,
|
||||
framebuffer_arg: &'static Once<BootloaderFramebufferArg>,
|
||||
memory_regions: &'static Once<Vec<MemoryRegion>>,
|
||||
) {
|
||||
init_bootloader_name(bootloader_name);
|
||||
init_kernel_commandline(kernel_cmdline);
|
||||
init_initramfs(initramfs);
|
||||
init_acpi_arg(acpi);
|
||||
init_framebuffer_info(framebuffer_arg);
|
||||
init_memory_regions(memory_regions);
|
||||
}
|
||||
|
||||
// The entry point of kernel code, which should be defined by the package that
|
@ -6,9 +6,10 @@ use core::{
|
||||
ptr::NonNull,
|
||||
};
|
||||
|
||||
use crate::arch::boot::{self, BootloaderAcpiArg};
|
||||
use crate::boot::{self, BootloaderAcpiArg};
|
||||
use crate::vm::paddr_to_vaddr;
|
||||
use acpi::{sdt::SdtHeader, AcpiHandler, AcpiTable, AcpiTables};
|
||||
use alloc::borrow::ToOwned;
|
||||
use log::info;
|
||||
use spin::{Mutex, Once};
|
||||
|
||||
@ -90,7 +91,7 @@ impl AcpiHandler for AcpiMemoryHandler {
|
||||
}
|
||||
|
||||
pub fn init() {
|
||||
let acpi_tables = match boot::get_acpi_rsdp() {
|
||||
let acpi_tables = match boot::acpi_arg().to_owned() {
|
||||
BootloaderAcpiArg::Rsdp(addr) => unsafe {
|
||||
AcpiTables::from_rsdp(AcpiMemoryHandler {}, addr as usize).unwrap()
|
||||
},
|
||||
|
@ -16,7 +16,6 @@ use log::{info, warn};
|
||||
pub(crate) fn before_all_init() {
|
||||
enable_common_cpu_features();
|
||||
device::serial::init();
|
||||
boot::init();
|
||||
}
|
||||
|
||||
pub(crate) fn after_all_init() {
|
||||
|
23
framework/jinux-frame/src/boot/kcmdline.rs
Normal file
23
framework/jinux-frame/src/boot/kcmdline.rs
Normal file
@ -0,0 +1,23 @@
|
||||
//! The module to parse kernel commandline arguments.
|
||||
//!
|
||||
|
||||
use alloc::string::String;
|
||||
|
||||
/// The struct to store parsed kernel commandline arguments.
|
||||
pub struct KCmdlineArg {
|
||||
initproc: Option<String>,
|
||||
}
|
||||
|
||||
// Define get APIs.
|
||||
impl KCmdlineArg {
|
||||
pub fn get_initproc(&self) -> Option<&str> {
|
||||
self.initproc.as_deref()
|
||||
}
|
||||
}
|
||||
|
||||
// Define the way to parse a string to `KCmdlineArg`.
|
||||
impl From<&str> for KCmdlineArg {
|
||||
fn from(cmdline: &str) -> Self {
|
||||
KCmdlineArg { initproc: None }
|
||||
}
|
||||
}
|
78
framework/jinux-frame/src/boot/mod.rs
Normal file
78
framework/jinux-frame/src/boot/mod.rs
Normal file
@ -0,0 +1,78 @@
|
||||
//! The architecture-independent boot module, which provides a universal interface
|
||||
//! from the bootloader to the rest of the framework.
|
||||
//!
|
||||
|
||||
use crate::arch::boot::init_boot_args;
|
||||
|
||||
pub mod kcmdline;
|
||||
use kcmdline::KCmdlineArg;
|
||||
|
||||
pub mod memory_region;
|
||||
use self::memory_region::MemoryRegion;
|
||||
|
||||
use alloc::{string::String, vec::Vec};
|
||||
use spin::Once;
|
||||
|
||||
/// The boot crate can choose either providing the raw RSDP physical address or
|
||||
/// providing the RSDT/XSDT physical address after parsing RSDP.
|
||||
/// This is because bootloaders differ in such behaviors.
|
||||
#[derive(Copy, Clone, Debug)]
|
||||
pub enum BootloaderAcpiArg {
|
||||
/// Physical address of the RSDP.
|
||||
Rsdp(usize),
|
||||
/// Address of RSDT provided in RSDP v1.
|
||||
Rsdt(usize),
|
||||
/// Address of XSDT provided in RSDP v2+.
|
||||
Xsdt(usize),
|
||||
}
|
||||
|
||||
/// The framebuffer arguments.
|
||||
#[derive(Copy, Clone, Debug)]
|
||||
pub struct BootloaderFramebufferArg {
|
||||
pub address: usize,
|
||||
pub width: usize,
|
||||
pub height: usize,
|
||||
/// Bits per pixel of the buffer.
|
||||
pub bpp: usize,
|
||||
}
|
||||
|
||||
// Use a macro to simplify coding.
|
||||
macro_rules! define_global_static_boot_arguments {
|
||||
( $( $lower:ident, $upper:ident, $typ:ty; )* ) => {
|
||||
// Define statics and corresponding public get APIs.
|
||||
$(
|
||||
static $upper: Once<$typ> = Once::new();
|
||||
/// Macro generated public get API.
|
||||
pub fn $lower() -> &'static $typ {
|
||||
$upper.get().unwrap()
|
||||
}
|
||||
)*
|
||||
// Produce a init function call. The init function must
|
||||
// be defined in the `arch::boot` module conforming to this
|
||||
// definition.
|
||||
fn arch_init_boot_args() {
|
||||
init_boot_args( $( &$upper, )* );
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
// Define a series of static variable definitions and its APIs. The names in
|
||||
// each line are:
|
||||
// 1. The lowercase name of the variable, also the name of the get API;
|
||||
// 2. the uppercase name of the variable;
|
||||
// 3. the type of the variable.
|
||||
define_global_static_boot_arguments!(
|
||||
bootloader_name, BOOTLOADER_NAME, String;
|
||||
kernel_cmdline, KERNEL_CMDLINE, KCmdlineArg;
|
||||
initramfs, INITRAMFS, &'static [u8];
|
||||
acpi_arg, ACPI_ARG, BootloaderAcpiArg;
|
||||
framebuffer_arg, FRAMEBUFFER_ARG, BootloaderFramebufferArg;
|
||||
memory_regions, MEMORY_REGIONS, Vec<MemoryRegion>;
|
||||
);
|
||||
|
||||
/// After initializing the boot module, the get functions could be called.
|
||||
/// The initialization must be done after the heap is set and before physical
|
||||
/// mappings are cancelled.
|
||||
pub fn init() {
|
||||
arch_init_boot_args();
|
||||
}
|
@ -18,6 +18,7 @@
|
||||
extern crate alloc;
|
||||
|
||||
pub mod arch;
|
||||
pub mod boot;
|
||||
pub mod bus;
|
||||
pub mod config;
|
||||
pub mod cpu;
|
||||
@ -44,9 +45,10 @@ use trapframe::TrapFrame;
|
||||
static mut IRQ_CALLBACK_LIST: Vec<IrqCallbackHandle> = Vec::new();
|
||||
|
||||
pub fn init() {
|
||||
vm::heap_allocator::init();
|
||||
arch::before_all_init();
|
||||
logger::init();
|
||||
vm::heap_allocator::init();
|
||||
boot::init();
|
||||
vm::init();
|
||||
trap::init();
|
||||
arch::after_all_init();
|
||||
|
@ -4,7 +4,7 @@ use buddy_system_allocator::FrameAllocator;
|
||||
use log::info;
|
||||
use spin::Once;
|
||||
|
||||
use crate::arch::boot::memory_region::{MemoryRegion, MemoryRegionType};
|
||||
use crate::boot::memory_region::{MemoryRegion, MemoryRegionType};
|
||||
use crate::{config::PAGE_SIZE, sync::SpinLock};
|
||||
|
||||
use super::{frame::VmFrameFlags, VmFrame};
|
||||
|
@ -26,10 +26,11 @@ pub use self::{
|
||||
page_table::PageTable,
|
||||
};
|
||||
|
||||
use alloc::borrow::ToOwned;
|
||||
use alloc::vec::Vec;
|
||||
use spin::Once;
|
||||
|
||||
use crate::arch::boot::memory_region::{MemoryRegion, MemoryRegionType};
|
||||
use crate::boot::memory_region::{MemoryRegion, MemoryRegionType};
|
||||
|
||||
/// Convert physical address to virtual address using offset, only available inside jinux-frame
|
||||
pub(crate) fn paddr_to_vaddr(pa: usize) -> usize {
|
||||
@ -55,7 +56,7 @@ pub(crate) static MEMORY_REGIONS: Once<Vec<MemoryRegion>> = Once::new();
|
||||
pub static FRAMEBUFFER_REGIONS: Once<Vec<MemoryRegion>> = Once::new();
|
||||
|
||||
pub(crate) fn init() {
|
||||
let memory_regions = crate::arch::boot::get_memory_regions();
|
||||
let memory_regions = crate::boot::memory_regions().to_owned();
|
||||
frame_allocator::init(&memory_regions);
|
||||
|
||||
let mut framebuffer_regions = Vec::new();
|
||||
|
@ -12,7 +12,7 @@ use core::{
|
||||
ops::{Index, IndexMut},
|
||||
};
|
||||
use font8x8::UnicodeFonts;
|
||||
use jinux_frame::{arch::boot, config::PAGE_SIZE, io_mem::IoMem, sync::SpinLock, vm::VmIo};
|
||||
use jinux_frame::{boot, config::PAGE_SIZE, io_mem::IoMem, sync::SpinLock, vm::VmIo};
|
||||
use spin::Once;
|
||||
|
||||
#[init_component]
|
||||
|
@ -25,7 +25,7 @@ use crate::{
|
||||
process::status::ProcessStatus,
|
||||
thread::{kernel_thread::KernelThreadExt, Thread},
|
||||
};
|
||||
use jinux_frame::{arch::boot, exit_qemu};
|
||||
use jinux_frame::{boot, exit_qemu};
|
||||
use process::Process;
|
||||
|
||||
extern crate alloc;
|
||||
@ -51,7 +51,7 @@ pub fn init() {
|
||||
driver::init();
|
||||
net::init();
|
||||
process::fifo_scheduler::init();
|
||||
fs::initramfs::init(boot::get_initramfs()).unwrap();
|
||||
fs::initramfs::init(boot::initramfs()).unwrap();
|
||||
device::init().unwrap();
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user