From 7496b24da16fb93243c4ca2c013da5d2b77a30f0 Mon Sep 17 00:00:00 2001 From: Zhang Junyang Date: Wed, 8 Jan 2025 20:30:03 +0800 Subject: [PATCH] Fix some incorrect memory region initialization --- ostd/src/arch/x86/boot/linux_boot/mod.rs | 18 ++++++++- ostd/src/arch/x86/boot/multiboot/mod.rs | 31 ++++++++++----- ostd/src/arch/x86/boot/multiboot2/mod.rs | 49 +++++++++++++++++++++--- 3 files changed, 82 insertions(+), 16 deletions(-) diff --git a/ostd/src/arch/x86/boot/linux_boot/mod.rs b/ostd/src/arch/x86/boot/linux_boot/mod.rs index 805e02b6f..d72601a45 100644 --- a/ostd/src/arch/x86/boot/linux_boot/mod.rs +++ b/ostd/src/arch/x86/boot/linux_boot/mod.rs @@ -12,7 +12,10 @@ use crate::{ memory_region::{MemoryRegion, MemoryRegionArray, MemoryRegionType}, BootloaderAcpiArg, BootloaderFramebufferArg, }, - mm::kspace::{paddr_to_vaddr, LINEAR_MAPPING_BASE_VADDR}, + mm::{ + kspace::{paddr_to_vaddr, LINEAR_MAPPING_BASE_VADDR}, + Paddr, + }, }; fn parse_bootloader_name(boot_params: &BootParams) -> &str { @@ -44,8 +47,9 @@ fn parse_bootloader_name(boot_params: &BootParams) -> &str { } fn parse_kernel_commandline(boot_params: &BootParams) -> &str { + let ptr = paddr_to_vaddr(boot_params.hdr.cmd_line_ptr as usize) as *const i8; // SAFETY: The pointer in the header points to a valid C string. - let cmdline_c_str: &CStr = unsafe { CStr::from_ptr(boot_params.hdr.cmd_line_ptr as *const i8) }; + let cmdline_c_str: &CStr = unsafe { CStr::from_ptr(ptr) }; let cmdline_str = cmdline_c_str.to_str().unwrap(); cmdline_str } @@ -140,6 +144,16 @@ fn parse_memory_regions(boot_params: &BootParams) -> MemoryRegionArray { )) .unwrap(); + // Add the region of the kernel cmdline since some bootloaders do not provide it. + let kcmdline_str = parse_kernel_commandline(boot_params); + regions + .push(MemoryRegion::new( + kcmdline_str.as_ptr() as Paddr - LINEAR_MAPPING_BASE_VADDR, + kcmdline_str.len(), + MemoryRegionType::Reclaimable, + )) + .unwrap(); + regions.into_non_overlapping() } diff --git a/ostd/src/arch/x86/boot/multiboot/mod.rs b/ostd/src/arch/x86/boot/multiboot/mod.rs index 11aa40325..33d8b679e 100644 --- a/ostd/src/arch/x86/boot/multiboot/mod.rs +++ b/ostd/src/arch/x86/boot/multiboot/mod.rs @@ -20,16 +20,11 @@ pub(super) const MULTIBOOT_ENTRY_MAGIC: u32 = 0x2BADB002; fn parse_bootloader_name(mb1_info: &MultibootLegacyInfo) -> &str { let mut name = "Unknown Multiboot loader"; if mb1_info.boot_loader_name != 0 { + let ptr = paddr_to_vaddr(mb1_info.boot_loader_name as usize) as *const i8; // SAFETY: the bootloader name is C-style zero-terminated string. - unsafe { - let cstr = paddr_to_vaddr(mb1_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"); + let cstr = unsafe { core::ffi::CStr::from_ptr(ptr) }; + if let Ok(s) = cstr.to_str() { + name = s; } } name @@ -148,6 +143,24 @@ fn parse_memory_regions(mb1_info: &MultibootLegacyInfo) -> MemoryRegionArray { )) .unwrap(); + // Add the kernel cmdline and boot loader name region since Grub does not specify it. + let kcmdline = parse_kernel_commandline(mb1_info); + regions + .push(MemoryRegion::new( + kcmdline.as_ptr() as Paddr - LINEAR_MAPPING_BASE_VADDR, + kcmdline.len(), + MemoryRegionType::Reclaimable, + )) + .unwrap(); + let bootloader_name = parse_bootloader_name(mb1_info); + regions + .push(MemoryRegion::new( + bootloader_name.as_ptr() as Paddr - LINEAR_MAPPING_BASE_VADDR, + bootloader_name.len(), + MemoryRegionType::Reclaimable, + )) + .unwrap(); + regions.into_non_overlapping() } diff --git a/ostd/src/arch/x86/boot/multiboot2/mod.rs b/ostd/src/arch/x86/boot/multiboot2/mod.rs index c3c6838ef..62d58f6f8 100644 --- a/ostd/src/arch/x86/boot/multiboot2/mod.rs +++ b/ostd/src/arch/x86/boot/multiboot2/mod.rs @@ -10,7 +10,10 @@ use crate::{ memory_region::{MemoryRegion, MemoryRegionArray, MemoryRegionType}, BootloaderAcpiArg, BootloaderFramebufferArg, }, - mm::kspace::paddr_to_vaddr, + mm::{ + kspace::{paddr_to_vaddr, LINEAR_MAPPING_BASE_VADDR}, + Paddr, + }, }; global_asm!(include_str!("header.S")); @@ -20,23 +23,41 @@ pub(super) const MULTIBOOT2_ENTRY_MAGIC: u32 = 0x36d76289; static MB2_INFO: Once = Once::new(); fn parse_bootloader_name() -> &'static str { - MB2_INFO + let s = MB2_INFO .get() .unwrap() .boot_loader_name_tag() .expect("Bootloader name not found from the Multiboot2 header!") .name() - .expect("UTF-8 error: failed to parse bootloader name!") + .expect("UTF-8 error: failed to parse bootloader name!"); + let pa = s.as_ptr() as Paddr; + // SAFETY: We just convert this to virtual address. + unsafe { + core::str::from_utf8(core::slice::from_raw_parts( + paddr_to_vaddr(pa) as *const u8, + s.len(), + )) + .unwrap() + } } fn parse_kernel_commandline() -> &'static str { - MB2_INFO + let s = MB2_INFO .get() .unwrap() .command_line_tag() .expect("Kernel command-line not found from the Multiboot2 header!") .cmdline() - .expect("UTF-8 error: failed to parse kernel command-line!") + .expect("UTF-8 error: failed to parse kernel command-line!"); + let pa = s.as_ptr() as Paddr; + // SAFETY: We just convert this to virtual address. + unsafe { + core::str::from_utf8(core::slice::from_raw_parts( + paddr_to_vaddr(pa) as *const u8, + s.len(), + )) + .unwrap() + } } fn parse_initramfs() -> Option<&'static [u8]> { @@ -146,6 +167,24 @@ fn parse_memory_regions() -> MemoryRegionArray { )) .unwrap(); + // Add the kernel cmdline and boot loader name region since Grub does not specify it. + let kcmdline = parse_kernel_commandline(); + regions + .push(MemoryRegion::new( + kcmdline.as_ptr() as Paddr - LINEAR_MAPPING_BASE_VADDR, + kcmdline.len(), + MemoryRegionType::Reclaimable, + )) + .unwrap(); + let bootloader_name = parse_bootloader_name(); + regions + .push(MemoryRegion::new( + bootloader_name.as_ptr() as Paddr - LINEAR_MAPPING_BASE_VADDR, + bootloader_name.len(), + MemoryRegionType::Reclaimable, + )) + .unwrap(); + regions.into_non_overlapping() }