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 //! We currently support Multiboot2. The support for Linux Boot Protocol is
//! on its way. //! 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; pub mod multiboot2;
use self::multiboot2::init_global_boot_statics; pub use self::multiboot2::init_boot_args;
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()
}

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 multiboot2::{BootInformation, BootInformationHeader, MemoryAreaType};
use super::{ use crate::boot::{
memory_region::{MemoryRegion, MemoryRegionType}, memory_region::{MemoryRegion, MemoryRegionType},
BootloaderAcpiArg, BootloaderFramebufferArg, ACPI_RSDP, BOOTLOADER_NAME, FRAMEBUFFER_INFO, kcmdline::KCmdlineArg, BootloaderAcpiArg, BootloaderFramebufferArg,
INITRAMFS, KERNEL_COMMANDLINE, MEMORY_REGIONS,
}; };
use core::{arch::global_asm, mem::swap}; use core::{arch::global_asm, mem::swap};
use spin::Once; use spin::Once;
@ -17,8 +16,8 @@ const MULTIBOOT2_ENTRY_MAGIC: u32 = 0x36d76289;
static MB2_INFO: Once<BootInformation> = Once::new(); static MB2_INFO: Once<BootInformation> = Once::new();
fn init_bootloader_name() { fn init_bootloader_name(bootloader_name: &'static Once<String>) {
BOOTLOADER_NAME.call_once(|| { bootloader_name.call_once(|| {
MB2_INFO MB2_INFO
.get() .get()
.unwrap() .unwrap()
@ -30,8 +29,8 @@ fn init_bootloader_name() {
}); });
} }
fn init_kernel_commandline() { fn init_kernel_commandline(kernel_cmdline: &'static Once<KCmdlineArg>) {
KERNEL_COMMANDLINE.call_once(|| { kernel_cmdline.call_once(|| {
MB2_INFO MB2_INFO
.get() .get()
.unwrap() .unwrap()
@ -39,11 +38,11 @@ fn init_kernel_commandline() {
.expect("Kernel commandline not found from the Multiboot2 header!") .expect("Kernel commandline not found from the Multiboot2 header!")
.cmdline() .cmdline()
.expect("UTF-8 error: failed to parse kernel commandline!") .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 let mb2_module_tag = MB2_INFO
.get() .get()
.unwrap() .unwrap()
@ -58,11 +57,11 @@ fn init_initramfs() {
base_addr base_addr
}; };
let length = mb2_module_tag.module_size() as usize; 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() { fn init_acpi_arg(acpi: &'static Once<BootloaderAcpiArg>) {
ACPI_RSDP.call_once(|| { acpi.call_once(|| {
if let Some(v2_tag) = MB2_INFO.get().unwrap().rsdp_v2_tag() { if let Some(v2_tag) = MB2_INFO.get().unwrap().rsdp_v2_tag() {
// check for rsdp v2 // check for rsdp v2
BootloaderAcpiArg::Xsdt(v2_tag.xsdt_address()) 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(); 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, address: fb_tag.address() as usize,
width: fb_tag.width() as usize, width: fb_tag.width() as usize,
height: fb_tag.height() 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 // We should later use regions in `regions_unusable` to truncate all
// regions in `regions_usable`. // regions in `regions_usable`.
// The difference is that regions in `regions_usable` could be used by // 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 // Initialize with regions_unusable + regions_src
MEMORY_REGIONS.call_once(move || { memory_regions.call_once(move || {
let mut all_regions = regions_unusable; let mut all_regions = regions_unusable;
all_regions.append(regions_src); all_regions.append(regions_src);
all_regions all_regions
@ -188,13 +187,20 @@ fn init_memory_regions() {
/// Initialize the global boot static varaiables in the boot module to allow /// Initialize the global boot static varaiables in the boot module to allow
/// other modules to get the boot information. /// other modules to get the boot information.
pub fn init_global_boot_statics() { pub fn init_boot_args(
init_bootloader_name(); bootloader_name: &'static Once<String>,
init_kernel_commandline(); kernel_cmdline: &'static Once<KCmdlineArg>,
init_initramfs(); initramfs: &'static Once<&'static [u8]>,
init_acpi_rsdp(); acpi: &'static Once<BootloaderAcpiArg>,
init_framebuffer_info(); framebuffer_arg: &'static Once<BootloaderFramebufferArg>,
init_memory_regions(); 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 // The entry point of kernel code, which should be defined by the package that

View File

@ -6,9 +6,10 @@ use core::{
ptr::NonNull, ptr::NonNull,
}; };
use crate::arch::boot::{self, BootloaderAcpiArg}; use crate::boot::{self, BootloaderAcpiArg};
use crate::vm::paddr_to_vaddr; use crate::vm::paddr_to_vaddr;
use acpi::{sdt::SdtHeader, AcpiHandler, AcpiTable, AcpiTables}; use acpi::{sdt::SdtHeader, AcpiHandler, AcpiTable, AcpiTables};
use alloc::borrow::ToOwned;
use log::info; use log::info;
use spin::{Mutex, Once}; use spin::{Mutex, Once};
@ -90,7 +91,7 @@ impl AcpiHandler for AcpiMemoryHandler {
} }
pub fn init() { pub fn init() {
let acpi_tables = match boot::get_acpi_rsdp() { let acpi_tables = match boot::acpi_arg().to_owned() {
BootloaderAcpiArg::Rsdp(addr) => unsafe { BootloaderAcpiArg::Rsdp(addr) => unsafe {
AcpiTables::from_rsdp(AcpiMemoryHandler {}, addr as usize).unwrap() AcpiTables::from_rsdp(AcpiMemoryHandler {}, addr as usize).unwrap()
}, },

View File

@ -16,7 +16,6 @@ use log::{info, warn};
pub(crate) fn before_all_init() { pub(crate) fn before_all_init() {
enable_common_cpu_features(); enable_common_cpu_features();
device::serial::init(); device::serial::init();
boot::init();
} }
pub(crate) fn after_all_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; extern crate alloc;
pub mod arch; pub mod arch;
pub mod boot;
pub mod bus; pub mod bus;
pub mod config; pub mod config;
pub mod cpu; pub mod cpu;
@ -44,9 +45,10 @@ use trapframe::TrapFrame;
static mut IRQ_CALLBACK_LIST: Vec<IrqCallbackHandle> = Vec::new(); static mut IRQ_CALLBACK_LIST: Vec<IrqCallbackHandle> = Vec::new();
pub fn init() { pub fn init() {
vm::heap_allocator::init();
arch::before_all_init(); arch::before_all_init();
logger::init(); logger::init();
vm::heap_allocator::init();
boot::init();
vm::init(); vm::init();
trap::init(); trap::init();
arch::after_all_init(); arch::after_all_init();

View File

@ -4,7 +4,7 @@ use buddy_system_allocator::FrameAllocator;
use log::info; use log::info;
use spin::Once; 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 crate::{config::PAGE_SIZE, sync::SpinLock};
use super::{frame::VmFrameFlags, VmFrame}; use super::{frame::VmFrameFlags, VmFrame};

View File

@ -26,10 +26,11 @@ pub use self::{
page_table::PageTable, page_table::PageTable,
}; };
use alloc::borrow::ToOwned;
use alloc::vec::Vec; use alloc::vec::Vec;
use spin::Once; 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 /// Convert physical address to virtual address using offset, only available inside jinux-frame
pub(crate) fn paddr_to_vaddr(pa: usize) -> usize { 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 static FRAMEBUFFER_REGIONS: Once<Vec<MemoryRegion>> = Once::new();
pub(crate) fn init() { 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); frame_allocator::init(&memory_regions);
let mut framebuffer_regions = Vec::new(); let mut framebuffer_regions = Vec::new();

View File

@ -12,7 +12,7 @@ use core::{
ops::{Index, IndexMut}, ops::{Index, IndexMut},
}; };
use font8x8::UnicodeFonts; 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; use spin::Once;
#[init_component] #[init_component]

View File

@ -25,7 +25,7 @@ use crate::{
process::status::ProcessStatus, process::status::ProcessStatus,
thread::{kernel_thread::KernelThreadExt, Thread}, thread::{kernel_thread::KernelThreadExt, Thread},
}; };
use jinux_frame::{arch::boot, exit_qemu}; use jinux_frame::{boot, exit_qemu};
use process::Process; use process::Process;
extern crate alloc; extern crate alloc;
@ -51,7 +51,7 @@ pub fn init() {
driver::init(); driver::init();
net::init(); net::init();
process::fifo_scheduler::init(); process::fifo_scheduler::init();
fs::initramfs::init(boot::get_initramfs()).unwrap(); fs::initramfs::init(boot::initramfs()).unwrap();
device::init().unwrap(); device::init().unwrap();
} }