From 66a8b404c22225b214ee2a4363f4d5fcca7c31b6 Mon Sep 17 00:00:00 2001 From: Yuke Peng Date: Sun, 27 Aug 2023 20:11:44 +0800 Subject: [PATCH] Support multiboot legacy protocol --- Cargo.lock | 1 + framework/jinux-frame/Cargo.toml | 1 + .../jinux-frame/src/arch/x86/boot/boot.S | 14 +- .../jinux-frame/src/arch/x86/boot/mod.rs | 58 ++- .../src/arch/x86/boot/multiboot.rs | 412 ++++++++++++++++++ .../src/arch/x86/boot/multiboot2.rs | 11 +- .../jinux-frame/src/arch/x86/device/cmos.rs | 20 +- .../src/arch/x86/kernel/acpi/dmar.rs | 3 + .../src/arch/x86/kernel/acpi/mod.rs | 16 +- .../src/arch/x86/kernel/apic/ioapic.rs | 3 + framework/jinux-frame/src/boot/kcmdline.rs | 4 + framework/jinux-frame/src/boot/mod.rs | 1 + 12 files changed, 527 insertions(+), 17 deletions(-) create mode 100644 framework/jinux-frame/src/arch/x86/boot/multiboot.rs diff --git a/Cargo.lock b/Cargo.lock index 30a55d29d..952bc7b2e 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -689,6 +689,7 @@ dependencies = [ "log", "multiboot2", "pod", + "rsdp", "spin 0.9.8", "tdx-guest", "trapframe", diff --git a/framework/jinux-frame/Cargo.toml b/framework/jinux-frame/Cargo.toml index 3ebd7069d..8397310cf 100644 --- a/framework/jinux-frame/Cargo.toml +++ b/framework/jinux-frame/Cargo.toml @@ -26,6 +26,7 @@ x86 = "0.52.0" acpi = "4.1.1" aml = "0.16.3" multiboot2 = "0.16.0" +rsdp = "2.0.0" [features] intel_tdx = ["dep:tdx-guest"] diff --git a/framework/jinux-frame/src/arch/x86/boot/boot.S b/framework/jinux-frame/src/arch/x86/boot/boot.S index 6492e447a..6250325fb 100644 --- a/framework/jinux-frame/src/arch/x86/boot/boot.S +++ b/framework/jinux-frame/src/arch/x86/boot/boot.S @@ -18,6 +18,10 @@ MB2_ARCHITECTURE = 0 // 32-bit (protected) mode of i386 MB2_HEADERLEN = header_end - header_start MB2_CHECKSUM = -(MB2_MAGIC + MB2_ARCHITECTURE + MB2_HEADERLEN) +MB_MAGIC = 0x1BADB002 +MB_FLAGS = 0 +MB_CHECKSUM = -(MB_MAGIC + MB_FLAGS) + header_start: .align 8 @@ -43,6 +47,12 @@ info_request_end: .long 8 // size header_end: +multiboot_header: + .align 8 + .long MB_MAGIC + .long MB_FLAGS + .long MB_CHECKSUM + initial_boot_setup: cli cld @@ -280,8 +290,8 @@ long_mode: // Clear the frame pointer to stop backtracing here. xor rbp, rbp -.extern __multiboot2_entry - lea rax, [rip + __multiboot2_entry] // jump into Rust code +.extern __boot_entry + lea rax, [rip + __boot_entry] // jump into Rust code call rax // In case boot() returns. diff --git a/framework/jinux-frame/src/arch/x86/boot/mod.rs b/framework/jinux-frame/src/arch/x86/boot/mod.rs index 88a9f28df..21b39a7f1 100644 --- a/framework/jinux-frame/src/arch/x86/boot/mod.rs +++ b/framework/jinux-frame/src/arch/x86/boot/mod.rs @@ -5,5 +5,61 @@ //! on its way. //! +mod multiboot; mod multiboot2; -pub use self::multiboot2::init_boot_args; + +use core::arch::global_asm; + +use alloc::{string::String, vec::Vec}; +use spin::Once; + +use crate::boot::{ + kcmdline::KCmdlineArg, memory_region::MemoryRegion, BootloaderAcpiArg, BootloaderFramebufferArg, +}; + +use self::{ + multiboot::{multiboot_entry, MULTIBOOT_ENTRY_MAGIC}, + multiboot2::{multiboot2_entry, MULTIBOOT2_ENTRY_MAGIC}, +}; + +/// Initialize the global boot static varaiables in the boot module to allow +/// other modules to get the boot information. +pub fn init_boot_args( + bootloader_name: &'static Once, + kernel_cmdline: &'static Once, + initramfs: &'static Once<&'static [u8]>, + acpi: &'static Once, + framebuffer_arg: &'static Once, + memory_regions: &'static Once>, +) { + if multiboot::boot_by_multiboot() { + multiboot::init_boot_args( + bootloader_name, + kernel_cmdline, + initramfs, + acpi, + framebuffer_arg, + memory_regions, + ); + } else if multiboot2::boot_by_multiboot2() { + multiboot2::init_boot_args( + bootloader_name, + kernel_cmdline, + initramfs, + acpi, + framebuffer_arg, + memory_regions, + ); + } +} + +global_asm!(include_str!("boot.S")); + +#[no_mangle] +unsafe extern "C" fn __boot_entry(boot_magic: u32, boot_params: u64) -> ! { + match boot_magic { + MULTIBOOT2_ENTRY_MAGIC => multiboot2_entry(boot_magic, boot_params), + MULTIBOOT_ENTRY_MAGIC => multiboot_entry(boot_magic, boot_params), + _ => panic!("Unknown boot magic:{:x?}", boot_magic), + } +} diff --git a/framework/jinux-frame/src/arch/x86/boot/multiboot.rs b/framework/jinux-frame/src/arch/x86/boot/multiboot.rs new file mode 100644 index 000000000..2026c833a --- /dev/null +++ b/framework/jinux-frame/src/arch/x86/boot/multiboot.rs @@ -0,0 +1,412 @@ +use core::mem::swap; + +use alloc::{string::String, vec::Vec}; +use multiboot2::MemoryAreaType; +use spin::Once; + +use crate::{ + arch::x86::kernel::acpi::AcpiMemoryHandler, + boot::{ + kcmdline::KCmdlineArg, + memory_region::{MemoryRegion, MemoryRegionType}, + BootloaderAcpiArg, BootloaderFramebufferArg, + }, + config::PHYS_OFFSET, + vm::paddr_to_vaddr, +}; + +pub(super) const MULTIBOOT_ENTRY_MAGIC: u32 = 0x2BADB002; + +/// Initialize the global boot static varaiables in the boot module to allow +/// other modules to get the boot information. +pub(super) fn init_boot_args( + bootloader_name: &'static Once, + kernel_cmdline: &'static Once, + initramfs: &'static Once<&'static [u8]>, + acpi: &'static Once, + framebuffer_arg: &'static Once, + memory_regions: &'static Once>, +) { + 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); +} + +pub fn boot_by_multiboot() -> bool { + MB1_INFO.is_completed() +} + +fn init_bootloader_name(bootloader_name: &'static Once) { + bootloader_name.call_once(|| { + let mut name = ""; + let info = MB1_INFO.get().unwrap(); + if info.boot_loader_name != 0 { + // Safety: the bootloader name is C-style zero-terminated string. + unsafe { + let cstr = paddr_to_vaddr(info.boot_loader_name as usize) as *const u8; + let mut len = 0; + while cstr.add(len).read() != 0 { + len += 1; + } + + name = core::str::from_utf8(core::slice::from_raw_parts(cstr, len)) + .expect("cmdline is not a utf-8 string"); + } + } + name.into() + }); +} + +fn init_kernel_commandline(kernel_cmdline: &'static Once) { + kernel_cmdline.call_once(|| { + let mut cmdline = ""; + let info = MB1_INFO.get().unwrap(); + if info.cmdline != 0 { + // Safety: the command line is C-style zero-terminated string. + unsafe { + let cstr = paddr_to_vaddr(info.cmdline as usize) as *const u8; + let mut len = 0; + while cstr.add(len).read() != 0 { + len += 1; + } + + cmdline = core::str::from_utf8(core::slice::from_raw_parts(cstr, len)) + .expect("cmdline is not a utf-8 string"); + } + } + cmdline.into() + }); +} + +fn init_initramfs(initramfs: &'static Once<&'static [u8]>) { + let info = MB1_INFO.get().unwrap(); + // FIXME: We think all modules are initramfs, can this cause problems? + if info.mods_count == 0 { + return; + } + let modules_addr = info.mods_addr as usize; + // We only use one module + let (start, end) = unsafe { + ( + (*(paddr_to_vaddr(modules_addr) as *const u32)) as usize, + (*(paddr_to_vaddr(modules_addr + 4) as *const u32)) as usize, + ) + }; + // We must return a slice composed by VA since kernel should read every in VA. + let base_va = if start < PHYS_OFFSET { + paddr_to_vaddr(start) + } else { + start + }; + let length = end - start; + initramfs.call_once(|| unsafe { core::slice::from_raw_parts(base_va as *const u8, length) }); +} + +fn init_acpi_arg(acpi: &'static Once) { + // The multiboot protocol does not contain RSDP address. + // TODO: What about UEFI? + let rsdp = unsafe { rsdp::Rsdp::search_for_on_bios(AcpiMemoryHandler {}) }; + match rsdp { + Ok(map) => match map.validate() { + Ok(_) => acpi.call_once(|| { + if map.revision() > 0 { + BootloaderAcpiArg::Xsdt(map.xsdt_address() as usize) + } else { + BootloaderAcpiArg::Rsdt(map.rsdt_address() as usize) + } + }), + Err(_) => acpi.call_once(|| BootloaderAcpiArg::NotExists), + }, + Err(_) => acpi.call_once(|| BootloaderAcpiArg::NotExists), + }; +} + +fn init_framebuffer_info(framebuffer_arg: &'static Once) { + let info = MB1_INFO.get().unwrap(); + framebuffer_arg.call_once(|| BootloaderFramebufferArg { + address: info.framebuffer_table.addr as usize, + width: info.framebuffer_table.width as usize, + height: info.framebuffer_table.height as usize, + bpp: info.framebuffer_table.bpp as usize, + }); +} + +fn init_memory_regions(memory_regions: &'static Once>) { + // 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 + // the frame allocator. + let mut regions_usable = Vec::::new(); + let mut regions_unusable = Vec::::new(); + + // Add the regions in the multiboot protocol. + let info = MB1_INFO.get().unwrap(); + let start = info.memory_map_addr as usize; + let length = info.memory_map_len as usize; + let mut current = start; + + while current < start + length { + let entry = unsafe { &*(paddr_to_vaddr(current) as *const MemoryEntry) }; + let start = entry.base_addr; + let area_type: MemoryRegionType = entry.memory_type.into(); + let region = MemoryRegion::new( + start.try_into().unwrap(), + entry.length.try_into().unwrap(), + area_type, + ); + match area_type { + MemoryRegionType::Usable | MemoryRegionType::Reclaimable => { + regions_usable.push(region); + } + _ => { + regions_unusable.push(region); + } + } + current += entry.size as usize + 4; + } + + // Add the framebuffer region. + let fb = BootloaderFramebufferArg { + address: info.framebuffer_table.addr as usize, + width: info.framebuffer_table.width as usize, + height: info.framebuffer_table.height as usize, + bpp: info.framebuffer_table.bpp as usize, + }; + regions_unusable.push(MemoryRegion::new( + fb.address, + (fb.width * fb.height * fb.bpp + 7) / 8, // round up when divide with 8 (bits/Byte) + MemoryRegionType::Framebuffer, + )); + // Add the kernel region. + // These are physical addresses provided by the linker script. + extern "C" { + fn __kernel_start(); + fn __kernel_end(); + } + regions_unusable.push(MemoryRegion::new( + __kernel_start as usize, + __kernel_end as usize - __kernel_start as usize, + MemoryRegionType::Kernel, + )); + + // Add the initramfs area. + // These are physical addresses provided by the linker script. + if info.mods_count != 0 { + let modules_addr = info.mods_addr as usize; + // We only use one module + let (start, end) = unsafe { + ( + (*(paddr_to_vaddr(modules_addr) as *const u32)) as usize, + (*(paddr_to_vaddr(modules_addr + 4) as *const u32)) as usize, + ) + }; + regions_unusable.push(MemoryRegion::new( + start, + end - start, + MemoryRegionType::Reserved, + )); + } + + // `regions_*` are 2 rolling vectors since we are going to truncate + // the regions in a iterative manner. + let mut regions = Vec::::new(); + let regions_src = &mut regions_usable; + let regions_dst = &mut regions; + // Truncate the usable regions. + for &r_unusable in ®ions_unusable { + regions_dst.clear(); + for r_usable in &*regions_src { + regions_dst.append(&mut r_usable.truncate(&r_unusable)); + } + swap(regions_src, regions_dst); + } + + // Initialize with regions_unusable + regions_src + memory_regions.call_once(move || { + let mut all_regions = regions_unusable; + all_regions.append(&mut regions_usable); + all_regions + }); +} + +/// Representation of Multiboot Information according to specification. +/// +/// Ref:https://www.gnu.org/software/grub/manual/multiboot/multiboot.html#Boot-information-format +/// +///```text +/// +-------------------+ +/// 0 | flags | (required) +/// +-------------------+ +/// 4 | mem_lower | (present if flags[0] is set) +/// 8 | mem_upper | (present if flags[0] is set) +/// +-------------------+ +/// 12 | boot_device | (present if flags[1] is set) +/// +-------------------+ +/// 16 | cmdline | (present if flags[2] is set) +/// +-------------------+ +/// 20 | mods_count | (present if flags[3] is set) +/// 24 | mods_addr | (present if flags[3] is set) +/// +-------------------+ +/// 28 - 40 | syms | (present if flags[4] or +/// | | flags[5] is set) +/// +-------------------+ +/// 44 | mmap_length | (present if flags[6] is set) +/// 48 | mmap_addr | (present if flags[6] is set) +/// +-------------------+ +/// 52 | drives_length | (present if flags[7] is set) +/// 56 | drives_addr | (present if flags[7] is set) +/// +-------------------+ +/// 60 | config_table | (present if flags[8] is set) +/// +-------------------+ +/// 64 | boot_loader_name | (present if flags[9] is set) +/// +-------------------+ +/// 68 | apm_table | (present if flags[10] is set) +/// +-------------------+ +/// 72 | vbe_control_info | (present if flags[11] is set) +/// 76 | vbe_mode_info | +/// 80 | vbe_mode | +/// 82 | vbe_interface_seg | +/// 84 | vbe_interface_off | +/// 86 | vbe_interface_len | +/// +-------------------+ +/// 88 | framebuffer_addr | (present if flags[12] is set) +/// 96 | framebuffer_pitch | +/// 100 | framebuffer_width | +/// 104 | framebuffer_height| +/// 108 | framebuffer_bpp | +/// 109 | framebuffer_type | +/// 110-115 | color_info | +/// +-------------------+ +///``` +/// +#[derive(Debug, Copy, Clone)] +#[repr(C, packed)] +struct MultibootLegacyInfo { + /// Indicate whether the below field exists. + flags: u32, + + /// Physical memory low. + mem_lower: u32, + /// Physical memory high. + mem_upper: u32, + + /// Indicates which BIOS disk device the boot loader loaded the OS image from. + boot_device: u32, + + /// Command line passed to kernel. + cmdline: u32, + + /// Modules count. + mods_count: u32, + /// The start address of modules list, each module structure format: + /// ```text + /// +-------------------+ + /// 0 | mod_start | + /// 4 | mod_end | + /// +-------------------+ + /// 8 | string | + /// +-------------------+ + /// 12 | reserved (0) | + /// +-------------------+ + /// ``` + mods_addr: u32, + + /// If flags[4] = 1, then the field starting at byte 28 are valid: + /// ```text + /// +-------------------+ + /// 28 | tabsize | + /// 32 | strsize | + /// 36 | addr | + /// 40 | reserved (0) | + /// +-------------------+ + /// ``` + /// These indicate where the symbol table from kernel image can be found. + /// + /// If flags[5] = 1, then the field starting at byte 28 are valid: + /// ```text + /// +-------------------+ + /// 28 | num | + /// 32 | size | + /// 36 | addr | + /// 40 | shndx | + /// +-------------------+ + /// ``` + /// These indicate where the section header table from an ELF kernel is, + /// the size of each entry, number of entries, and the string table used as the index of names. + symbols: [u8; 16], + + memory_map_len: u32, + /// The start address of memory map list, each structure format: + /// ```text + /// +-------------------+ + /// -4 | size | + /// +-------------------+ + /// 0 | base_addr | + /// 8 | length | + /// 16 | type | + /// +-------------------+ + /// ``` + memory_map_addr: u32, + + drives_length: u32, + drives_addr: u32, + + config_table: u32, + + boot_loader_name: u32, + + apm_table: u32, + + vbe_table: VbeTable, + + framebuffer_table: FramebufferTable, +} + +#[derive(Debug, Copy, Clone)] +#[repr(C, packed)] +struct VbeTable { + control_info: u32, + mode_info: u32, + mode: u16, + interface_seg: u16, + interface_off: u16, + interface_len: u16, +} + +#[derive(Debug, Copy, Clone)] +#[repr(C, packed)] +struct FramebufferTable { + addr: u64, + pitch: u32, + width: u32, + height: u32, + bpp: u8, + typ: u8, + color_info: [u8; 6], +} + +#[derive(Debug, Copy, Clone)] +#[repr(C, packed)] +struct MemoryEntry { + size: u32, + base_addr: u64, + length: u64, + memory_type: MemoryAreaType, +} + +// The entry point of kernel code, which should be defined by the package that +// uses jinux-frame. +extern "Rust" { + fn jinux_main() -> !; +} + +static MB1_INFO: Once<&'static MultibootLegacyInfo> = Once::new(); + +pub(super) unsafe fn multiboot_entry(boot_magic: u32, boot_params: u64) -> ! { + assert_eq!(boot_magic, MULTIBOOT_ENTRY_MAGIC); + MB1_INFO.call_once(|| &*(paddr_to_vaddr(boot_params as usize) as *const MultibootLegacyInfo)); + jinux_main(); +} diff --git a/framework/jinux-frame/src/arch/x86/boot/multiboot2.rs b/framework/jinux-frame/src/arch/x86/boot/multiboot2.rs index 725a1354c..52e7c6fd1 100644 --- a/framework/jinux-frame/src/arch/x86/boot/multiboot2.rs +++ b/framework/jinux-frame/src/arch/x86/boot/multiboot2.rs @@ -9,14 +9,16 @@ use crate::boot::{ memory_region::{MemoryRegion, MemoryRegionType}, BootloaderAcpiArg, BootloaderFramebufferArg, }; -use core::{arch::global_asm, mem::swap}; +use core::mem::swap; use spin::Once; use crate::{config::PHYS_OFFSET, vm::paddr_to_vaddr}; -global_asm!(include_str!("boot.S")); +pub(super) const MULTIBOOT2_ENTRY_MAGIC: u32 = 0x36d76289; -const MULTIBOOT2_ENTRY_MAGIC: u32 = 0x36d76289; +pub(super) fn boot_by_multiboot2() -> bool { + MB2_INFO.is_completed() +} static MB2_INFO: Once = Once::new(); @@ -214,8 +216,7 @@ extern "Rust" { } /// The entry point of Rust code called by inline asm. -#[no_mangle] -unsafe extern "C" fn __multiboot2_entry(boot_magic: u32, boot_params: u64) -> ! { +pub(super) unsafe fn multiboot2_entry(boot_magic: u32, boot_params: u64) -> ! { assert_eq!(boot_magic, MULTIBOOT2_ENTRY_MAGIC); MB2_INFO.call_once(|| unsafe { BootInformation::load(boot_params as *const BootInformationHeader).unwrap() diff --git a/framework/jinux-frame/src/arch/x86/device/cmos.rs b/framework/jinux-frame/src/arch/x86/device/cmos.rs index ef8b1a836..0d2867caf 100644 --- a/framework/jinux-frame/src/arch/x86/device/cmos.rs +++ b/framework/jinux-frame/src/arch/x86/device/cmos.rs @@ -9,14 +9,26 @@ pub static CMOS_ADDRESS: IoPort = unsafe { IoPort::new(0x70 pub static CMOS_DATA: IoPort = unsafe { IoPort::new(0x71) }; pub fn get_century() -> u8 { + const DEFAULT_21_CENTURY: u8 = 50; + if !ACPI_TABLES.is_completed() { + return DEFAULT_21_CENTURY; + } unsafe { - let a = ACPI_TABLES + match ACPI_TABLES .get() .unwrap() .lock() .get_sdt::(Signature::FADT) - .unwrap() - .expect("not found FACP in ACPI table"); - a.century + { + Ok(a) => { + let century = a.unwrap().century; + if century == 0 { + DEFAULT_21_CENTURY + } else { + century + } + } + Err(er) => DEFAULT_21_CENTURY, + } } } diff --git a/framework/jinux-frame/src/arch/x86/kernel/acpi/dmar.rs b/framework/jinux-frame/src/arch/x86/kernel/acpi/dmar.rs index cb15c812c..8c7e0130c 100644 --- a/framework/jinux-frame/src/arch/x86/kernel/acpi/dmar.rs +++ b/framework/jinux-frame/src/arch/x86/kernel/acpi/dmar.rs @@ -63,6 +63,9 @@ impl AcpiTable for DmarHeader { impl Dmar { /// Create a instance from ACPI table. pub fn new() -> Option { + if !super::ACPI_TABLES.is_completed() { + return None; + } let acpi_table_lock = super::ACPI_TABLES.get().unwrap().lock(); // Safety: The DmarHeader is the header for the DMAR structure, it fits all the field described in Intel manual. let dmar_mapping = unsafe { diff --git a/framework/jinux-frame/src/arch/x86/kernel/acpi/mod.rs b/framework/jinux-frame/src/arch/x86/kernel/acpi/mod.rs index d269731f5..7367d3c32 100644 --- a/framework/jinux-frame/src/arch/x86/kernel/acpi/mod.rs +++ b/framework/jinux-frame/src/arch/x86/kernel/acpi/mod.rs @@ -6,16 +6,18 @@ use core::{ ptr::NonNull, }; -use crate::boot::{self, BootloaderAcpiArg}; -use crate::sync::Mutex; use crate::vm::paddr_to_vaddr; +use crate::{ + boot::{self, BootloaderAcpiArg}, + sync::SpinLock, +}; use acpi::{sdt::SdtHeader, AcpiHandler, AcpiTable, AcpiTables}; use alloc::borrow::ToOwned; -use log::info; +use log::{info, warn}; use spin::Once; /// RSDP information, key is the signature, value is the virtual address of the signature -pub static ACPI_TABLES: Once>> = Once::new(); +pub static ACPI_TABLES: Once>> = Once::new(); /// Sdt header wrapper, user can use this structure to easily derive Debug, get table information without creating a new struture. /// @@ -102,12 +104,16 @@ pub fn init() { BootloaderAcpiArg::Xsdt(addr) => unsafe { AcpiTables::from_rsdt(AcpiMemoryHandler {}, 1, addr).unwrap() }, + BootloaderAcpiArg::NotExists => { + warn!("Not found ACPI table"); + return; + } }; for (signature, sdt) in acpi_tables.sdts.iter() { info!("ACPI found signature:{:?}", signature); } - ACPI_TABLES.call_once(|| Mutex::new(acpi_tables)); + ACPI_TABLES.call_once(|| SpinLock::new(acpi_tables)); info!("acpi init complete"); } diff --git a/framework/jinux-frame/src/arch/x86/kernel/apic/ioapic.rs b/framework/jinux-frame/src/arch/x86/kernel/apic/ioapic.rs index 77e526ec3..2398af0ee 100644 --- a/framework/jinux-frame/src/arch/x86/kernel/apic/ioapic.rs +++ b/framework/jinux-frame/src/arch/x86/kernel/apic/ioapic.rs @@ -44,6 +44,9 @@ unsafe impl Sync for IoApicWrapper {} pub static IO_APIC: Once> = Once::new(); pub fn init() { + if !ACPI_TABLES.is_completed() { + return; + } let c = ACPI_TABLES.get().unwrap().lock(); let platform_info = PlatformInfo::new(&*c).unwrap(); diff --git a/framework/jinux-frame/src/boot/kcmdline.rs b/framework/jinux-frame/src/boot/kcmdline.rs index 09982c01d..8400a99e0 100644 --- a/framework/jinux-frame/src/boot/kcmdline.rs +++ b/framework/jinux-frame/src/boot/kcmdline.rs @@ -81,6 +81,10 @@ impl From<&str> for KCmdlineArg { // The main parse loop. The processing steps are arranged (not very strictly) // by the analysis over the Backus–Naur form syntax tree. for arg in split_arg(cmdline) { + // FIXME: The -kernel option in QEMU seems to add this string to the command line, which we skip for now. + if arg.starts_with("target/x86_64-custom/debug/jinux") { + continue; + } // Cmdline => KernelArg "--" InitArg // KernelArg => Arg "\s+" KernelArg | %empty // InitArg => Arg "\s+" InitArg | %empty diff --git a/framework/jinux-frame/src/boot/mod.rs b/framework/jinux-frame/src/boot/mod.rs index 17e953d42..78b9466f3 100644 --- a/framework/jinux-frame/src/boot/mod.rs +++ b/framework/jinux-frame/src/boot/mod.rs @@ -18,6 +18,7 @@ use spin::Once; /// This is because bootloaders differ in such behaviors. #[derive(Copy, Clone, Debug)] pub enum BootloaderAcpiArg { + NotExists, /// Physical address of the RSDP. Rsdp(usize), /// Address of RSDT provided in RSDP v1.