xref: /DragonOS/kernel/src/init/boot.rs (revision 2b7818e80e00fcfe4d03533f587cc125ea5e4bec)
1*2b7818e8SLoGin use core::cmp::min;
2*2b7818e8SLoGin 
3*2b7818e8SLoGin use acpi::rsdp::Rsdp;
4*2b7818e8SLoGin use alloc::string::String;
5*2b7818e8SLoGin use system_error::SystemError;
6*2b7818e8SLoGin 
7*2b7818e8SLoGin use crate::{
8*2b7818e8SLoGin     arch::init::ArchBootParams,
9*2b7818e8SLoGin     driver::video::fbdev::base::BootTimeScreenInfo,
10*2b7818e8SLoGin     libs::lazy_init::Lazy,
11*2b7818e8SLoGin     mm::{PhysAddr, VirtAddr},
12*2b7818e8SLoGin };
13*2b7818e8SLoGin 
14*2b7818e8SLoGin use super::boot_params;
15*2b7818e8SLoGin #[derive(Debug)]
16*2b7818e8SLoGin pub struct BootParams {
17*2b7818e8SLoGin     pub screen_info: BootTimeScreenInfo,
18*2b7818e8SLoGin     bootloader_name: Option<String>,
19*2b7818e8SLoGin     #[allow(dead_code)]
20*2b7818e8SLoGin     pub arch: ArchBootParams,
21*2b7818e8SLoGin     boot_command_line: [u8; Self::BOOT_COMMAND_LINE_SIZE],
22*2b7818e8SLoGin     pub acpi: BootloaderAcpiArg,
23*2b7818e8SLoGin }
24*2b7818e8SLoGin 
25*2b7818e8SLoGin impl BootParams {
26*2b7818e8SLoGin     const DEFAULT: Self = BootParams {
27*2b7818e8SLoGin         screen_info: BootTimeScreenInfo::DEFAULT,
28*2b7818e8SLoGin         bootloader_name: None,
29*2b7818e8SLoGin         arch: ArchBootParams::DEFAULT,
30*2b7818e8SLoGin         boot_command_line: [0u8; Self::BOOT_COMMAND_LINE_SIZE],
31*2b7818e8SLoGin         acpi: BootloaderAcpiArg::NotProvided,
32*2b7818e8SLoGin     };
33*2b7818e8SLoGin 
34*2b7818e8SLoGin     /// 开机命令行参数字符串最大大小
35*2b7818e8SLoGin     pub const BOOT_COMMAND_LINE_SIZE: usize = 2048;
36*2b7818e8SLoGin 
37*2b7818e8SLoGin     pub(super) const fn new() -> Self {
38*2b7818e8SLoGin         Self::DEFAULT
39*2b7818e8SLoGin     }
40*2b7818e8SLoGin 
41*2b7818e8SLoGin     /// 开机命令行参数(原始字节数组)
42*2b7818e8SLoGin     #[allow(dead_code)]
43*2b7818e8SLoGin     pub fn boot_cmdline(&self) -> &[u8] {
44*2b7818e8SLoGin         &self.boot_command_line
45*2b7818e8SLoGin     }
46*2b7818e8SLoGin 
47*2b7818e8SLoGin     /// 开机命令行参数字符串
48*2b7818e8SLoGin     pub fn boot_cmdline_str(&self) -> &str {
49*2b7818e8SLoGin         core::str::from_utf8(self.boot_cmdline()).unwrap()
50*2b7818e8SLoGin     }
51*2b7818e8SLoGin 
52*2b7818e8SLoGin     pub fn bootloader_name(&self) -> Option<&str> {
53*2b7818e8SLoGin         self.bootloader_name.as_deref()
54*2b7818e8SLoGin     }
55*2b7818e8SLoGin 
56*2b7818e8SLoGin     /// 追加开机命令行参数
57*2b7818e8SLoGin     ///
58*2b7818e8SLoGin     /// 如果开机命令行参数已经满了,则不会追加。
59*2b7818e8SLoGin     /// 如果超过了最大长度,则截断。
60*2b7818e8SLoGin     ///
61*2b7818e8SLoGin     /// ## 参数
62*2b7818e8SLoGin     ///
63*2b7818e8SLoGin     /// - `data`:追加的数据
64*2b7818e8SLoGin     pub fn boot_cmdline_append(&mut self, data: &[u8]) {
65*2b7818e8SLoGin         if data.is_empty() {
66*2b7818e8SLoGin             return;
67*2b7818e8SLoGin         }
68*2b7818e8SLoGin 
69*2b7818e8SLoGin         let mut pos: Option<usize> = None;
70*2b7818e8SLoGin         // 寻找结尾
71*2b7818e8SLoGin         for (i, x) in self.boot_command_line.iter().enumerate() {
72*2b7818e8SLoGin             if *x == 0 {
73*2b7818e8SLoGin                 pos = Some(i);
74*2b7818e8SLoGin                 break;
75*2b7818e8SLoGin             }
76*2b7818e8SLoGin         }
77*2b7818e8SLoGin         let pos = pos.unwrap_or(self.boot_command_line.len() - 1) as isize;
78*2b7818e8SLoGin 
79*2b7818e8SLoGin         let avail = self.boot_command_line.len() as isize - pos - 1;
80*2b7818e8SLoGin         if avail <= 0 {
81*2b7818e8SLoGin             return;
82*2b7818e8SLoGin         }
83*2b7818e8SLoGin 
84*2b7818e8SLoGin         let len = min(avail as usize, data.len());
85*2b7818e8SLoGin         let pos = pos as usize;
86*2b7818e8SLoGin         self.boot_command_line[pos..pos + len].copy_from_slice(&data[0..len]);
87*2b7818e8SLoGin 
88*2b7818e8SLoGin         self.boot_command_line[pos + len] = 0;
89*2b7818e8SLoGin     }
90*2b7818e8SLoGin 
91*2b7818e8SLoGin     /// 获取FDT的虚拟地址
92*2b7818e8SLoGin     #[allow(dead_code)]
93*2b7818e8SLoGin     pub fn fdt(&self) -> Option<VirtAddr> {
94*2b7818e8SLoGin         #[cfg(target_arch = "riscv64")]
95*2b7818e8SLoGin         return Some(self.arch.arch_fdt());
96*2b7818e8SLoGin 
97*2b7818e8SLoGin         #[cfg(target_arch = "x86_64")]
98*2b7818e8SLoGin         return None;
99*2b7818e8SLoGin     }
100*2b7818e8SLoGin 
101*2b7818e8SLoGin     /// 获取FDT的物理地址
102*2b7818e8SLoGin     #[allow(dead_code)]
103*2b7818e8SLoGin     pub fn fdt_paddr(&self) -> Option<PhysAddr> {
104*2b7818e8SLoGin         #[cfg(target_arch = "riscv64")]
105*2b7818e8SLoGin         return Some(self.arch.fdt_paddr);
106*2b7818e8SLoGin 
107*2b7818e8SLoGin         #[cfg(target_arch = "x86_64")]
108*2b7818e8SLoGin         return None;
109*2b7818e8SLoGin     }
110*2b7818e8SLoGin }
111*2b7818e8SLoGin 
112*2b7818e8SLoGin /// 开机引导回调,用于初始化内核启动参数
113*2b7818e8SLoGin pub trait BootCallbacks: Send + Sync {
114*2b7818e8SLoGin     /// 初始化引导程序名称
115*2b7818e8SLoGin     fn init_bootloader_name(&self) -> Result<Option<String>, SystemError>;
116*2b7818e8SLoGin     /// 初始化ACPI参数
117*2b7818e8SLoGin     fn init_acpi_args(&self) -> Result<BootloaderAcpiArg, SystemError>;
118*2b7818e8SLoGin     /// 初始化内核命令行参数
119*2b7818e8SLoGin     ///
120*2b7818e8SLoGin     /// 该函数应该把内核命令行参数追加到`boot_params().boot_cmdline`中
121*2b7818e8SLoGin     fn init_kernel_cmdline(&self) -> Result<(), SystemError>;
122*2b7818e8SLoGin     /// 初始化帧缓冲区信息
123*2b7818e8SLoGin     ///
124*2b7818e8SLoGin     /// - 该函数应该把帧缓冲区信息写入`scinfo`中。
125*2b7818e8SLoGin     /// - 该函数应该在内存管理初始化之前调用。
126*2b7818e8SLoGin     fn early_init_framebuffer_info(
127*2b7818e8SLoGin         &self,
128*2b7818e8SLoGin         scinfo: &mut BootTimeScreenInfo,
129*2b7818e8SLoGin     ) -> Result<(), SystemError>;
130*2b7818e8SLoGin 
131*2b7818e8SLoGin     /// 初始化内存块
132*2b7818e8SLoGin     fn early_init_memory_blocks(&self) -> Result<(), SystemError>;
133*2b7818e8SLoGin }
134*2b7818e8SLoGin 
135*2b7818e8SLoGin static BOOT_CALLBACKS: Lazy<&'static dyn BootCallbacks> = Lazy::new();
136*2b7818e8SLoGin 
137*2b7818e8SLoGin /// 注册开机引导回调
138*2b7818e8SLoGin pub fn register_boot_callbacks(callbacks: &'static dyn BootCallbacks) {
139*2b7818e8SLoGin     BOOT_CALLBACKS.init(callbacks);
140*2b7818e8SLoGin }
141*2b7818e8SLoGin 
142*2b7818e8SLoGin /// 获取开机引导回调
143*2b7818e8SLoGin pub fn boot_callbacks() -> &'static dyn BootCallbacks {
144*2b7818e8SLoGin     let p = BOOT_CALLBACKS
145*2b7818e8SLoGin         .try_get()
146*2b7818e8SLoGin         .expect("Boot callbacks not initialized");
147*2b7818e8SLoGin 
148*2b7818e8SLoGin     *p
149*2b7818e8SLoGin }
150*2b7818e8SLoGin 
151*2b7818e8SLoGin pub(super) fn boot_callback_except_early() {
152*2b7818e8SLoGin     boot_callbacks()
153*2b7818e8SLoGin         .init_kernel_cmdline()
154*2b7818e8SLoGin         .expect("Failed to init kernel cmdline");
155*2b7818e8SLoGin     let mut boot_params = boot_params().write();
156*2b7818e8SLoGin     boot_params.bootloader_name = boot_callbacks()
157*2b7818e8SLoGin         .init_bootloader_name()
158*2b7818e8SLoGin         .expect("Failed to init bootloader name");
159*2b7818e8SLoGin     boot_params.acpi = boot_callbacks()
160*2b7818e8SLoGin         .init_acpi_args()
161*2b7818e8SLoGin         .unwrap_or(BootloaderAcpiArg::NotProvided);
162*2b7818e8SLoGin }
163*2b7818e8SLoGin 
164*2b7818e8SLoGin /// ACPI information from the bootloader.
165*2b7818e8SLoGin #[derive(Copy, Clone, Debug)]
166*2b7818e8SLoGin pub enum BootloaderAcpiArg {
167*2b7818e8SLoGin     /// The bootloader does not provide one, a manual search is needed.
168*2b7818e8SLoGin     NotProvided,
169*2b7818e8SLoGin     /// Physical address of the RSDP.
170*2b7818e8SLoGin     #[allow(dead_code)]
171*2b7818e8SLoGin     Rsdp(PhysAddr),
172*2b7818e8SLoGin     /// Address of RSDT provided in RSDP v1.
173*2b7818e8SLoGin     Rsdt(Rsdp),
174*2b7818e8SLoGin     /// Address of XSDT provided in RSDP v2+.
175*2b7818e8SLoGin     Xsdt(Rsdp),
176*2b7818e8SLoGin }
177