xref: /DragonOS/kernel/src/arch/x86_64/init/multiboot.rs (revision db7c782a9aaacb320027167bda4f23751b8f36e1)
1*db7c782aSLoGin use core::ffi::CStr;
2*db7c782aSLoGin 
3*db7c782aSLoGin use alloc::string::{String, ToString};
4*db7c782aSLoGin 
5*db7c782aSLoGin use multiboot::MultibootInfo;
6*db7c782aSLoGin use system_error::SystemError;
7*db7c782aSLoGin 
8*db7c782aSLoGin use crate::{
9*db7c782aSLoGin     arch::MMArch,
10*db7c782aSLoGin     driver::{
11*db7c782aSLoGin         serial::serial8250::send_to_default_serial8250_port,
12*db7c782aSLoGin         video::fbdev::{
13*db7c782aSLoGin             base::{BootTimeScreenInfo, BootTimeVideoType},
14*db7c782aSLoGin             vesafb::vesafb_early_map,
15*db7c782aSLoGin         },
16*db7c782aSLoGin     },
17*db7c782aSLoGin     init::{
18*db7c782aSLoGin         boot::{register_boot_callbacks, BootCallbacks, BootloaderAcpiArg},
19*db7c782aSLoGin         boot_params,
20*db7c782aSLoGin     },
21*db7c782aSLoGin     libs::lazy_init::Lazy,
22*db7c782aSLoGin     mm::{memblock::mem_block_manager, MemoryManagementArch, PhysAddr},
23*db7c782aSLoGin };
24*db7c782aSLoGin 
25*db7c782aSLoGin static MB1_INFO: Lazy<MultibootInfo> = Lazy::new();
26*db7c782aSLoGin 
27*db7c782aSLoGin struct Mb1Ops;
28*db7c782aSLoGin 
29*db7c782aSLoGin impl multiboot::MultibootOps for Mb1Ops {
phys_2_virt(&self, paddr: usize) -> usize30*db7c782aSLoGin     fn phys_2_virt(&self, paddr: usize) -> usize {
31*db7c782aSLoGin         unsafe { MMArch::phys_2_virt(PhysAddr::new(paddr)).unwrap().data() }
32*db7c782aSLoGin     }
33*db7c782aSLoGin }
34*db7c782aSLoGin struct Mb1Callback;
35*db7c782aSLoGin 
36*db7c782aSLoGin impl BootCallbacks for Mb1Callback {
init_bootloader_name(&self) -> Result<Option<String>, SystemError>37*db7c782aSLoGin     fn init_bootloader_name(&self) -> Result<Option<String>, SystemError> {
38*db7c782aSLoGin         let info = MB1_INFO.get();
39*db7c782aSLoGin         if info.boot_loader_name != 0 {
40*db7c782aSLoGin             // SAFETY: the bootloader name is C-style zero-terminated string.
41*db7c782aSLoGin             unsafe {
42*db7c782aSLoGin                 let cstr_ptr =
43*db7c782aSLoGin                     MMArch::phys_2_virt(PhysAddr::new(info.boot_loader_name as usize)).unwrap();
44*db7c782aSLoGin                 let cstr = CStr::from_ptr(cstr_ptr.data() as *const i8);
45*db7c782aSLoGin 
46*db7c782aSLoGin                 let result = cstr.to_str().unwrap_or("unknown").to_string();
47*db7c782aSLoGin                 return Ok(Some(result));
48*db7c782aSLoGin             }
49*db7c782aSLoGin         }
50*db7c782aSLoGin         Ok(None)
51*db7c782aSLoGin     }
52*db7c782aSLoGin 
init_acpi_args(&self) -> Result<BootloaderAcpiArg, SystemError>53*db7c782aSLoGin     fn init_acpi_args(&self) -> Result<BootloaderAcpiArg, SystemError> {
54*db7c782aSLoGin         // MB1不提供rsdp信息。因此,将来需要让内核支持从UEFI获取RSDP表。
55*db7c782aSLoGin         Ok(BootloaderAcpiArg::NotProvided)
56*db7c782aSLoGin     }
57*db7c782aSLoGin 
init_kernel_cmdline(&self) -> Result<(), SystemError>58*db7c782aSLoGin     fn init_kernel_cmdline(&self) -> Result<(), SystemError> {
59*db7c782aSLoGin         let info = MB1_INFO.get();
60*db7c782aSLoGin 
61*db7c782aSLoGin         if !info.has_cmdline() {
62*db7c782aSLoGin             log::debug!("No kernel command line found in multiboot1 info");
63*db7c782aSLoGin             return Ok(());
64*db7c782aSLoGin         }
65*db7c782aSLoGin 
66*db7c782aSLoGin         if let Some(cmdline) = unsafe { info.cmdline(&Mb1Ops) } {
67*db7c782aSLoGin             let mut guard = boot_params().write_irqsave();
68*db7c782aSLoGin             guard.boot_cmdline_append(cmdline.as_bytes());
69*db7c782aSLoGin 
70*db7c782aSLoGin             log::info!("Kernel command line: {}\n", cmdline);
71*db7c782aSLoGin         }
72*db7c782aSLoGin 
73*db7c782aSLoGin         Ok(())
74*db7c782aSLoGin     }
75*db7c782aSLoGin 
early_init_framebuffer_info( &self, scinfo: &mut BootTimeScreenInfo, ) -> Result<(), SystemError>76*db7c782aSLoGin     fn early_init_framebuffer_info(
77*db7c782aSLoGin         &self,
78*db7c782aSLoGin         scinfo: &mut BootTimeScreenInfo,
79*db7c782aSLoGin     ) -> Result<(), SystemError> {
80*db7c782aSLoGin         let info = MB1_INFO.get();
81*db7c782aSLoGin         let fb_table = info.framebuffer_table;
82*db7c782aSLoGin         let width = fb_table.width;
83*db7c782aSLoGin         let height = fb_table.height;
84*db7c782aSLoGin         scinfo.is_vga = true;
85*db7c782aSLoGin         scinfo.lfb_base = PhysAddr::new(fb_table.paddr as usize);
86*db7c782aSLoGin         let fb_type = fb_table.color_info().unwrap();
87*db7c782aSLoGin 
88*db7c782aSLoGin         match fb_type {
89*db7c782aSLoGin             multiboot::ColorInfoType::Palette(_) => todo!(),
90*db7c782aSLoGin             multiboot::ColorInfoType::Rgb(rgb) => {
91*db7c782aSLoGin                 scinfo.lfb_width = width;
92*db7c782aSLoGin                 scinfo.lfb_height = height;
93*db7c782aSLoGin                 scinfo.video_type = BootTimeVideoType::Vlfb;
94*db7c782aSLoGin                 scinfo.lfb_depth = fb_table.bpp;
95*db7c782aSLoGin                 scinfo.red_pos = rgb.red_field_position;
96*db7c782aSLoGin                 scinfo.red_size = rgb.red_mask_size;
97*db7c782aSLoGin                 scinfo.green_pos = rgb.green_field_position;
98*db7c782aSLoGin                 scinfo.green_size = rgb.green_mask_size;
99*db7c782aSLoGin                 scinfo.blue_pos = rgb.blue_field_position;
100*db7c782aSLoGin                 scinfo.blue_size = rgb.blue_mask_size;
101*db7c782aSLoGin             }
102*db7c782aSLoGin             multiboot::ColorInfoType::Text => {
103*db7c782aSLoGin                 scinfo.origin_video_cols = width as u8;
104*db7c782aSLoGin                 scinfo.origin_video_lines = height as u8;
105*db7c782aSLoGin                 scinfo.video_type = BootTimeVideoType::Mda;
106*db7c782aSLoGin                 scinfo.lfb_depth = 8;
107*db7c782aSLoGin             }
108*db7c782aSLoGin         }
109*db7c782aSLoGin         scinfo.lfb_size = (width * height * ((scinfo.lfb_depth as u32 + 7) / 8)) as usize;
110*db7c782aSLoGin 
111*db7c782aSLoGin         scinfo.lfb_virt_base = Some(vesafb_early_map(scinfo.lfb_base, scinfo.lfb_size)?);
112*db7c782aSLoGin 
113*db7c782aSLoGin         return Ok(());
114*db7c782aSLoGin     }
115*db7c782aSLoGin 
early_init_memory_blocks(&self) -> Result<(), SystemError>116*db7c782aSLoGin     fn early_init_memory_blocks(&self) -> Result<(), SystemError> {
117*db7c782aSLoGin         let info = MB1_INFO.get();
118*db7c782aSLoGin         let mut total_mem_size = 0usize;
119*db7c782aSLoGin         let mut usable_mem_size = 0usize;
120*db7c782aSLoGin         for entry in unsafe { info.memory_map(&Mb1Ops) } {
121*db7c782aSLoGin             let start = PhysAddr::new(entry.base_addr() as usize);
122*db7c782aSLoGin             let size = entry.length() as usize;
123*db7c782aSLoGin             let area_typ = entry.memory_type();
124*db7c782aSLoGin             total_mem_size += size;
125*db7c782aSLoGin 
126*db7c782aSLoGin             match area_typ {
127*db7c782aSLoGin                 multiboot::MemoryType::Available => {
128*db7c782aSLoGin                     usable_mem_size += size;
129*db7c782aSLoGin                     mem_block_manager()
130*db7c782aSLoGin                         .add_block(start, size)
131*db7c782aSLoGin                         .unwrap_or_else(|e| {
132*db7c782aSLoGin                             log::warn!(
133*db7c782aSLoGin                                 "Failed to add memory block: base={:?}, size={:#x}, error={:?}",
134*db7c782aSLoGin                                 start,
135*db7c782aSLoGin                                 size,
136*db7c782aSLoGin                                 e
137*db7c782aSLoGin                             );
138*db7c782aSLoGin                         });
139*db7c782aSLoGin                 }
140*db7c782aSLoGin                 _ => {
141*db7c782aSLoGin                     mem_block_manager()
142*db7c782aSLoGin                         .reserve_block(start, size)
143*db7c782aSLoGin                         .unwrap_or_else(|e| {
144*db7c782aSLoGin                             log::warn!(
145*db7c782aSLoGin                                 "Failed to reserve memory block: base={:?}, size={:#x}, error={:?}",
146*db7c782aSLoGin                                 start,
147*db7c782aSLoGin                                 size,
148*db7c782aSLoGin                                 e
149*db7c782aSLoGin                             );
150*db7c782aSLoGin                         });
151*db7c782aSLoGin                 }
152*db7c782aSLoGin             }
153*db7c782aSLoGin         }
154*db7c782aSLoGin         send_to_default_serial8250_port("init_memory_area_from_multiboot1 end\n\0".as_bytes());
155*db7c782aSLoGin         log::info!(
156*db7c782aSLoGin             "Total memory size: {:#x}, Usable memory size: {:#x}",
157*db7c782aSLoGin             total_mem_size,
158*db7c782aSLoGin             usable_mem_size
159*db7c782aSLoGin         );
160*db7c782aSLoGin 
161*db7c782aSLoGin         if let Some(modules_iter) = unsafe { info.modules(&Mb1Ops) } {
162*db7c782aSLoGin             for m in modules_iter {
163*db7c782aSLoGin                 let base = PhysAddr::new(m.start() as usize);
164*db7c782aSLoGin                 let size = m.end() as usize - m.start() as usize;
165*db7c782aSLoGin                 mem_block_manager()
166*db7c782aSLoGin                     .reserve_block(base, size)
167*db7c782aSLoGin                     .unwrap_or_else(|e| {
168*db7c782aSLoGin                         log::warn!(
169*db7c782aSLoGin                         "Failed to reserve modules memory block: base={:?}, size={:#x}, error={:?}",
170*db7c782aSLoGin                         base,
171*db7c782aSLoGin                         size,
172*db7c782aSLoGin                         e
173*db7c782aSLoGin                     );
174*db7c782aSLoGin                     });
175*db7c782aSLoGin             }
176*db7c782aSLoGin         }
177*db7c782aSLoGin 
178*db7c782aSLoGin         Ok(())
179*db7c782aSLoGin     }
180*db7c782aSLoGin }
181*db7c782aSLoGin 
early_multiboot_init(boot_magic: u32, boot_info: u64) -> Result<(), SystemError>182*db7c782aSLoGin pub(super) fn early_multiboot_init(boot_magic: u32, boot_info: u64) -> Result<(), SystemError> {
183*db7c782aSLoGin     assert_eq!(boot_magic, multiboot::MAGIC);
184*db7c782aSLoGin     let boot_info = unsafe { MMArch::phys_2_virt(PhysAddr::new(boot_info as usize)).unwrap() };
185*db7c782aSLoGin     let mb1_info = unsafe { (boot_info.data() as *const MultibootInfo).as_ref().unwrap() };
186*db7c782aSLoGin     MB1_INFO.init(*mb1_info);
187*db7c782aSLoGin 
188*db7c782aSLoGin     register_boot_callbacks(&Mb1Callback);
189*db7c782aSLoGin 
190*db7c782aSLoGin     Ok(())
191*db7c782aSLoGin }
192