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