Skip to content

Commit 0f4e53c

Browse files
feat(acpi): add RSDP discovery from BIOS memory regions. (#2124)
* acpi: add RSDP discovery from BIOS memory regions. impl ACPI RSDP discovery for legacy BIOS platforms by scanning the standard locations defined by the ACPI specification. The impl follow the linux kernel drivers/acpi/acpica/tbxfroot.c checking: - EBDA region - BIOS reserved memory range 0xE0000-0xFFFFF Signed-off-by: DonjuanPlatinum <donplat@barrensea.org> * 1. change RSDP scan before mm_init into early_init to follow the linux impl. 2. when len < 36 || len > available_len, rsdp_valid return false * fmt * change the scan window into min(1KiB, 0xA0000 - ebda_phys) Signed-off-by: Donjuanplatinum <donplat@barrensea.org> * fix EarlyRemapPage. Signed-off-by: Donjuanplatinum <donplat@barrensea.org> * Update acpi and aml dependencies Updated acpi and aml dependencies to a new commit hash. * fix(acpi): add legacy BIOS RSDP fallback Signed-off-by: longjin <longjin@dragonos.org> * fix(acpi): bound early RSDP mappings Signed-off-by: longjin <longjin@dragonos.org> --------- Signed-off-by: DonjuanPlatinum <donplat@barrensea.org> Signed-off-by: Donjuanplatinum <donplat@barrensea.org> Signed-off-by: longjin <longjin@dragonos.org> Co-authored-by: longjin <longjin@dragonos.org>
1 parent 229557c commit 0f4e53c

10 files changed

Lines changed: 366 additions & 32 deletions

File tree

kernel/Cargo.lock

Lines changed: 2 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

kernel/Cargo.toml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -36,8 +36,8 @@ fifo_demo = []
3636

3737
# 运行时依赖项
3838
[dependencies]
39-
acpi = { git = "https://git.mirrors.dragonos.org.cn/DragonOS-Community/acpi-rs.git", rev = "282df2af7b" }
40-
aml = { git = "https://git.mirrors.dragonos.org.cn/DragonOS-Community/acpi-rs.git", rev = "282df2af7b" }
39+
acpi = { git = "https://git.mirrors.dragonos.org.cn/DragonOS-Community/acpi-rs.git", rev = "1bbdc9767ac72725fa7bdbc53260b5b6baa2bce1" }
40+
aml = { git = "https://git.mirrors.dragonos.org.cn/DragonOS-Community/acpi-rs.git", rev = "1bbdc9767ac72725fa7bdbc53260b5b6baa2bce1" }
4141
asm_macros = { path = "crates/asm_macros" }
4242
atomic_enum = "=0.2.0"
4343
bit_field = "=0.10"

kernel/src/arch/x86_64/init/mod.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ use super::{
2727
mod boot;
2828
mod multiboot2;
2929
mod pvh;
30+
mod rsdp;
3031

3132
mod boot_params;
3233

kernel/src/arch/x86_64/init/multiboot2.rs

Lines changed: 36 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -22,12 +22,23 @@ use crate::{
2222
mm::{memblock::mem_block_manager, PhysAddr},
2323
};
2424

25+
use super::rsdp::{cache_bios_rsdp_result, cached_bios_rsdp};
26+
2527
pub(super) const MULTIBOOT2_ENTRY_MAGIC: u32 = multiboot2::MAGIC;
2628
static MB2_INFO: Lazy<BootInformation> = Lazy::new();
2729
const MB2_RAW_INFO_MAX_SIZE: usize = 4096;
2830

2931
static mut MB2_RAW_INFO: [u8; MB2_RAW_INFO_MAX_SIZE] = [0u8; MB2_RAW_INFO_MAX_SIZE];
3032

33+
fn has_efi_context(boot_info: &BootInformation) -> bool {
34+
boot_info.efi_sdt32_tag().is_some()
35+
|| boot_info.efi_sdt64_tag().is_some()
36+
|| boot_info.efi_memory_map_tag().is_some()
37+
|| boot_info.efi_bs_not_exited_tag().is_some()
38+
|| boot_info.efi_ih32_tag().is_some()
39+
|| boot_info.efi_ih64_tag().is_some()
40+
}
41+
3142
fn mb2_rsdp_v1_tag_to_rsdp_struct(tag: &RsdpV1Tag) -> Rsdp {
3243
Rsdp {
3344
signature: tag.signature,
@@ -70,17 +81,23 @@ impl BootCallbacks for Mb2Callback {
7081
}
7182

7283
fn init_acpi_args(&self) -> Result<BootloaderAcpiArg, SystemError> {
73-
if let Some(v1_tag) = MB2_INFO.get().rsdp_v1_tag() {
74-
Ok(BootloaderAcpiArg::Rsdt(mb2_rsdp_v1_tag_to_rsdp_struct(
75-
v1_tag,
76-
)))
77-
} else if let Some(v2_tag) = MB2_INFO.get().rsdp_v2_tag() {
78-
Ok(BootloaderAcpiArg::Xsdt(mb2_rsdp_v2_tag_to_rsdp_struct(
84+
let boot_info = MB2_INFO.get();
85+
if let Some(v2_tag) = boot_info.rsdp_v2_tag() {
86+
return Ok(BootloaderAcpiArg::Xsdt(mb2_rsdp_v2_tag_to_rsdp_struct(
7987
v2_tag,
80-
)))
81-
} else {
82-
Ok(BootloaderAcpiArg::NotProvided)
88+
)));
89+
}
90+
if let Some(v1_tag) = boot_info.rsdp_v1_tag() {
91+
return Ok(BootloaderAcpiArg::Rsdt(mb2_rsdp_v1_tag_to_rsdp_struct(
92+
v1_tag,
93+
)));
94+
}
95+
if let Some(paddr) = cached_bios_rsdp()? {
96+
log::info!("multiboot2: found RSDP at {:#x}", paddr.data());
97+
return Ok(BootloaderAcpiArg::Rsdp(paddr));
8398
}
99+
100+
Ok(BootloaderAcpiArg::NotProvided)
84101
}
85102

86103
fn init_kernel_cmdline(&self) -> Result<(), SystemError> {
@@ -209,6 +226,16 @@ impl BootCallbacks for Mb2Callback {
209226
// setup kernel load base
210227
self.setup_kernel_load_base();
211228

229+
// Legacy BIOS fallback is valid only when no ACPI tag and no EFI
230+
// context were supplied. UEFI systems must use their configuration
231+
// table and must not probe the fixed Legacy BIOS regions.
232+
if mb2_info.rsdp_v2_tag().is_none()
233+
&& mb2_info.rsdp_v1_tag().is_none()
234+
&& !has_efi_context(mb2_info)
235+
{
236+
cache_bios_rsdp_result();
237+
}
238+
212239
Ok(())
213240
}
214241

kernel/src/arch/x86_64/init/pvh/mod.rs

Lines changed: 34 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,8 @@ use crate::{
2121

2222
mod param;
2323

24+
use super::rsdp::{cache_bios_rsdp_result, cached_bios_rsdp};
25+
2426
static START_INFO: Lazy<HvmStartInfo> = Lazy::new();
2527

2628
struct PvhBootCallback;
@@ -31,12 +33,29 @@ impl BootCallbacks for PvhBootCallback {
3133
}
3234

3335
fn init_acpi_args(&self) -> Result<BootloaderAcpiArg, SystemError> {
34-
let rsdp_paddr = PhysAddr::new(START_INFO.get().rsdp_paddr as usize);
36+
let si = START_INFO.get();
37+
log::info!(
38+
"pvh: HvmStartInfo: magic={:#010x} version={} flags={:#x} nr_modules={} rsdp_paddr={:#x} memmap_paddr={:#x} memmap_entries={}",
39+
si.magic, si.version, si.flags, si.nr_modules,
40+
si.rsdp_paddr, si.memmap_paddr, si.memmap_entries
41+
);
42+
43+
let rsdp_paddr = PhysAddr::new(si.rsdp_paddr as usize);
44+
45+
// if RSDP has been provided
3546
if rsdp_paddr.data() != 0 {
36-
Ok(BootloaderAcpiArg::Rsdp(rsdp_paddr))
37-
} else {
38-
Ok(BootloaderAcpiArg::NotProvided)
47+
return Ok(BootloaderAcpiArg::Rsdp(rsdp_paddr));
3948
}
49+
50+
// The bootloader did not provide an RSDP. Consume the shared x86
51+
// early-discovery result without touching EarlyIoRemap after mm_init.
52+
if let Some(paddr) = cached_bios_rsdp()? {
53+
log::info!("pvh: found RSDP at {:#x}", paddr.data());
54+
return Ok(BootloaderAcpiArg::Rsdp(paddr));
55+
}
56+
57+
log::warn!("pvh: RSDP not found");
58+
Ok(BootloaderAcpiArg::NotProvided)
4059
}
4160

4261
fn init_kernel_cmdline(&self) -> Result<(), SystemError> {
@@ -86,7 +105,7 @@ impl BootCallbacks for PvhBootCallback {
86105

87106
total_mem_size += size;
88107
match typ {
89-
param::E820Type::Ram => {
108+
E820Type::Ram => {
90109
usable_mem_size += size;
91110
mem_block_manager()
92111
.add_block(start, size)
@@ -121,6 +140,16 @@ impl BootCallbacks for PvhBootCallback {
121140
total_mem_size,
122141
usable_mem_size
123142
);
143+
144+
// Discover the RSDP here, in the early boot stage: the bootstrap page
145+
// table is still active and mm_init has not run yet, so EarlyIoRemap may
146+
// be used safely (this mirrors Linux, which scans the RSDP in setup_arch
147+
// via early_memremap). If the bootloader already provided rsdp_paddr we
148+
// skip the scan. The result is cached for init_acpi_args.
149+
if start_info.rsdp_paddr == 0 {
150+
cache_bios_rsdp_result();
151+
}
152+
124153
Ok(())
125154
}
126155

kernel/src/arch/x86_64/init/pvh/param.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -160,7 +160,7 @@ pub struct HvmMemmapTableEntry {
160160
}
161161

162162
/// The E820 types known to the kernel.
163-
#[derive(Copy, Clone, Debug)]
163+
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
164164
#[repr(u32)]
165165
pub enum E820Type {
166166
Ram = 1,

0 commit comments

Comments
 (0)