Fix some incorrect memory region initialization

This commit is contained in:
Zhang Junyang 2025-01-08 20:30:03 +08:00 committed by Tate, Hongliang Tian
parent 8a6c8c44e9
commit 7496b24da1
3 changed files with 82 additions and 16 deletions

View File

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

View File

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

View File

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