Refactor boot and add placeholder kcmdline struct

This commit is contained in:
Zhang Junyang
2023-07-25 12:22:03 +08:00
committed by Tate, Hongliang Tian
parent eb8eb440b3
commit 69cbfc72f5
13 changed files with 145 additions and 113 deletions

View File

@ -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;

View File

@ -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

View File

@ -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()
},

View File

@ -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() {

View 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 }
}
}

View 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();
}

View File

@ -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();

View File

@ -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};

View File

@ -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();

View File

@ -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]

View File

@ -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();
}