1*59a6bcf6SLoGin //! x86/HVM启动
2*59a6bcf6SLoGin //!
3*59a6bcf6SLoGin //! 初始化代码可参考:https://code.dragonos.org.cn/xref/linux-6.6.21/arch/x86/platform/pvh/enlighten.c#45
4*59a6bcf6SLoGin use alloc::string::{String, ToString};
5*59a6bcf6SLoGin use core::{ffi::CStr, hint::spin_loop};
6*59a6bcf6SLoGin use param::{E820Type, HvmMemmapTableEntry, HvmStartInfo};
7*59a6bcf6SLoGin use system_error::SystemError;
8*59a6bcf6SLoGin
9*59a6bcf6SLoGin use crate::{
10*59a6bcf6SLoGin arch::MMArch,
11*59a6bcf6SLoGin driver::{
12*59a6bcf6SLoGin serial::serial8250::send_to_default_serial8250_port, video::fbdev::base::BootTimeScreenInfo,
13*59a6bcf6SLoGin },
14*59a6bcf6SLoGin init::{
15*59a6bcf6SLoGin boot::{register_boot_callbacks, BootCallbacks, BootloaderAcpiArg},
16*59a6bcf6SLoGin boot_params,
17*59a6bcf6SLoGin },
18*59a6bcf6SLoGin libs::lazy_init::Lazy,
19*59a6bcf6SLoGin mm::{memblock::mem_block_manager, MemoryManagementArch, PhysAddr},
20*59a6bcf6SLoGin };
21*59a6bcf6SLoGin
22*59a6bcf6SLoGin mod param;
23*59a6bcf6SLoGin
24*59a6bcf6SLoGin static START_INFO: Lazy<HvmStartInfo> = Lazy::new();
25*59a6bcf6SLoGin
26*59a6bcf6SLoGin struct PvhBootCallback;
27*59a6bcf6SLoGin
28*59a6bcf6SLoGin impl BootCallbacks for PvhBootCallback {
init_bootloader_name(&self) -> Result<Option<String>, SystemError>29*59a6bcf6SLoGin fn init_bootloader_name(&self) -> Result<Option<String>, SystemError> {
30*59a6bcf6SLoGin return Ok(Some("x86 PVH".to_string()));
31*59a6bcf6SLoGin }
32*59a6bcf6SLoGin
init_acpi_args(&self) -> Result<BootloaderAcpiArg, SystemError>33*59a6bcf6SLoGin fn init_acpi_args(&self) -> Result<BootloaderAcpiArg, SystemError> {
34*59a6bcf6SLoGin let rsdp_paddr = PhysAddr::new(START_INFO.get().rsdp_paddr as usize);
35*59a6bcf6SLoGin if rsdp_paddr.data() != 0 {
36*59a6bcf6SLoGin Ok(BootloaderAcpiArg::Rsdp(rsdp_paddr))
37*59a6bcf6SLoGin } else {
38*59a6bcf6SLoGin Ok(BootloaderAcpiArg::NotProvided)
39*59a6bcf6SLoGin }
40*59a6bcf6SLoGin }
41*59a6bcf6SLoGin
init_kernel_cmdline(&self) -> Result<(), SystemError>42*59a6bcf6SLoGin fn init_kernel_cmdline(&self) -> Result<(), SystemError> {
43*59a6bcf6SLoGin let cmdline_c_str: &CStr = unsafe {
44*59a6bcf6SLoGin CStr::from_ptr(
45*59a6bcf6SLoGin MMArch::phys_2_virt(PhysAddr::new(START_INFO.get().cmdline_paddr as usize))
46*59a6bcf6SLoGin .unwrap()
47*59a6bcf6SLoGin .data() as *const i8,
48*59a6bcf6SLoGin )
49*59a6bcf6SLoGin };
50*59a6bcf6SLoGin let cmdline = cmdline_c_str.to_str().unwrap();
51*59a6bcf6SLoGin boot_params()
52*59a6bcf6SLoGin .write_irqsave()
53*59a6bcf6SLoGin .boot_cmdline_append(cmdline.as_bytes());
54*59a6bcf6SLoGin log::info!("pvh boot cmdline: {:?}", cmdline_c_str);
55*59a6bcf6SLoGin Ok(())
56*59a6bcf6SLoGin }
57*59a6bcf6SLoGin
early_init_framebuffer_info( &self, _scinfo: &mut BootTimeScreenInfo, ) -> Result<(), SystemError>58*59a6bcf6SLoGin fn early_init_framebuffer_info(
59*59a6bcf6SLoGin &self,
60*59a6bcf6SLoGin _scinfo: &mut BootTimeScreenInfo,
61*59a6bcf6SLoGin ) -> Result<(), SystemError> {
62*59a6bcf6SLoGin return Err(SystemError::ENODEV);
63*59a6bcf6SLoGin }
64*59a6bcf6SLoGin
early_init_memory_blocks(&self) -> Result<(), SystemError>65*59a6bcf6SLoGin fn early_init_memory_blocks(&self) -> Result<(), SystemError> {
66*59a6bcf6SLoGin let start_info = START_INFO.get();
67*59a6bcf6SLoGin let mut total_mem_size = 0usize;
68*59a6bcf6SLoGin let mut usable_mem_size = 0usize;
69*59a6bcf6SLoGin send_to_default_serial8250_port("init_memory_area by pvh boot\n\0".as_bytes());
70*59a6bcf6SLoGin
71*59a6bcf6SLoGin if (start_info.version > 0) && start_info.memmap_entries > 0 {
72*59a6bcf6SLoGin let mut ep = unsafe {
73*59a6bcf6SLoGin MMArch::phys_2_virt(PhysAddr::new(start_info.memmap_paddr as usize)).unwrap()
74*59a6bcf6SLoGin }
75*59a6bcf6SLoGin .data() as *const HvmMemmapTableEntry;
76*59a6bcf6SLoGin
77*59a6bcf6SLoGin for _ in 0..start_info.memmap_entries {
78*59a6bcf6SLoGin let entry = unsafe { *ep };
79*59a6bcf6SLoGin let start = PhysAddr::new(entry.addr as usize);
80*59a6bcf6SLoGin let size = entry.size as usize;
81*59a6bcf6SLoGin let typ = E820Type::from(entry.type_);
82*59a6bcf6SLoGin
83*59a6bcf6SLoGin total_mem_size += size;
84*59a6bcf6SLoGin match typ {
85*59a6bcf6SLoGin param::E820Type::Ram => {
86*59a6bcf6SLoGin usable_mem_size += size;
87*59a6bcf6SLoGin mem_block_manager()
88*59a6bcf6SLoGin .add_block(start, size)
89*59a6bcf6SLoGin .unwrap_or_else(|e| {
90*59a6bcf6SLoGin log::warn!(
91*59a6bcf6SLoGin "Failed to add memory block: base={:?}, size={:#x}, error={:?}",
92*59a6bcf6SLoGin start,
93*59a6bcf6SLoGin size,
94*59a6bcf6SLoGin e
95*59a6bcf6SLoGin );
96*59a6bcf6SLoGin });
97*59a6bcf6SLoGin }
98*59a6bcf6SLoGin _ => {
99*59a6bcf6SLoGin mem_block_manager()
100*59a6bcf6SLoGin .reserve_block(start, size)
101*59a6bcf6SLoGin .unwrap_or_else(|e| {
102*59a6bcf6SLoGin log::warn!(
103*59a6bcf6SLoGin "Failed to reserve memory block: base={:?}, size={:#x}, error={:?}",
104*59a6bcf6SLoGin start,
105*59a6bcf6SLoGin size,
106*59a6bcf6SLoGin e
107*59a6bcf6SLoGin );
108*59a6bcf6SLoGin });
109*59a6bcf6SLoGin }
110*59a6bcf6SLoGin }
111*59a6bcf6SLoGin ep = unsafe { ep.add(1) };
112*59a6bcf6SLoGin }
113*59a6bcf6SLoGin }
114*59a6bcf6SLoGin send_to_default_serial8250_port("init_memory_area_from pvh boot end\n\0".as_bytes());
115*59a6bcf6SLoGin log::info!(
116*59a6bcf6SLoGin "Total memory size: {:#x}, Usable memory size: {:#x}",
117*59a6bcf6SLoGin total_mem_size,
118*59a6bcf6SLoGin usable_mem_size
119*59a6bcf6SLoGin );
120*59a6bcf6SLoGin Ok(())
121*59a6bcf6SLoGin }
122*59a6bcf6SLoGin }
123*59a6bcf6SLoGin
124*59a6bcf6SLoGin #[inline(never)]
early_linux32_pvh_init(params_ptr: usize) -> Result<(), SystemError>125*59a6bcf6SLoGin pub(super) fn early_linux32_pvh_init(params_ptr: usize) -> Result<(), SystemError> {
126*59a6bcf6SLoGin let start_info = unsafe { *(params_ptr as *const HvmStartInfo) };
127*59a6bcf6SLoGin if start_info.magic != HvmStartInfo::XEN_HVM_START_MAGIC_VALUE {
128*59a6bcf6SLoGin send_to_default_serial8250_port(
129*59a6bcf6SLoGin "early_linux32_pvh_init failed: Magic number not matched.\n\0".as_bytes(),
130*59a6bcf6SLoGin );
131*59a6bcf6SLoGin
132*59a6bcf6SLoGin loop {
133*59a6bcf6SLoGin spin_loop();
134*59a6bcf6SLoGin }
135*59a6bcf6SLoGin }
136*59a6bcf6SLoGin
137*59a6bcf6SLoGin START_INFO.init(start_info);
138*59a6bcf6SLoGin
139*59a6bcf6SLoGin register_boot_callbacks(&PvhBootCallback);
140*59a6bcf6SLoGin send_to_default_serial8250_port("early_linux32_pvh_init done.\n\0".as_bytes());
141*59a6bcf6SLoGin Ok(())
142*59a6bcf6SLoGin }
143